1# @fixtures/vocs
2
3E2E fixture for [vocs](https://vocs.dev) (the minimal React documentation
4framework) on Cloudflare Workers.
5
6Vocs 2.x is built on **waku**: its `vocs()` vite plugin (public export
7`vocs/vite`) composes waku's own `waku/vite-plugins` (environments,
8adapter-alias, static-build, ...) with vocs's mdx/config/patch plugins, and it
9peer-depends on `waku ^1.0.0-beta.6`. It is _not_ a fully static site: page
10bodies are prerendered RSC elements, but the document shell is SSR'd per
11request and there are dynamic API routes (`/api/search`, `/api/og`,
12`/api/mcp`, `/api/feedback`) — so it runs as a worker.
13
14Vocs does not use waku's `unstable_combinedPlugins`, so the
15`@alchemy.run/frontend-frameworks/waku` Framework layer can't drive it directly. Instead,
16`@alchemy.run/frontend-frameworks/vocs` provides a first-class Vocs framework
17integration and target contract. Its Cloudflare target composes the established
18Waku adapter and RSC environment primitives while owning Vocs-specific target
19selection, runtime requirements, config bridging, and public exports.
20
21There is no `vite.config.ts` and no `wrangler.jsonc`: `e2e.config.ts` carries
22the entire worker configuration in memory; `vocs.config.ts` is vocs's own
23(platform-agnostic) docs config.
24
25## What it exercises
26
27- **Worker SSR** — the docs shell (sidebar, layout) is rendered by the worker
28 at request time in both dev (workerd module-runner) and preview (miniflare).
29- **MDX pages** — `src/pages/*.mdx` with sidebar navigation.
30- **Client interactivity** — `src/components/Counter.tsx` is a
31 `"use client"` component embedded in MDX, hydrated in the browser.
32- **Static assets** — `public/hello.txt` rides along in `dist/public`, next to
33 vocs's build-time artifacts (`llms.txt`, `llms-full.txt`).
34
35## Workerd bridges (and why vocs is pinned exactly)
36
37Upstream vocs only ships node/vercel/netlify adapters — nothing targets a
38no-fs runtime. Runtime config resolution needs a small bridge, implemented as
39the `workerdConfigBridge` Vite plugin in the public Vocs integration:
40
411. **Runtime config resolution** — vocs's server code calls
42 `Config.resolve({ server: true })` per request; in production that branch
43 dynamically imports an on-disk `dist/server/vocs.config.js` via
44 `import.meta.dirname` (Node server layout), which crashes in workerd. The
45 bridge rewrites that branch to import a virtual module which re-exports
46 the project's original `vocs.config.*`. Vite therefore loads and bundles
47 the config itself, preserving its imports and functions; Alchemy does not
48 separately resolve or serialize it.
49
50The transform hard-fails with a descriptive error if the installed vocs no
51longer matches the expected internals — which is why `vocs` is pinned to an
52exact version. On a bump, re-check the guarded patterns in
53`packages/frontend-frameworks/src/vocs/Vocs.ts`.
54
55`nodejs_compat` (not just `nodejs_als`) is required: vocs's server bundle
56imports `node:fs` and friends (guarded with try/catch at runtime).
57
58## Commands
59
60```sh
61bun run dev # vocs dev over workerd (port 3105)
62bun run build # programmatic vocs build -> dist/ + dist/build.json
63bun run preview # miniflare over dist/build.json
64bun run test # playwright: live (built worker) + dev
65```