mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-05 04:08:03 +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
@@ -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