2.6 KiB
2.6 KiB
ADR-003: SSR Strategy - Go Templates with Preact Hydration
Status
Accepted
Context
The application needs to serve document pages that are readable without JavaScript (for performance and accessibility), while providing rich interactivity (comments, editing, search) when JavaScript is available. We need a server-side rendering strategy that works with our Go backend and Preact frontend.
Decision
Strategy C: Go's html/template renders initial HTML for all pages. Preact hydrates interactive components on the client.
Implementation Details
-
Server Rendering:
- Go handlers query database for document content
- Markdown parsed to HTML server-side (Goldmark)
html/templaterenders full page with document HTML embedded- No JavaScript required for reading
-
Client Hydration:
- Preact components mount into designated DOM containers
- Comments, search, editor are Preact islands
- Static content remains server-rendered HTML
preact-isohandles client-side navigation between pages
-
Data Passing:
- Initial state embedded as JSON in
<script type="application/json">tags - Preact reads initial state during hydration, avoids extra API calls
- CSP nonce applied to all inline scripts
- Initial state embedded as JSON in
Consequences
Positive
- First contentful paint is instant (pure HTML)
- SEO-friendly without extra complexity
- Graceful degradation: works without JS
- Go templates are auto-escaping XSS-safe
- No V8/JS runtime embedded in Go binary
- Smaller client bundle (only interactive components)
Negative
- Some code duplication: markdown parsing logic in both Go and JS (for preview)
- Template syntax is verbose compared to JSX
- Hydration can cause flicker if not carefully managed
- Client state must reconcile with server-rendered HTML
Alternatives Considered
Go Templates Only (No Preact)
- Pros: Zero client JS, maximum performance
- Cons: No interactive features (comments, real-time sync, search)
- Rejected: Doesn't meet collaboration requirements
Embedded JS Runtime (QuickJS/V8)
- Pros: True isomorphic rendering, JSX templates
- Cons: Adds C dependency, complex build, larger binary, security surface area
- Rejected: Violates minimal dependency principle
Preact SSR via WASM
- Pros: Same templates on server and client
- Cons: WASM overhead, complex build pipeline, slower than Go templates
- Rejected: Go templates are faster and simpler
References
- Go html/template security: https://pkg.go.dev/html/template
- Preact hydration: https://preactjs.com/guide/v10/server-side-rendering
- Islands Architecture: https://jasonformat.com/islands-architecture/