Skip to content
Draft
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
1,513 changes: 1,348 additions & 165 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions workbench/react-router/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
.env
/node_modules/

# React Router
/.react-router/
/build/
22 changes: 22 additions & 0 deletions workbench/react-router/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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Dockerfile is incompatible with the project's package manager. It uses npm and references package-lock.json, but this project is configured to use pnpm with pnpm-lock.yaml.

View Details
📝 Patch Details
diff --git a/workbench/react-router/Dockerfile b/workbench/react-router/Dockerfile
index 207bf93..694fc6c 100644
--- a/workbench/react-router/Dockerfile
+++ b/workbench/react-router/Dockerfile
@@ -1,22 +1,26 @@
 FROM node:20-alpine AS development-dependencies-env
+RUN npm install -g pnpm@10.20.0
 COPY . /app
 WORKDIR /app
-RUN npm ci
+RUN pnpm install
 
 FROM node:20-alpine AS production-dependencies-env
-COPY ./package.json package-lock.json /app/
+RUN npm install -g pnpm@10.20.0
+COPY ./package.json pnpm-lock.yaml /app/
 WORKDIR /app
-RUN npm ci --omit=dev
+RUN pnpm install --prod
 
 FROM node:20-alpine AS build-env
+RUN npm install -g pnpm@10.20.0
 COPY . /app/
 COPY --from=development-dependencies-env /app/node_modules /app/node_modules
 WORKDIR /app
-RUN npm run build
+RUN pnpm run build
 
 FROM node:20-alpine
-COPY ./package.json package-lock.json /app/
+RUN npm install -g pnpm@10.20.0
+COPY ./package.json pnpm-lock.yaml /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"]
\ No newline at end of file
+CMD ["pnpm", "run", "start"]
\ No newline at end of file

Analysis

Dockerfile incompatible with project's pnpm package manager

What fails: workbench/react-router/Dockerfile uses npm ci and references package-lock.json which doesn't exist. The project is configured for pnpm with pnpm-lock.yaml.

How to reproduce:

# Attempt to build the Docker image
cd workbench/react-router
npm ci

Result:

npm error code EUSAGE
npm error The `npm ci` command can only install with an existing package-lock.json or
npm error npm-shrinkwrap.json with lockfileVersion >= 1.

Expected behavior: The Dockerfile should use pnpm since:

  • Root package.json specifies packageManager: "pnpm@10.20.0"
  • Project uses pnpm-lock.yaml (exists at repository root)
  • No package-lock.json exists in the repository
  • Monorepo dependencies use pnpm workspace syntax (workspace:*) in workbench/react-router/package.json

Fix applied: Updated Dockerfile to use pnpm:

  • Replaced npm ci with pnpm install (and pnpm install --prod for production stage)
  • Changed file references from package-lock.json to pnpm-lock.yaml
  • Installed pnpm globally in each stage before running commands
  • Updated all npm script invocations to use pnpm


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"]
87 changes: 87 additions & 0 deletions workbench/react-router/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Welcome to React Router!

A modern, production-ready template for building full-stack React applications using React Router.

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

## Features

- 🚀 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
```

Your application will be available at `http://localhost:5173`.

## Building for Production

Create a production build:

```bash
npm run build
```

## Deployment

### Docker Deployment

To build and run using Docker:

```bash
docker build -t my-app .

# 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`

```
├── 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.
15 changes: 15 additions & 0 deletions workbench/react-router/app/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@import "tailwindcss";

@theme {
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}

html,
body {
@apply bg-white dark:bg-gray-950;

@media (prefers-color-scheme: dark) {
color-scheme: dark;
}
}
75 changes: 75 additions & 0 deletions workbench/react-router/app/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
isRouteErrorResponse,
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from 'react-router';

import type { Route } from './+types/root';
import './app.css';

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',
},
];

export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}

export default function App() {
return <Outlet />;
}

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>
);
}
3 changes: 3 additions & 0 deletions workbench/react-router/app/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { type RouteConfig, index } from '@react-router/dev/routes';

export default [index('routes/home.tsx')] satisfies RouteConfig;
13 changes: 13 additions & 0 deletions workbench/react-router/app/routes/home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Route } from './+types/home';
import { Welcome } from '../welcome/welcome';

export function meta({}: Route.MetaArgs) {
return [
{ title: 'New React Router App' },
{ name: 'description', content: 'Welcome to React Router!' },
];
}

export default function Home() {
return <Welcome />;
}
23 changes: 23 additions & 0 deletions workbench/react-router/app/welcome/logo-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions workbench/react-router/app/welcome/logo-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading