Skip to content

feat(cloudflare/website): Waku, Astro, SvelteKit resources - #886

Draft
john-royal wants to merge 23 commits into
mainfrom
claude/frameworks-integration
Draft

feat(cloudflare/website): Waku, Astro, SvelteKit resources#886
john-royal wants to merge 23 commits into
mainfrom
claude/frameworks-integration

Conversation

@john-royal

@john-royal john-royal commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Framework website resources built on the SourceProvider interface from #884 (this PR is stacked on claude/source-provider; Website.Nextjs is split out to #923).

const app = yield* Cloudflare.Website.Astro("App", {
  bindings: { MESSAGE: "hello" },
});
// likewise Website.Waku and Website.SvelteKit

Each resource selects a source descriptor (@distilled.cloud/<fw>/source) on the Worker resource — the framework package's WorkerSourceModule does the build (programmatic, no wrangler binary, no wrangler.json), asset manifesting, and rebuild-free input hashing for diff memoization. Builds are pure (no dist/build.json or other artifacts written into user projects).

  • Website.Waku — RSC SSR + SSG via waku's programmatic vite APIs
  • Website.Astro — programmatic astro build() with the wrangler-free forked integration
  • Website.SvelteKit — in-memory kit adapter + rolldown finishing pass

Verified live against the testing account: full create → noop (hash memo hit, no rebuild) → update → destroy lifecycle per resource, alongside the pre-existing Vite and StaticSite suites. Each framework ships an examples/cloudflare-website-<fw> example with an integ test (deploy → HTTP assertions → destroy).

Submodule: bumps cloudflare-tools to alchemy-run/cloudflare-tools#74.

🤖 Generated with Claude Code

john-royal and others added 13 commits July 20, 2026 13:32
…er-bundler branching

Replace the per-bundler if/else ladders in WorkerProvider
(prepareAssetsAndBundle, hasChanged) and LocalWorkerProvider
(runVite vs runWorker) with a uniform SourceProvider interface —
build() / hash() / dev() — implemented by the five existing arms:
InlineScript (props.script), Vite (props.vite), Python (.py main),
Prebuilt (bundle:false), Rolldown (default). Selection precedence,
hash slot semantics, Artifacts.cached("build") usage, the
AssetsWithHash/keepAssets fast path, and the #745 metadata hash
path are all preserved.

Also fixes local dev of prebuilt (bundle:false) workers: they were
re-bundled with rolldown in dev, violating the byte-for-byte
contract of the deploy path. PrebuiltSource.dev now fs-watches the
entry directory and re-reads the module graph instead
(watchPrebuiltWorkerBundle), and toRuntimeModules decodes
byte-content modules for workerd's string-typed module kinds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…kers

Regression test for the bundle:false local-dev bug fixed by the
SourceProvider refactor: the local provider used to re-bundle
prebuilt entries with rolldown, breaking the byte-for-byte contract
(this fixture's .txt module import is not even bundleable), so local
dev of prebuilt workers failed while deploy worked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…am submodules + research)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…oader

Add the serializable `source` prop to WorkerProps for external source
providers (framework integrations):

    Worker("Site", {
      source: {
        provider: "@alchemy.run/cloudflare-next",
        options: { rootDir: "." },
      },
    })

`loadSource` dynamically imports the specifier, validates the
WorkerSourceModule contract ({ make(options) }), and wraps failures in
the typed SourceProviderError naming the package to install.
`resolveSource` gives the descriptor precedence over the legacy props
and rejects `source` combined with script/vite/main. The descriptor is
hashed into the #745 metadata surface so switching providers (or
changing provider options) always triggers an update.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…proxy)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…bsite resources

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ample

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@alchemy-version-bot

alchemy-version-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Install the packages built from this commit:

alchemy

bun add alchemy@https://pkg.ing/alchemy/ea20518

@alchemy.run/better-auth

bun add @alchemy.run/better-auth@https://pkg.ing/@alchemy.run/better-auth/ea20518

@alchemy.run/pr-package

bun add @alchemy.run/pr-package@https://pkg.ing/@alchemy.run/pr-package/ea20518

john-royal and others added 2 commits July 20, 2026 22:51
…fixes)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…kit,nextjs}

Each example gets a bun-test integ suite mirroring cloudflare-tanstack:
deploy via Test.make (stage "test", Cloudflare state), assert the SSR page
renders the GREETING binding, a static asset serves, and destroy in afterAll
(NO_DESTROY-gated). Static-asset checks retry on body content because
Cloudflare masks the propagation window for /robots.txt with a managed
content-signals robots.txt served as 200.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@john-royal
john-royal marked this pull request as draft July 22, 2026 15:50
@john-royal
john-royal changed the base branch from claude/source-provider to main July 22, 2026 16:16
Next.js needs more iteration (bundler consolidation, dependency
internalization, adapters-api migration) — moved to its own branch +
draft PR. Bumps cloudflare-tools to the matching split (build.json now
harness-owned; Framework.build() is pure).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@john-royal john-royal changed the title feat(cloudflare/website): Waku, Astro, SvelteKit, Nextjs resources feat(cloudflare/website): Waku, Astro, SvelteKit resources Jul 22, 2026
…s, research retirement)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
john-royal and others added 4 commits July 27, 2026 10:28
SvelteKit dev now serves platform = { env, ctx, caches, cf } through
cloudflare-runtime's platform proxy: the Worker's binding hooks
(ctx.worker.bindings) round-trip on platform.env, caches actually
stores/matches, and literal env values remain as overrides.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…uto-provisioning

- Website.Waku defaults assets.htmlHandling to drop-trailing-slash (SSG
  pages serve 200 at /about instead of 307-redirecting to /about/) and
  appends nodejs_als when compatibility flags include neither nodejs_als
  nor nodejs_compat, so a zero-config waku deploy works.
- Website.Astro auto-provisions a KV namespace bound under the session
  binding name (SESSION by default) so Astro.session works zero-config;
  opt out with sessionKVBindingName: false or bring your own namespace
  under that name.
- Tests: Waku deploy now relies on the flag default and asserts the SSG
  page serves without a redirect (new expectDirectStatus helper); Astro
  test covers the session cookie round-trip and that destroy removes the
  auto-provisioned namespace.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…resource handle

Physical KV titles truncate the logical id out of long test-derived stack
names, so title scanning cannot find the auto-provisioned namespace.
Re-yield KV.Namespace("AstroSiteSession") in the deploy program (resource
creation dedupes by logical id) and assert its namespaceId exists after
deploy and is gone after destroy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Terminal create/update/replace commits stored the raw plan-time bindings,
whose unresolved Output proxies (e.g. a same-deploy-created KV namespace's
id) are silently dropped by JSON state stores. The next plan then diffed
its fully-resolved binding data against the truncated persisted shape and
reported a spurious binding update — forcing a Worker update (and source
rebuild) on every deploy immediately following a create.

Persist the resolved binding payload reconcile received (bindingOutputs)
instead, at all four terminal commit sites. Interim commits (creating/
updating/replacing) still store raw bindings — resolution hasn't happened
yet at those points.

Surfaced by the Astro session live test: deploy 2 of an unchanged app
planned [Site/SESSION] update because deploy 1 persisted the kv_namespace
binding without its namespaceId.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
john-royal and others added 2 commits July 27, 2026 13:46
Auto-detected memo workspaces fold workspace-linked integration packages
into the input hash; concurrent development in this monorepo churns those
trees between deploys and breaks the unchanged-rebuild assertion. Pass
workspaces: [] so the memo covers fixture sources only — workspace-aware
memoization keeps its dedicated coverage in Vite.test.ts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ects/_headers, base, astro:env)

Pulls the ct-side zero-config Astro sessions driver (SESSION KV binding)
that Website.Astro's auto-provisioned namespace pairs with, plus
_redirects/_headers emission, base-path support, astro:env secrets, and
injectTypes. bun.lock picks up the astro package's new dependency
declarations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vocs SSR deployment on Cloudflare Question: About SvelteKit adapter + local dev philosophy shift from v1

1 participant