Migrate to Astro (SSR on the Cloudflare adapter)#25
Merged
Conversation
Replace the React 19 + Vite single-page app with an Astro static multi-page build. Pages (home, about, legal, privacy, 404) become .astro files with shared Layout/Nav/Footer/Block components; the interactive briefing form is reimplemented as an Astro component with a bundled vanilla-TS script reusing the same Zod schema and Turnstile flow, dropping React entirely. The Cloudflare Worker backend is unchanged: it still serves ./dist via the ASSETS binding and handles /api/briefing, /.well-known/*, and the telemetry-config injection. Adjusted the worker's static-asset detection for Astro's /_astro/ output and switched the assets SPA fallback to a 404 page. Tooling: Astro + @tailwindcss/vite (Tailwind v4), ESLint via eslint-plugin-astro with formatting owned by standalone Prettier (prettier-plugin-astro), tsconfig extends astro/tsconfigs/strict. https://claude.ai/code/session_01JVCrYCxEmVLcgKaDfzNdLu
…ts + middleware)
Replace the static-build + standalone worker with a fully Astro-native
setup on @astrojs/cloudflare (output: "server"):
- API + OIDC move into Astro server routes: src/pages/api/briefing.ts and
src/pages/.well-known/{openid-configuration,jwks.json}.ts
- Request telemetry moves into src/middleware.ts; the App Insights client
config is now rendered into the page head by the Layout (no HTMLRewriter)
- worker/* business logic moves to src/lib/server/* unchanged in behavior
- bindings via `import { env } from "cloudflare:workers"`; execution context
via Astro.locals.cfContext (Astro v6 removed locals.runtime.env/ctx)
- the standalone worker/index.ts entrypoint is removed
Build now emits dist/client (assets) + dist/server (worker + generated
wrangler.json). Deploys target dist/server/wrangler.json; scripts/preview-deploy.sh
swaps the D1 binding to the preview DB there and migrates via the root config.
NOTE: the production deploy command in the Cloudflare dashboard must be updated
to `npx wrangler deploy -c dist/server/wrangler.json` (after `npm run build`).
See AGENTS.md.
https://claude.ai/code/session_01JVCrYCxEmVLcgKaDfzNdLu
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
decipher-ms | 13d783e | Commit Preview URL Branch Preview URL |
May 28 2026, 05:59 PM |
There was a problem hiding this comment.
Pull request overview
Migrates decipher.ms from a Vite/React SPA plus standalone Cloudflare Worker to an Astro SSR app deployed via the Cloudflare adapter, preserving the marketing pages, briefing intake, OIDC endpoints, D1/Graph integration, Turnstile, and App Insights telemetry.
Changes:
- Replaces React pages/components with Astro pages, layout, shared navigation/footer/block components, and a vanilla-TS briefing form.
- Moves Worker backend behavior into Astro server routes, middleware, and
src/lib/server/*. - Updates build, lint, deploy, preview documentation, and Cloudflare/Astro configuration for SSR output under
dist/clientanddist/server.
Reviewed changes
Copilot reviewed 43 out of 47 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
.gitignore |
Ignores Astro generated cache/types. |
.prettierignore |
Excludes Astro generated files from formatting. |
.prettierrc |
Adds Astro Prettier support. |
AGENTS.md |
Documents Astro/Cloudflare build output and deploy flow. |
README.md |
Updates stack, development, and deployment documentation. |
astro.config.mjs |
Adds Astro SSR Cloudflare adapter and Tailwind Vite setup. |
eslint.config.js |
Switches lint config from React-oriented rules to Astro support. |
index.html |
Removes Vite SPA HTML entrypoint. |
package.json |
Replaces React/Vite dependencies and scripts with Astro/Cloudflare tooling. |
scripts/preview-deploy.sh |
Updates preview deploy flow for generated Astro Cloudflare config. |
src/App.tsx |
Removes React router application shell. |
src/components/Block.astro |
Adds shared Astro content block component. |
src/components/BriefingForm.astro |
Adds Astro briefing form with bundled client-side validation and Turnstile flow. |
src/components/BriefingForm.tsx |
Removes React briefing form. |
src/components/Footer.astro |
Adds shared Astro footer. |
src/components/Nav.astro |
Adds shared Astro navigation. |
src/env.d.ts |
Adds Astro/Cloudflare typing augmentation. |
src/layouts/Layout.astro |
Adds shared document layout, SEO metadata, JSON-LD, and telemetry config rendering. |
src/lib/server/briefing.ts |
Adapts briefing handler to Astro route usage. |
src/lib/server/env.ts |
Moves/updates Worker binding types for server code. |
src/lib/server/graph.ts |
Formatting-only updates in Graph mail helper. |
src/lib/server/jwt.ts |
Formatting-only update in OIDC key import. |
src/lib/server/oidc.ts |
Formatting-only update in JWKS response. |
src/lib/server/telemetry.ts |
Updates Worker type import for server telemetry. |
src/main.tsx |
Removes React client entrypoint. |
src/middleware.ts |
Adds Astro middleware for per-request server telemetry. |
src/pages/.well-known/jwks.json.ts |
Adds Astro JWKS endpoint. |
src/pages/.well-known/openid-configuration.ts |
Adds Astro OIDC discovery endpoint. |
src/pages/404.astro |
Adds Astro 404 page. |
src/pages/About.tsx |
Removes React About page. |
src/pages/Index.tsx |
Removes React home page. |
src/pages/Legal.tsx |
Removes React Legal page. |
src/pages/NotFound.tsx |
Removes React 404 component. |
src/pages/Privacy.tsx |
Removes React Privacy page. |
src/pages/about.astro |
Adds Astro About page. |
src/pages/api/briefing.ts |
Adds Astro briefing POST route. |
src/pages/index.astro |
Adds Astro home page. |
src/pages/legal.astro |
Adds Astro Legal page. |
src/pages/privacy.astro |
Adds Astro Privacy page. |
src/styles/global.css |
Adjusts Tailwind source scanning path for Astro structure. |
tsconfig.app.json |
Removes old Vite app TypeScript config. |
tsconfig.json |
Replaces project references with Astro strict TypeScript config. |
tsconfig.worker.json |
Removes old standalone Worker TypeScript config. |
vite.config.ts |
Removes old Vite React config. |
worker/index.ts |
Removes standalone Worker entrypoint. |
wrangler.jsonc |
Removes direct Worker entrypoint and SPA asset fallback for adapter-generated deploy config. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Migrates the site from the Vite + React 19 SPA to a fully Astro-native app running SSR on Cloudflare Workers via
@astrojs/cloudflare. React, react-router, react-helmet-async and @tanstack/react-query are removed entirely.Two commits:
.astrofiles (index,about,legal,privacy,404) sharingLayout/Nav/Footer/Block; the briefing form is an Astro component with a bundled vanilla-TS script reusing the same Zod schema + Turnstile flow. Tailwind v4 via@tailwindcss/vite.worker/index.tsis gone; its logic is expressed in Astro primitives:src/pages/api/briefing.ts—POST /api/briefingsrc/pages/.well-known/{openid-configuration,jwks.json}.ts— OIDC discovery + JWKSsrc/middleware.ts— per-request App Insights telemetry; the client config is rendered into the page head by the Layout (replacing the old HTMLRewriter injection)src/lib/server/*— D1, Microsoft Graph, JWT/OIDC, Turnstile, telemetry (moved fromworker/*, behavior unchanged)import { env } from "cloudflare:workers"; exec context viaAstro.locals.cfContext(Astro v6 removedlocals.runtime.env/ctx)D1, Microsoft Graph, Turnstile, OIDC federated creds, and the Azure App Insights telemetry model are all preserved.
The Astro Cloudflare adapter (v13, Astro 6) builds with the official
@cloudflare/vite-plugin, so the output and deploy flow changed:dist/client/(assets) +dist/server/(worker + a generateddist/server/wrangler.json).npx wrangler deploy), withnpm run buildrunning in the build step first.scripts/preview-deploy.shis updated for the new flow (no dashboard change needed there — it still runsbash scripts/preview-deploy.sh).See
AGENTS.md→ “Build output” / “Migrations ship with the deploy”.Test plan
npm run buildgreen; emitsdist/client+dist/servernpm run lintgreenwrangler deploy --dry-run -c dist/server/wrangler.jsonvalidates (bundles worker, reads 17 assets, binds DB + vars)wrangler devsmoke:/,/about,/legal,/privacy→ 200; unknown → 404;/.well-known/openid-configuration→ correct JSON;POST /api/briefing {}→ 400 with validation error<branch>-decipher-ms.*.workers.dev): verifywindow.__telemetryConfigis injected, JWKS endpoint returns keys (needsOIDC_PRIVATE_KEYsecret), a real briefing submission writes to the preview D1 + sends mail, and Web Vitals/pageviews land in App Insights (environment = preview:<branch>)https://claude.ai/code/session_01JVCrYCxEmVLcgKaDfzNdLu
Generated by Claude Code