Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate from Remix to React Router #24

Merged
merged 6 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
yarn.lock
node_modules

.react-router/

# Editor Configs
.idea
.vscode
Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion infra/www.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { domain } from './dns'
import { email } from './email'
import { secret } from './secret'

export const www = new sst.aws.Remix('Remix', {
export const www = new sst.aws.React('ReactRouter', {
path: './packages/www',
domain: {
name: domain,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
"@biomejs/biome": "^1.9.4",
"typescript": "^5.7.2"
},
"trustedDependencies": ["@biomejs/biome"]
"trustedDependencies": ["@biomejs/biome", "esbuild"]
}
4 changes: 2 additions & 2 deletions packages/core/sst-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
"Remix": {
"type": "sst.aws.Remix"
"ReactRouter": {
"type": "sst.aws.React"
"url": string
}
"SESSION_SECRET": {
Expand Down
4 changes: 2 additions & 2 deletions packages/functions/sst-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
"Remix": {
"type": "sst.aws.Remix"
"ReactRouter": {
"type": "sst.aws.React"
"url": string
}
"SESSION_SECRET": {
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/components/misc/client-hints.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect } from 'react'
import { useRevalidator } from '@remix-run/react'
import { useRevalidator } from 'react-router'
import { subscribeToSchemeChange } from '@epic-web/client-hints/color-scheme'
import { hintsUtils } from '#app/utils/hooks/use-hints'

Expand Down
4 changes: 2 additions & 2 deletions packages/www/app/components/misc/error-boundary.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ErrorResponse } from '@remix-run/router'
import { isRouteErrorResponse, useParams, useRouteError } from '@remix-run/react'
import type { ErrorResponse } from 'react-router'
import { isRouteErrorResponse, useParams, useRouteError } from 'react-router'

type StatusHandler = (info: {
error: ErrorResponse
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/components/misc/language-switcher.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useNavigate } from '@remix-run/react'
import { useNavigate } from 'react-router'
import { useTranslation } from 'react-i18next'
import { LucideLanguages } from 'lucide-react'
import {
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/components/misc/theme-switcher.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Theme, ThemeExtended } from '#app/utils/hooks/use-theme'
import { useSubmit } from '@remix-run/react'
import { useSubmit } from 'react-router'
import { LucideSun, LucideMoon, LucideMonitor } from 'lucide-react'
import { useOptimisticThemeMode } from '#app/utils/hooks/use-theme'
import { cn } from '#app/utils/misc'
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/components/navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Link, useLocation, useNavigate, useSubmit } from '@remix-run/react'
import { Link, useLocation, useNavigate, useSubmit } from 'react-router'
import {
LucideCheck,
LucideChevronDown,
Expand Down
4 changes: 2 additions & 2 deletions packages/www/app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RemixBrowser } from '@remix-run/react'
import { HydratedRouter } from 'react-router/dom'
import i18next from 'i18next'
import I18nextBrowserLanguageDetector from 'i18next-browser-languagedetector'
import { startTransition } from 'react'
Expand Down Expand Up @@ -27,7 +27,7 @@ async function main() {
hydrateRoot(
document,
<I18nextProvider i18n={i18next}>
<RemixBrowser />
<HydratedRouter />
</I18nextProvider>,
)
})
Expand Down
12 changes: 6 additions & 6 deletions packages/www/app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { AppLoadContext, EntryContext } from '@remix-run/node'
import type { AppLoadContext, EntryContext } from 'react-router'
import { isbot } from 'isbot'
import { PassThrough } from 'node:stream'
import crypto from 'node:crypto'
import { RemixServer } from '@remix-run/react'
import { createReadableStreamFromReadable } from '@remix-run/node'
import { ServerRouter } from 'react-router'
import { createReadableStreamFromReadable } from '@react-router/node'
import { renderToPipeableStream } from 'react-dom/server'
import { createInstance } from 'i18next'
import { I18nextProvider, initReactI18next } from 'react-i18next'
Expand All @@ -17,7 +17,7 @@ export default async function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
reactRouterContext: EntryContext,
_: AppLoadContext,
) {
const callbackName = isbot(request.headers.get('user-agent'))
Expand All @@ -40,7 +40,7 @@ export default async function handleRequest(
*/
const instance = createInstance()
const lng = await i18nServer.getLocale(request)
const ns = i18nServer.getRouteNamespaces(remixContext)
const ns = i18nServer.getRouteNamespaces(reactRouterContext)

await instance.use(initReactI18next).init({
...i18n,
Expand All @@ -54,7 +54,7 @@ export default async function handleRequest(
const { pipe, abort } = renderToPipeableStream(
<NonceProvider value={nonce}>
<I18nextProvider i18n={instance}>
<RemixServer nonce={nonce} context={remixContext} url={request.url} />
<ServerRouter nonce={nonce} context={reactRouterContext} url={request.url} />
</I18nextProvider>
</NonceProvider>,
{
Expand Down
22 changes: 22 additions & 0 deletions packages/www/app/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { AppLoadContext } from 'react-router'

declare module 'lucide-react' {
// Only show type suggestions for Lucide icons with a prefix.
// Otherwise you editor will try to import an icon instead of some component you actually want.
export * from 'lucide-react/dist/lucide-react.prefixed'
}

declare module 'react-router' {
// TODO: remove this once we've migrated to `Route.LoaderArgs` instead for our loaders
interface LoaderFunctionArgs {
context: AppLoadContext
}

// TODO: remove this once we've migrated to `Route.ActionArgs` instead for our actions
interface ActionFunctionArgs {
context: AppLoadContext
}
}

// biome-ignore lint/complexity/noUselessEmptyExport: <explanation>
export {} // necessary for TS to treat this as a module
2 changes: 1 addition & 1 deletion packages/www/app/modules/auth/auth-session.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createCookieSessionStorage } from '@remix-run/node'
import { createCookieSessionStorage } from 'react-router'
import { Resource } from 'sst'

export const AUTH_SESSION_KEY = '_auth'
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/modules/auth/auth.server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { db, schema } from '@company/core/src/drizzle/index'
import { Email } from '@company/core/src/email/index'
import { redirect } from '@remix-run/node'
import { redirect } from 'react-router'
import { eq } from 'drizzle-orm'
import { Authenticator } from 'remix-auth'
import { GitHubStrategy } from 'remix-auth-github'
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/modules/i18n/i18n.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createCookie } from '@remix-run/node'
import { createCookie } from 'react-router'
import { RemixI18Next } from 'remix-i18next/server'

import * as i18n from '#app/modules/i18n/i18n'
Expand Down
6 changes: 3 additions & 3 deletions packages/www/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MetaFunction, LinksFunction, LoaderFunctionArgs } from '@remix-run/node'
import type { MetaFunction, LinksFunction, LoaderFunctionArgs } from 'react-router'
import type { Theme } from '#app/utils/hooks/use-theme'
import {
Links,
Expand All @@ -7,8 +7,8 @@ import {
Scripts,
ScrollRestoration,
useLoaderData,
} from '@remix-run/react'
import { data } from '@remix-run/node'
} from 'react-router'
import { data } from 'react-router'
import { useChangeLanguage } from 'remix-i18next/react'
import { AuthenticityTokenProvider } from 'remix-utils/csrf/react'
import { HoneypotProvider } from 'remix-utils/honeypot/react'
Expand Down
4 changes: 2 additions & 2 deletions packages/www/app/routes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { RouteConfig } from '@remix-run/route-config'
import { remixRoutesOptionAdapter } from '@remix-run/routes-option-adapter'
import type { RouteConfig } from '@react-router/dev/routes'
import { remixRoutesOptionAdapter } from '@react-router/remix-routes-option-adapter'
import { flatRoutes } from 'remix-flat-routes'

export default remixRoutesOptionAdapter((defineRoutes) =>
Expand Down
4 changes: 2 additions & 2 deletions packages/www/app/routes/$.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { MetaFunction } from '@remix-run/node'
import { Link } from '@remix-run/react'
import type { MetaFunction } from 'react-router'
import { Link } from 'react-router'
import { LucideHelpCircle, LucideExternalLink } from 'lucide-react'
import { siteConfig } from '#app/utils/constants/brand'
import { GenericErrorBoundary } from '#app/components/misc/error-boundary'
Expand Down
4 changes: 2 additions & 2 deletions packages/www/app/routes/_home+/_index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { MetaFunction, LoaderFunctionArgs } from '@remix-run/node'
import { Link, useLoaderData } from '@remix-run/react'
import type { MetaFunction, LoaderFunctionArgs } from 'react-router'
import { Link, useLoaderData } from 'react-router'
import Markdown from 'react-markdown'
import rehypeSlug from 'rehype-slug'
import { authenticator } from '#app/modules/auth/auth.server'
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/routes/_home+/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Outlet } from '@remix-run/react'
import { Outlet } from 'react-router'

export const ROUTE_PATH = '/' as const

Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/routes/admin+/_index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { LoaderFunctionArgs } from '@remix-run/node'
import type { LoaderFunctionArgs } from 'react-router'
import { requireUserWithRole } from '#app/utils/permissions.server'

export async function loader({ request }: LoaderFunctionArgs) {
Expand Down
4 changes: 2 additions & 2 deletions packages/www/app/routes/admin+/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { MetaFunction, LoaderFunctionArgs } from '@remix-run/node'
import { useLoaderData } from '@remix-run/react'
import type { MetaFunction, LoaderFunctionArgs } from 'react-router'
import { useLoaderData } from 'react-router'
import { LucideShoppingBasket, LucideExternalLink } from 'lucide-react'
import { requireUserWithRole } from '#app/utils/permissions.server'
import { cn } from '#app/utils/misc.js'
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/routes/auth+/$provider.callback.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { LoaderFunctionArgs } from '@remix-run/node'
import type { LoaderFunctionArgs } from 'react-router'
import { authenticator } from '#app/modules/auth/auth.server'
import { ROUTE_PATH as LOGIN_PATH } from '#app/routes/auth+/login'
import { ROUTE_PATH as DASHBOARD_PATH } from '#app/routes/dashboard+/_layout'
Expand Down
4 changes: 2 additions & 2 deletions packages/www/app/routes/auth+/$provider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ActionFunctionArgs } from '@remix-run/node'
import { redirect } from '@remix-run/node'
import type { ActionFunctionArgs } from 'react-router'
import { redirect } from 'react-router'
import { authenticator } from '#app/modules/auth/auth.server'
import { ROUTE_PATH as LOGIN_PATH } from '#app/routes/auth+/login'

Expand Down
6 changes: 3 additions & 3 deletions packages/www/app/routes/auth+/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { LoaderFunctionArgs } from '@remix-run/node'
import { Link, Outlet } from '@remix-run/react'
import { redirect } from '@remix-run/node'
import type { LoaderFunctionArgs } from 'react-router'
import { Link, Outlet } from 'react-router'
import { redirect } from 'react-router'
import { authenticator } from '#app/modules/auth/auth.server'
import { getDomainPathname } from '#app/utils/misc.server'
import { ROUTE_PATH as HOME_PATH } from '#app/routes/_home+/_layout'
Expand Down
10 changes: 3 additions & 7 deletions packages/www/app/routes/auth+/login.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import type {
MetaFunction,
LoaderFunctionArgs,
ActionFunctionArgs,
} from '@remix-run/node'
import type { MetaFunction, LoaderFunctionArgs, ActionFunctionArgs } from 'react-router'
import { useRef, useEffect } from 'react'
import { Form, useLoaderData } from '@remix-run/react'
import { data } from '@remix-run/node'
import { Form, useLoaderData } from 'react-router'
import { data } from 'react-router'
import { useHydrated } from 'remix-utils/use-hydrated'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/routes/auth+/logout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { LoaderFunctionArgs, ActionFunctionArgs } from '@remix-run/node'
import type { LoaderFunctionArgs, ActionFunctionArgs } from 'react-router'
import { authenticator } from '#app/modules/auth/auth.server'

export const ROUTE_PATH = '/auth/logout' as const
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/routes/auth+/magic-link.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { LoaderFunctionArgs } from '@remix-run/node'
import type { LoaderFunctionArgs } from 'react-router'
import { authenticator } from '#app/modules/auth/auth.server'

import { ROUTE_PATH as DASHBOARD_PATH } from '#app/routes/dashboard+/_layout'
Expand Down
10 changes: 3 additions & 7 deletions packages/www/app/routes/auth+/verify.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import type {
MetaFunction,
LoaderFunctionArgs,
ActionFunctionArgs,
} from '@remix-run/node'
import type { MetaFunction, LoaderFunctionArgs, ActionFunctionArgs } from 'react-router'
import { useRef, useEffect } from 'react'
import { Form, useLoaderData } from '@remix-run/react'
import { data, redirect } from '@remix-run/node'
import { Form, useLoaderData } from 'react-router'
import { data, redirect } from 'react-router'
import { useHydrated } from 'remix-utils/use-hydrated'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/routes/dashboard+/_index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MetaFunction, LoaderFunctionArgs } from '@remix-run/node'
import type { MetaFunction, LoaderFunctionArgs } from 'react-router'
import { LucidePlus, LucideExternalLink } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import { requireUser } from '#app/modules/auth/auth.server'
Expand Down
6 changes: 3 additions & 3 deletions packages/www/app/routes/dashboard+/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { LoaderFunctionArgs } from '@remix-run/node'
import { Outlet, useLoaderData } from '@remix-run/react'
import { redirect } from '@remix-run/node'
import type { LoaderFunctionArgs } from 'react-router'
import { Outlet, useLoaderData } from 'react-router'
import { redirect } from 'react-router'
import { requireUser } from '#app/modules/auth/auth.server'
import { ROUTE_PATH as ONBOARDING_USERNAME_PATH } from '#app/routes/onboarding+/username'
import { Navigation } from '#app/components/navigation'
Expand Down
6 changes: 3 additions & 3 deletions packages/www/app/routes/dashboard+/checkout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { MetaFunction, LoaderFunctionArgs } from '@remix-run/node'
import type { MetaFunction, LoaderFunctionArgs } from 'react-router'
import { useState } from 'react'
import { Link, useLoaderData, useRevalidator } from '@remix-run/react'
import { redirect } from '@remix-run/node'
import { Link, useLoaderData, useRevalidator } from 'react-router'
import { redirect } from 'react-router'
import {
LucideLoader2,
LucideBadgeCheck,
Expand Down
10 changes: 3 additions & 7 deletions packages/www/app/routes/dashboard+/settings.billing.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import type {
MetaFunction,
LoaderFunctionArgs,
ActionFunctionArgs,
} from '@remix-run/node'
import type { MetaFunction, LoaderFunctionArgs, ActionFunctionArgs } from 'react-router'
import type { Interval, Plan as PlanEnum } from '@company/core/src/constants'
import { useState } from 'react'
import { Form, useLoaderData } from '@remix-run/react'
import { redirect } from '@remix-run/node'
import { Form, useLoaderData } from 'react-router'
import { redirect } from 'react-router'
import { requireSessionUser } from '#app/modules/auth/auth.server'
import { PLANS, PRICING_PLANS, INTERVALS, CURRENCIES } from '@company/core/src/constants'
import { getLocaleCurrency } from '#app/utils/misc.server'
Expand Down
6 changes: 3 additions & 3 deletions packages/www/app/routes/dashboard+/settings.index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { LoaderFunctionArgs, ActionFunctionArgs } from '@remix-run/node'
import type { LoaderFunctionArgs, ActionFunctionArgs } from 'react-router'
import { useRef, useState } from 'react'
import { Form, useFetcher, useLoaderData, useActionData } from '@remix-run/react'
import { data, redirect } from '@remix-run/node'
import { Form, useFetcher, useLoaderData, useActionData } from 'react-router'
import { data, redirect } from 'react-router'
import { z } from 'zod'
import { getZodConstraint, parseWithZod } from '@conform-to/zod'
import { getFormProps, getInputProps, useForm } from '@conform-to/react'
Expand Down
4 changes: 2 additions & 2 deletions packages/www/app/routes/dashboard+/settings.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { MetaFunction, LoaderFunctionArgs } from '@remix-run/node'
import { Link, Outlet, useLocation } from '@remix-run/react'
import type { MetaFunction, LoaderFunctionArgs } from 'react-router'
import { Link, Outlet, useLocation } from 'react-router'
import { z } from 'zod'
import { requireUser } from '#app/modules/auth/auth.server'
import { cn } from '#app/utils/misc'
Expand Down
6 changes: 3 additions & 3 deletions packages/www/app/routes/onboarding+/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { LoaderFunctionArgs } from '@remix-run/node'
import { Outlet } from '@remix-run/react'
import { json, redirect } from '@remix-run/node'
import type { LoaderFunctionArgs } from 'react-router'
import { Outlet } from 'react-router'
import { redirect } from 'react-router'
import { requireUser } from '#app/modules/auth/auth.server'
import { getDomainPathname } from '#app/utils/misc.server'
import { ROUTE_PATH as DASHBOARD_PATH } from '#app/routes/dashboard+/_layout'
Expand Down
10 changes: 3 additions & 7 deletions packages/www/app/routes/onboarding+/username.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import type {
MetaFunction,
LoaderFunctionArgs,
ActionFunctionArgs,
} from '@remix-run/node'
import type { MetaFunction, LoaderFunctionArgs, ActionFunctionArgs } from 'react-router'
import { useRef, useEffect } from 'react'
import { Form, useActionData } from '@remix-run/react'
import { data, redirect } from '@remix-run/node'
import { Form, useActionData } from 'react-router'
import { data, redirect } from 'react-router'
import { useHydrated } from 'remix-utils/use-hydrated'
import { AuthenticityTokenInput } from 'remix-utils/csrf/react'
import { HoneypotInputs } from 'remix-utils/honeypot/react'
Expand Down
2 changes: 1 addition & 1 deletion packages/www/app/routes/resources+/reset-image.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ActionFunctionArgs } from '@remix-run/router'
import type { ActionFunctionArgs } from 'react-router'
import { requireUser } from '#app/modules/auth/auth.server'
import { db, schema } from '@company/core/src/drizzle/index'
import { eq } from 'drizzle-orm'
Expand Down
Loading
Loading