Skip to content

Commit a460166

Browse files
committed
refactor(frontend): better gateway errors
1 parent 2e537d4 commit a460166

8 files changed

Lines changed: 1515 additions & 492 deletions

File tree

frontend/CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# Frontend
22

33
- When building new UI components, ship a Ladle story alongside the component (`*.stories.tsx` next to the source). Cover the meaningful states (empty, loading, error, success, edge cases) so the component can be reviewed and iterated on in isolation without booting the whole dashboard. Run with `pnpm dev:ladle` from `frontend/`. Existing example: [src/app/runner-pool-error-popover.stories.tsx](src/app/runner-pool-error-popover.stories.tsx).
4+
- HTTP responses can be mocked end-to-end in dev via MSW. Append `?mock=1` to any dashboard URL (dev only, gated by `import.meta.env.DEV` in [src/lib/agent-mocks.ts](src/lib/agent-mocks.ts)) to boot the worker. Then in DevTools / agent-browser console: `window.__rivetMock("*/actors/:id/kv/keys/*", { status: 503, body: { group: "guard", code: "service_unavailable", message: "..." } })`. Mocks persist across reloads via sessionStorage; `window.__rivetClearMocks()` resets. Use this to exercise error UIs without standing up real engine state. Prod bundle is unaffected (dynamic `import("msw/browser")` behind the dev gate).

frontend/package.json

Lines changed: 168 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -1,163 +1,169 @@
11
{
2-
"name": "@rivetkit/engine-frontend",
3-
"private": true,
4-
"version": "2.0.21",
5-
"type": "module",
6-
"scripts": {
7-
"dev": "vite",
8-
"check-types": "tsc --noEmit",
9-
"build": "NODE_OPTIONS='--max-old-space-size=8192' vite build --mode=production",
10-
"preview": "vite preview",
11-
"test": "vitest run",
12-
"test:watch": "vitest",
13-
"dev:ladle": "ladle dev",
14-
"build:ladle": "ladle build"
15-
},
16-
"dependencies": {
17-
"@codemirror/autocomplete": "^6.18.7",
18-
"@codemirror/commands": "^6.8.1",
19-
"@codemirror/lang-javascript": "^6.2.4",
20-
"@codemirror/lang-json": "^6.0.2",
21-
"@codemirror/lang-sql": "^6.8.0",
22-
"@codemirror/lint": "^6.8.5",
23-
"@codemirror/merge": "^6.10.2",
24-
"@codemirror/state": "^6.5.2",
25-
"@codemirror/view": "^6.38.2",
26-
"@date-fns/utc": "^1.2.0",
27-
"@fortawesome/fontawesome-svg-core": "^6.7.2",
28-
"@fortawesome/free-brands-svg-icons": "^6.7.2",
29-
"@fortawesome/free-solid-svg-icons": "^6.7.2",
30-
"@fortawesome/react-fontawesome": "^0.2.6",
31-
"@hookform/resolvers": "^5.2",
32-
"@ladle/react": "^5.1.1",
33-
"@marsidev/react-turnstile": "^1.5.0",
34-
"@microsoft/fetch-event-source": "^2.0.1",
35-
"@radix-ui/react-accordion": "^1.2.12",
36-
"@radix-ui/react-avatar": "^1.1.10",
37-
"@radix-ui/react-checkbox": "^1.3.3",
38-
"@radix-ui/react-collapsible": "^1.1.12",
39-
"@radix-ui/react-dialog": "^1.1.15",
40-
"@radix-ui/react-dropdown-menu": "^2.1.16",
41-
"@radix-ui/react-label": "^2.1.7",
42-
"@radix-ui/react-popover": "^1.1.15",
43-
"@radix-ui/react-progress": "^1.1.7",
44-
"@radix-ui/react-radio-group": "^1.3.8",
45-
"@radix-ui/react-scroll-area": "^1.2.10",
46-
"@radix-ui/react-select": "^2.2.6",
47-
"@radix-ui/react-separator": "^1.1.7",
48-
"@radix-ui/react-slider": "^1.3.6",
49-
"@radix-ui/react-slot": "^1.2.3",
50-
"@radix-ui/react-switch": "^1.2.6",
51-
"@radix-ui/react-tabs": "^1.1.13",
52-
"@radix-ui/react-toggle": "^1.1.10",
53-
"@radix-ui/react-toggle-group": "^1.1.11",
54-
"@radix-ui/react-tooltip": "^1.2.8",
55-
"@radix-ui/react-visually-hidden": "^1.2.3",
56-
"@rivet-gg/cloud": "*",
57-
"@rivet-gg/icons": "workspace:*",
58-
"@rivetkit/engine-api-full": "workspace:*",
59-
"@rivetkit/shared-data": "workspace:*",
60-
"@rivetkit/traces": "workspace:*",
61-
"@sentry/react": "^8.55.0",
62-
"@sentry/vite-plugin": "^2.23.1",
63-
"@shikijs/langs": "^3.12.2",
64-
"@shikijs/transformers": "^3.12.2",
65-
"@stepperize/react": "^5.1.8",
66-
"@tailwindcss/container-queries": "^0.1.1",
67-
"@tailwindcss/typography": "^0.5.16",
68-
"@tanstack/history": "^1.133.28",
69-
"@tanstack/pacer": "^0.21.0",
70-
"@tanstack/query-core": "^5.87.1",
71-
"@tanstack/react-hotkeys": "^0.3.0",
72-
"@tanstack/react-query": "^5.87.1",
73-
"@tanstack/react-query-devtools": "^5.87.3",
74-
"@tanstack/react-router": "^1.167.1",
75-
"@tanstack/react-router-devtools": "^1.166.8",
76-
"@tanstack/react-store": "^0.7.5",
77-
"@tanstack/react-table": "^8.21.3",
78-
"@tanstack/react-virtual": "^3.13.12",
79-
"@tanstack/router-devtools": "^1.166.8",
80-
"@tanstack/router-plugin": "^1.166.10",
81-
"@tanstack/store": "^0.7.5",
82-
"@tanstack/zod-adapter": "^1.131.36",
83-
"@types/bcryptjs": "^2.4.6",
84-
"@types/canvas-confetti": "^1.9.0",
85-
"@types/d3-array": "^3.2.1",
86-
"@types/escape-html": "^1.0.4",
87-
"@types/file-saver": "^2.0.7",
88-
"@types/lodash": "^4.17.20",
89-
"@types/mdx": "^2.0.13",
90-
"@types/node": "^20.19.13",
91-
"@types/react": "^19",
92-
"@types/react-dom": "^19",
93-
"@types/reconnectingwebsocket": "^1.0.10",
94-
"@uiw/codemirror-extensions-basic-setup": "^4.25.1",
95-
"@uiw/codemirror-theme-github": "^4.25.1",
96-
"@uiw/react-codemirror": "^4.25.1",
97-
"@visx/axis": "^3.12.0",
98-
"@visx/brush": "^3.12.0",
99-
"@visx/curve": "^3.12.0",
100-
"@visx/event": "^3.12.0",
101-
"@visx/grid": "^3.12.0",
102-
"@visx/group": "^3.12.0",
103-
"@visx/pattern": "^3.12.0",
104-
"@visx/responsive": "^3.12.0",
105-
"@visx/scale": "^3.12.0",
106-
"@visx/shape": "^3.12.0",
107-
"@visx/tooltip": "^3.12.0",
108-
"@vitejs/plugin-react": "^4.7.0",
109-
"@xyflow/react": "^12.10.0",
110-
"actor-core": "^0.6.3",
111-
"autoprefixer": "^10.4.21",
112-
"bcryptjs": "^2.4.3",
113-
"better-auth": "^1.5.6",
114-
"canvas-confetti": "^1.9.3",
115-
"cbor-x": "^1.6.0",
116-
"class-variance-authority": "^0.7.1",
117-
"clsx": "^2.1.1",
118-
"cmdk": "^1.1.1",
119-
"d3-array": "^3.2.4",
120-
"date-fns": "^4.1.0",
121-
"es-toolkit": "^1.45.1",
122-
"esast-util-from-js": "^2.0.1",
123-
"escape-html": "^1.0.3",
124-
"estree-util-to-js": "^2.0.0",
125-
"fast-deep-equal": "^3.1.3",
126-
"fast-json-patch": "^3.1.1",
127-
"favigo": "^1.1.0",
128-
"file-saver": "^2.0.5",
129-
"filesize": "^11.0.2",
130-
"framer-motion": "^11.18.2",
131-
"input-otp": "^1.4.2",
132-
"lodash": "^4.17.21",
133-
"postcss": "^8.5.6",
134-
"posthog-js": "^1.275.1",
135-
"react": "^19.1.1",
136-
"react-day-picker": "8.10.1",
137-
"react-dom": "^19.1.1",
138-
"react-error-boundary": "^6.0.3",
139-
"react-hook-form": "^7.62.0",
140-
"react-inspector": "^6.0.2",
141-
"react-resizable-panels": "^2.1.9",
142-
"recharts": "^2.15.4",
143-
"reconnectingwebsocket": "^1.0.0",
144-
"rivetkit": "workspace:*",
145-
"shiki": "^3.12.2",
146-
"sonner": "^1.7.4",
147-
"tailwind-merge": "^2.6.0",
148-
"tailwindcss": "^3.4.17",
149-
"tailwindcss-animate": "^1.0.7",
150-
"ts-pattern": "^5.8.0",
151-
"typescript": "^5.9.2",
152-
"typescript-plugin-css-modules": "^5.2.0",
153-
"unplugin-macros": "^0.18.3",
154-
"usehooks-ts": "^3.1.1",
155-
"vite": "^5.4.20",
156-
"vite-plugin-favicons-inject": "^2.2.0",
157-
"vite-tsconfig-paths": "^5.1.4",
158-
"zod": "^3.25.76"
159-
},
160-
"devDependencies": {
161-
"vitest": "^4.0.18"
162-
}
163-
}
2+
"name": "@rivetkit/engine-frontend",
3+
"private": true,
4+
"version": "2.0.21",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite",
8+
"check-types": "tsc --noEmit",
9+
"build": "NODE_OPTIONS='--max-old-space-size=8192' vite build --mode=production",
10+
"preview": "vite preview",
11+
"test": "vitest run",
12+
"test:watch": "vitest",
13+
"dev:ladle": "ladle dev",
14+
"build:ladle": "ladle build"
15+
},
16+
"dependencies": {
17+
"@codemirror/autocomplete": "^6.18.7",
18+
"@codemirror/commands": "^6.8.1",
19+
"@codemirror/lang-javascript": "^6.2.4",
20+
"@codemirror/lang-json": "^6.0.2",
21+
"@codemirror/lang-sql": "^6.8.0",
22+
"@codemirror/lint": "^6.8.5",
23+
"@codemirror/merge": "^6.10.2",
24+
"@codemirror/state": "^6.5.2",
25+
"@codemirror/view": "^6.38.2",
26+
"@date-fns/utc": "^1.2.0",
27+
"@fortawesome/fontawesome-svg-core": "^6.7.2",
28+
"@fortawesome/free-brands-svg-icons": "^6.7.2",
29+
"@fortawesome/free-solid-svg-icons": "^6.7.2",
30+
"@fortawesome/react-fontawesome": "^0.2.6",
31+
"@hookform/resolvers": "^5.2",
32+
"@ladle/react": "^5.1.1",
33+
"@marsidev/react-turnstile": "^1.5.0",
34+
"@microsoft/fetch-event-source": "^2.0.1",
35+
"@radix-ui/react-accordion": "^1.2.12",
36+
"@radix-ui/react-avatar": "^1.1.10",
37+
"@radix-ui/react-checkbox": "^1.3.3",
38+
"@radix-ui/react-collapsible": "^1.1.12",
39+
"@radix-ui/react-dialog": "^1.1.15",
40+
"@radix-ui/react-dropdown-menu": "^2.1.16",
41+
"@radix-ui/react-label": "^2.1.7",
42+
"@radix-ui/react-popover": "^1.1.15",
43+
"@radix-ui/react-progress": "^1.1.7",
44+
"@radix-ui/react-radio-group": "^1.3.8",
45+
"@radix-ui/react-scroll-area": "^1.2.10",
46+
"@radix-ui/react-select": "^2.2.6",
47+
"@radix-ui/react-separator": "^1.1.7",
48+
"@radix-ui/react-slider": "^1.3.6",
49+
"@radix-ui/react-slot": "^1.2.3",
50+
"@radix-ui/react-switch": "^1.2.6",
51+
"@radix-ui/react-tabs": "^1.1.13",
52+
"@radix-ui/react-toggle": "^1.1.10",
53+
"@radix-ui/react-toggle-group": "^1.1.11",
54+
"@radix-ui/react-tooltip": "^1.2.8",
55+
"@radix-ui/react-visually-hidden": "^1.2.3",
56+
"@rivet-gg/cloud": "*",
57+
"@rivet-gg/icons": "workspace:*",
58+
"@rivetkit/engine-api-full": "workspace:*",
59+
"@rivetkit/shared-data": "workspace:*",
60+
"@rivetkit/traces": "workspace:*",
61+
"@sentry/react": "^8.55.0",
62+
"@sentry/vite-plugin": "^2.23.1",
63+
"@shikijs/langs": "^3.12.2",
64+
"@shikijs/transformers": "^3.12.2",
65+
"@stepperize/react": "^5.1.8",
66+
"@tailwindcss/container-queries": "^0.1.1",
67+
"@tailwindcss/typography": "^0.5.16",
68+
"@tanstack/history": "^1.133.28",
69+
"@tanstack/pacer": "^0.21.0",
70+
"@tanstack/query-core": "^5.87.1",
71+
"@tanstack/react-hotkeys": "^0.3.0",
72+
"@tanstack/react-query": "^5.87.1",
73+
"@tanstack/react-query-devtools": "^5.87.3",
74+
"@tanstack/react-router": "^1.167.1",
75+
"@tanstack/react-router-devtools": "^1.166.8",
76+
"@tanstack/react-store": "^0.7.5",
77+
"@tanstack/react-table": "^8.21.3",
78+
"@tanstack/react-virtual": "^3.13.12",
79+
"@tanstack/router-devtools": "^1.166.8",
80+
"@tanstack/router-plugin": "^1.166.10",
81+
"@tanstack/store": "^0.7.5",
82+
"@tanstack/zod-adapter": "^1.131.36",
83+
"@types/bcryptjs": "^2.4.6",
84+
"@types/canvas-confetti": "^1.9.0",
85+
"@types/d3-array": "^3.2.1",
86+
"@types/escape-html": "^1.0.4",
87+
"@types/file-saver": "^2.0.7",
88+
"@types/lodash": "^4.17.20",
89+
"@types/mdx": "^2.0.13",
90+
"@types/node": "^20.19.13",
91+
"@types/react": "^19",
92+
"@types/react-dom": "^19",
93+
"@types/reconnectingwebsocket": "^1.0.10",
94+
"@uiw/codemirror-extensions-basic-setup": "^4.25.1",
95+
"@uiw/codemirror-theme-github": "^4.25.1",
96+
"@uiw/react-codemirror": "^4.25.1",
97+
"@visx/axis": "^3.12.0",
98+
"@visx/brush": "^3.12.0",
99+
"@visx/curve": "^3.12.0",
100+
"@visx/event": "^3.12.0",
101+
"@visx/grid": "^3.12.0",
102+
"@visx/group": "^3.12.0",
103+
"@visx/pattern": "^3.12.0",
104+
"@visx/responsive": "^3.12.0",
105+
"@visx/scale": "^3.12.0",
106+
"@visx/shape": "^3.12.0",
107+
"@visx/tooltip": "^3.12.0",
108+
"@vitejs/plugin-react": "^4.7.0",
109+
"@xyflow/react": "^12.10.0",
110+
"actor-core": "^0.6.3",
111+
"autoprefixer": "^10.4.21",
112+
"bcryptjs": "^2.4.3",
113+
"better-auth": "^1.5.6",
114+
"canvas-confetti": "^1.9.3",
115+
"cbor-x": "^1.6.0",
116+
"class-variance-authority": "^0.7.1",
117+
"clsx": "^2.1.1",
118+
"cmdk": "^1.1.1",
119+
"d3-array": "^3.2.4",
120+
"date-fns": "^4.1.0",
121+
"es-toolkit": "^1.45.1",
122+
"esast-util-from-js": "^2.0.1",
123+
"escape-html": "^1.0.3",
124+
"estree-util-to-js": "^2.0.0",
125+
"fast-deep-equal": "^3.1.3",
126+
"fast-json-patch": "^3.1.1",
127+
"favigo": "^1.1.0",
128+
"file-saver": "^2.0.5",
129+
"filesize": "^11.0.2",
130+
"framer-motion": "^11.18.2",
131+
"input-otp": "^1.4.2",
132+
"lodash": "^4.17.21",
133+
"postcss": "^8.5.6",
134+
"posthog-js": "^1.275.1",
135+
"react": "^19.1.1",
136+
"react-day-picker": "8.10.1",
137+
"react-dom": "^19.1.1",
138+
"react-error-boundary": "^6.0.3",
139+
"react-hook-form": "^7.62.0",
140+
"react-inspector": "^6.0.2",
141+
"react-resizable-panels": "^2.1.9",
142+
"recharts": "^2.15.4",
143+
"reconnectingwebsocket": "^1.0.0",
144+
"rivetkit": "workspace:*",
145+
"shiki": "^3.12.2",
146+
"sonner": "^1.7.4",
147+
"tailwind-merge": "^2.6.0",
148+
"tailwindcss": "^3.4.17",
149+
"tailwindcss-animate": "^1.0.7",
150+
"ts-pattern": "^5.8.0",
151+
"typescript": "^5.9.2",
152+
"typescript-plugin-css-modules": "^5.2.0",
153+
"unplugin-macros": "^0.18.3",
154+
"usehooks-ts": "^3.1.1",
155+
"vite": "^5.4.20",
156+
"vite-plugin-favicons-inject": "^2.2.0",
157+
"vite-tsconfig-paths": "^5.1.4",
158+
"zod": "^3.25.76"
159+
},
160+
"devDependencies": {
161+
"msw": "^2.14.4",
162+
"vitest": "^4.0.18"
163+
},
164+
"msw": {
165+
"workerDirectory": [
166+
"public"
167+
]
168+
}
169+
}

0 commit comments

Comments
 (0)