mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-04 03:47:36 +00:00
chore(agents): update skill metadata timestamps, source URLs, and documentation wording across dot_agents files
This commit is contained in:
1 parent
12155ad58c
commit
c96c19c0f9
45 files changed
+1819
-1395
No files matched your search
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: remix
|
||||
description: Build and review Remix 3 applications using the `remix` npm package and subpath imports. Use when working on Remix app structure, routes, controllers, middleware, validation, data access, auth, sessions, file uploads, server setup, UI components, hydration, navigation, or tests.
|
||||
description: Build and review Remix 3 applications using the `remix` npm package and subpath imports. Use when working on Remix app structure, routes, controllers, middleware, validation, data access, auth, sessions, file uploads, server setup, UI components, hydration, HMR, navigation, or tests.
|
||||
---
|
||||
|
||||
# Build a Remix App
|
||||
@@ -42,19 +42,19 @@ Classify the task first, then load the smallest useful reference set. Each refer
|
||||
|
||||
Use the table below to find candidates. Loading more than two or three files at once is usually a sign that the task hasn't been narrowed enough yet.
|
||||
|
||||
| Task involves... | Start with |
|
||||
| ----------------------------------------------------------------------------- | ------------------------------------------- |
|
||||
| Defining URLs, writing controllers and actions, returning responses | `references/routing-and-controllers.md` |
|
||||
| Composing the request lifecycle, ordering middleware, bridging to a server | `references/middleware-and-server.md` |
|
||||
| Compiling and serving browser modules, asset URL namespaces, preloads | `references/assets-and-browser-modules.md` |
|
||||
| Parsing input, validating with schemas, defining tables, querying, migrations | `references/data-and-validation.md` |
|
||||
| Per-browser state, login flows, route protection, identity | `references/auth-and-sessions.md` |
|
||||
| Component setup, state, lifecycle, updates, `queueTask`, context | `references/component-model.md` |
|
||||
| Event handlers, styles, refs, click/key behavior, simple animations | `references/mixins-styling-events.md` |
|
||||
| `clientEntry`, `run`, `<Frame>`, navigation, `<head>` | `references/hydration-frames-navigation.md` |
|
||||
| Router tests, component tests, test isolation | `references/testing-patterns.md` |
|
||||
| Spring physics, tweens, layout transitions | `references/animate-elements.md` |
|
||||
| Authoring custom reusable mixins | `references/create-mixins.md` |
|
||||
| Task involves... | Start with |
|
||||
| ------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
||||
| Defining URLs, writing controllers and actions, returning responses | `references/routing-and-controllers.md` |
|
||||
| Composing the request lifecycle, ordering middleware, bridging to a server, development HMR | `references/middleware-and-server.md` |
|
||||
| Compiling and serving browser modules, asset URL namespaces, preloads, browser HMR | `references/assets-and-browser-modules.md` |
|
||||
| Parsing input, validating with schemas, defining tables, querying, migrations | `references/data-and-validation.md` |
|
||||
| Per-browser state, login flows, route protection, identity | `references/auth-and-sessions.md` |
|
||||
| Component setup, state, lifecycle, updates, `queueTask`, context | `references/component-model.md` |
|
||||
| Event handlers, styles, refs, click/key behavior, simple animations | `references/mixins-styling-events.md` |
|
||||
| `clientEntry`, `run`, `<Frame>`, navigation, browser HMR update handling, `<head>` | `references/hydration-frames-navigation.md` |
|
||||
| Router tests, component tests, test isolation | `references/testing-patterns.md` |
|
||||
| Spring physics, tweens, layout transitions | `references/animate-elements.md` |
|
||||
| Authoring custom reusable mixins | `references/create-mixins.md` |
|
||||
|
||||
Common bundles:
|
||||
|
||||
@@ -62,6 +62,7 @@ Common bundles:
|
||||
- **Protected area** -> auth and sessions, routing, testing
|
||||
- **Interactive widget** -> component model, mixins and styling; add hydration only if it runs in the browser
|
||||
- **Browser asset pipeline** -> assets and browser modules, hydration, middleware and server
|
||||
- **Development HMR** -> middleware and server, assets and browser modules, hydration
|
||||
- **File upload** -> middleware and server, data and validation, testing
|
||||
- **Navigation or frames** -> hydration, frames, navigation
|
||||
|
||||
@@ -205,7 +206,11 @@ Use this map to find the right package quickly. Each entry says what the package
|
||||
- `remix/router` — the router itself. Use for `createRouter`, controllers, middleware types, and registering routes
|
||||
- `remix/routes` — declarative route builders. Use for `route`, `get`, `post`, `put`, `del`, `form`, `resources` when defining `app/routes.ts`
|
||||
- `remix/node-fetch-server` — default Node adapter for new apps. Use `createRequestListener` with `node:http`, `node:https`, or `node:http2` in `server.ts` when booting the template-style app
|
||||
- `remix/assets` — browser asset server. Use for `createAssetServer` when serving compiled scripts and styles, getting public hrefs, and emitting preloads. Configure a `basePath`, and keep `fileMap` URL patterns relative to it. Shared compiler options such as `target`, `sourceMaps`, `sourceMapSourcePaths`, and `minify` live at the top level
|
||||
- `remix/node-hmr` — optional development Node HMR runner for rapid UI edits. Use `run` in `hmr.ts` to supervise `server.ts` behind an `hmr` script, and use `createHmrReadyFetch` when a stable public proxy should wait for child server readiness during updates
|
||||
- `remix/node-hmr/runtime` — child-process runtime API for code running under `remix/node-hmr`. Use to create browser HMR channels for asset servers and to emit server readiness after the child server starts listening
|
||||
- `remix/node-hmr/types` — type-only entry for `import.meta.hot` in Node modules
|
||||
- `remix/assets` — browser asset server. Use for `createAssetServer` when serving compiled scripts and styles, getting public hrefs, emitting preloads, and wiring browser HMR. Configure a `basePath`, keep `fileMap` URL patterns relative to it, use `allowFiles`/`denyFiles` for path and glob rules, and use exact package names in `allowPackages` for package-level access. Shared compiler options such as `target`, `sourceMaps`, `sourceMapSourcePaths`, and `minify` live at the top level
|
||||
- `remix/assets/types/hmr` — type-only entry for `import.meta.hot` in browser modules compiled by `remix/assets`
|
||||
- `remix/headers` — `SuperHeaders` plus typed header parsers and builders. Use the default export when you want a `Headers` subclass with typed accessors like `headers.contentType`, `headers.cacheControl`, and `headers.setCookie`; use named classes such as `CacheControl`, `ContentDisposition`, and `Vary` when working with individual header values
|
||||
- `remix/response/redirect` — `redirect(href, status?)`. Use for the canonical "POST then redirect" pattern and other location changes
|
||||
- `remix/response/html` — `createHtmlResponse`. Use when you need an HTML `Response` from a string or stream without rendering through `remix/ui`
|
||||
@@ -244,6 +249,10 @@ Use this map to find the right package quickly. Each entry says what the package
|
||||
|
||||
- `remix/ui` — the component runtime: components, core mixins, `clientEntry`, `run`, `<Frame>`, navigation helpers, and `createRoot`. Use for app UI behavior
|
||||
- `remix/ui/server` — server rendering: `renderToStream`, `renderToString`. Use in the `app/actions/render.tsx` helper that returns HTML responses
|
||||
- `remix/ui-hmr` — direct Remix UI component HMR transforms. Use only when writing a custom module hook or build integration
|
||||
- `remix/ui-hmr/node` — Node import hook for Remix UI component HMR. Use with `--import remix/ui-hmr/node` in development servers that run through `remix/node-hmr`
|
||||
- `remix/ui-hmr/assets` — `remix/assets` loader for Remix UI component HMR. Use `uiHmr()` in `createAssetServer({ scripts: { loaders } })` during development
|
||||
- `remix/ui/dev/refresh` — development refresh support used by HMR tooling, not normal application code
|
||||
- `remix/ui/animation` — animation APIs: `animateEntrance`, `animateExit`, `animateLayout`, `spring`, `tween`, and `easings`
|
||||
- `remix/ui/<primitive>` — UI primitives, mixins, and component helpers. Current subpaths include `remix/ui/accordion`, `remix/ui/anchor`, `remix/ui/button`, `remix/ui/checkbox`, `remix/ui/combobox`, `remix/ui/input`, `remix/ui/listbox`, `remix/ui/menu`, `remix/ui/popover`, and `remix/ui/select`
|
||||
- `remix/ui/test` — component test rendering helpers such as `render`
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
|
||||
How to serve browser scripts and styles from source. Read this when the task involves:
|
||||
|
||||
- Configuring `createAssetServer` (`basePath`, `fileMap`, `allow`, `deny`, fingerprinting, compiler options)
|
||||
- Configuring `createAssetServer` (`basePath`, `fileMap`, `allowFiles`, `allowPackages`, `denyFiles`, fingerprinting, compiler options)
|
||||
- Choosing between `staticFiles()` for already-built files and `createAssetServer()` for source assets that need import rewriting, preloads, or fingerprinted URLs
|
||||
- Generating script URLs or `<link rel="modulepreload">` tags for a client entry
|
||||
- Keeping server-only files out of the browser via `deny` rules
|
||||
- Enabling browser HMR for source-served modules
|
||||
- Keeping server-only files out of the browser via `denyFiles` rules
|
||||
|
||||
For routing the URL namespace itself, see `routing-and-controllers.md`. For client entry hydration, see `hydration-frames-navigation.md`.
|
||||
For routing the URL namespace itself, see `routing-and-controllers.md`. For client entry hydration and browser update handling, see `hydration-frames-navigation.md`. For the Node HMR runner and browser HMR channel, see `middleware-and-server.md`.
|
||||
|
||||
## When To Reach For It
|
||||
|
||||
@@ -35,8 +36,9 @@ let assetServer = createAssetServer({
|
||||
'app/*path': 'app/*path',
|
||||
'node_modules/*path': 'node_modules/*path',
|
||||
},
|
||||
allow: ['app/assets/**', 'node_modules/**'],
|
||||
deny: ['app/**/*.server.*'],
|
||||
allowFiles: ['app/assets/**'],
|
||||
allowPackages: ['remix'],
|
||||
denyFiles: ['app/**/*.server.*'],
|
||||
target: { es: '2020', chrome: '109', safari: '16.4' },
|
||||
sourceMaps: process.env.NODE_ENV === 'development' ? 'external' : undefined,
|
||||
minify: process.env.NODE_ENV === 'production',
|
||||
@@ -58,8 +60,11 @@ export default createController(routes, {
|
||||
|
||||
## Rules
|
||||
|
||||
- Treat `allow` and `deny` as the security boundary for browser-reachable source files.
|
||||
- Add a `deny` list for server-only modules such as `*.server.*`, private config, or other files that should never be exposed.
|
||||
- Treat `allowFiles`/`allowPackages` and `denyFiles` as the security boundary for browser-reachable source files.
|
||||
- Use `allowFiles` and `denyFiles` for file paths and globs. Relative values resolve from `rootDir`.
|
||||
- Use `allowPackages` for exact package names, not globs or subpaths. Packages allowed by `allowPackages` also allow their installed `dependencies` and `optionalDependencies`; peer dependencies must be listed explicitly if they should be browser-reachable.
|
||||
- `denyFiles` takes precedence over both file and package allow rules.
|
||||
- Add `denyFiles` rules for server-only modules such as `*.server.*`, private config, or other files that should never be exposed.
|
||||
- Set `rootDir` explicitly in monorepos so relative paths resolve from the intended project root.
|
||||
- `basePath` is the public URL namespace handled by the asset server.
|
||||
- `fileMap` keys are URL patterns relative to `basePath`, and values are root-relative file path patterns. They use `route-pattern` syntax on both sides.
|
||||
@@ -86,6 +91,8 @@ In development:
|
||||
- Keep `watch` enabled so source changes are picked up without restarting the server
|
||||
- Prefer stable URLs with normal revalidation
|
||||
- Enable source maps when debugging browser code
|
||||
- Use `hmr` only when the app is running under `remix/node-hmr`
|
||||
- Use `scripts.loaders` for development-only browser transforms such as `uiHmr()`
|
||||
|
||||
In deployment:
|
||||
|
||||
@@ -95,6 +102,38 @@ In deployment:
|
||||
|
||||
Fingerprinting assumes files on disk are stable and requires `watch: false`.
|
||||
|
||||
## Browser HMR
|
||||
|
||||
Use browser HMR when source-served browser modules should update without a full page reload during development. Let `remix/node-hmr` own the browser HMR channel so browser updates stay coordinated with server restarts.
|
||||
|
||||
```typescript
|
||||
import { createAssetServer } from 'remix/assets'
|
||||
import { uiHmr } from 'remix/ui-hmr/assets'
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV === 'development'
|
||||
const isHmr = Boolean(isDevelopment && process.env.REMIX_NODE_HMR)
|
||||
|
||||
const assetServer = createAssetServer({
|
||||
basePath: '/assets',
|
||||
fileMap: { '/app/*path': 'app/*path' },
|
||||
allowFiles: ['app/assets/**'],
|
||||
watch: isDevelopment,
|
||||
hmr: isHmr
|
||||
? async () => (await import('remix/node-hmr/runtime')).createBrowserHmrChannel()
|
||||
: undefined,
|
||||
scripts: {
|
||||
loaders: isHmr ? [uiHmr()] : undefined,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Guard `remix/node-hmr/runtime` imports with `process.env.REMIX_NODE_HMR`; that runtime API is only available inside the supervised child process.
|
||||
- Keep browser HMR and loaders development-only.
|
||||
- Add `remix/assets/types/hmr` to `compilerOptions.types` only when browser source modules use `import.meta.hot` directly.
|
||||
- Write HMR accept calls directly as `import.meta.hot.accept(...)` with literal dependency specifiers.
|
||||
|
||||
## Useful Compiler Options
|
||||
|
||||
- `minify` for production minification of scripts and styles
|
||||
@@ -103,6 +142,7 @@ Fingerprinting assumes files on disk are stable and requires `watch: false`.
|
||||
- `target` as an object for shared browser targets and script-only ECMAScript output, such as `{ es: '2020', chrome: '109', safari: '16.4' }`
|
||||
- `scripts.define` to replace globals such as `process.env.NODE_ENV`
|
||||
- `scripts.external` to leave specific script imports untouched
|
||||
- `scripts.loaders` to transform browser modules during compilation
|
||||
|
||||
Do not nest shared compiler options under `scripts`. Use top-level `minify`, `sourceMaps`, `sourceMapSourcePaths`, and `target` so they apply to styles as well as scripts.
|
||||
|
||||
|
||||
@@ -7,11 +7,12 @@ How server-rendered UI becomes interactive in the browser, and how the page upda
|
||||
- Marking a component for client-side hydration with `clientEntry`
|
||||
- Booting the client runtime with `run`
|
||||
- Streaming server content into a region of the page with `<Frame>` and reloading those regions
|
||||
- Handling browser HMR updates for hydrated entries
|
||||
- Triggering Navigation API transitions with `navigate(...)` or `link(...)`
|
||||
- Server rendering with `renderToStream` or `renderToString`
|
||||
- Managing the document `<head>`
|
||||
|
||||
For component-local state and updates, see `component-model.md`. For host-element behavior and events, see `mixins-styling-events.md`.
|
||||
For component-local state and updates, see `component-model.md`. For host-element behavior and events, see `mixins-styling-events.md`. For browser asset HMR setup, see `assets-and-browser-modules.md`.
|
||||
|
||||
## Server First, Then Hydrate
|
||||
|
||||
@@ -96,7 +97,7 @@ Use `run` to start the client runtime. It scans the document for client entry ma
|
||||
```tsx
|
||||
import { run } from 'remix/ui'
|
||||
|
||||
let app = run({
|
||||
const app = run({
|
||||
async loadModule(moduleUrl, exportName) {
|
||||
let mod = await import(moduleUrl)
|
||||
return mod[exportName]
|
||||
@@ -129,6 +130,19 @@ await app.ready()
|
||||
|
||||
`app` is an `EventTarget` that emits `error` events from any hydrated component.
|
||||
|
||||
## Browser HMR Updates
|
||||
|
||||
When `remix/node-hmr` reports a server update, reload the top frame to apply the latest server-rendered document while preserving browser state:
|
||||
|
||||
```tsx
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.on('server:update', async () => {
|
||||
await app.ready()
|
||||
await app.frames.top.reload()
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Frames
|
||||
|
||||
A `<Frame>` renders server content into the page. Frames stream after the initial HTML, nest inside other frames, contain client entries, and can be reloaded without full page navigation.
|
||||
|
||||
@@ -8,8 +8,9 @@ How to compose the request lifecycle and bridge the router to a runtime. Read th
|
||||
- Writing custom middleware that sets typed context values
|
||||
- Adding fast-exit handling (static files, CORS preflights) versus request-enriching layers (sessions, auth, data loading)
|
||||
- Choosing when to keep the generated Node server versus switching server adapters
|
||||
- Running the app server under development HMR
|
||||
|
||||
For data and persistence specifics, see `data-and-validation.md`. For session and auth specifics, see `auth-and-sessions.md`.
|
||||
For data and persistence specifics, see `data-and-validation.md`. For session and auth specifics, see `auth-and-sessions.md`. For browser asset HMR, see `assets-and-browser-modules.md`.
|
||||
|
||||
## Middleware Stack
|
||||
|
||||
@@ -80,6 +81,7 @@ let router = createRouter({ middleware })
|
||||
- **Session-backed HTML app** -> `compression()`, `staticFiles()`, optional `cop()`, `formData()`, `methodOverride()`, `session()`, optional `csrf()`, `asyncContext()`, `auth({ schemes })`
|
||||
- **Cross-origin API** -> `compression()`, `cors()`, optional `asyncContext()`, optional `auth({ schemes })`
|
||||
- **Upload flow** -> `compression()`, `staticFiles()`, `formData({ uploadHandler })`, then sessions, auth, and data-loading middleware as needed
|
||||
- **Optional development HMR** -> keep `server.ts` as the child app server, add `hmr.ts` for `remix/node-hmr`, and proxy public requests through `createHmrReadyFetch()`
|
||||
|
||||
### Middleware with options
|
||||
|
||||
@@ -214,3 +216,62 @@ Prefer inline arrays for `middleware` options. Use `RouterContext<typeof router>
|
||||
New apps already include a `server.ts` that adapts the app router with `remix/node-fetch-server`. Keep that generated server unless the task specifically needs to change runtime behavior such as host/protocol handling, TLS, HTTP/2, WebSockets, deployment lifecycle, or test-only server setup.
|
||||
|
||||
Use `remix/node-fetch-server` when you want to keep owning a standard Node `http`, `https`, or `http2` server directly.
|
||||
|
||||
## Development HMR
|
||||
|
||||
Treat HMR as an optional mode for rapid UI edits. Keep HMR supervision out of normal app code:
|
||||
put the real app server in `server.ts`, keep the `dev` script running it directly (usually with
|
||||
Node's watch mode), then add a development-only `hmr.ts` behind an `hmr` script when the project
|
||||
benefits from HMR.
|
||||
|
||||
```typescript
|
||||
// hmr.ts
|
||||
import * as http from 'node:http'
|
||||
|
||||
import { createFetchProxy } from 'remix/fetch-proxy'
|
||||
import { createHmrReadyFetch, run } from 'remix/node-hmr'
|
||||
import { createRequestListener } from 'remix/node-fetch-server'
|
||||
|
||||
const hmrProxyPort = 44100
|
||||
const hmrEventPort = 44101
|
||||
const appPort = 44102
|
||||
|
||||
const hmrRunner = run('./server.ts', {
|
||||
env: {
|
||||
...process.env,
|
||||
PORT: String(appPort),
|
||||
HMR_PROXY_PORT: String(hmrProxyPort),
|
||||
},
|
||||
nodeArgs: ['--import', 'remix/node-tsx', '--import', 'remix/ui-hmr/node'],
|
||||
browserHmrChannel: { port: hmrEventPort },
|
||||
})
|
||||
|
||||
let proxyFetch = createFetchProxy(`http://127.0.0.1:${appPort}`, {
|
||||
xForwardedHeaders: true,
|
||||
})
|
||||
|
||||
let server = http.createServer(createRequestListener(createHmrReadyFetch(hmrRunner, proxyFetch)))
|
||||
|
||||
server.listen(hmrProxyPort, '127.0.0.1')
|
||||
```
|
||||
|
||||
Keep `browserHmrChannel.port` stable so browser HMR clients can reconnect to the same event channel if the dev server is manually restarted.
|
||||
|
||||
Use a stable public proxy when browser requests may happen while the child server is restarting. `createHmrReadyFetch()` waits for the active child generation before forwarding requests and retries safe unavailable responses when the child changes during a request.
|
||||
|
||||
In the child `server.ts`, report readiness after the server is listening:
|
||||
|
||||
```typescript
|
||||
server.listen(port, () => {
|
||||
if (process.env.REMIX_NODE_HMR) {
|
||||
import('remix/node-hmr/runtime').then((nodeHmr) => nodeHmr.emitServerReady())
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Guard `remix/node-hmr/runtime` imports with `process.env.REMIX_NODE_HMR`.
|
||||
- Use `--import remix/ui-hmr/node` only when server-rendered Remix UI component modules should hot update.
|
||||
- Keep the default development and production startup paths independent from `hmr.ts`.
|
||||
- Close the public server and `hmrRunner` during `SIGINT` and `SIGTERM` shutdown.
|
||||
@@ -70,28 +70,29 @@ try {
|
||||
|
||||
## Test Runner Config
|
||||
|
||||
Configure discovery and coverage in `remix-test.config.ts` or with CLI flags:
|
||||
Configure discovery and coverage in the `test` section of `remix.json` or with CLI flags:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
glob: {
|
||||
test: '**/*.test{,.e2e}.{ts,tsx}',
|
||||
e2e: '**/*.test.e2e.{ts,tsx}',
|
||||
exclude: 'node_modules/**',
|
||||
},
|
||||
coverage: {
|
||||
dir: '.coverage',
|
||||
include: ['app/**/*.{ts,tsx}'],
|
||||
exclude: ['app/**/*.test.{ts,tsx}'],
|
||||
statements: 80,
|
||||
lines: 80,
|
||||
branches: 70,
|
||||
functions: 80,
|
||||
```jsonc
|
||||
{
|
||||
"$schema": "https://remix.run/schemas/remix.json",
|
||||
"test": {
|
||||
"files": ["**/*.test{,.e2e}.{ts,tsx}"],
|
||||
"e2eFiles": ["**/*.test.e2e.{ts,tsx}"],
|
||||
"exclude": ["node_modules/**"],
|
||||
"coverage": {
|
||||
"dir": ".coverage",
|
||||
"include": ["app/**/*.{ts,tsx}"],
|
||||
"exclude": ["app/**/*.test.{ts,tsx}"],
|
||||
"statements": 80,
|
||||
"lines": 80,
|
||||
"branches": 70,
|
||||
"functions": 80,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Use `remix test --coverage` to enable coverage with defaults. Use `glob.exclude` when discovery would otherwise enter generated output, symlinked workspaces, or other paths that should not produce tests.
|
||||
Use `remix test --coverage` to enable coverage with defaults. Use `exclude` when discovery would otherwise enter generated output, symlinked workspaces, or other paths that should not produce tests.
|
||||
|
||||
## Component Tests
|
||||
|
||||
|
||||
Reference in new issue
Block a user