create-rivet 0.0.0-stage → 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +45 -2
- package/cli.d.ts +2 -0
- package/cli.js +10 -0
- package/deploy.d.ts +32 -0
- package/deploy.js +99 -0
- package/index.d.ts +118 -0
- package/index.js +184 -0
- package/main.d.ts +9 -0
- package/main.js +169 -0
- package/package.json +57 -4
- package/prompt.d.ts +24 -0
- package/prompt.js +127 -0
- package/templates/starter-minimal/.agents/skills/rivet-add-route/LICENSE.txt +21 -0
- package/templates/starter-minimal/.agents/skills/rivet-add-route/SKILL.md +36 -0
- package/templates/starter-minimal/.agents/skills/rivet-add-ui-page/LICENSE.txt +21 -0
- package/templates/starter-minimal/.agents/skills/rivet-add-ui-page/SKILL.md +42 -0
- package/templates/starter-minimal/.agents/skills/rivet-fix-resumability-error/LICENSE.txt +21 -0
- package/templates/starter-minimal/.agents/skills/rivet-fix-resumability-error/SKILL.md +26 -0
- package/templates/starter-minimal/.agents/skills/rivet-form-in-drawer/LICENSE.txt +21 -0
- package/templates/starter-minimal/.agents/skills/rivet-form-in-drawer/SKILL.md +63 -0
- package/templates/starter-minimal/.agents/skills/rivet-port-react-component/LICENSE.txt +21 -0
- package/templates/starter-minimal/.agents/skills/rivet-port-react-component/SKILL.md +36 -0
- package/templates/starter-minimal/.agents/skills/rivet-ui-design/LICENSE.txt +21 -0
- package/templates/starter-minimal/.agents/skills/rivet-ui-design/SKILL.md +41 -0
- package/templates/starter-minimal/.agents/skills/rivet-ui-design/references/component-composition.md +55 -0
- package/templates/starter-minimal/.agents/skills/rivet-ui-design/references/interactions.md +49 -0
- package/templates/starter-minimal/.agents/skills/rivet-ui-design/references/rivet-implementation.md +66 -0
- package/templates/starter-minimal/.agents/skills/rivet-ui-design/references/structure-and-layout.md +51 -0
- package/templates/starter-minimal/.agents/skills/rivet-ui-design/references/visual-foundations.md +64 -0
- package/templates/starter-minimal/.claude/skills/rivet-add-route/LICENSE.txt +21 -0
- package/templates/starter-minimal/.claude/skills/rivet-add-route/SKILL.md +36 -0
- package/templates/starter-minimal/.claude/skills/rivet-add-ui-page/LICENSE.txt +21 -0
- package/templates/starter-minimal/.claude/skills/rivet-add-ui-page/SKILL.md +42 -0
- package/templates/starter-minimal/.claude/skills/rivet-fix-resumability-error/LICENSE.txt +21 -0
- package/templates/starter-minimal/.claude/skills/rivet-fix-resumability-error/SKILL.md +26 -0
- package/templates/starter-minimal/.claude/skills/rivet-form-in-drawer/LICENSE.txt +21 -0
- package/templates/starter-minimal/.claude/skills/rivet-form-in-drawer/SKILL.md +63 -0
- package/templates/starter-minimal/.claude/skills/rivet-port-react-component/LICENSE.txt +21 -0
- package/templates/starter-minimal/.claude/skills/rivet-port-react-component/SKILL.md +36 -0
- package/templates/starter-minimal/.claude/skills/rivet-ui-design/LICENSE.txt +21 -0
- package/templates/starter-minimal/.claude/skills/rivet-ui-design/SKILL.md +41 -0
- package/templates/starter-minimal/.claude/skills/rivet-ui-design/references/component-composition.md +55 -0
- package/templates/starter-minimal/.claude/skills/rivet-ui-design/references/interactions.md +49 -0
- package/templates/starter-minimal/.claude/skills/rivet-ui-design/references/rivet-implementation.md +66 -0
- package/templates/starter-minimal/.claude/skills/rivet-ui-design/references/structure-and-layout.md +51 -0
- package/templates/starter-minimal/.claude/skills/rivet-ui-design/references/visual-foundations.md +64 -0
- package/templates/starter-minimal/.cursor/rules/rivet-add-route.mdc +37 -0
- package/templates/starter-minimal/.cursor/rules/rivet-add-ui-page.mdc +43 -0
- package/templates/starter-minimal/.cursor/rules/rivet-fix-resumability-error.mdc +27 -0
- package/templates/starter-minimal/.cursor/rules/rivet-form-in-drawer.mdc +64 -0
- package/templates/starter-minimal/.cursor/rules/rivet-port-react-component.mdc +37 -0
- package/templates/starter-minimal/.cursor/rules/rivet-ui-design.mdc +42 -0
- package/templates/starter-minimal/.cursor/rules/rivet.mdc +27 -0
- package/templates/starter-minimal/.github/copilot-instructions.md +21 -0
- package/templates/starter-minimal/AGENTS.md +461 -0
- package/templates/starter-minimal/CLAUDE.md +461 -0
- package/templates/starter-minimal/README.md +26 -0
- package/templates/starter-minimal/_gitignore +3 -0
- package/templates/starter-minimal/package.json +28 -0
- package/templates/starter-minimal/prerender.js +5 -0
- package/templates/starter-minimal/src/document.ts +14 -0
- package/templates/starter-minimal/src/routes/index.tsx +16 -0
- package/templates/starter-minimal/tsconfig.json +21 -0
- package/templates/starter-minimal/vite.config.ts +4 -0
- package/templates/starter-server/.agents/skills/rivet-add-route/LICENSE.txt +21 -0
- package/templates/starter-server/.agents/skills/rivet-add-route/SKILL.md +36 -0
- package/templates/starter-server/.agents/skills/rivet-add-ui-page/LICENSE.txt +21 -0
- package/templates/starter-server/.agents/skills/rivet-add-ui-page/SKILL.md +42 -0
- package/templates/starter-server/.agents/skills/rivet-fix-resumability-error/LICENSE.txt +21 -0
- package/templates/starter-server/.agents/skills/rivet-fix-resumability-error/SKILL.md +26 -0
- package/templates/starter-server/.agents/skills/rivet-form-in-drawer/LICENSE.txt +21 -0
- package/templates/starter-server/.agents/skills/rivet-form-in-drawer/SKILL.md +63 -0
- package/templates/starter-server/.agents/skills/rivet-port-react-component/LICENSE.txt +21 -0
- package/templates/starter-server/.agents/skills/rivet-port-react-component/SKILL.md +36 -0
- package/templates/starter-server/.agents/skills/rivet-ui-design/LICENSE.txt +21 -0
- package/templates/starter-server/.agents/skills/rivet-ui-design/SKILL.md +41 -0
- package/templates/starter-server/.agents/skills/rivet-ui-design/references/component-composition.md +55 -0
- package/templates/starter-server/.agents/skills/rivet-ui-design/references/interactions.md +49 -0
- package/templates/starter-server/.agents/skills/rivet-ui-design/references/rivet-implementation.md +66 -0
- package/templates/starter-server/.agents/skills/rivet-ui-design/references/structure-and-layout.md +51 -0
- package/templates/starter-server/.agents/skills/rivet-ui-design/references/visual-foundations.md +64 -0
- package/templates/starter-server/.claude/skills/rivet-add-route/LICENSE.txt +21 -0
- package/templates/starter-server/.claude/skills/rivet-add-route/SKILL.md +36 -0
- package/templates/starter-server/.claude/skills/rivet-add-ui-page/LICENSE.txt +21 -0
- package/templates/starter-server/.claude/skills/rivet-add-ui-page/SKILL.md +42 -0
- package/templates/starter-server/.claude/skills/rivet-fix-resumability-error/LICENSE.txt +21 -0
- package/templates/starter-server/.claude/skills/rivet-fix-resumability-error/SKILL.md +26 -0
- package/templates/starter-server/.claude/skills/rivet-form-in-drawer/LICENSE.txt +21 -0
- package/templates/starter-server/.claude/skills/rivet-form-in-drawer/SKILL.md +63 -0
- package/templates/starter-server/.claude/skills/rivet-port-react-component/LICENSE.txt +21 -0
- package/templates/starter-server/.claude/skills/rivet-port-react-component/SKILL.md +36 -0
- package/templates/starter-server/.claude/skills/rivet-ui-design/LICENSE.txt +21 -0
- package/templates/starter-server/.claude/skills/rivet-ui-design/SKILL.md +41 -0
- package/templates/starter-server/.claude/skills/rivet-ui-design/references/component-composition.md +55 -0
- package/templates/starter-server/.claude/skills/rivet-ui-design/references/interactions.md +49 -0
- package/templates/starter-server/.claude/skills/rivet-ui-design/references/rivet-implementation.md +66 -0
- package/templates/starter-server/.claude/skills/rivet-ui-design/references/structure-and-layout.md +51 -0
- package/templates/starter-server/.claude/skills/rivet-ui-design/references/visual-foundations.md +64 -0
- package/templates/starter-server/.cursor/rules/rivet-add-route.mdc +37 -0
- package/templates/starter-server/.cursor/rules/rivet-add-ui-page.mdc +43 -0
- package/templates/starter-server/.cursor/rules/rivet-fix-resumability-error.mdc +27 -0
- package/templates/starter-server/.cursor/rules/rivet-form-in-drawer.mdc +64 -0
- package/templates/starter-server/.cursor/rules/rivet-port-react-component.mdc +37 -0
- package/templates/starter-server/.cursor/rules/rivet-ui-design.mdc +42 -0
- package/templates/starter-server/.cursor/rules/rivet.mdc +27 -0
- package/templates/starter-server/.dockerignore +7 -0
- package/templates/starter-server/.github/copilot-instructions.md +21 -0
- package/templates/starter-server/AGENTS.md +461 -0
- package/templates/starter-server/CLAUDE.md +461 -0
- package/templates/starter-server/Dockerfile +18 -0
- package/templates/starter-server/README.md +30 -0
- package/templates/starter-server/_gitignore +3 -0
- package/templates/starter-server/package.json +31 -0
- package/templates/starter-server/serve.js +6 -0
- package/templates/starter-server/src/document.ts +14 -0
- package/templates/starter-server/src/routes/index.tsx +41 -0
- package/templates/starter-server/src/styles.css +9 -0
- package/templates/starter-server/tsconfig.json +21 -0
- package/templates/starter-server/vite.config.ts +8 -0
- package/templates/starter-static/.agents/skills/rivet-add-route/LICENSE.txt +21 -0
- package/templates/starter-static/.agents/skills/rivet-add-route/SKILL.md +36 -0
- package/templates/starter-static/.agents/skills/rivet-add-ui-page/LICENSE.txt +21 -0
- package/templates/starter-static/.agents/skills/rivet-add-ui-page/SKILL.md +42 -0
- package/templates/starter-static/.agents/skills/rivet-fix-resumability-error/LICENSE.txt +21 -0
- package/templates/starter-static/.agents/skills/rivet-fix-resumability-error/SKILL.md +26 -0
- package/templates/starter-static/.agents/skills/rivet-form-in-drawer/LICENSE.txt +21 -0
- package/templates/starter-static/.agents/skills/rivet-form-in-drawer/SKILL.md +63 -0
- package/templates/starter-static/.agents/skills/rivet-port-react-component/LICENSE.txt +21 -0
- package/templates/starter-static/.agents/skills/rivet-port-react-component/SKILL.md +36 -0
- package/templates/starter-static/.agents/skills/rivet-ui-design/LICENSE.txt +21 -0
- package/templates/starter-static/.agents/skills/rivet-ui-design/SKILL.md +41 -0
- package/templates/starter-static/.agents/skills/rivet-ui-design/references/component-composition.md +55 -0
- package/templates/starter-static/.agents/skills/rivet-ui-design/references/interactions.md +49 -0
- package/templates/starter-static/.agents/skills/rivet-ui-design/references/rivet-implementation.md +66 -0
- package/templates/starter-static/.agents/skills/rivet-ui-design/references/structure-and-layout.md +51 -0
- package/templates/starter-static/.agents/skills/rivet-ui-design/references/visual-foundations.md +64 -0
- package/templates/starter-static/.claude/skills/rivet-add-route/LICENSE.txt +21 -0
- package/templates/starter-static/.claude/skills/rivet-add-route/SKILL.md +36 -0
- package/templates/starter-static/.claude/skills/rivet-add-ui-page/LICENSE.txt +21 -0
- package/templates/starter-static/.claude/skills/rivet-add-ui-page/SKILL.md +42 -0
- package/templates/starter-static/.claude/skills/rivet-fix-resumability-error/LICENSE.txt +21 -0
- package/templates/starter-static/.claude/skills/rivet-fix-resumability-error/SKILL.md +26 -0
- package/templates/starter-static/.claude/skills/rivet-form-in-drawer/LICENSE.txt +21 -0
- package/templates/starter-static/.claude/skills/rivet-form-in-drawer/SKILL.md +63 -0
- package/templates/starter-static/.claude/skills/rivet-port-react-component/LICENSE.txt +21 -0
- package/templates/starter-static/.claude/skills/rivet-port-react-component/SKILL.md +36 -0
- package/templates/starter-static/.claude/skills/rivet-ui-design/LICENSE.txt +21 -0
- package/templates/starter-static/.claude/skills/rivet-ui-design/SKILL.md +41 -0
- package/templates/starter-static/.claude/skills/rivet-ui-design/references/component-composition.md +55 -0
- package/templates/starter-static/.claude/skills/rivet-ui-design/references/interactions.md +49 -0
- package/templates/starter-static/.claude/skills/rivet-ui-design/references/rivet-implementation.md +66 -0
- package/templates/starter-static/.claude/skills/rivet-ui-design/references/structure-and-layout.md +51 -0
- package/templates/starter-static/.claude/skills/rivet-ui-design/references/visual-foundations.md +64 -0
- package/templates/starter-static/.cursor/rules/rivet-add-route.mdc +37 -0
- package/templates/starter-static/.cursor/rules/rivet-add-ui-page.mdc +43 -0
- package/templates/starter-static/.cursor/rules/rivet-fix-resumability-error.mdc +27 -0
- package/templates/starter-static/.cursor/rules/rivet-form-in-drawer.mdc +64 -0
- package/templates/starter-static/.cursor/rules/rivet-port-react-component.mdc +37 -0
- package/templates/starter-static/.cursor/rules/rivet-ui-design.mdc +42 -0
- package/templates/starter-static/.cursor/rules/rivet.mdc +27 -0
- package/templates/starter-static/.github/copilot-instructions.md +21 -0
- package/templates/starter-static/AGENTS.md +461 -0
- package/templates/starter-static/CLAUDE.md +461 -0
- package/templates/starter-static/README.md +30 -0
- package/templates/starter-static/_gitignore +3 -0
- package/templates/starter-static/package.json +31 -0
- package/templates/starter-static/prerender.js +5 -0
- package/templates/starter-static/serve.js +21 -0
- package/templates/starter-static/src/components/Counter.tsx +15 -0
- package/templates/starter-static/src/document.ts +14 -0
- package/templates/starter-static/src/routes/_layout.tsx +18 -0
- package/templates/starter-static/src/routes/about.tsx +11 -0
- package/templates/starter-static/src/routes/index.tsx +14 -0
- package/templates/starter-static/src/styles.css +9 -0
- package/templates/starter-static/tsconfig.json +21 -0
- package/templates/starter-static/vite.config.ts +9 -0
- package/templates/starter-ui/.agents/skills/rivet-add-route/LICENSE.txt +21 -0
- package/templates/starter-ui/.agents/skills/rivet-add-route/SKILL.md +36 -0
- package/templates/starter-ui/.agents/skills/rivet-add-ui-page/LICENSE.txt +21 -0
- package/templates/starter-ui/.agents/skills/rivet-add-ui-page/SKILL.md +42 -0
- package/templates/starter-ui/.agents/skills/rivet-fix-resumability-error/LICENSE.txt +21 -0
- package/templates/starter-ui/.agents/skills/rivet-fix-resumability-error/SKILL.md +26 -0
- package/templates/starter-ui/.agents/skills/rivet-form-in-drawer/LICENSE.txt +21 -0
- package/templates/starter-ui/.agents/skills/rivet-form-in-drawer/SKILL.md +63 -0
- package/templates/starter-ui/.agents/skills/rivet-port-react-component/LICENSE.txt +21 -0
- package/templates/starter-ui/.agents/skills/rivet-port-react-component/SKILL.md +36 -0
- package/templates/starter-ui/.agents/skills/rivet-ui-design/LICENSE.txt +21 -0
- package/templates/starter-ui/.agents/skills/rivet-ui-design/SKILL.md +41 -0
- package/templates/starter-ui/.agents/skills/rivet-ui-design/references/component-composition.md +55 -0
- package/templates/starter-ui/.agents/skills/rivet-ui-design/references/interactions.md +49 -0
- package/templates/starter-ui/.agents/skills/rivet-ui-design/references/rivet-implementation.md +66 -0
- package/templates/starter-ui/.agents/skills/rivet-ui-design/references/structure-and-layout.md +51 -0
- package/templates/starter-ui/.agents/skills/rivet-ui-design/references/visual-foundations.md +64 -0
- package/templates/starter-ui/.claude/skills/rivet-add-route/LICENSE.txt +21 -0
- package/templates/starter-ui/.claude/skills/rivet-add-route/SKILL.md +36 -0
- package/templates/starter-ui/.claude/skills/rivet-add-ui-page/LICENSE.txt +21 -0
- package/templates/starter-ui/.claude/skills/rivet-add-ui-page/SKILL.md +42 -0
- package/templates/starter-ui/.claude/skills/rivet-fix-resumability-error/LICENSE.txt +21 -0
- package/templates/starter-ui/.claude/skills/rivet-fix-resumability-error/SKILL.md +26 -0
- package/templates/starter-ui/.claude/skills/rivet-form-in-drawer/LICENSE.txt +21 -0
- package/templates/starter-ui/.claude/skills/rivet-form-in-drawer/SKILL.md +63 -0
- package/templates/starter-ui/.claude/skills/rivet-port-react-component/LICENSE.txt +21 -0
- package/templates/starter-ui/.claude/skills/rivet-port-react-component/SKILL.md +36 -0
- package/templates/starter-ui/.claude/skills/rivet-ui-design/LICENSE.txt +21 -0
- package/templates/starter-ui/.claude/skills/rivet-ui-design/SKILL.md +41 -0
- package/templates/starter-ui/.claude/skills/rivet-ui-design/references/component-composition.md +55 -0
- package/templates/starter-ui/.claude/skills/rivet-ui-design/references/interactions.md +49 -0
- package/templates/starter-ui/.claude/skills/rivet-ui-design/references/rivet-implementation.md +66 -0
- package/templates/starter-ui/.claude/skills/rivet-ui-design/references/structure-and-layout.md +51 -0
- package/templates/starter-ui/.claude/skills/rivet-ui-design/references/visual-foundations.md +64 -0
- package/templates/starter-ui/.cursor/rules/rivet-add-route.mdc +37 -0
- package/templates/starter-ui/.cursor/rules/rivet-add-ui-page.mdc +43 -0
- package/templates/starter-ui/.cursor/rules/rivet-fix-resumability-error.mdc +27 -0
- package/templates/starter-ui/.cursor/rules/rivet-form-in-drawer.mdc +64 -0
- package/templates/starter-ui/.cursor/rules/rivet-port-react-component.mdc +37 -0
- package/templates/starter-ui/.cursor/rules/rivet-ui-design.mdc +42 -0
- package/templates/starter-ui/.cursor/rules/rivet.mdc +27 -0
- package/templates/starter-ui/.github/copilot-instructions.md +21 -0
- package/templates/starter-ui/AGENTS.md +461 -0
- package/templates/starter-ui/CLAUDE.md +461 -0
- package/templates/starter-ui/README.md +32 -0
- package/templates/starter-ui/_gitignore +3 -0
- package/templates/starter-ui/package.json +34 -0
- package/templates/starter-ui/prerender.js +5 -0
- package/templates/starter-ui/serve.js +21 -0
- package/templates/starter-ui/src/components/LikeButton.tsx +12 -0
- package/templates/starter-ui/src/document.ts +14 -0
- package/templates/starter-ui/src/routes/index.tsx +39 -0
- package/templates/starter-ui/src/styles.css +11 -0
- package/templates/starter-ui/tsconfig.json +21 -0
- package/templates/starter-ui/vite.config.ts +9 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Build a page or component from @rivetjs/ui components - correct subpath imports, compound parts, two-way signal props, styles and lucide icons. Use when the user asks for UI built with Rivet UI components (buttons, selects, modals, cards, forms) in a Rivet app."
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- Generated by libs/mcp/ai/sync.ts from libs/mcp/ai/skills/add-ui-page.md in the Rivet repository: edit the source there and run the script. In an app created from a starter this file is yours to edit. -->
|
|
8
|
+
|
|
9
|
+
# Page with @rivetjs/ui components
|
|
10
|
+
|
|
11
|
+
1. Setup (the `ui` starter has it): dependencies `@rivetjs/ui`, `@rivetjs/kit`, `lucide`; `src/styles.css` = `@import "tailwindcss";` then `@import "@rivetjs/ui/styles";` (other looks: `@rivetjs/ui/theme` presets, variables pasted after it).
|
|
12
|
+
2. For every component: `get_component("Select")` (import path, parts, props, example source) or `get_doc("ui:/components/select/")`. Copy the structure of the docs example, not React component-library code.
|
|
13
|
+
3. Rules that differ from React component libraries:
|
|
14
|
+
- Subpath imports: `import { Select } from "@rivetjs/ui/select"`, `import { ListBox } from "@rivetjs/ui/list-box"`, `import { Label } from "@rivetjs/ui/label"`.
|
|
15
|
+
- `class`, not `className`. Events follow React Aria: `onPress`, `onSelectionChange`, `onOpenChange`.
|
|
16
|
+
- Two-way props take a signal: `isOpen={open}`, `value={selected}`, `selectedKeys={keys}`; a plain value is one-way.
|
|
17
|
+
- Render props are accessors: `({ isPlaceholder }) => (isPlaceholder() ? … : …)`.
|
|
18
|
+
- Icons: `<Icon icon={ChevronDown} />` (`@rivetjs/kit/icon` + lucide); never inline SVG paths or Unicode glyphs.
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { signal } from "@rivetjs/reactivity";
|
|
22
|
+
import { Button } from "@rivetjs/ui/button";
|
|
23
|
+
import { Modal } from "@rivetjs/ui/modal";
|
|
24
|
+
|
|
25
|
+
export default function Page() {
|
|
26
|
+
const open = signal(false);
|
|
27
|
+
return (
|
|
28
|
+
<>
|
|
29
|
+
<Button onPress={() => open.set(true)}>Open</Button>
|
|
30
|
+
<Modal.Content isOpen={open}>
|
|
31
|
+
<Modal.Header>Title</Modal.Header>
|
|
32
|
+
<Modal.Body>…</Modal.Body>
|
|
33
|
+
<Modal.Footer>
|
|
34
|
+
<Button slot="close">Close</Button>
|
|
35
|
+
</Modal.Footer>
|
|
36
|
+
</Modal.Content>
|
|
37
|
+
</>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
4. Custom-styled widget instead: the headless `@rivetjs/cdk/<module>` (same parts, `rv-*` classes + `data-*` state, no styles).
|
|
43
|
+
5. `check_code`, `npm run check`, then look at it in `npm run dev` (overlays render in a portal on the div overlay layer, never native `<dialog>` / `popover`).
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Diagnose and fix Rivet resumability errors - RV2xxx compiler diagnostics, RV1016 handler errors, \"is not serializable\" / \"Cannot resume\" build or prerender errors, browser globals during server rendering, state that resets after the first click. Use when a Rivet build, check or page fails with such an error."
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- Generated by libs/mcp/ai/sync.ts from libs/mcp/ai/skills/fix-resumability-error.md in the Rivet repository: edit the source there and run the script. In an app created from a starter this file is yours to edit. -->
|
|
8
|
+
|
|
9
|
+
# Fix a resumability error
|
|
10
|
+
|
|
11
|
+
A Rivet page is rendered on the server and resumed in the browser: handlers, bindings and client effects run there with the values they capture, which the server serialized into the HTML. Errors come from code that cannot cross that line.
|
|
12
|
+
|
|
13
|
+
1. Get the exact diagnostic: `npm run check` (`file:line:col - error RVnnnn`), the Vite overlay (`[RVnnnn] file:line:col`), or `check_code(source, filename)`. For the fix: `explain_diagnostic("RVnnnn")`; `check_code` also returns the quick-fixed source when one applies.
|
|
14
|
+
2. Common codes:
|
|
15
|
+
- RV2001 browser global (`window`, `document`, `localStorage`) read during server rendering → move it into a handler, `clientEffect(() => …)`, `clientEvent(window, "resize", …)` or `clientOnly(() => import("…"))`.
|
|
16
|
+
- RV2003 captured class instance (`new Intl.NumberFormat`, an SDK client) → capture plain data; create the object inside the handler or `clientEffect`, or build it with `reconstruct(() => new X(…))` from `@rivetjs/runtime/dom` (the browser runs the factory on first read). A data class declared in the component module (plain fields) resumes as is.
|
|
17
|
+
- RV2102 captured instance of a module class that cannot resume as data (`#private` field, a decorator, a field arrow using `super`, a base that is not a data class of the module, `window` / `document` / `WebSocket` read while constructing) → create it inside the handler, build it with `reconstruct(() => new X(…))`, keep only plain fields, or add `[serialize]()` + `static [revive](data)` (from `@rivetjs/runtime/resume-format`; package classes: `registerClass(Cls, { id, serialize, revive })` in a module imported by the server code and the resume entry). At render, `RV2102: X has [serialize] but no static [revive]` → add the `static [revive]`.
|
|
18
|
+
- RV1016 handler expression reads state when it binds (`onClick={a() ? f : g}`) → wrap: `onClick={(e) => (a() ? f(e) : g(e))}`.
|
|
19
|
+
- RV2002 ref callback must assign a local → `ref={(el) => (local = el)}` or `const el = ref()` + `ref={el}`.
|
|
20
|
+
- RV2006 JSX inside a handler / effect / computed → render JSX in the component, switch it with a signal.
|
|
21
|
+
- RV2007 `this` in resumable code → `event.currentTarget`.
|
|
22
|
+
- RV2009 two module references share a browser name (two imports of different modules under one name) → rename one import (`import { fmt as fmtDate } from …`).
|
|
23
|
+
- RV2101 (warning, type-aware) a captured value's type does not serialize → as RV2003.
|
|
24
|
+
3. Build / prerender error `Cannot resume <file>#<Component>$<hash>: function is not serializable` (dev server: ``capture `<name>` function is not serializable``; dev build: `capture #<i> …`): a captured function Rivet did not compile (created at runtime by a library such as `memoize(fn)`, a `.bind(…)` written inside an object literal (keep `const inc = add.bind(null, 2)` in a local constant and store `inc`; `.bind(ctx)` of a function using `this` stays RV2007), a method, or held by an object built outside a component: at module level such as `const table = { format: formatEuro }`, or by your own hook / helper such as `function useFormat() { return { format: formatEuro }; }`). Wrap it in an inline arrow, or build the object inside the component (module-level and imported functions used by name there resume by reference). A library object holding functions (a chart, editor, socket client from a package): build it with `reconstruct(() => createChart(…))` from `@rivetjs/runtime/dom` — no value in the page, the browser runs the factory on first read (module level: one server instance per process, never read request state in it). A class instance at render (`X instance is not serializable`): your class → `reconstruct(() => new X(…))` or `[serialize]()` + `static [revive](data)`; a package class → `registerClass(X, { id, serialize, revive })` from `@rivetjs/runtime/resume-format`. `NODE_ENV=development vite build` names the value path. Rules: `get_doc("docs:/best-practices/serializable-captures/")`.
|
|
25
|
+
4. State resets on the first change after resume: a child destructures its props (`function C({ value })`) and is re-created → read `props.value`. Copies of `props.children` in a local are not tracked → render `{props.children}` directly.
|
|
26
|
+
5. `.ts` module importing `@rivetjs/runtime/dom` (bundles the DOM runtime into SSR) → move that code into a `.tsx` file.
|
|
27
|
+
6. Re-run `npm run check` and `npm run build` (prerender exercises serialization); both must be clean.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Build a validated form inside a drawer or dialog on a Rivet live page, so a submit updates the list behind it in place, keeps the overlay open on errors and works without JavaScript. Use for \"add/edit X in a drawer/modal/dialog\" tasks in a Rivet project."
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- Generated by libs/mcp/ai/sync.ts from libs/mcp/ai/skills/form-in-drawer.md in the Rivet repository: edit the source there and run the script. In an app created from a starter this file is yours to edit. -->
|
|
8
|
+
|
|
9
|
+
# Form in a drawer with a live page
|
|
10
|
+
|
|
11
|
+
Reference implementation: `get_doc("docs:/guides/forms/forms-in-overlays/")` (example `docs:/examples/drawer-form/`). Read it first; the steps below are its shape.
|
|
12
|
+
|
|
13
|
+
1. Define the form once, shared by page and action (any Standard Schema library):
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// src/forms/customer.ts
|
|
17
|
+
import { defineForm } from "@rivetjs/forms";
|
|
18
|
+
import { z } from "zod";
|
|
19
|
+
export const customerForm = defineForm({ name: "customer", schema: z.object({ name: z.string().min(1), email: z.string().email() }) });
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
2. Make the page live and add the action:
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import type { LivePageProps } from "@rivetjs/router";
|
|
26
|
+
import { actionResult } from "@rivetjs/router/client";
|
|
27
|
+
import { action, invalid } from "@rivetjs/forms/server";
|
|
28
|
+
import { load, actions } from "@rivetjs/router";
|
|
29
|
+
|
|
30
|
+
export const live = true; // data is an accessor, refreshed in place after a submit: signals (open drawer, input, focus) survive
|
|
31
|
+
export const loader = load(({ url }: { url: URL }) => ({ customers: [...customers], creating: url.searchParams.has("new") }));
|
|
32
|
+
export const forms = actions({
|
|
33
|
+
customer: action(customerForm, (value) => {
|
|
34
|
+
if (customers.some((c) => c.email === value.email)) return invalid({ email: "Already a customer" });
|
|
35
|
+
customers.push({ id: customers.length + 1, ...value });
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
38
|
+
export default function Customers({ data }: LivePageProps<typeof loader>) {
|
|
39
|
+
/* … */
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
3. In the component: `const result = actionResult("customer")`, `const open = signal(data().creating || (result?.status ?? 0) >= 400)` (no-JS entry: `<a href="?new" onClick={(e) => { e.preventDefault(); open.set(true); }}>`), `const form = createForm(customerForm, { result })`. Render the list from `data()` with `<For each={data().customers} by={(c) => c.id}>`; never copy `data()` into a signal.
|
|
44
|
+
4. The overlay: `@rivetjs/ui` (`Drawer` / `Modal`, `isOpen={open}`) or cdk `ModalOverlay isDismissable isOpen={open}` + `Modal` + `Dialog` (div overlay layer, two-way `isOpen`). The form inside:
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
<form id={formId(form)} method="post" action="?/customer" onSubmit={async (event) => (await onSubmit(customerForm, form, event)) && open.set(false)}>
|
|
48
|
+
<label for={fieldId(form, "email")}>Email</label>
|
|
49
|
+
<input
|
|
50
|
+
id={fieldId(form, "email")}
|
|
51
|
+
name="email"
|
|
52
|
+
value={defaultValue(form, "email")}
|
|
53
|
+
aria-invalid={isInvalid(form, "email")}
|
|
54
|
+
aria-describedby={describedBy(form, "email")}
|
|
55
|
+
/>
|
|
56
|
+
<FieldError of={form} name="email" />
|
|
57
|
+
<button aria-disabled={submitting(form) ? "true" : undefined}>Save</button>
|
|
58
|
+
</form>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`onSubmit` resolves true once the server accepted the form and the page data is fresh: close the drawer then. Errors stay in the open drawer. Imports: `createForm, defaultValue, describedBy, fieldId, formId, isInvalid, onSubmit, submitting` from `@rivetjs/forms`, `FieldError` from `@rivetjs/forms/components`.
|
|
62
|
+
|
|
63
|
+
5. A layout `load(…)` re-runs too (counts in headers update).
|
|
64
|
+
6. Check: `check_code` on the page, `npm run check`, then try it with JavaScript disabled (plain POST, 400 re-render with the drawer open).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Port a React (or Solid / Next.js) component or page to Rivet idioms - signals instead of useState, clientEffect instead of useEffect, For with a key, live props, class, serializable handlers. Use when the user pastes React code or asks to convert / migrate a component to Rivet."
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- Generated by libs/mcp/ai/sync.ts from libs/mcp/ai/skills/port-react-component.md in the Rivet repository: edit the source there and run the script. In an app created from a starter this file is yours to edit. -->
|
|
8
|
+
|
|
9
|
+
# Port a React component to Rivet
|
|
10
|
+
|
|
11
|
+
Map each construct (full table: `get_doc("docs:/start/coming-from-other-frameworks/")`):
|
|
12
|
+
|
|
13
|
+
| React | Rivet |
|
|
14
|
+
| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
15
|
+
| `const [n, setN] = useState(0)` | `const n = signal(0)`; read `n()`, write `n.set(1)` / `n.update((v) => v + 1)` (`@rivetjs/reactivity`) |
|
|
16
|
+
| `useMemo(() => a * 2, [a])` | `computed(() => a() * 2)` (no dependency list) |
|
|
17
|
+
| `useEffect(() => …, [deps])` | `clientEffect(() => …)` from `@rivetjs/runtime/dom` (browser only, re-runs when read signals change; return a cleanup) |
|
|
18
|
+
| `useRef()` for an element | `const el = ref<HTMLInputElement>()` + `ref={el}`; read `el()` |
|
|
19
|
+
| `useCallback`, `memo` | nothing: components run once |
|
|
20
|
+
| `useContext` | `createContext` / `useContext` (`@rivetjs/reactivity`) + `<Provider token value>` (`@rivetjs/runtime/dom`) |
|
|
21
|
+
| `items.map((i) => <li key={i.id}>…)` | `<For each={items} by={(i) => i.id}>{(i) => <li>{i().name}</li>}</For>` (item / index are accessors); `.map` is fine for fixed data |
|
|
22
|
+
| `cond && <p />` | `cond() && <p />` or `<Show when={cond()}>` |
|
|
23
|
+
| `className`, `htmlFor`, `onChange` on text inputs | `class`, `for`, `onInput` or `model:value={signal}` |
|
|
24
|
+
| `style="…"` strings | `style={{ color: c() }}` or `style:color={c()}` |
|
|
25
|
+
| `function Badge({ count })` | `function Badge(props: { count: number })` + `props.count` (props are live; destructuring reads once) |
|
|
26
|
+
| `React.lazy`, `<Suspense>` | `lazyComponent`, `Async`, `Suspense` (`@rivetjs/runtime/dom`) |
|
|
27
|
+
| Next.js `getServerSideProps`, Remix `loader` / `action` | `export const loader = load(…)` / `actions(…)` in the route file |
|
|
28
|
+
| `useRouter().push`, `useSearchParams` | `navigate()`, `useSearchParams()` from `@rivetjs/router/client` |
|
|
29
|
+
| icon components / inline SVG | `<Icon icon={Check} />` from `@rivetjs/kit/icon` + `import { Check } from "lucide"` |
|
|
30
|
+
|
|
31
|
+
Then fix what resuming requires:
|
|
32
|
+
|
|
33
|
+
1. Move browser reads (`window`, `document`, `localStorage`, `matchMedia`) out of the component body into handlers or `clientEffect` (RV2001).
|
|
34
|
+
2. Handlers: inline arrows or local consts. Values they capture must serialize: create class instances (`Intl.*`, SDK clients) inside the handler or build them with `reconstruct(() => new X(…))` (`import { reconstruct } from "@rivetjs/runtime/dom"`; RV2003); wrap library callbacks: `onPress={() => track("save")}`.
|
|
35
|
+
3. Render props and item renderers stay functions (`{(item) => …}`).
|
|
36
|
+
4. Third-party React UI → `@rivetjs/ui` / `@rivetjs/cdk` equivalents: `list_components`, `get_component(name)`; React Aria-style names carry over (`onPress`, `isOpen={signal}`).
|
|
37
|
+
5. `check_code` the result, fix every RV code (`explain_diagnostic`), then `npm run check`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Use when designing, building, or polishing Rivet interfaces with @rivetjs/ui or @rivetjs/cdk, including colors, spacing, typography, page structure, app layouts, component composition, responsive behavior, and interactions."
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- Generated by libs/mcp/ai/sync.ts from libs/mcp/ai/skills/design-ui.md in the Rivet repository: edit the source there and run the script. In an app created from a starter this file is yours to edit. -->
|
|
8
|
+
|
|
9
|
+
# Design with Rivet UI and CDK
|
|
10
|
+
|
|
11
|
+
Design a coherent experience around the user's task, then express it with Rivet components. Preserve the app's brand, established patterns, and requested scope. This skill works in consumer projects; MCP is optional.
|
|
12
|
+
|
|
13
|
+
## Start with the task and existing system
|
|
14
|
+
|
|
15
|
+
Read project instructions, the relevant screens, installed package versions, global styles, and theme overrides. Identify the main task, content priorities, primary action, data density, and target devices. Ask only about missing information that materially changes the design; otherwise state a reasonable assumption and proceed.
|
|
16
|
+
|
|
17
|
+
For a new or substantially redesigned screen, establish a compact design contract:
|
|
18
|
+
|
|
19
|
+
- **Structure:** navigation, page regions, reading order, and what changes on mobile.
|
|
20
|
+
- **Visual system:** semantic color roles, type hierarchy, spacing rhythm, density, and surface treatment.
|
|
21
|
+
- **Composition:** chosen UI/CDK components and why they fit the task.
|
|
22
|
+
- **Behavior:** primary action, focus/keyboard behavior, feedback, and loading/empty/error/success states.
|
|
23
|
+
|
|
24
|
+
Use that contract to guide the implementation, not as a mandatory separate deliverable or approval gate. For a small edit, preserve the existing contract and change only what is needed.
|
|
25
|
+
|
|
26
|
+
## Read the relevant design references
|
|
27
|
+
|
|
28
|
+
| Decision | Reference |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| Palette, contrast, spacing, typography, radius, visual hierarchy | [Visual foundations](../../.agents/skills/rivet-ui-design/references/visual-foundations.md) |
|
|
31
|
+
| Information architecture, app shell, page regions, responsive and scrolling behavior | [Structure and app layouts](../../.agents/skills/rivet-ui-design/references/structure-and-layout.md) |
|
|
32
|
+
| Choosing and combining components, forms, lists, overlays, reusable patterns | [Component composition](../../.agents/skills/rivet-ui-design/references/component-composition.md) |
|
|
33
|
+
| Action hierarchy, states, feedback, keyboard, focus, motion | [Interactions](../../.agents/skills/rivet-ui-design/references/interactions.md) |
|
|
34
|
+
| Actual imports, APIs, signals, resumability, styles, MCP and offline lookup | [Rivet implementation](../../.agents/skills/rivet-ui-design/references/rivet-implementation.md) |
|
|
35
|
+
|
|
36
|
+
Load the references needed for the task. Before writing code, consult the implementation reference and verify the selected components against the installed version.
|
|
37
|
+
|
|
38
|
+
## Implement and assess the whole experience
|
|
39
|
+
|
|
40
|
+
Use styled `@rivetjs/ui` for its supported patterns. Use headless `@rivetjs/cdk` when the task requires a different visual treatment or a behavior primitive; custom styling still needs every interactive state. Compose semantic HTML for regions that need no component behavior.
|
|
41
|
+
|
|
42
|
+
Evaluate the screen with realistic content: long titles, many rows, empty data, validation errors, pending actions, and narrow widths. Check hierarchy, alignment, contrast, readable text, keyboard access, focus restoration, and overflow. Inspect light/dark modes if supported and reduced motion when adding movement. Run the project's available checks and build; use MCP `check_code` when connected. Report the design decisions and what was actually verified. If browser inspection is unavailable, say which visual checks remain.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Rivet framework rules (not React / Solid)"
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- Generated by libs/mcp/ai/sync.ts from libs/mcp/ai/digest.md in the Rivet repository: edit the source there and run the script. In an app created from a starter this file is yours to edit. -->
|
|
8
|
+
|
|
9
|
+
# Rivet: rules for AI assistants
|
|
10
|
+
|
|
11
|
+
This project uses Rivet, a compiled, resumable JSX framework. It is NOT React and NOT Solid. Full instructions: `AGENTS.md` at the project root (read it before editing). Docs: the Rivet MCP server (`npx -y @rivetjs/mcp`: `search_docs`, `get_doc`, `get_component`, `check_code`, `explain_diagnostic`) or each docs site's `/llms.txt`.
|
|
12
|
+
|
|
13
|
+
- Components run once, on the server; the browser resumes the page and never re-runs them. No hooks, no re-renders, no dependency arrays.
|
|
14
|
+
- Component body = server code: no `window` / `document` / `localStorage` there (RV2001). Browser code goes in handlers, `clientEffect` / `clientEvent` / `clientOnly` from `@rivetjs/runtime/dom`.
|
|
15
|
+
- Signals (`@rivetjs/reactivity`): `const n = signal(0)`; read `n()`; write `n.set(1)` / `n.update((v) => v + 1)`; `computed(() => n() * 2)`; `untrack(n)` (no `.peek`).
|
|
16
|
+
- JSX: `class` (not `className`), `for`, events `onClick` / `onInput` (PascalCase; not `onclick`, not React's `onChange` for text), `model:value={signal}` for two-way inputs, style objects (no style strings).
|
|
17
|
+
- Props are live: read `props.x` where it is shown; destructuring reads once. `mergeProps` / `splitProps` from `@rivetjs/runtime/props`.
|
|
18
|
+
- Lists: `<For each={items} by={(i) => i.id}>{(item, index) => … item() … index()}</For>`; `Show`, `Switch` / `Match`, `ref()` from `@rivetjs/runtime/dom` (named imports).
|
|
19
|
+
- Captures must serialize: handlers are inline arrows or local consts. Functions stored by name in objects / arrays and imported functions (npm exports too) resume by reference; functions in objects built at module level or returned by library code / hooks do not. Class instances: data classes of the module, classes with `[serialize]` / `static [revive]`, package classes registered with `registerClass`. Library objects (`new Intl.NumberFormat`, SDK clients, charts) → create them in the handler or `reconstruct(() => new Intl.NumberFormat())` (`import { reconstruct } from "@rivetjs/runtime/dom"`). No `.bind` inside an object literal (inline in a prop or a local `const` of it is fine).
|
|
20
|
+
- Render props and item renderers are functions (`{(item) => …}`, `({ close }) => …`).
|
|
21
|
+
- Import `@rivetjs/runtime/dom` only from `.tsx` files, never from `.ts`.
|
|
22
|
+
- Routes: `src/routes/**.tsx`; `_layout.tsx`, `[param]`, `_404.tsx`; page exports `load(…)`, `actions(…)`, `head`, `live`; page `data` is a value, layout `data()` / `params()` / `url()` are accessors; `export const live = true` makes page `data` an accessor updated in place (forms in drawers).
|
|
23
|
+
- Forms: `@rivetjs/forms` (`defineForm`, `createForm`, `onSubmit`, `FieldError`; server `action` / `invalid` from `@rivetjs/forms/server`).
|
|
24
|
+
- i18n: `t("key", { param })` from `@rivetjs/i18n`, compile-time; key a string literal.
|
|
25
|
+
- Icons: `<Icon icon={Check} />` from `@rivetjs/kit/icon` with lucide (`import { Check } from "lucide"`). Never inline SVG paths, never Unicode glyphs as icons.
|
|
26
|
+
- UI: `@rivetjs/ui/<component>` (styled compound parts `Select.Trigger`, `onPress`, two-way props take a signal); headless `@rivetjs/cdk/<module>`.
|
|
27
|
+
- After every change: `npm run check` (`rivet sync && rivet-check`) and fix every `RVnnnn` diagnostic; never edit `.rivet/` or `Generated … Do not edit` files.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!-- Generated by libs/mcp/ai/sync.ts from libs/mcp/ai/digest.md in the Rivet repository: edit the source there and run the script. In an app created from a starter this file is yours to edit. -->
|
|
2
|
+
|
|
3
|
+
# Rivet: rules for AI assistants
|
|
4
|
+
|
|
5
|
+
This project uses Rivet, a compiled, resumable JSX framework. It is NOT React and NOT Solid. Full instructions: `AGENTS.md` at the project root (read it before editing). Docs: the Rivet MCP server (`npx -y @rivetjs/mcp`: `search_docs`, `get_doc`, `get_component`, `check_code`, `explain_diagnostic`) or each docs site's `/llms.txt`.
|
|
6
|
+
|
|
7
|
+
- Components run once, on the server; the browser resumes the page and never re-runs them. No hooks, no re-renders, no dependency arrays.
|
|
8
|
+
- Component body = server code: no `window` / `document` / `localStorage` there (RV2001). Browser code goes in handlers, `clientEffect` / `clientEvent` / `clientOnly` from `@rivetjs/runtime/dom`.
|
|
9
|
+
- Signals (`@rivetjs/reactivity`): `const n = signal(0)`; read `n()`; write `n.set(1)` / `n.update((v) => v + 1)`; `computed(() => n() * 2)`; `untrack(n)` (no `.peek`).
|
|
10
|
+
- JSX: `class` (not `className`), `for`, events `onClick` / `onInput` (PascalCase; not `onclick`, not React's `onChange` for text), `model:value={signal}` for two-way inputs, style objects (no style strings).
|
|
11
|
+
- Props are live: read `props.x` where it is shown; destructuring reads once. `mergeProps` / `splitProps` from `@rivetjs/runtime/props`.
|
|
12
|
+
- Lists: `<For each={items} by={(i) => i.id}>{(item, index) => … item() … index()}</For>`; `Show`, `Switch` / `Match`, `ref()` from `@rivetjs/runtime/dom` (named imports).
|
|
13
|
+
- Captures must serialize: handlers are inline arrows or local consts. Functions stored by name in objects / arrays and imported functions (npm exports too) resume by reference; functions in objects built at module level or returned by library code / hooks do not. Class instances: data classes of the module, classes with `[serialize]` / `static [revive]`, package classes registered with `registerClass`. Library objects (`new Intl.NumberFormat`, SDK clients, charts) → create them in the handler or `reconstruct(() => new Intl.NumberFormat())` (`import { reconstruct } from "@rivetjs/runtime/dom"`). No `.bind` inside an object literal (inline in a prop or a local `const` of it is fine).
|
|
14
|
+
- Render props and item renderers are functions (`{(item) => …}`, `({ close }) => …`).
|
|
15
|
+
- Import `@rivetjs/runtime/dom` only from `.tsx` files, never from `.ts`.
|
|
16
|
+
- Routes: `src/routes/**.tsx`; `_layout.tsx`, `[param]`, `_404.tsx`; page exports `load(…)`, `actions(…)`, `head`, `live`; page `data` is a value, layout `data()` / `params()` / `url()` are accessors; `export const live = true` makes page `data` an accessor updated in place (forms in drawers).
|
|
17
|
+
- Forms: `@rivetjs/forms` (`defineForm`, `createForm`, `onSubmit`, `FieldError`; server `action` / `invalid` from `@rivetjs/forms/server`).
|
|
18
|
+
- i18n: `t("key", { param })` from `@rivetjs/i18n`, compile-time; key a string literal.
|
|
19
|
+
- Icons: `<Icon icon={Check} />` from `@rivetjs/kit/icon` with lucide (`import { Check } from "lucide"`). Never inline SVG paths, never Unicode glyphs as icons.
|
|
20
|
+
- UI: `@rivetjs/ui/<component>` (styled compound parts `Select.Trigger`, `onPress`, two-way props take a signal); headless `@rivetjs/cdk/<module>`.
|
|
21
|
+
- After every change: `npm run check` (`rivet sync && rivet-check`) and fix every `RVnnnn` diagnostic; never edit `.rivet/` or `Generated … Do not edit` files.
|