static-page-stack
SOTA stack recommendations for elegant, controlled, semantic static HTML pages — dashboards, post-mortems, technical-investigation reports,
What this skill does
# Static Page Stack (SOTA, 2026)
> **Self-Evolving Skill**: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.
## When to use this skill
The user wants to produce **static HTML pages** that combine three aesthetic DNAs:
- Magazine / data-journalism (The Pudding, NYT Upshot)
- Technical documentation (Material/Docusaurus/Starlight)
- Computational notebook (Quarto/Observable/Jupyter Book)
…and embed three kinds of SVG:
- Programmatic charts (Vega-Lite / Observable Plot / D3)
- Hand-authored inline SVG (illustrative)
- Whiteboard-style (Excalidraw / tldraw)
Triggers include: "create a static page", "build a dashboard", "design a post-mortem", "set up a technical-doc site", "what HTML/CSS stack should I use", "this Tailwind soup is unmaintainable".
## The recommended stack (TL;DR)
| Layer | Pick | Backup | Why |
| ------------------------ | ---------------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Authoring | **Quarto** | Quartz, Jupyter Book 2 / MyST | Multi-page, native code+prose+math+execution, MIT, used by Bundesbank/BIS/USGS |
| Visual system | **Open Props + native modern CSS** | Pico.css | Replaces Tailwind utility soup with semantic tokens (4 KB Brotli); OKLCH + container queries + light-dark() are production-ready in 2026 |
| Typography | **Inter + Crimson Pro + Fira Code** | IBM Plex family | All FOSS; pairing tested at NYT/Pudding-grade |
| Programmatic charts | **Observable Plot** | Vega-Lite, ECharts | Cleaner defaults than Vega-Lite, ~95% of needs without going to D3, ISC, Bostock-led |
| Whiteboard | **Excalidraw** + `excalidraw_export` CLI | tldraw (note: $6k/yr commercial license) | MIT, mature, build-time SVG render works |
| Hand-drawn programmatic | **rough.js** (sparingly) | roughViz, chart.xkcd | Only for "this is exploratory / uncertainty implied" framing |
| Hand-authored inline SVG | CSS-vars-in-SVG pattern | `<symbol><use>` for shared icons | `var(--token)` propagates through inline SVG, giving single design-token surface |
| Scrollytelling | **Closeread** (Quarto-native) | Scrollama | Closeread is purpose-built for Quarto; Scrollama (~7 KB) for non-Quarto |
## Critical clarifications (don't skip these)
### "XHTML" in 2026 means semantic HTML5, not strict XHTML
Nobody writes literal `application/xhtml+xml` any more. What "elegant XHTML" actually means in modern usage is **well-formed semantic HTML5 enforced by the build tool**. Quarto outputs exactly this — `<article>`, `<aside>`, `<figure>` — without making you hand-author every angle bracket. If a user says "XHTML", clarify they probably mean semantic HTML5 with structural discipline.
### Tailwind itself isn't the problem
The problem is **Tailwind CDN + ad-hoc utility-class soup, no design system, regenerated each time**. Open Props gives you the same "drop-in tokens for everything" feel but as semantic CSS variables that propagate INTO inline SVG. That last property is what makes the stack coherent.
### Distill is dead, Idyll is dormant — don't recommend them
- Distill.pub stopped publishing in 2021. The `distillpub/template` repo looks alive (972 stars) but has no funding story.
- Idyll-lang's last meaningful update was Feb 2023.
- The 2026 spiritual successor is **Quarto's article layout + Closeread**, not a Distill fork.
### tldraw has a non-FOSS commercial clause
tldraw 2.x+ is source-available under a dual license: hobby (watermarked, non-commercial) or **$6,000/year** for commercial. Default to **Excalidraw** (MIT) unless tldraw's specific features (interactive embeds, polished hand-drawn aesthetic) justify the cost.
## Decision flow
```
User wants a static page →
├─ Single document, code-heavy, math? → Quarto (single-file render)
├─ Multi-page investigation/dashboard? → Quarto with sidebar nav OR Quartz (digital garden) if cross-linking dominates
├─ "Pure data dashboard, no narrative"? → Observable Framework (caveat: Observable Inc layoff risk)
├─ "I want sidebar nav, search, code blocks"? → Astro Starlight + MDX (functional docs aesthetic)
└─ "I want maximum flexibility, willing to design"? → Astro + custom theme + Open Props
User wants a chart →
├─ Static, magazine-quality default? → Observable Plot (default pick)
├─ Need interactivity, dynamic spec generation? → Vega-Lite
├─ Need polished interactive dashboards, Canvas OK? → ECharts
├─ Want sketchy "this is exploratory" framing? → rough.js / roughViz
└─ Need bespoke custom path/glyph? → D3 (rare; Plot covers ~95%)
User wants a diagram →
├─ Architecture, flow, illustrative? → Excalidraw + excalidraw_export
├─ Premium aesthetic, budget for $6k/yr? → tldraw + tldraw-cli
├─ Inline SVG with design tokens? → Hand-author with var(--token-*)
└─ Reused across many pages? → <symbol><use> pattern (caveat: shadow DOM blocks per-instance CSS)
```
## Concrete migration: Tailwind CDN soup → Quarto + Open Props
Phased migration (~5-6 weeks total for a multi-spoke dashboard):
**Phase 1 — Pilot (1-2 weeks):** Convert one page/spoke to Quarto. Match current visual output by writing custom SCSS theme that reuses existing palette but expressed as Open Props tokens + OKLCH. Ship as separate `dashboard-quarto/` directory.
**Phase 2 — Aesthetic upgrade (1 week):** Swap to Inter + Crimson Pro + Fira Code, replace ad-hoc Tailwind colors with OKLCH-generated palette ramps from `oklch.fyi`, standardize figure/chart components.
**Phase 3 — Charts (1 week):** Convert hand-authored data-bearing SVGs to Observable Plot specs. Illustrative SVGs (architecture, flowcharts) move to Excalidraw.
**Phase 4 — Scrollytelling (1 week):** Pick 2-3 mechanism explainer pages. Rewrite as Closeread scroll-driven explainers.
**Phase 5 — Roll out (~1 week per remaining page):** Use phase 1's templates.
## Anti-patterns to call out
When you see these in user code, recommend alternatives from the stack:
1. **`<script src="https://cdn.tailwindcss.com">`** in a static page → Use Quarto + Open Props instead. Tailwind CDN doesn't tree-shake → bloated CSS, no design system, every regeneration drifts.
2. **Inline base64-encoded SVG `<img>`** → Use inline `<svg>` with `var(--token)` for design-system propagation, OR `<svg><use href="#sym">` for shared icons.
3. **Hand-typed numeric values in charts** ("forecast: 189K, actual: 223K") → Use Observable Plot reading from a CSV/parquet so the chart re-renders if the number is corrected.
4. **`style="color: #abc123"` repeated across pages** → Define an OKLCH palette in `:root`, expose via Open Props tokens, reference via `var(--color-*)`.
5. **Mermaid/Graphviz in a project that wants editorial-quality diagrams** → Switch to Excalidraw or haRelated in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.