### Install and Run Bookstore Demo Source: https://github.com/remix-run/remix/blob/main/demos/bookstore/README.md Commands to install dependencies and start the Bookstore Demo application. Visit http://localhost:44100 after running. ```bash cd demos/bookstore pnpm install pnpm start ``` -------------------------------- ### Install and Run UNPKG Demo Source: https://github.com/remix-run/remix/blob/main/demos/unpkg/README.md Commands to install dependencies and start the UNPKG demo. Visit http://localhost:44100 to access the demo. ```bash cd demos/unpkg pnpm install pnpm start ``` -------------------------------- ### Install and Run Timeboxer Demo Source: https://github.com/remix-run/remix/blob/main/demos/timeboxer/README.md Steps to install dependencies and start the Timeboxer demo application. ```sh cd demos/timeboxer cp .env.example .env pnpm install pnpm start ``` -------------------------------- ### Install and Run Remix App Commands Source: https://github.com/remix-run/remix/blob/main/template/AGENTS.md Standard npm commands for installing dependencies, starting the development server, running tests, and performing type checks. ```sh npm i npm run start npm test npm run typecheck ``` -------------------------------- ### Install Dependencies Source: https://github.com/remix-run/remix/blob/main/packages/fetch-router/demos/cf-workers/README.md Run this command to install the necessary project dependencies. ```sh pnpm install ``` -------------------------------- ### Track Window Resize Events Source: https://github.com/remix-run/remix/blob/main/packages/ui/AGENTS.md This example sets up global event listeners for window resize events within the setup scope. It captures the window's dimensions and updates them on resize, ensuring cleanup is handled automatically via `handle.signal`. Use this for responsive UI components. ```tsx function WindowResizeTracker(handle: Handle) { let width = window.innerWidth let height = window.innerHeight // Set up global listeners once addEventListeners(window, handle.signal, { resize() { width = window.innerWidth height = window.innerHeight handle.update() }, }) return () => (
Window size: {width} × {height}
) } ``` -------------------------------- ### Install and Run Demo Source: https://github.com/remix-run/remix/blob/main/demos/social-auth/README.md Steps to set up and run the social authentication demo locally. ```sh cd demos/social-auth cp .env.example .env pnpm install pnpm start ``` -------------------------------- ### Install Remix Beta Source: https://github.com/remix-run/remix/blob/main/README.md Use this command to install the current beta version of Remix. ```sh npm install remix@next ``` -------------------------------- ### Run List Files Demo Source: https://github.com/remix-run/remix/blob/main/packages/static-middleware/demos/list-files/README.md Navigate to the demo directory and run the server script to start the demo. ```bash cd packages/static-middleware/demos/list-files node server.js ``` -------------------------------- ### Install remix Source: https://github.com/remix-run/remix/blob/main/packages/assert/README.md Install the remix package to use the assert module. ```sh npm i remix ``` -------------------------------- ### Corrected Component with `setup` Prop Source: https://github.com/remix-run/remix/blob/main/packages/ui/docs/component-changelog.md Demonstrates the correct usage of the `setup` prop, preventing stale prop captures by separating setup-specific props from render props. ```tsx function Counter( handle: Handle, // only the setup prop is passed here, no access to `label` setup: { count: number }, ) { let count = setup.count return ({ label }: { label: string }) => ( ) } let el = ``` -------------------------------- ### List and Create Users (Python) Source: https://github.com/remix-run/remix/blob/main/docs/src/prerender/bench/fixtures/docs-page.html Examples of using an API client to list users with a limit and create a new user. ```python from example_api import ApiClient client = ApiClient(api_key=os.environ['API_KEY']) # List users users = client.users.list(limit=10) # Create a user new_user = client.users.create( email='user@example.com', name='John Doe' ) ``` -------------------------------- ### Session-Backed Browser Login Flow Source: https://github.com/remix-run/remix/blob/main/packages/auth-middleware/README.md This example demonstrates the request-time authentication setup for a session-backed browser login flow. It configures session management, defines an authentication scheme using session data, and protects a dashboard route using `requireAuth`. ```ts import { auth, createSessionAuthScheme, requireAuth } from 'remix/middleware/auth' import { createRouter } from 'remix/router' import { route } from 'remix/routes' import { session } from 'remix/middleware/session' let routes = route({ app: { dashboard: '/dashboard', }, }) type User = { id: string; email: string } let router = createRouter({ middleware: [ session(sessionCookie, sessionStorage), auth({ schemes: [ createSessionAuthScheme({ read(session) { return session.get('auth') as { userId: string } | null }, verify(value) { return users.getById(value.userId) }, invalidate(session) { session.unset('auth') }, }), ], }), ], }) router.get(routes.app.dashboard, { middleware: [requireAuth()], handler(context) { let auth = context.auth if (!auth.ok) { return new Response('Unauthorized', { status: 401 }) } return Response.json({ id: auth.identity.id, email: auth.identity.email, method: auth.method, }) }, }) ``` -------------------------------- ### Remix CLI Usage Examples Source: https://github.com/remix-run/remix/blob/main/packages/cli/README.md Common commands for managing Remix projects using the installed CLI. ```sh remix new my-remix-app ``` ```sh remix completion bash >> ~/.bashrc ``` ```sh remix doctor ``` ```sh remix doctor --fix ``` ```sh remix routes ``` ```sh remix routes --table ``` ```sh remix routes --table --no-headers ``` ```sh remix test ``` ```sh remix version ``` ```sh remix --no-color doctor ``` -------------------------------- ### Ruby SDK Example Source: https://github.com/remix-run/remix/blob/main/docs/src/prerender/bench/fixtures/docs-page.html Example usage of the API client library in Ruby. ```APIDOC ### Ruby require 'example_api' client = ExampleApi::Client.new(api_key: ENV['API_KEY']) # List users users = client.users.list(limit: 10) # Create a user new_user = client.users.create( email: 'user@example.com', name: 'John Doe' ) ``` -------------------------------- ### Stale Prop Capture Example Source: https://github.com/remix-run/remix/blob/main/packages/ui/docs/component-changelog.md Illustrates how props could be accidentally captured with stale values in the setup scope before the `setup` prop was introduced. ```tsx function Counter( this: Handle, // captured `label` in the wrong scope props: { label: string; initialCount: number }, ) { let count = initialCount return () => ( ) } ``` -------------------------------- ### List and Create Users (Ruby) Source: https://github.com/remix-run/remix/blob/main/docs/src/prerender/bench/fixtures/docs-page.html Examples of using an API client to list users with a limit and create a new user. ```ruby require 'example_api' client = ExampleApi::Client.new(api_key: ENV['API_KEY']) # List users users = client.users.list(limit: 10) # Create a user new_user = client.users.create( email: 'user@example.com', name: 'John Doe' ) ``` -------------------------------- ### Python SDK Example Source: https://github.com/remix-run/remix/blob/main/docs/src/prerender/bench/fixtures/docs-page.html Example usage of the API client library in Python. ```APIDOC ### Python from example_api import ApiClient client = ApiClient(api_key=os.environ['API_KEY']) # List users users = client.users.list(limit=10) # Create a user new_user = client.users.create( email='user@example.com', name='John Doe' ) ``` -------------------------------- ### Install Remix Preview Build with pnpm Source: https://github.com/remix-run/remix/blob/main/CONTRIBUTING.md Use this command to install the latest `main` branch build of Remix directly from the `preview/main` branch using pnpm version 9 or higher. This is useful for testing unreleased features. ```sh pnpm install "remix-run/remix#preview/main&path:packages/remix" ``` ```sh # Or, just install a single package pnpm install "remix-run/remix#preview/main&path:packages/fetch-router" ``` -------------------------------- ### Create a Standard File Object Source: https://github.com/remix-run/remix/blob/main/packages/lazy-file/README.md Example of creating a standard File object with content provided upfront. ```ts let file = new File(['hello world'], 'hello.txt', { type: 'text/plain' }) ``` -------------------------------- ### Install Remix Source: https://github.com/remix-run/remix/blob/main/packages/async-context-middleware/README.md Install the Remix package to use its routing and middleware functionalities. ```sh npm i remix ``` -------------------------------- ### File System Storage Example Source: https://github.com/remix-run/remix/blob/main/packages/file-storage/README.md Demonstrates creating and using a filesystem-based file storage. Files are stored with their original metadata and can be streamed. ```ts import { createFsFileStorage } from 'remix/file-storage/fs' let storage = createFsFileStorage('./user/files') let file = new File(['hello world'], 'hello.txt', { type: 'text/plain' }) let key = 'hello-key' // Put the file in storage. await storage.set(key, file) // Then, sometime later... let fileFromStorage = await storage.get(key) if (fileFromStorage != null) { // All of the original file's metadata is intact fileFromStorage.name // 'hello.txt' fileFromStorage.type // 'text/plain' // The filesystem backend returns a LazyFile, so you can stream it directly. let response = new Response(fileFromStorage.stream()) } // To remove from storage await storage.remove(key) ``` -------------------------------- ### Run Assets Demo Source: https://github.com/remix-run/remix/blob/main/demos/assets/README.md Starts the Remix assets demo in watch-mode. Open the provided URL to view the demo. ```sh pnpm -C demos/assets dev ``` -------------------------------- ### JavaScript/TypeScript SDK Example Source: https://github.com/remix-run/remix/blob/main/docs/src/prerender/bench/fixtures/docs-page.html Example usage of the API client library in JavaScript/TypeScript. ```APIDOC ### JavaScript/TypeScript import { ApiClient } from '@example/api-client' let client = new ApiClient({ apiKey: process.env.API_KEY }) // List users let users = await client.users.list({ limit: 10 }) // Create a user let newUser = await client.users.create({ email: 'user@example.com', name: 'John Doe' }) ``` -------------------------------- ### Define and Install Admin Routes Source: https://github.com/remix-run/remix/blob/main/packages/fetch-router/README.md Define route definitions and use a route installer function to map them under a mount prefix. This allows for modular route management. ```typescript import { createRouter, type RouteBuilder } from 'remix/router' import { get, route } from 'remix/routes' const adminRouteDefs = { index: get('/'), users: { show: get('/users/:id'), }, } // Use relative route groups inside installers. These routes are registered below // the mount prefix when `installAdminRoutes()` runs. const adminRouteGroup = route(adminRouteDefs) // Use full app routes for links and redirects. const routes = { admin: route('/admin', adminRouteDefs), } function installAdminRoutes(router: RouteBuilder) { router.map(adminRouteGroup, { actions: { index() { return new Response('Admin') }, }, }) router.map(adminRouteGroup.users, { actions: { show({ params, currentUser }) { return new Response(`User ${params.id} for ${currentUser.id}`) }, }, }) } let router = createRouter({ middleware }) router.mount('/admin', installAdminRoutes) ``` -------------------------------- ### Install Remix Main Branch Preview with pnpm Source: https://github.com/remix-run/remix/blob/main/README.md Install the latest development version from the main branch using pnpm. This is for users who want to test the bleeding edge. ```sh pnpm install "remix-run/remix#preview/main&path:packages/remix" ``` -------------------------------- ### Start Local MySQL Container Source: https://github.com/remix-run/remix/blob/main/packages/data-table-mysql/README.md Run a local MySQL container using Podman for integration testing. ```sh podman run --name mysql \ -e MYSQL_ROOT_PASSWORD=root \ -e MYSQL_DATABASE=remix \ -p 3306:3306 \ -d mysql:8 ``` -------------------------------- ### Global Setup and Teardown Functions Source: https://github.com/remix-run/remix/blob/main/packages/test/README.md Define `globalSetup` and `globalTeardown` functions in a setup module (e.g., `./test/setup.ts`) to run code once before and after the entire test suite. This is useful for database migrations or cleanup operations. ```typescript // ./test/setup.ts export async function globalSetup() { await db.migrate() } export async function globalTeardown() { await db.close() } ``` -------------------------------- ### List and Create Users (JavaScript/TypeScript) Source: https://github.com/remix-run/remix/blob/main/docs/src/prerender/bench/fixtures/docs-page.html Examples of using an API client to list users with a limit and create a new user. ```javascript import { ApiClient } from '@example/api-client' let client = new ApiClient({ apiKey: process.env.API_KEY }) // List users let users = await client.users.list({ limit: 10 }) // Create a user let newUser = await client.users.create({ email: 'user@example.com', name: 'John Doe' }) ``` -------------------------------- ### Migration Runner Command Line Examples Source: https://github.com/remix-run/remix/blob/main/packages/data-table/README.md Illustrates common command-line invocations for the migration runner script, including direction, target migration, and rollback. ```sh node ./app/db/migrate.ts up node ./app/db/migrate.ts up 20260301113000 node ./app/db/migrate.ts down node ./app/db/migrate.ts down 20260228090000 ``` -------------------------------- ### Example TypeScript Migration (Old Method) Source: https://github.com/remix-run/remix/blob/main/decisions/006-sql-migrations.md Illustrates the previous approach of using TypeScript files for database migrations in Remix. ```typescript import { column as c, table } from 'remix/data-table' import { createMigration } from 'remix/data-table/migrations' let users = table(/* ... */) export default createMigration({ async up({ db, schema }) { await schema.createTable(users) }, async down({ schema }) { await schema.dropTable(users, { ifExists: true }) }, }) ``` -------------------------------- ### Run the Demo App Source: https://github.com/remix-run/remix/blob/main/packages/ui/demo/README.md Use this command to start the local development server for the UI demo application. After running, access the demos at http://localhost:44100. ```sh pnpm -C packages/ui/demo dev ``` -------------------------------- ### Intentional Stale Prop Example (Discouraged) Source: https://github.com/remix-run/remix/blob/main/packages/ui/docs/component-changelog.md Shows an intentionally complex and ill-advised method of making a prop value static by moving props into the setup scope, highlighting the difficulty of achieving this now. ```tsx // this is a bad example, showing the difficulty and ill-advised method of // making a prop value static by moving props into the setup scope function Counter(handle: Handle, setup: number) { let count = setup let initialLabel: string return (props: { label: string }) => { // what used to be an accident is now difficult to do on purpose if (!initialLabel) { initialLabel = props.label } return ( ) } } ``` -------------------------------- ### Setup PostgreSQL Database Adapter Source: https://github.com/remix-run/remix/blob/main/packages/data-table/README.md Define tables and create a database instance using the PostgreSQL adapter. This involves importing necessary functions, defining table schemas, and configuring the database connection. ```ts import { Pool } from 'pg' import { column as c, createDatabase, hasMany, query, table } from 'remix/data-table' import { createPostgresDatabaseAdapter } from 'remix/data-table/postgres' let users = table({ name: 'users', columns: { id: c.uuid(), email: c.varchar(255), role: c.enum(['customer', 'admin']), created_at: c.integer(), }, }) let orders = table({ name: 'orders', columns: { id: c.uuid(), user_id: c.uuid(), status: c.enum(['pending', 'processing', 'shipped', 'delivered']), total: c.decimal(10, 2), created_at: c.integer(), }, }) let userOrders = hasMany(users, orders) let pool = new Pool({ connectionString: process.env.DATABASE_URL }) let db = createDatabase(createPostgresDatabaseAdapter(pool)) ``` -------------------------------- ### Type-Safe Links and Form Actions with Remix Router Source: https://github.com/remix-run/remix/blob/main/packages/fetch-router/README.md Demonstrates generating type-safe links and form actions using the `href()` function on routes. Includes setup for a basic site with home and contact pages, and registers GET and POST actions for routes. ```typescript import { route } from 'remix/routes' import { createRouter } from 'remix/router' import { html } from 'remix/html-template' import { createHtmlResponse } from 'remix/response/html' let routes = route({ home: '/', contact: '/contact', }) let router = createRouter() // Register an action for `GET /` router.get(routes.home, () => { return createHtmlResponse(

Home

Contact Us

) }) // Register an action for `GET /contact` router.get(routes.contact, () => { return createHtmlResponse(

Contact Us

) }) // Register an action for `POST /contact` router.post(routes.contact, ({ get }) => { // POST actions can read parsed FormData from request context using FormData // as the context key after the formData middleware has run. let formData = get(FormData) let message = formData.get('message') as string let body = html`

Thanks!

You said: ${message}

` return createHtmlResponse(body) }) ``` -------------------------------- ### Remix Test Configuration File Source: https://github.com/remix-run/remix/blob/main/packages/test/README.md Configure test runner behavior by creating a `remix-test.config.ts` file. This example shows default values for browser options, concurrency, coverage, glob patterns, Playwright configuration, reporter, setup path, test types, and watch mode. ```typescript import type { RemixTestConfig } from 'remix/test' export default { // Browser options for E2E tests browser: { // Echo browser console output to the terminal echo: false, // Open browser (via playwright `headless:false`) and keep it open after tests // complete (useful for debugging) open: false, }, // Max number of concurrent test workers (default `os.availableParallelism()`) concurrency: 2, // Pool for server and E2E test files ("forks", "threads") pool: 'forks', // Code coverage options coverage: { // Enable coverage reporting enabled: true, // Output directory (default: ".coverage") dir: '.coverage', // Glob pattern(s) to include/exclude include: 'src/**', exclude: 'src/**/*.test.ts', // Minimum thresholds (%) statements: 80, lines: 80, branches: 80, functions: 80, }, // Glob pattern(s) identifying test files glob: { // All test files (default: "**/*.test{,.browser,.e2e}.{ts,tsx}"). test: '**/*.test{,.browser,.e2e}.ts', // Browser test files (default: "**/*.test.browser.{ts,tsx}") browser: '**/*.test.browser.ts', // E2E test files (default: "**/*.test.e2e.{ts,tsx}") e2e: '**/*.test.e2e.ts', }, // Playwright configuration for E2E tests, or string path to an existing // config file on disk playwrightConfig: { projects: [ { name: 'chromium', use: { browserName: 'chromium' } }, { name: 'firefox', use: { browserName: 'firefox' } }, ], use: { navigationTimeout: 5_000, actionTimeout: 5_000, }, }, // Playwright project(s) to run E2E tests for project: 'chromium', // Test reporter ("spec", "files", "tap", "dot") reporter: 'spec', // Path to a setup module (see Setup section below) setup: './test/setup.ts', // Test type(s) to run ("server", "browser", "e2e") type: ['server', 'browser', 'e2e'], // Watch for file changes and re-run watch: false, } satisfies RemixTestConfig ``` -------------------------------- ### Initialize Database, Apply Migrations, and Seed Data Source: https://github.com/remix-run/remix/blob/main/demos/bookstore/README.md Data setup script (`app/data/setup.ts`) that initializes the SQLite database, applies migrations from `db/migrations/20260228090000_create_bookstore_schema.ts`, and seeds demo data. ```typescript app/data/setup.ts ``` ```typescript db/migrations/20260228090000_create_bookstore_schema.ts ``` -------------------------------- ### Initialize API client and list users (Python) Source: https://github.com/remix-run/remix/blob/main/docs/src/prerender/bench/fixtures/docs-page.html Initialize the API client with an API key from environment variables. Use the client to list users with an optional limit parameter. ```python from example_api import ApiClient client = ApiClient(api_key=os.environ['API_KEY']) # List users users = client.users.list(limit=10) ``` -------------------------------- ### Initialize API client and list users (JavaScript/TypeScript) Source: https://github.com/remix-run/remix/blob/main/docs/src/prerender/bench/fixtures/docs-page.html Instantiate the API client with an API key from environment variables. Use the client to list users with optional limit parameter. ```javascript import { ApiClient } from '@example/api-client' let client = new ApiClient({ apiKey: process.env.API_KEY }) // List users let users = await client.users.list({ limit: 10 }) ``` -------------------------------- ### Initialize API client and list users (Ruby) Source: https://github.com/remix-run/remix/blob/main/docs/src/prerender/bench/fixtures/docs-page.html Initialize the API client with an API key from environment variables. Use the client to list users with an optional limit parameter. ```ruby require 'example_api' client = ExampleApi::Client.new(api_key: ENV['API_KEY']) # List users users = client.users.list(limit: 10) ``` -------------------------------- ### Install Data Table and PostgreSQL Dependencies Source: https://github.com/remix-run/remix/blob/main/packages/data-table-postgres/README.md Install the necessary packages for data-table and PostgreSQL integration. ```sh npm i remix pg ``` -------------------------------- ### Install Dependencies Source: https://github.com/remix-run/remix/blob/main/packages/data-table/README.md Install the necessary dependencies for data-table, including the core package and a database adapter like 'pg' or 'mysql2'. ```sh npm i remix npm i pg # or npm i mysql2 # or # use the SQLite client built into your runtime ``` -------------------------------- ### Install Remix Data Table and MySQL2 Source: https://github.com/remix-run/remix/blob/main/packages/data-table-mysql/README.md Install the necessary packages for using the MySQL adapter with Remix Data Table. ```sh npm i remix mysql2 ``` -------------------------------- ### Create Asset Server with Basic Configuration Source: https://github.com/remix-run/remix/blob/main/packages/assets/README.md Initialize an asset server with a base path, file mapping, access control, and file extensions. This setup serves compiled browser assets from specified directories. ```typescript import { createRouter } from 'remix/router' import { createAssetServer } from 'remix/assets' let assetServer = createAssetServer({ basePath: '/assets', fileMap: { '/app/*path': 'app/*path', '/npm/*path': 'node_modules/*path', }, allow: ['app/assets/**', 'node_modules/**'], files: { extensions: ['.svg', '.png', '.jpg', '.jpeg', '.woff2'], }, }) let router = createRouter() router.get('/assets/*', ({ request }) => { return assetServer.fetch(request) }) ``` -------------------------------- ### Start Development Server Source: https://github.com/remix-run/remix/blob/main/packages/fetch-router/demos/cf-workers/README.md Starts the local development server for the Cloudflare Worker application. The application will be accessible at http://localhost:44100. ```sh pnpm run dev ``` -------------------------------- ### Nested Route Map Controller Example Source: https://github.com/remix-run/remix/blob/main/demos/bookstore/README.md Demonstrates a controller for a nested route map, shown with the contact form example in `app/actions/contact/controller.tsx`. ```typescript app/actions/contact/controller.tsx ``` -------------------------------- ### Basic Router Setup and Usage Source: https://github.com/remix-run/remix/blob/main/packages/fetch-router/README.md Defines a router with middleware and maps controllers to different route groups. Demonstrates handling dynamic route parameters. ```ts import { route } from 'remix/routes' import { createRouter } from 'remix/router' import { logger } from 'remix/middleware/logger' // `route()` creates a "route map" that organizes routes by name. The keys // of the map may be any name, and may be nested to group related routes. let routes = route({ home: '/', about: '/about', blog: { index: '/blog', show: '/blog/:slug', }, }) let router = createRouter({ // Middleware is used to run code before and/or after actions run. // In this case, the `logger()` middleware logs the request to the console. middleware: [logger()] }) // Map a controller that supplies actions for the root routes. // A controller is a plain object with an `actions` property that // matches the direct route leaves in a route map. router.map(routes, { actions: { home() { return new Response('Home') }, about() { return new Response('About') }, }, }) // Map another controller that supplies actions for the blog routes. router.map(routes.blog, { actions: { index() { return new Response('Blog') }, show({ params }) { // params is a type-safe object with the parameters from the route pattern return new Response(`Post ${params.slug}`) }, }, }) let response = await router.fetch('https://remix.run/blog/hello-remix') console.log(await response.text()) // "Post hello-remix" ``` -------------------------------- ### Install Single Package from Remix Main Branch Source: https://github.com/remix-run/remix/blob/main/README.md Install a specific package, like fetch-router, directly from the main branch of the Remix repository using pnpm. ```sh pnpm install "remix-run/remix#preview/main&path:packages/fetch-router" ``` -------------------------------- ### Boot the Client Runtime Source: https://github.com/remix-run/remix/blob/main/packages/ui/docs/hydration.md Use `run` to initialize the client-side hydration process. It requires a `loadModule` function to dynamically import components and optionally a `resolveFrame` function for handling frame content. ```tsx import { run } from 'remix/ui' let app = run({ async loadModule(moduleUrl, exportName) { let mod = await import(moduleUrl) return mod[exportName] }, async resolveFrame(src, signal) { let res = await fetch(src, { headers: { Accept: 'text/html' }, signal }) return res.body ?? (await res.text()) }, }) await app.ready() ``` -------------------------------- ### Key Prop Usage Examples in Remix Source: https://github.com/remix-run/remix/blob/main/packages/ui/docs/composition.md Provides examples of correct and incorrect usage of the `key` prop for list items. Emphasizes using stable and unique identifiers. ```tsx // Good: stable, unique IDs { items.map((item) => ) } // Good: index can work if list never reorders { items.map((item, index) => ) } // Bad: don't use random values or values that change { items.map((item) => ) } ``` -------------------------------- ### Initialize API client and create a user (Python) Source: https://github.com/remix-run/remix/blob/main/docs/src/prerender/bench/fixtures/docs-page.html Use the API client to create a new user by providing their email and name in the request body. ```python # Create a user new_user = client.users.create( email='user@example.com', name='John Doe' ) ``` -------------------------------- ### Install HTML Renderer Middleware Source: https://github.com/remix-run/remix/blob/main/demos/bookstore/README.md Middleware (`app/middleware/render.tsx`) that installs the request-scoped HTML renderer. This is used by actions via `context.render` and supports server-side frame resolution for fragment-based rendering. ```typescript app/middleware/render.tsx ``` -------------------------------- ### Basic Framework Listbox Example Source: https://github.com/remix-run/remix/blob/main/packages/ui/src/listbox/README.md Demonstrates how to use the listbox primitive to create a controlled list of selectable framework options. It manages selection and highlighting state externally. ```tsx import type { Handle } from 'remix/ui' import * as listbox from 'remix/ui/listbox' import type { ListboxValue } from 'remix/ui/listbox' import { listStyle, optionStyle } from './listbox.styles' function FrameworkListbox(handle: Handle) { let value: ListboxValue = 'remix' let activeValue: ListboxValue = 'remix' return () => ( { value = nextValue void handle.update() }} onHighlight={(nextValue) => { activeValue = nextValue void handle.update() }} >
{frameworks.map((option) => (
{option.label}
))}
) } let frameworks = [ { label: 'Remix', value: 'remix' }, { disabled: true, label: 'React Router', value: 'react-router' }, { label: 'React', value: 'react' }, { label: 'Preact', value: 'preact' }, ] ``` -------------------------------- ### Complete Product Card Example Source: https://github.com/remix-run/remix/blob/main/packages/ui/docs/styling.md A comprehensive example of a ProductCard component demonstrating parent hover effects on children, element-specific styles, element states, and responsive media queries. ```tsx function ProductCard(handle: Handle<{ title: string; price: number; image: string }>) { return () => (
{handle.props.title}

{handle.props.title}

${handle.props.price}
) } ``` -------------------------------- ### Integrate with File Storage Library Source: https://github.com/remix-run/remix/blob/main/packages/form-data-parser/README.md Use the `file-storage` library for flexible storage of uploaded files. This example demonstrates setting up file storage and using it within the upload handler. ```ts import { createFsFileStorage } from 'remix/file-storage/fs' import type { FileUpload } from 'remix/form-data-parser' import { parseFormData } from 'remix/form-data-parser' // Set up storage for uploaded files const fileStorage = createFsFileStorage('/uploads/user-avatars') // Define how to handle incoming file uploads async function uploadHandler(fileUpload: FileUpload) { // Is this file upload from the field? if (fileUpload.fieldName === 'user-avatar') { let storageKey = `user-${user.id}-avatar` // Put the file in storage and return the stored LazyFile return fileStorage.put(storageKey, fileUpload) } // Ignore unrecognized fields } ``` -------------------------------- ### Complete Spring Animation Example in a React Component Source: https://github.com/remix-run/remix/blob/main/packages/ui/docs/spring.md A full example demonstrating a clickable card component that animates its size using Spring transitions. It utilizes `spring.transition` for defining the animation properties and `on('click')` for interactivity. ```tsx function AnimatedCard(handle: Handle) { let isExpanded = false return () => (
{ isExpanded = !isExpanded handle.update() }), ]} style={{ width: isExpanded ? '300px' : '100px', height: isExpanded ? '200px' : '100px', }} > Click me
) } ``` -------------------------------- ### Spring Presets and Custom Configuration Source: https://github.com/remix-run/remix/blob/main/packages/ui/docs/spring.md Demonstrates how to use predefined spring presets or configure a custom spring with specific parameters like duration and bounce. ```tsx import { spring } from './spring.ts' // Using a preset spring('bouncy') // bouncy with overshoot spring('snappy') // quick, no overshoot (default) spring('smooth') // gentle, overdamped // Custom spring spring({ duration: 400, bounce: 0.3 }) ``` ```tsx spring('bouncy', { duration: 300 }) // faster bouncy spring('smooth', { duration: 800 }) // slower smooth ``` ```tsx spring({ duration: 500, // perceived duration in milliseconds bounce: 0.3, // -1 to 1 (negative = overdamped, 0 = critical, positive = bouncy) velocity: 0, // initial velocity in units per second }) ``` ```tsx spring({ bounce: -0.5 }) // very smooth, slow spring({ bounce: 0 }) // snappy, no bounce spring({ bounce: 0.3 }) // slight bounce spring({ bounce: 0.7 }) // very bouncy ``` ```tsx spring('bouncy', { velocity: 2 }) // fast start spring('bouncy', { velocity: -1 }) // initially going backward ``` ```tsx // velocity is in px/s, distance is in px let normalizedVelocity = velocityTowardTarget / distanceToTarget spring('bouncy', { velocity: normalizedVelocity }) ``` -------------------------------- ### Initialize PostgreSQL Database Adapter Source: https://github.com/remix-run/remix/blob/main/packages/data-table-postgres/README.md Set up the PostgreSQL adapter for use with the data-table API. Ensure your DATABASE_URL environment variable is set. ```ts import { Pool } from 'pg' import { createDatabase } from 'remix/data-table' import { createPostgresDatabaseAdapter } from 'remix/data-table/postgres' let pool = new Pool({ connectionString: process.env.DATABASE_URL, }) let db = createDatabase(createPostgresDatabaseAdapter(pool)) ``` -------------------------------- ### Initial Data Loading in Setup Scope Source: https://github.com/remix-run/remix/blob/main/packages/ui/docs/patterns.md Load initial data within the setup scope using queueTask for components that require data before rendering. Note that changes to props like 'userId' won't automatically restart the request unless explicitly handled. ```tsx function UserProfile(handle: Handle<{ userId: string; showEmail?: boolean }>) { let user: User | null = null let loading = true // Load initial data in setup scope using queueTask handle.queueTask(async (signal) => { let response = await fetch(`/api/users/${handle.props.userId}`, { signal }) let data = await response.json() if (signal.aborted) return user = data loading = false handle.update() }) return () => { if (loading) return
Loading user...
return (

{user.name}

{handle.props.showEmail &&

{user.email}

}
) } } ``` -------------------------------- ### Remix CLI Commands Source: https://github.com/remix-run/remix/blob/main/packages/remix/README.md Common commands available through the Remix CLI after installation. ```sh remix new my-remix-app ``` ```sh remix completion bash >> ~/.bashrc ``` ```sh remix doctor ``` ```sh remix doctor --fix ``` ```sh remix routes ``` ```sh remix routes --table ``` ```sh remix routes --table --no-headers ``` ```sh remix skills install ``` ```sh remix test ``` ```sh remix version ``` ```sh remix --no-color doctor ``` -------------------------------- ### Basic Context Implementation in Remix UI Source: https://github.com/remix-run/remix/blob/main/packages/ui/AGENTS.md Demonstrates a basic context setup where context changes require manual updates using `handle.update()`. Use this for simple context sharing when granular updates are not critical. ```tsx function ThemeProvider(handle: Handle<{ children?: RemixNode }, { theme: 'light' | 'dark' }>) { let theme: 'light' | 'dark' = 'light' handle.context.set({ theme }) return () => (
{handle.props.children}
) } function ThemedContent(handle: Handle) { let { theme } = handle.context.get(ThemeProvider) return () => (
Current theme: {theme}
) } ``` -------------------------------- ### Create Patch Change File Source: https://github.com/remix-run/remix/blob/main/CONTRIBUTING.md Example of a change file for a bug fix. ```md patch.fix-something.md ``` -------------------------------- ### Basic Menu with Checkbox and Radio Items Source: https://github.com/remix-run/remix/blob/main/packages/ui/src/menu/README.md Demonstrates how to use the Menu, MenuItem, and Submenu components to create a menu with word wrap (checkbox) and density (radio) options. It also shows how to handle selection events using `onMenuSelect`. ```tsx import type { Handle } from 'remix/ui' import { css } from 'remix/ui' import { Menu, MenuItem, Submenu } from 'remix/ui/menu' import { onMenuSelect } from 'remix/ui/menu/primitives' export function ViewMenu(handle: Handle) { let wordWrap = false let density = 'comfortable' return () => ( { if (event.item.name === 'wordWrap') { wordWrap = event.item.checked ?? false } else if (event.item.name === 'density' && event.item.value) { density = event.item.value } void handle.update() })} > Word wrap Minimap
Compact Comfortable Zoom in Zoom out
) } let separatorStyle = css({ border: 0, borderBlockStart: '1px solid #e5e7eb', marginBlock: '4px', }) ``` -------------------------------- ### Create New Feature Change File Source: https://github.com/remix-run/remix/blob/main/CONTRIBUTING.md Example of a change file for adding a new feature. ```md minor.add-something.md ``` -------------------------------- ### Initialize MySQL Database Adapter Source: https://github.com/remix-run/remix/blob/main/packages/data-table-mysql/README.md Create a MySQL database adapter instance using a mysql2/promise Pool and initialize the data table database. ```ts import { createPool } from 'mysql2/promise' import { createDatabase } from 'remix/data-table' import { createMysqlDatabaseAdapter } from 'remix/data-table/mysql' let pool = createPool(process.env.DATABASE_URL as string) let db = createDatabase(createMysqlDatabaseAdapter(pool)) ``` -------------------------------- ### Color Interpolation with Spring Source: https://github.com/remix-run/remix/blob/main/packages/ui/docs/spring.md Example of interpolating between two RGB color values using the spring iterator. ```ts let fromRGB = [255, 0, 0] // red let toRGB = [0, 0, 255] // blue for (let t of spring('smooth')) { let r = Math.round(fromRGB[0] + (toRGB[0] - fromRGB[0]) * t) let g = Math.round(fromRGB[1] + (toRGB[1] - fromRGB[1]) * t) let b = Math.round(fromRGB[2] + (toRGB[2] - fromRGB[2]) * t) element.style.backgroundColor = `rgb(${r}, ${g}, ${b})` await nextFrame() } ```