Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
230 commits
Select commit Hold shift + click to select a range
0fa5591
adding react things
remorses Feb 9, 2025
420227a
adding js extension
remorses Feb 9, 2025
f949eca
fix tsc errors
remorses Feb 9, 2025
50edca0
making vite plugin
remorses Feb 9, 2025
e4b82f1
it works, vite optimize deps thing is awful, added util in exclude or…
remorses Feb 9, 2025
76698ad
nn
remorses Feb 9, 2025
2dc1480
spiceflow works, removed noExternal because commonjs does not work th…
remorses Feb 9, 2025
c9b94b6
kind of works, adding example app in react and react method
remorses Feb 9, 2025
fc86f44
fix, use parcel rsc-html-stream
remorses Feb 9, 2025
66808b9
adding e2e tests
remorses Feb 9, 2025
2c593ca
fix e2e
remorses Feb 9, 2025
5a43d58
adding prettier, fixing tests
remorses Feb 9, 2025
6c39c92
fix tests because of deleted config
remorses Feb 9, 2025
e544c99
nn
remorses Feb 9, 2025
762cc46
redirect works on top level
remorses Feb 9, 2025
879ed71
vendored medley router
remorses Feb 9, 2025
5863664
vendoring router, better types refactoring, only one InternalRoute,
remorses Feb 9, 2025
3f28d55
vendoring router, testing * does not do anything weird
remorses Feb 9, 2025
7355268
adding layouts support, api part still works
remorses Feb 9, 2025
8f5cb42
adding id to the router
remorses Feb 9, 2025
7204e9c
adding hono trie router
remorses Feb 9, 2025
11c0461
using hono router
remorses Feb 9, 2025
869ca83
adding more hono router, strugglying with *
remorses Feb 9, 2025
01f3d9e
trying to make getAllDecodedParams work
remorses Feb 9, 2025
55ea8fb
fix * handling for a case, another one is todo
remorses Feb 9, 2025
90adb97
fixed * somehow
remorses Feb 9, 2025
561c281
fixed extractWildcardParam, tests were inverted
remorses Feb 9, 2025
0b27f8c
remove logs
remorses Feb 9, 2025
d3d98dc
it works, managed to make the vite plugin work, fixed the issue where…
remorses Feb 10, 2025
5a26a90
build kind of works too
remorses Feb 10, 2025
d24a928
trying better generateId, still does not work
remorses Feb 10, 2025
2f9da19
fix redirect thing
remorses Feb 10, 2025
c1c3445
layouts seem to work too
remorses Feb 10, 2025
6bf8bf1
more layouts
remorses Feb 10, 2025
d70da5e
tried links too
remorses Feb 10, 2025
75f3443
tailwindcss works
remorses Feb 10, 2025
df79c24
fix build time css, debugging missing server references
remorses Feb 10, 2025
76a569e
fix missing server references from client components in build
remorses Feb 10, 2025
1e57519
fix css during build, need to copy them, thanks to preserveEntrySigna…
remorses Feb 10, 2025
41db076
use routeSorter to make sure static routes have priority
remorses Feb 10, 2025
bffac7d
checking what happens on errors
remorses Feb 10, 2025
e75204f
run prettier
remorses Feb 10, 2025
5815178
put rsc entry inside spiceflow
remorses Feb 10, 2025
c74c6af
fix tsc errors
remorses Feb 10, 2025
7cdecea
adding a bit of error handling in ssr and client
remorses Feb 10, 2025
c08e768
using react-dom/server.edge fixes hanging on error
remorses Feb 10, 2025
3d5d5ed
add css in error page
remorses Feb 10, 2025
ff956c0
made link component, tested client navigations, back buttons waits wh…
remorses Feb 11, 2025
4f9e4c0
fix hmr from server, tested suspense in rsc
remorses Feb 11, 2025
692e631
added how-is-this-not-illegal, even simpler
remorses Feb 11, 2025
981aaa2
added pokemon view, works well
remorses Feb 11, 2025
54ffe26
added progress component
remorses Feb 11, 2025
594cb63
payload is always a promise, this way navigations state does not trig…
remorses Feb 11, 2025
106e812
fix support for redirect, fix hot module replacement for client impor…
remorses Feb 11, 2025
0253795
all redirect tests pass
remorses Feb 11, 2025
8331a41
separating hooks from components
remorses Feb 11, 2025
95ee6c0
managed to catch errors in rsc, cool, fix page ordering with :id
remorses Feb 11, 2025
f2cc826
added not found function
remorses Feb 11, 2025
447ac5b
refactored renderReact
remorses Feb 11, 2025
77d8157
adding middleware support for react too, works pretty well, hope perf…
remorses Feb 11, 2025
312a69b
fix validation errors, forgot to change request in context
remorses Feb 11, 2025
eec8ad6
not found
remorses Feb 11, 2025
c346438
show error overlay on rsc errors
remorses Feb 12, 2025
8d07987
tested errors in useEffect
remorses Feb 12, 2025
5c1e69e
use @jacob-ebey/react-server-dom-vite directly because of pnpm bug, a…
remorses Feb 12, 2025
47716d0
tried out using hmr true
remorses Feb 12, 2025
637ea5c
use .rsc to support prerendering in cdn
remorses Feb 12, 2025
5a5fa6e
fixed progress bar, stop on data set, which means transition ended
remorses Feb 12, 2025
7467b27
added prerender feature
remorses Feb 12, 2025
db0018c
adding meta component, vendoring rsc stream
remorses Feb 12, 2025
135767a
transform stream works,
remorses Feb 12, 2025
aec5a0b
add support for relative urls in meta
remorses Feb 12, 2025
57765fc
fix meta, head, also adding server launcher support
remorses Feb 12, 2025
6c1d25f
put first arg of context first, so it is easier to use
remorses Feb 12, 2025
6f6dfe3
fix css, adding prerender example with generate stacic segments
remorses Feb 12, 2025
afe340f
write node.js to run a node server
remorses Feb 12, 2025
fbc1731
adding more abort signals
remorses Feb 12, 2025
f0793bc
renamed references files
remorses Feb 12, 2025
29aa1e3
fix static generated pages
remorses Feb 12, 2025
29aad7a
fix rsc prerender
remorses Feb 12, 2025
dae438f
got actions errors working
remorses Feb 12, 2025
39b9849
testing form actions
remorses Feb 14, 2025
1536fa3
handle errors in passthrough
remorses Feb 17, 2025
cc1259a
handle error in ssr entry
remorses Feb 17, 2025
ae43a13
made a prerelease
remorses Feb 17, 2025
3d16eb8
merge main into rsc branch
remorses Mar 1, 2026
a64a400
migrate RSC from custom implementation to @vitejs/plugin-rsc
remorses Mar 1, 2026
61ac4fc
clean up post-migration RSC leftovers and harden runtime behavior
remorses Mar 1, 2026
c5592b5
fix stale location: use getter to always return current history.location
remorses Mar 1, 2026
4b199da
Update vite.tsx
remorses Mar 1, 2026
0df73fd
add @vitejs/plugin-rsc skill: comprehensive framework author guide
remorses Mar 2, 2026
7c0211d
fix: clean up RSC merge — remove duplicated code, fix bugs, re-enable…
remorses Mar 2, 2026
27db83e
expand vite-plugin-rsc skill with React Router RSC patterns
remorses Mar 2, 2026
330bb1e
docs: add RSC alignment plan — gaps between spiceflow and @vitejs/plu…
remorses Mar 2, 2026
e93e913
chore: commit remaining workspace updates from other agents
remorses Mar 2, 2026
46e2f25
feat: RSC alignment — CSRF protection, __NO_HYDRATE error fallback, t…
remorses Mar 2, 2026
20763c2
test: add e2e tests for SSR error fallback and CSRF, fix HMR test loc…
remorses Mar 2, 2026
6897040
docs: expand Vite RSC skill HMR section with module caching internals
remorses Mar 2, 2026
c66bf36
docs: add React framework (RSC) section to README
remorses Mar 2, 2026
a86467a
test: add serverRenderCount counter and verify client HMR doesn't tri…
remorses Mar 2, 2026
101c867
test: streaming async generator from server to client component
remorses Mar 2, 2026
c644d27
test: add e2e tests for status codes (sync redirect 307, not-found 404)
remorses Mar 3, 2026
375dce6
migrate importRscEntry from loadModule to import.meta.viteRsc.import
remorses Mar 3, 2026
4e7d8f9
add bundler adapter layer to decouple RSC entry points from Vite
remorses Mar 6, 2026
c11fdb9
test: add e2e tests for CSS loading (tailwind, server component, clie…
remorses Mar 6, 2026
a2094d2
migrate CSS from custom virtual:app-styles to @vitejs/plugin-rsc nati…
remorses Mar 6, 2026
ef41bee
docs: add CSS migration plan (rscCssTransform)
remorses Mar 6, 2026
2d729e9
docs: update multi-bundler plan Phase 3 with actual Bun Bake APIs
remorses Mar 6, 2026
184f3b9
Merge branch 'main' of https://github.com/remorses/spiceflow into rsc…
remorses Mar 9, 2026
8d2e739
fix router specificity and wildcard params in spiceflow
remorses Mar 9, 2026
5d73e20
docs: update changeset authoring guidance
remorses Mar 12, 2026
f2c1788
Update package.json
remorses Mar 12, 2026
f0fd799
merge main: HEAD method handling, cors HEAD fix, middleware body cach…
remorses Mar 14, 2026
73712f6
Update Vite 8 compatibility and integration coverage
remorses Mar 13, 2026
ce787a3
add /vite in exports
remorses Mar 13, 2026
7941760
Update vite.config.ts
remorses Mar 13, 2026
68fc2cf
fix: strip .rsc suffix from request path before route matching
remorses Mar 13, 2026
e5c3e63
update example apps: replace @vercel/postgres with postgres, fix vite…
remorses Mar 13, 2026
f6ae55d
updates
remorses Mar 13, 2026
36c8fe0
add ProgressBar to how-is-this-not-illegal example
remorses Mar 14, 2026
6b88b34
add e2e test: layout client components are not remounted during navig…
remorses Mar 14, 2026
f599140
add /react export
remorses Mar 14, 2026
5210e9f
release: spiceflow@1.18.0-rsc.3
remorses Mar 14, 2026
01d5c42
export router singleton from spiceflow/react
remorses Mar 14, 2026
63b678e
fix Head metadata override rules in SSR
remorses Mar 14, 2026
1824521
add ScrollRestoration component for RSC framework
remorses Mar 14, 2026
dad5bc4
harden scroll restoration state and isolate e2e ports
remorses Mar 14, 2026
a88e77e
avoid router event wiring during SSR
remorses Mar 14, 2026
6ff53d5
Protect stale RSC navigations across deployments
remorses Mar 14, 2026
45572b4
Document public RSC imports and refresh React framework docs
remorses Mar 14, 2026
d0bc3b5
refactor deployment ID to use build timestamp via virtual module
remorses Mar 14, 2026
3ff12b1
Update pnpm-lock.yaml
remorses Mar 14, 2026
d236457
fix: restore HEAD method fallback and shouldStripHeadBody logic
remorses Mar 14, 2026
1fcd879
port main runtime fixes: HEAD body stripping, request body caching, q…
remorses Mar 14, 2026
848cf34
update param prefix tests to document actual trie router behavior (404)
remorses Mar 14, 2026
1e65c69
refactor: improve path parameter type inference for optional and wild…
remorses Mar 14, 2026
9913cd2
port main runtime fixes: HEAD body stripping, request body caching, q…
remorses Mar 14, 2026
b0e0107
refactor: remove Node.js launcher, use export const app + .listen()
remorses Mar 14, 2026
c8cad19
remove placeholder todo tests from 2024
remorses Mar 14, 2026
a2ed7f4
Merge branch 'rsc-merge-main' of https://github.com/remorses/spiceflo…
remorses Mar 14, 2026
870c63a
feat: add safePath support for .page() and .staticPage() routes, fix …
remorses Mar 15, 2026
afdf552
feat: add object-style .page() and .staticPage() with query schema su…
remorses Mar 15, 2026
87e6ee1
docs: update README with object-style .page() query schema and safePa…
remorses Mar 15, 2026
74a754c
feat: replace Vite-specific import.meta.env checks with conditional p…
remorses Mar 15, 2026
5fc11fa
feat: add cloudflare-example — Spiceflow RSC on Cloudflare Workers wi…
remorses Mar 15, 2026
fbab4d7
fix: restore state in client Config and fix index route type mapping
remorses Mar 15, 2026
68ae2ba
suppress IMPORT_IS_UNDEFINED warning for virtual:app-entry
remorses Mar 15, 2026
98a645c
add ./cloudflare-entrypoint
remorses Mar 15, 2026
903b316
fix static fallback priority and directory handling
remorses Mar 15, 2026
b534f0b
docs explain static middleware priority
remorses Mar 15, 2026
a56f88f
export serve static
remorses Mar 15, 2026
46398d9
update example
remorses Mar 15, 2026
4c7e3c5
fix example
remorses Mar 15, 2026
7748d61
docs add static middleware to react examples
remorses Mar 15, 2026
478bff2
Clean up local agent guidance and remove obsolete Claude scaffolding
remorses Mar 15, 2026
f871c00
Fix Cloudflare RSC worker builds and add automated example validation
remorses Mar 15, 2026
4606766
Update vite.config.ts
remorses Mar 15, 2026
14e6455
Make app.handle the top-level RSC bridge again
remorses Mar 15, 2026
d6d1361
Fix Node static serving for built client assets
remorses Mar 15, 2026
1304a4f
Expand static middleware coverage with Hono-style edge cases
remorses Mar 15, 2026
4251e7e
Document Cloudflare RSC setup in the README
remorses Mar 15, 2026
8fa759a
Rename example-react to integration-tests and how-is-this-not-illegal…
remorses Mar 15, 2026
b9bce52
Remove handle-listen conditional export, inline listen() logic
remorses Mar 15, 2026
d86527a
release: spiceflow@1.18.0-rsc.4
remorses Mar 15, 2026
6e69aa9
Update README.md
remorses Mar 15, 2026
de7bcf3
fix: exclude spiceflow from client optimizeDeps to prevent duplicate …
remorses Mar 15, 2026
94b39cc
release: spiceflow@1.18.0-rsc.5
remorses Mar 15, 2026
2caed9c
fix: skip listen() in Vite dev mode — Vite owns the server
remorses Mar 15, 2026
7a94cba
release: spiceflow@1.18.0-rsc.6
remorses Mar 15, 2026
3b815eb
feat: render React 404 page for browser requests hitting unmatched ro…
remorses Mar 15, 2026
8a190d9
fix: strengthen browser detection for React 404 page
remorses Mar 15, 2026
ac22e67
test: add integration tests for throw redirect/notFound in pages and …
remorses Mar 15, 2026
a9b5de4
test: add nested layout child route tests, URL assertions for notFoun…
remorses Mar 15, 2026
ed9141a
Update .gitignore
remorses Mar 15, 2026
809b443
fix: define process.env.NODE_ENV as production in vite builds
remorses Mar 15, 2026
785f9c0
perf: add lazy stat result cache to serveStatic middleware
remorses Mar 15, 2026
7e8b306
perf: single Flight deserialization and faster chunk flushing
remorses Mar 15, 2026
8ce18df
add benchmark suite to nodejs-example
remorses Mar 15, 2026
6959e80
add experimental-fast-webstreams dependency (unused for now)
remorses Mar 15, 2026
3630125
add --bun flag to benchmark script with cpu-prof support
remorses Mar 15, 2026
d0156bb
add Next.js baseline to benchmark suite
remorses Mar 16, 2026
192c517
refactor redirect/notFound to throw Response objects and export from …
remorses Mar 16, 2026
349c74e
fix flaky client component CSS e2e test in dev mode
remorses Mar 16, 2026
c39ac76
add redirect and notFound documentation to README
remorses Mar 16, 2026
fc52c04
add redirect benchmark route to all servers
remorses Mar 16, 2026
ad7bec5
use process.env.NODE_ENV if possible
remorses Mar 16, 2026
e9b6230
remove spiceflowCloudflareViteConfig helper, inline config at call sites
remorses Mar 16, 2026
6015851
auto-inject cloudflare SSR outDir in spiceflow plugin
remorses Mar 16, 2026
4bda55d
migrate website to spiceflow
remorses Mar 16, 2026
083f6e9
fix: throw redirect() inside page handler returns 307 instead of 200
remorses Mar 16, 2026
e45a533
Update pnpm-lock.yaml
remorses Mar 16, 2026
31f59bf
fix: API routes take priority over layout-only React route matches
remorses Mar 16, 2026
865ea3f
feat: rewrite cryptic RSC errors for client-only React APIs into acti…
remorses Mar 16, 2026
9e41f63
fix: SSR client reference preloads + wire formatServerError into SSR …
remorses Mar 16, 2026
f1a2edd
fix: restore SSR client-reference preload hints
remorses Mar 16, 2026
70d747e
fix: harden SSR redirect race — abort guard, timer cleanup, error pri…
remorses Mar 16, 2026
32fb124
test: add e2e test for RSC client-only API error messages + fix creat…
remorses Mar 16, 2026
fa002e5
release: spiceflow@1.18.0-rsc.7
remorses Mar 16, 2026
707fb78
perf: reduce RSC SSR decode and stream overhead
remorses Mar 16, 2026
b42ea4c
fix: cloudflare-example test failures — strip ANSI codes from server …
remorses Mar 16, 2026
032579e
test: tighten e2e feedback loops and align start-mode naming
remorses Mar 16, 2026
56417df
docs: add redirect() and notFound() documentation to README
remorses Mar 16, 2026
304c8a5
fix: escape full flight script content including prefix and suffix
remorses Mar 16, 2026
21fc8d9
perf: reduce e2e test sleep durations from ~4s to ~120ms total
remorses Mar 16, 2026
b37047e
fix: add 5s timeout to fetch in waitForReady to prevent CI hangs
remorses Mar 16, 2026
8ca8082
fix: increase waitForReady timeout to 90s for CI
remorses Mar 16, 2026
eadc85e
fix: wait for dep optimization to settle before fetching in dev test
remorses Mar 16, 2026
4099167
fix: pre-bundle deps to prevent dual React crash in Cloudflare dev
remorses Mar 16, 2026
9594bc3
website: remove code block padding/border, fix alignment, add system …
remorses Mar 16, 2026
af3f3bb
fix: mitigate Cloudflare Workers hung request error during HMR
remorses Mar 16, 2026
dbb4b9d
fix: stop collapsing code block lines by preserving translateY
remorses Mar 16, 2026
d6c93f9
website: serif headings, larger font sizes, tighter code spacing, nar…
remorses Mar 16, 2026
b4a94a2
website: tighten vertical spacing, reduce page padding, update tagline
remorses Mar 16, 2026
48f2dc5
deprecate old client
remorses Mar 16, 2026
d4d16ab
use safeFetch for client examples
remorses Mar 16, 2026
4143d1b
fix: replace eager start() loop with pull()-based backpressure in SSE…
remorses Mar 17, 2026
59b3a2a
fix: use per-URL abort controllers to prevent RSC and non-RSC request…
remorses Mar 17, 2026
7e5f43d
refactor: extract HMR tests into dedicated hmr.test.ts and disable pa…
remorses Mar 17, 2026
85b1f48
improve node adapter: backpressure, set-cookie, rawHeaders, pipeline
remorses Mar 17, 2026
7c6e261
fix: prevent @tailwindcss/vite from triggering full page reload durin…
remorses Mar 17, 2026
2df09b4
feat: auto-configure optimizeDeps.entries and include per Vite enviro…
remorses Mar 17, 2026
cafa49d
release: spiceflow@1.18.0-rsc.8
remorses Mar 17, 2026
76b1dfa
remove bundler-adapter abstraction layer, import directly from @vitej…
remorses Mar 17, 2026
4fa96f4
nn
remorses Mar 17, 2026
d54e8d4
clean up spiceflow dependencies: remove unused packages, move react a…
remorses Mar 17, 2026
093448b
decouple index entry from @vitejs/plugin-rsc via conditional #rsc-run…
remorses Mar 17, 2026
a82d053
vendor @standard-schema/spec and copy-anything to remove external dep…
remorses Mar 17, 2026
ae3624d
inline rsc-html-stream/client, remove dependency
remorses Mar 17, 2026
6e1a638
run check-entry during build, document bundleability guard in AGENTS.md
remorses Mar 17, 2026
842a325
optimize flight binary base64 encoding in SSR transform
remorses Mar 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,315 changes: 1,315 additions & 0 deletions .agents/skills/vite-plugin-rsc/SKILL.md

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"mode": "pre",
"tag": "rsc",
"initialVersions": {
"openapi-schema-diff": "0.0.1",
"spiceflow": "1.6.1",
"nodejs-example": "0.1.0"
},
"changesets": [
"five-toes-learn"
]
}
5 changes: 0 additions & 5 deletions .changeset/sour-breads-matter.md

This file was deleted.

37 changes: 0 additions & 37 deletions .github/workflows/claude.yml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ debug
.last-run.json
.react-router
opensrc
/di
tmp
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
[submodule "openapi-schema-diff"]
path = openapi-schema-diff
url = https://github.com/remorses/openapi-schema-diff.git
140 changes: 132 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@

# package manager: pnpm with workspace

This project uses pnpm workspaces to manage dependencies. Important scripts are in the root package.json or various packages package.json

try to run commands inside the package folder that you are working on. for example you should never run `pnpm test` from the root


# typescript

Try to use object arguments for new typescript functions if the function would accept more than one argument, this way you can use the object as a sort of named argument feature, where order of arguments does not matter and it's easier to discover parameters.

Always run `pnpm tsc --noEmit` from the package you changed after code edits, and fix any reported issues before finishing.

do not add useless comments if the code is self descriptive. only add comments if requested or if this was a change that i asked for, meaning it is not obvious code and needs some inline documentation.

try to use early returns and breaks, try nesting code as little as possible, follow the go best practice of if statements: avoid else, nest as little as possible, use top level ifs. minimize nesting.


# testing

Use vitest to run tests. Tests should be run from the current package directory and not root, try using the test script instead of vitest directly. Additional vitest flags can be added at the end, like --run to disable watch mode or -u to update snapshots.
Expand All @@ -29,6 +28,112 @@ Sometimes tests work directly on database data, using prisma. To run these tests

Never write tests yourself that call prisma or interact with database or emails. For these asks the user to write them for you.

# e2e testing (integration-tests)

E2e tests live in `integration-tests/e2e/` and use Playwright (chromium only). The dev server starts automatically via the `webServer` config in `playwright.config.ts`.

## running e2e tests

These are the integration test commands for the RSC app in `integration-tests/`:

- `pnpm test-e2e` runs the Playwright suite against the dev server, so it covers dev-only behavior like HMR and middleware behavior during development.
- `pnpm test-e2e-start` runs the same Playwright suite against the production start server, so it catches build-only regressions that do not show up in dev.
- Run both commands when validating an integration change, because they exercise different environments and one passing does not imply the other passes.

```bash
# run from integration-tests directory, never from root
cd integration-tests

# run all e2e tests
pnpm test-e2e

# filter by test name
pnpm test-e2e --grep "SSR error"

# run against production build
pnpm test-e2e-start
```

Tests tagged `@dev` are skipped during start runs; tests tagged `@build` are skipped during dev runs (controlled by `grepInvert` in `integration-tests/playwright.config.ts`).

## rebuild dist before testing

The Vite SSR middleware imports from `spiceflow/dist/` (the compiled package), NOT from source. If you modify files in `spiceflow/src/`, you must rebuild before e2e tests will pick up the changes:

```bash
cd spiceflow
pnpm tsc --noCheck # --noCheck skips pre-existing type errors
```

This is the most common reason e2e tests fail after code changes — stale dist files.

## writing e2e tests

- The base URL and port are defined at the top of `basic.test.ts`:
```ts
const port = Number(process.env.E2E_PORT || 6174)
const baseURL = `http://localhost:${port}`
```
- Use `page.goto("/path")` for browser-based tests that need rendering, JS execution, or DOM interaction.
- Use Node.js `fetch(baseURL + "/path")` directly (not `page.evaluate`) when you need to control HTTP headers like `Origin` — browsers restrict forbidden headers.
- Use `page.getByTestId()`, `page.getByText()`, `page.getByRole()` for locators. Prefer test-ids for stability.
- When a `data-testid` matches multiple elements (e.g. multiple counter components on a page), use `.filter({ hasText: "..." })` to disambiguate:
```ts
const clientCounter = page
.getByTestId('client-counter')
.filter({ hasText: 'Client counter' })
await clientCounter.getByRole('button', { name: '+' }).click()
```
- If a locator's text changes during the test (e.g. HMR edits), do NOT use it through a pre-filtered variable — query the page directly for the new text.

## adding test routes

To add a route for e2e testing, add it in `integration-tests/src/main.tsx` using the spiceflow API:

```ts
.page("/my-test-route", async () => {
return <MyComponent />;
})
```

Client components used in tests should be created in `integration-tests/src/app/` with a `"use client"` directive.

## HMR tests

- `createEditor("src/app/file.tsx")` from `e2e/helper.ts` edits a file and auto-reverts on dispose.
- Always call `file[Symbol.dispose]()` or use `try/finally` to restore files after edits.
- When editing files, make sure the `replace()` string actually exists in the source. For example, `client.tsx` has `name = "Client"` as a default prop — the literal string "Client counter" does NOT exist in the file, so `replace("Client counter", ...)` would be a no-op and the HMR test would silently fail.
- **Client HMR preserves state**: editing a client component triggers React Fast Refresh without a server re-render. Client state is preserved. Vite's SSR environment logs `page reload` internally but the browser does not actually reload — Fast Refresh handles it.
- **Server HMR preserves server state**: editing a server component triggers RSC HMR. Server-side state (e.g. counters stored in module scope) is preserved. Client state is NOT preserved — `router.refresh()` re-fetches the full RSC payload, and React reconciliation remounts client components with fresh state.
- The home page has a `serverRenderCount` counter (`data-testid="server-render-count"`) that increments on each RSC render. Use it in tests to verify whether a server re-render happened.
- To detect full page reloads in tests, set a window sentinel before the edit and check it after: `await page.evaluate((s) => { window.__hmrSentinel = s }, sentinel)` — if the sentinel is gone after the edit, a full reload happened.

## debugging unwanted full page reloads in vite

When HMR triggers a full page reload instead of a hot update, the cause is a `{type:"full-reload"}` WebSocket message sent to the browser. To find who sends it, patch `hot.send` on every Vite environment with `console.trace` in a temporary plugin:

```ts
{
name: 'debug-full-reload',
configureServer(server) {
for (const envName of Object.keys(server.environments)) {
const env = server.environments[envName]
const origSend = env.hot.send.bind(env.hot)
env.hot.send = function (...args) {
if (args[0]?.type === 'full-reload') {
console.trace(`[full-reload] env=${envName} payload=${JSON.stringify(args[0])}`)
}
return origSend(...args)
}
}
},
},
```

The stack trace reveals exactly which plugin and hook is responsible. Common culprits:
- `@tailwindcss/vite` hotUpdate sending bare `{type:"full-reload"}` for server-only files it scans for class names
- Vite's dep optimizer (`runOptimizer` → `fullReload`) when deps change — usually harmless, triggers once
- `updateModules` in Vite core when `propagateUpdate` hits a dead end (no HMR boundary found)

# website

Expand Down Expand Up @@ -58,25 +163,44 @@ For example if the current file is `src/routes/home.tsx` you can import `import

always use tailwind for styling, prefer using simple styles using flex and gap. Try to use the built in tailwind colors like gray, red, green, etc. Margins should be avoided, instead use flexbox gaps, grid gaps, or separate spacing divs.

## spiceflow/react exports

All React-facing APIs (components, router, utilities) must be exported from `spiceflow/react` (i.e. `spiceflow/src/react/index.ts`). Never import from `spiceflow/dist/react/...` directly — that's an internal path that breaks when the build output changes. If something is meant for users (like `Head`, `Link`, `ProgressBar`, `router`), it must be in the public export.

## files

always use kebab case for new filenames. never use uppercase letters in filenames

## changesets

after you make a change that is noteworthy, add a changeset. these will be used later on to create a changelog for the package. use `pnpm changeset add --empty` to create a changeset file in `.changeset` folder, then write there the changes you made in a single concise paragraph. never run other changeset commands, like `pnpm changeset version` or `pnpm changeset publish`. Notice that sometimes the cwd is missing `.changeset` folder, in that case check the parents directories.
after you make a change that is noteworthy, add a changeset manually as a markdown file inside the `.changeset` folder. these files are used later on to create the changelog for the package. if the current cwd does not have a `.changeset` folder, check parent directories.

NEVER make breaking changes changesets. our releases are close enough in time that you should never do breaking changes, even if we do one you have nothing to worry about because it's probably a publish so close in time that on one will ever use the current version.

Only add changesets for packages that are not marked as `private` in their `package.json` and have a `version` in the package.json.

Changeset files are structured like this:
Changeset files should be plain `.md` files with this structure:

```md
---
'package-name': patch # can also be `minor` or `major`, never use major
'package-name': patch # can also be `minor`, never use `major`
---

markdown describing the changes you made, in present tense, like "add support for X" or "fix bug with Y". Be detailed but concise, and never use bullet points or lists. Always show example code snippets if applicable, and use proper markdown formatting.

markdown describing the changes you made, in present tense, like "add support for X" or "fix bug with Y". write a single concise paragraph, not bullet points or lists. include example code snippets if useful, and use proper markdown formatting.
```

## check-entry (bundleability guard)

`pnpm check-entry` in the spiceflow package bundles `src/index.ts` with esbuild using zero externals. It runs automatically during `pnpm build`. This validates that `import { Spiceflow } from 'spiceflow'` works for users who are NOT using the React/RSC features and bundle with esbuild, webpack, or similar — without needing to externalize anything.

If this check fails, it means a Vite-only dependency (like `@vitejs/plugin-rsc`) leaked into the main import path. RSC-only imports must go through the `#rsc-runtime` subpath import (defined in package.json `imports` field) which uses the `react-server` condition to resolve to the real implementation in Vite RSC environments and to an empty fallback everywhere else.

## vite-rsc

the spiceflow vite plugin depends on vite-rsc plugin. you can read its source code with `opensrc vitejs/vite-plugin-react`. inside folder packages/plugin-rsc`. there are also examples there. inside examples folder

we also try to work well with the cloudflare vite plugin. the source code of that is in `https://github.com/cloudflare/workers-sdk/blob/main/packages/vite-plugin-cloudflare`

we have an example `cloudflare-example` that we can use to make sure pnpm dev, build, preview and deployment work well.

Waku (`opensrc dai-shi/waku`, packages/waku/) is another Vite RSC framework we use as reference for Vite integration patterns. It uses the same `@vitejs/plugin-rsc` plugin and has a similar multi-environment setup (client, ssr, rsc). Useful to check how they handle `optimizeDeps`, `resolve.noExternal`, SSR middleware, and RSC environment config. Their Vite plugins live in `packages/waku/src/lib/vite-plugins/`.
1 change: 0 additions & 1 deletion CLAUDE.md

This file was deleted.

Loading
Loading