Part 2 · The Frontend — Astro on Rust
A backend with no face is a curl demo. In Part 2, quill gets a real Astro frontend — the same
framework these books are built with — talking to your Rust API. The interesting engineering here isn’t
the HTML; it’s the contract between a JavaScript frontend and a Rust backend, and the two hard
things every full-stack app must solve: who is this user, and how do I stream a response as it’s
being produced.
What you’ll build
Section titled “What you’ll build” ┌────────────────────┐ fetch (build + runtime) ┌──────────────────────┐ │ Astro frontend │ ─────────────────────────► │ quill · Rust backend │ │ · post list (SSG) │ │ · /api/posts │ │ · post page (SSR) │ ◄───────────────────────── │ · /api/auth/session │ │ · editor (client) │ JSON + SSE │ · /api/*/stream │ └────────────────────┘ └──────────────────────┘- A reader site: the post list and each post, rendered from the Rust API — static where it can be, server-rendered where it must be fresh.
- An editor: a real form that creates and updates posts through the API.
- Sessions: signed cookies so the editor knows who you are, verified on the Rust side.
- Server-Sent Events: a streaming endpoint the frontend can consume token-by-token — built now, because Part 3’s AI drafting rides on exactly this pipe.
Why Astro on Rust
Section titled “Why Astro on Rust”| Concern | Where it lives | Why |
|---|---|---|
| Content rendering | Astro (SSG/SSR) | ship HTML, hydrate only what’s interactive |
| Data & auth | Rust (axum) | one source of truth, typed, fast, secure |
| The contract | JSON + SSE over HTTP | language-agnostic, cache-friendly, streamable |
The lesson that transfers everywhere: keep the frontend dumb and the backend authoritative. The Rust service owns data, identity, and business rules; Astro owns presentation. This is the same split you’d draw for a mobile app, a CLI, or a third-party integration hitting the same API.
The chapters
Section titled “The chapters”| Ch | Title | You add | The idea it teaches |
|---|---|---|---|
| 1 | The contract | Astro app, typed API client, CORS | SSG vs SSR against a live API, sharing a schema |
| 2 | The editor | create/update forms → API | forms, optimistic UI, error surfaces |
| 3 | Sessions | signed-cookie auth, /session | cookies, CSRF basics, auth as middleware in axum |
| 4 | Streaming | an SSE endpoint + consumer | text/event-stream, backpressure, the AI-ready pipe |
The thread
Section titled “The thread”Once it compiles, what does it take to run for real users? Part 2’s answer: a trust boundary. The
moment a browser can talk to your service, every request is untrusted input. You’ll see how Rust’s type
system and axum’s extractors turn “parse, don’t validate” into the default, and how the same
Send/Sync discipline from async Rust makes a streaming endpoint safe under many simultaneous
readers.