Web Frontend Stack
Build modern, performant web applications using Bun + Astro + React/Preact + Tailwind v4 + Shadcn UI.
Core Philosophy
Astro is always the foundation. We don't choose between Astro and React — we use them together:
- Astro handles routing, pages, layouts, and static content (zero JS by default)
- React/Preact powers interactive islands within Astro pages
- Tailwind v4 provides utility-first styling with CSS variables
- Shadcn UI gives us accessible, customizable React components
- Bun accelerates development with fast installs, builds, and testing
┌─────────────────────────────────────────────────────────────────┐
│ Astro (Foundation) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ Static Page │ │ Static Page │ │ Dynamic Page │ │
│ │ (0 JS) │ │ (0 JS) │ │ ┌────────────────┐ │ │
│ │ │ │ │ │ │ React Island │ │ │
│ │ Hero.astro │ │ About.astro │ │ │ client:load │ │ │
│ │ Footer.astro│ │ │ │ └────────────────┘ │ │
│ │ │ │ │ │ ┌────────────────┐ │ │
│ │ │ │ │ │ │ Preact Island │ │ │
│ │ │ │ │ │ │ client:visible │ │ │
│ └──────────────┘ └──────────────┘ │ └────────────────┘ │ │
│ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘Workflow: New Project
Follow these steps when creating a new frontend project from scratch.
Step 1: Check for Agentation
Before writing any frontend code, check if the user has Agentation installed — a visual feedback tool that lets you click elements on the page and generate structured context for AI agents.
- Look for
"agentation"inpackage.jsondevDependencies - If NOT found, propose to the user:
Agentation provides visual feedback for AI-assisted frontend development — you click elements, add notes, and I get precise selectors and context. Want me to install it?
If they agree:
bun add -d agentation
# Also install the Claude Code skill for setup automation:
npx skills add benjitaylor/agentationAdd to the dev-only layout wrapper:
import { Agentation } from 'agentation';
// Only render in development
{import.meta.env.DEV && <Agentation />}Step 2: Scaffold the Project
# Initialize Astro project
bun create astro@latest my-project
cd my-project
# Add integrations
bunx astro add react # React islands
bunx astro add tailwind # Tailwind CSS v4
# Initialize Shadcn UI
bunx shadcn@latest init
bunx shadcn@latest add button card form input dialog
# Start dev server
bun run devStep 3: Configure Logging
Set up LogTape for structured logging across all runtimes. See references/bun.md for full patterns.
bun add @logtape/logtapeimport { configure, getConsoleSink } from '@logtape/logtape';
await configure({
sinks: { console: getConsoleSink() },
loggers: [{ category: ['myapp'], lowestLevel: 'info', sinks: ['console'] }],
});Step 4: Set Up Testing
Set up Playwright for E2E testing. Ask the user which browser(s) they want:
| Browser | Best For | Speed |
|---|---|---|
| Chromium | Default, full compat | Baseline |
| Firefox | Cross-browser | Similar |
| WebKit | Safari compat | Similar |
| Lightpanda | Fast CI, headless | 11x faster |
See references/testing.md for full Playwright config, Lightpanda setup, and component testing patterns.
bun add -d @playwright/test
bunx playwright install chromium # or user's chosen browserStep 5: First Dev Run
bun run dev
# Open http://localhost:4321Workflow: Existing Project
When working on an existing frontend project:
- Detect the stack — read
astro.config.mjs,package.json,tsconfig.jsonto understand what's already configured - Check for Agentation — same as Step 1 above. If missing, propose it.
- Route to the right reference based on the task:
- Building pages/routing → references/astro.md - React/Preact components → references/react.md or references/preact.md - Styling/theming → references/tailwind.md - Forms/tables/UI → references/shadcn.md - Testing → references/testing.md - Deploying → references/deployment.md
Project Type Decision
| Building | Astro Config | Key Integrations |
|---|---|---|
| Content site (blog, docs) | Static (default) | Content Collections, MDX, Tailwind |
| Web app (dashboard, SaaS) | SSR or hybrid | React islands, Shadcn UI, React Query |
| E-commerce | Hybrid | Static product pages, React cart island |
| Landing page | Static | Minimal islands, Tailwind, Astro components |
| Documentation | Static | Content Collections, MDX, search island |
| Internal tool | SSR | React islands (heavy), Shadcn DataTable, Forms |
Island Framework: React vs Preact
| Need | Choose | Why |
|---|---|---|
| Shadcn UI components | React | Shadcn is built for React |
| Complex state (React Query, Zustand) | React | Ecosystem support |
| Bundle size critical (<50KB page JS) | Preact | ~3KB vs ~40KB |
| High-frequency updates (live data) | Preact + Signals | Fine-grained reactivity |
| Simple widget (counter, toggle, form) | Preact | Smaller, sufficient |
| Web Component output | Preact | Smaller, easier to wrap |
| Default (no specific need) | Preact without Shadcn, React with Shadcn |
Both can coexist in the same Astro project:
bunx astro add react preactFile convention: *.tsx for React, *.preact.tsx for Preact (or use folders).
Hydration Strategy
| Directive | When | Use Case |
|---|---|---|
| (none) | Never | Static content — zero JS |
client:load | Page load | Critical interactivity (nav, auth) |
client:idle | Browser idle | Non-critical features (analytics, chat) |
client:visible | In viewport | Below-fold content (comments, footer) |
client:media | Media match | Responsive features (desktop-only) |
client:only | Page load, no SSR | Browser-only APIs (WebGL, canvas) |
State Management
| State Type | Solution |
|---|---|
| UI state (form, toggle) | useState / useReducer |
| Derived state | useMemo / computed signals |
| Server state (API data) | React Query / SWR |
| Global UI (theme, sidebar) | Zustand (React) or @preact/signals (Preact) |
| Form state (complex) | react-hook-form + Zod |
| URL state (filters, pagination) | Query params / nuqs |
| Cross-island state | Astro nanostores or custom events |
Testing Strategy
| Layer | Tool | What to Test | Count |
|---|---|---|---|
| Unit | bun test / Vitest | Utils, hooks, pure functions | Many |
| Component | Testing Library | React/Preact interactions | Some |
| Integration | Testing Library + MSW | Features with mocked APIs | Some |
| E2E | Playwright | Critical user flows | Few |
See references/testing.md for full setup, browser selection, Lightpanda integration, and MSW patterns.
Tool Integration: Agentation
Agentation provides visual feedback for AI- assisted frontend development. It renders a toolbar in the bottom-right corner during development — click any element to annotate it and generate structured context with CSS selectors and positions.
Detection: Check package.json for "agentation" in devDependencies.
If not installed, propose to the user:
bun add -d agentation
npx skills add benjitaylor/agentationSetup in Astro layout:
import { Agentation } from 'agentation';
// Dev-only — renders toolbar for visual annotation
{import.meta.env.DEV && <Agentation />}MCP Integration: Agentation has an MCP server that lets Claude Code access annotations directly in real-time without manual copy-pasting. Recommend the user set this up for the best experience.
Requirements: React 18+, desktop browsers only.
Tool Integration: LogTape
LogTape is the preferred logging library — zero dependencies, 5.3KB, works across Node.js, Deno, Bun, browsers, and edge functions. ~2x faster than Pino with nested categories and lazy evaluation.
bun add @logtape/logtapeKey advantages over Pino:
- Multi-runtime: One logger for server + client + edge
- Library-friendly: Libraries log without configuring; apps configure sinks
- Lazy evaluation: Templates only interpolated if level is enabled
- Integrations: Express, Fastify, Hono, OpenTelemetry, Sentry
See references/bun.md for full LogTape patterns, request logging middleware, and OpenTelemetry integration.
Tool Integration: Lightpanda
Lightpanda is a Zig-based headless browser — 11x faster than Chrome, 9x less memory. CDP-compatible with Playwright.
# Install
curl -fsSL https://pkg.lightpanda.io/install.sh | bash
# Or Docker: docker run -p 9222:9222 lightpanda/browser:nightly
# Connect from Playwright
lightpanda serve --host 127.0.0.1 --port 9222Use for: fast CI tests, web scraping, AI browser automation. Not for: visual regression, screenshot testing, CSS layout checks.
See references/testing.md for full Playwright + Lightpanda configuration.
Architecture Principles
- Astro-First — Every page starts static, add islands only when needed
- Mobile-First — Base styles for mobile, responsive variants for larger
- Accessibility-First — Semantic HTML, keyboard nav, ARIA when needed
- Performance Budget — <100KB JS per page, LCP <2.5s, CLS <0.1
Quick Start: Page with Islands
---
// src/pages/index.astro
import Layout from '../layouts/Layout.astro';
import Hero from '../components/Hero.astro';
import Counter from '../components/Counter';
import Comments from '../components/Comments';
---
<Layout title="Home">
<Hero /> <!-- Static: Zero JS -->
<Counter client:load /> <!-- Immediate hydration -->
<Comments client:visible /> <!-- Hydrate when visible -->
</Layout>Reference Files
Consult these based on what you're working on:
| When you need to... | Read |
|---|---|
| Build Astro pages, routing, content collections, View Transitions, error pages, SSR, MDX | references/astro.md |
| Write React components, hooks, state management, React Query, error boundaries | references/react.md |
| Use Preact, Signals, fine-grained reactivity, Web Components | references/preact.md |
Style with Tailwind v4, @theme, container queries, CVA variants, dark mode | references/tailwind.md |
| Use Shadcn UI forms, data tables, dialogs, command palette | references/shadcn.md |
| Set up Bun server, LogTape logging, bundling, TypeScript config | references/bun.md |
| Configure testing: Playwright, Lightpanda, Vitest, Testing Library, MSW, E2E | references/testing.md |
| Deploy to Vercel, Netlify, Cloudflare, Docker, static hosting | references/deployment.md |
| Implement security: XSS prevention, CSRF, CSP, auth, rate limiting | references/security.md |
| Add accessibility: ARIA, focus management, keyboard nav, screen readers | references/accessibility.md |
Common Pitfalls
| Area | Pitfall | Solution |
|---|---|---|
| Astro | Making everything an island | Only client:* for interactivity |
| Astro | client:load everywhere | Use idle/visible for non-critical |
| React | React libs for simple widgets | Use Preact for small islands |
| Preact | Mixing signals with useState | Signals outside components |
| Tailwind | Hardcoded colors | Use semantic tokens via @theme |
| Shadcn | Not customizing components | Own the code, modify freely |
| Testing | Only testing in Chromium | Add Firefox/WebKit, consider Lightpanda for CI |
| Deploy | Not testing production build | Always bun run preview before deploying |