Skip to content

In this recipe, we'll show you how to create a Remix application with Nx.

npx create-nx-workspace@latest acme --preset=apps
NX Let's create a new workspace [https://nx.dev/getting-started/intro]
✔ Which CI provider would you like to use? · skip
✔ Would you like remote caching to make your build faster? · skip
nx add @nx/remix
nx g @nx/remix:app apps/myapp
NX Generating @nx/remix:application
✔ What unit test runner should be used? · vitest
✔ Which E2E test runner would you like to use? · playwright
UPDATE package.json
UPDATE nx.json
CREATE apps/myapp/project.json
CREATE apps/myapp/README.md
CREATE apps/myapp/app/nx-welcome.tsx
CREATE apps/myapp/app/root.tsx
CREATE apps/myapp/app/routes/_index.tsx
CREATE apps/myapp/public/favicon.ico
CREATE apps/myapp/remix.config.js
CREATE apps/myapp/remix.env.d.ts
CREATE apps/myapp/tests/routes/_index.spec.tsx
CREATE apps/myapp/tsconfig.app.json
CREATE apps/myapp/tsconfig.json
CREATE apps/myapp/.gitignore
CREATE apps/myapp/package.json
CREATE apps/myapp/tsconfig.spec.json
CREATE apps/myapp/vitest.config.ts
CREATE apps/myapp/test-setup.ts
CREATE apps/myapp/.eslintrc.json
CREATE apps/myapp/.eslintignore
CREATE apps/myapp-e2e/project.json
CREATE apps/myapp-e2e/src/example.spec.ts
CREATE apps/myapp-e2e/playwright.config.ts
CREATE apps/myapp-e2e/tsconfig.json
CREATE apps/myapp-e2e/.eslintrc.json
  1. To build your application run:
nx build myapp
> nx run myapp:build
Building Remix app in production mode...
Built in 857ms
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
NX Successfully ran target build for project myapp (3s)
  1. To serve your application for use during development run:
nx dev myapp
> nx run myapp:dev
💿 Building...
💿 Rebuilt in 377ms
Remix App Server started at http://localhost:3000 (http://192.168.0.14:3000)
  1. To test the application using vitest run:
nx test myapp
> nx run myapp:test
RUN v0.31.4 /Users/columferry/dev/nrwl/issues/remixguide/acme/apps/myapp
stderr | app/routes/index.spec.ts > test > should render
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
✓ app/routes/index.spec.ts (1 test) 10ms
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 16:15:45
Duration 1.20s (transform 51ms, setup 139ms, collect 180ms, tests 10ms, environment 379ms, prepare 103ms)
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
NX Successfully ran target test for project myapp (2s)

When developing your application, it often makes sense to split your codebase into smaller more focused libraries.

To generate a library to use in your Remix application run:

nx g @nx/remix:lib libs/login
NX Generating @nx/remix:library
✔ What test runner should be used? · vitest
UPDATE nx.json
UPDATE package.json
CREATE babel.config.json
CREATE libs/login/project.json
CREATE libs/login/.eslintrc.json
CREATE libs/login/README.md
CREATE libs/login/src/index.ts
CREATE libs/login/tsconfig.lib.json
CREATE libs/login/tsconfig.json
CREATE libs/login/vite.config.ts
CREATE libs/login/tsconfig.spec.json
CREATE libs/login/src/lib/login.module.css
CREATE libs/login/src/lib/login.spec.tsx
CREATE libs/login/src/lib/login.tsx
UPDATE tsconfig.base.json
CREATE libs/login/src/test-setup.ts
CREATE libs/login/src/server.ts

You can then use the library by importing one of the exports into your application:

apps/myapp/app/routes/index.tsx

apps/myapp/app/routes/index.tsx
import { Login } from '@acme/login';
export default function Index() {
return (
<div>
<Login />
</div>
);
}

You can also run test on your library:

nx test login

To generate a route for your application:

nx g @nx/remix:route apps/myapp/app/routes/admin
NX Generating @nx/remix:route
CREATE apps/myapp/app/routes/admin.tsx
CREATE apps/myapp/app/styles/admin.css

To use a Route Loader where the logic lives in your library, follow the steps below.

  1. Generate a loader for your route:
nx g @nx/remix:loader apps/myapp/app/routes/admin.tsx
NX Generating @nx/remix:loader
UPDATE apps/myapp/app/routes/admin.tsx
  1. Add a new file in your login lib

libs/login/src/lib/admin/admin.loader.ts

libs/login/src/lib/admin/admin.loader.ts
import { json, LoaderFunctionArgs } from '@remix-run/node';
export const adminLoader = async ({ request }: LoaderFunctionArgs) => {
return json({
message: 'Hello, world!',
});
};

Export the function from the libs/login/src/server.ts file:

libs/login/src/server.ts
export * from './lib/admin/admin.loader';
  1. Use the loader in your apps/myapp/app/routes/admin.tsx

Replace the default loader code:

apps/myapp/app/routes/admin.tsx
export const loader = async ({ request }: LoaderFunctionArgs) => {
return json({
message: 'Hello, world!',
});
};

with

apps/myapp/app/routes/admin.tsx
import { adminLoader } from '@acme/login/server';
export const loader = adminLoader;

You can see an example of an Nx Workspace using Remix by clicking below.