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

Adapt remix-themes for react-router-v7 #48

Closed
wants to merge 3 commits into from
Closed
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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,7 @@ dist

build
/test-results
/playwright-report
/playwright-report
.idea/
.yarn/
.yarnrc.yml
2 changes: 1 addition & 1 deletion e2e-tests/themes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@ test('sync between tabs when theme change', async ({context}) => {
await pageOne.locator('select').selectOption({value: oppositeTheme})

await expect(html(pageOne)).toHaveAttribute(themeAttribute, oppositeTheme)
await expect(html(pageTwo)).toHaveAttribute(themeAttribute, oppositeTheme)
await expect(html(pageTwo)).toHaveAttribute(themeAttribute, oppositeTheme, { timeout: 100 })
})
4 changes: 4 additions & 0 deletions packages/remix-themes-app/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.react-router
build
node_modules
README.md
10 changes: 5 additions & 5 deletions packages/remix-themes-app/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
node_modules
.DS_Store
/node_modules/

/.cache
/build
/public/build
.env
# React Router
/.react-router/
/build/
2 changes: 0 additions & 2 deletions packages/remix-themes-app/.npmrc

This file was deleted.

22 changes: 22 additions & 0 deletions packages/remix-themes-app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM node:20-alpine AS development-dependencies-env
COPY . /app
WORKDIR /app
RUN npm ci

FROM node:20-alpine AS production-dependencies-env
COPY ./package.json package-lock.json /app/
WORKDIR /app
RUN npm ci --omit=dev

FROM node:20-alpine AS build-env
COPY . /app/
COPY --from=development-dependencies-env /app/node_modules /app/node_modules
WORKDIR /app
RUN npm run build

FROM node:20-alpine
COPY ./package.json package-lock.json /app/
COPY --from=production-dependencies-env /app/node_modules /app/node_modules
COPY --from=build-env /app/build /app/build
WORKDIR /app
CMD ["npm", "run", "start"]
110 changes: 77 additions & 33 deletions packages/remix-themes-app/README.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,100 @@
# Welcome to Remix!
# Welcome to React Router!

- [Remix Docs](https://remix.run/docs)
A modern, production-ready template for building full-stack React applications using React Router.

## Development
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router-templates/tree/main/default)

From your terminal:
## Features

```sh
- 🚀 Server-side rendering
- ⚡️ Hot Module Replacement (HMR)
- 📦 Asset bundling and optimization
- 🔄 Data loading and mutations
- 🔒 TypeScript by default
- 🎉 TailwindCSS for styling
- 📖 [React Router docs](https://reactrouter.com/)

## Getting Started

### Installation

Install the dependencies:

```bash
npm install
```

### Development

Start the development server with HMR:

```bash
npm run dev
```

This starts your app in development mode, rebuilding assets on file changes.
Your application will be available at `http://localhost:5173`.

## Deployment
## Building for Production

First, build your app for production:
Create a production build:

```sh
```bash
npm run build
```

Then run the app in production mode:
## Deployment

```sh
npm start
```
### Docker Deployment

Now you'll need to pick a host to deploy it to.
This template includes three Dockerfiles optimized for different package managers:

### DIY
- `Dockerfile` - for npm
- `Dockerfile.pnpm` - for pnpm
- `Dockerfile.bun` - for bun

If you're familiar with deploying node applications, the built-in Remix app
server is production-ready.
To build and run using Docker:

Make sure to deploy the output of `remix build`
```bash
# For npm
docker build -t my-app .

- `build/`
- `public/build/`
# For pnpm
docker build -f Dockerfile.pnpm -t my-app .

### Using a Template
# For bun
docker build -f Dockerfile.bun -t my-app .

When you ran `npx create-remix@latest` there were a few choices for hosting. You
can run that again to create a new project, then copy over your `app/` folder to
the new project that's pre-configured for your target server.
# Run the container
docker run -p 3000:3000 my-app
```

The containerized application can be deployed to any platform that supports Docker, including:

- AWS ECS
- Google Cloud Run
- Azure Container Apps
- Digital Ocean App Platform
- Fly.io
- Railway

### DIY Deployment

If you're familiar with deploying Node applications, the built-in app server is production-ready.

Make sure to deploy the output of `npm run build`

```sh
cd ..
# create a new project, and pick a pre-configured host
npx create-remix@latest
cd my-new-remix-app
# remove the new project's app (not the old one!)
rm -rf app
# copy your app over
cp -R ../my-old-remix-app/app app
```
├── package.json
├── package-lock.json (or pnpm-lock.yaml, or bun.lockb)
├── build/
│ ├── client/ # Static assets
│ └── server/ # Server-side code
```

## Styling

This template comes with [Tailwind CSS](https://tailwindcss.com/) already configured for a simple default starting experience. You can use whatever CSS framework you prefer.

---

Built with ❤️ using React Router.
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

.dark,
[data-theme='dark'] {
color-scheme: dark;
Expand Down
4 changes: 0 additions & 4 deletions packages/remix-themes-app/app/entry.client.tsx

This file was deleted.

21 changes: 0 additions & 21 deletions packages/remix-themes-app/app/entry.server.tsx

This file was deleted.

96 changes: 64 additions & 32 deletions packages/remix-themes-app/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,55 @@
import type {LinksFunction, LoaderFunction, MetaFunction} from '@remix-run/node'
import {
isRouteErrorResponse,
Links,
LiveReload,
type LoaderFunction,
Meta,
Outlet,
Scripts,
ScrollRestoration,
useLoaderData,
} from '@remix-run/react'

import {ThemeProvider, useTheme, PreventFlashOnWrongTheme} from 'remix-themes'
ScrollRestoration, useLoaderData,
} from 'react-router'
import {PreventFlashOnWrongTheme, ThemeProvider, useTheme} from 'remix-themes'
import {themeSessionResolver} from './sessions.server'
import styles from './styles/index.css'

export const links: LinksFunction = () => {
return [{rel: 'stylesheet', href: styles}]
}
import type {Route} from './+types/root'
import stylesheet from './app.css?url'

export const meta: MetaFunction = () => ({
charset: 'utf-8',
title: 'New Remix App',
viewport: 'width=device-width,initial-scale=1',
})
export const links: Route.LinksFunction = () => [
{rel: 'preconnect', href: 'https://fonts.googleapis.com'},
{
rel: 'preconnect',
href: 'https://fonts.gstatic.com',
crossOrigin: 'anonymous',
},
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
},
{rel: 'stylesheet', href: stylesheet},
]

export const loader: LoaderFunction = async ({request}) => {
const {getTheme} = await themeSessionResolver(request)

return {
theme: getTheme(),
}
}

function App() {
const data = useLoaderData()
const [theme] = useTheme()

export function App({children}: {children: React.ReactNode}) {
const data = useLoaderData();
const [theme] = useTheme();
return (
<html lang="en" data-theme={theme ?? ''}>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<PreventFlashOnWrongTheme ssrTheme={Boolean(data.theme)} />
<Links />
</head>
<body>
<Outlet />
{children}
<ScrollRestoration />
<PreventFlashOnWrongTheme ssrTheme={Boolean(data.theme)} />
<Scripts />
{process.env.NODE_ENV === 'development' && <LiveReload />}
</body>
</html>
)
Expand All @@ -57,12 +58,43 @@ function App() {
export default function AppWithProviders() {
const data = useLoaderData()
return (
<ThemeProvider
specifiedTheme={data.theme}
themeAction="/action/set-theme"
disableTransitionOnThemeChange={true}
>
<App />
</ThemeProvider>
<ThemeProvider
specifiedTheme={data.theme}
themeAction="/action/set-theme"
disableTransitionOnThemeChange={true}
>
<App>
<Outlet />
</App>
</ThemeProvider>
)
}

export function ErrorBoundary({error}: Route.ErrorBoundaryProps) {
let message = 'Oops!'
let details = 'An unexpected error occurred.'
let stack: string | undefined

if (isRouteErrorResponse(error)) {
message = error.status === 404 ? '404' : 'Error'
details =
error.status === 404
? 'The requested page could not be found.'
: error.statusText || details
} else if (import.meta.env.DEV && error && error instanceof Error) {
details = error.message
stack = error.stack
}

return (
<main className="pt-16 p-4 container mx-auto">
<h1>{message}</h1>
<p>{details}</p>
{stack && (
<pre className="w-full p-4 overflow-x-auto">
<code>{stack}</code>
</pre>
)}
</main>
)
}
7 changes: 7 additions & 0 deletions packages/remix-themes-app/app/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {type RouteConfig, index, route} from "@react-router/dev/routes";

export default [
index("routes/index.tsx"),
route("action/set-theme", "./routes/action.set-theme.ts"),
route("about", "./routes/about.tsx"),
] satisfies RouteConfig;
Loading
Loading