My Dev Stack for 2025: Astro, TailwindCSS, Alpine.js, Netlify, Decap CMS, and ChatGPT5
A lean, fast, and genuinely fun stack for building modern sites that feel handcrafted—without the complexity tax.

- Jay McBride
- 9 min read

Why This Stack in 2025
Principles: Speed, Simplicity, Sustainability
The web doesn’t need more bloat. This stack leans hard into server-first rendering with tiny, targeted enhancements. Astro gives static speed by default. Tailwind keeps styling tight and consistent. Alpine adds just enough interaction without wiring a full framework. Netlify takes builds and delivery to the edge. Decap CMS keeps content close to Git, so the site’s history and governance are transparent. ChatGPT5 acts like a flexible co-pilot for brainstorming, boilerplate, and “vibe checks” that keep the product cohesive.
Enjoying this? 👉 Tip a coffee and keep posts coming
Who This Stack Is For
- Makers who want a premium feel without a heavy JavaScript framework.
- Teams that like Git-based content and preview flows.
- Clients who value speed, accessibility, and maintainability over trends.
High-Level Architecture
Island-Based, Content-First, Edge-Powered
- Content-first: Markdown/MDX + Decap as a Git editor.
- Render: Astro compiles pages to static HTML by default.
- Enhance: Alpine.js hydrates only the bits that need interactivity.
- Serve: Netlify handles edge delivery, functions, redirects, forms, and CI/CD.
The Request Flow From Edit to Publish
- An editor updates content in Decap CMS.
- A Git commit opens a Netlify build with branch preview.
- Astro builds a static site with optimized assets.
- Netlify deploys to the edge with preview URLs; once approved, production goes live.
Astro for the Core
Content Collections and MD/MDX
Astro’s Content Collections let you define schemas (title, date, tags, slug, SEO fields) so your content is uniform. MD/MDX keeps writing simple, but you can still drop in components (like a pricing table or CTA) when needed—no context switch to a monolithic app.
Partial Hydration and Islands
Instead of shipping an entire SPA for every route, Astro hydrates individual “islands” of interactivity only where they appear. That means your blog post renders as near-zero JavaScript, while the newsletter signup or a gallery component hydrates in isolation.
When to Opt Into Client-Side JS
- Components that truly require state across interactions (tabs, modals, accordions).
- Widgets that fetch client-only data (e.g., local storage preferences).
- Anything that benefits from instant client feedback without server round trips.
Rule of thumb: if it’s content, render it server-side; if it’s behavior, hydrate sparingly.
TailwindCSS for Styling
Design Tokens, Theming, and Dark Mode
Tailwind’s config acts like your living design system. Define color tokens, spacing scale, typography, and shadows once; reuse everywhere. Dark mode is a class-toggle away—use utility variants to swap colors, borders, and background gradients cleanly.
Production Safelist and Purge Strategy
Tailwind’s JIT handles most of the heavy lifting, but be deliberate:
- Keep a safelist for dynamic classes (e.g.,
prose-*
,bg-*
from CMS). - Avoid string-built class names where possible; if you must, document them.
- Audit CSS bundle sizes with each release; guard against drift.
Alpine.js for Interactivity (The “JavaScript Sprinkle”)
Common UI Patterns (Accordions, Modals, Tabs)
Alpine shines when you want to keep state near the markup:
- Accordions: Simple
x-data
withx-show
and transition directives. - Modals: Toggle with
x-trap
for focus management and accessibility. - Tabs: Bind active index and use
:class
to change styles in place.
This reads like HTML and behaves like a minimal framework—without bundling a full runtime.
State, Refs, and Lifecycle in Alpine
x-data
initializes component state.x-ref
grabs DOM nodes for focus or measurement.- Lifecycle hooks like
x-init
boot behavior without a separate JS file. Tip: keep Alpine components tiny and composable; don’t recreate a SPA.
Decap CMS for Content Editing
Git-based Workflows Your Team Actually Understands
Decap is a file-based CMS. Every change is a commit with history and review. No opaque database, no surprise vendor lock-in. Writers use a friendly UI; developers get diffs and PRs they can trust.
Collections, Previews, and Editorial Controls
- Collections: Structure posts, pages, and product data with validation.
- Previews: See content exactly as it will render in Astro templates.
- Editorial Workflow: Draft → Review → Approve → Publish with branch previews on Netlify so stakeholders approve visually, not just in theory.
Netlify for Hosting and CI/CD
Build Hooks, Branch Previews, and Edge Functions
- Build Hooks: Trigger rebuilds from Decap or external events.
- Branch Previews: Every PR gets a live URL. Say goodbye to “works on my machine.”
- Edge Functions: Personalize at the edge (geo-aware banners, A/B tests) with negligible latency.
Forms, Redirects, and Environment Variables
- Forms: Progressive enhancement—works without a single line of server code.
- Redirects: Clean routes, legacy URL support, and multilingual mapping.
- Env Vars: Keep secrets safe and inject them per-environment.
ChatGPT5 for “Vibe Coding” and Workflow
Prompts That Ship: Pairing, Rubber-Duck, and Boilerplate
Treat ChatGPT5 like a creative partner:
- Pairing: “Draft a minimal Alpine accordion component with keyboard support; Tailwind utility classes only.”
- Rubber-duck: “Explain why my CLS spiked after adding a custom font and how to fix it.”
- Boilerplate: “Scaffold an Astro content collection schema for case studies with fields X, Y, Z.”
You stay in control; the model accelerates exploration, ideation, and first drafts.
Guardrails to Keep You Honest (Linting, Tests, PRs)
- Always run formatters and linters after pasting generated code.
- Keep unit/e2e tests for critical paths.
- Treat model-authored code as a PR from a junior teammate: review, refine, merge.
Performance & Core Web Vitals
Images, Fonts, and Critical CSS
- Images: Use Astro’s image utilities for responsive sources and lazy-loading. Preload LCP hero images; compress aggressively.
- Fonts: Prefer system fonts or self-hosted variable fonts. Use
font-display: swap
and preconnect to reduce FOIT/FOUT. - Critical CSS: Tailwind is already tight; keep above-the-fold layouts lean, avoid layout shifts with fixed dimensions and aspect-ratio utilities.
Measuring What Matters
- Lighthouse is a start; add WebPageTest, or Netlify Analytics for real traffic.
- Track LCP, CLS, INP. Set budgets and enforce them in CI.
- Treat regressions as blockers—not “we’ll fix it later.”
Accessibility & SEO
Semantic HTML, Landmarks, and Keyboard
- Use headings logically (H1→H2→H3).
- Provide ARIA only when necessary; semantic tags should do most of the work.
- Ensure every interactive element is keyboard-navigable; Alpine +
x-trap
helps keep focus in modals.
Structured Data and OG Tags
- Add JSON-LD for articles, products, or events from frontmatter fields.
- OG/Twitter cards come from your Content Collections—title, description, hero image—so social previews always look intentional.
DX: Local Dev, Tooling, and Scripts
NPM Scripts and Project Structure
A clean, boring structure beats a clever one:
/src
/components
/layouts
/pages
/content
/styles
/netlify
/public
NPM scripts to cover the bases:
dev
: Astro dev serverbuild
: Astro buildpreview
: Serve the build locallylint
,format
: Prettier + ESLinttypecheck
: if using TS (highly recommended)
Linting, Formatting, and Pre-commit Hooks
- Prettier keeps the codebase consistent.
- ESLint catches bad patterns.
- Husky + lint-staged runs fast checks before every commit. Small frictions early prevent big refactors later.
Security, Privacy, and Compliance
Handling Secrets and User Data
- Keep secrets in Netlify env vars; never commit them.
- If collecting form data, provide a clear privacy policy and minimal fields.
- Sanitize any user-generated content before rendering; even static sites can embed risky HTML if you’re not careful.
- For multi-region users, consider consent banners and localized policies where required.
Cost, Scale, and Limits
From Solo Project to Production
- Solo/Small: Free/low-cost tiers get you very far with static output.
- Growing: Add Netlify functions for server bits (webhooks, light APIs).
- Production: Move heavy APIs to dedicated services, keep the site static at the edge. This stack scales horizontally because content is files, builds are predictable, and runtime JS is minimal.
Real-World Workflow: From Idea to Live in an Hour
A Repeatable Checklist
- Kickoff: Outline the page, audience, and CTA.
- Scaffold: Use Astro to generate routes and a base layout.
- Design: Define Tailwind tokens (colors, spacing, typography) and a minimal component library (buttons, cards, sections).
- Content: Write in MD/MDX; wire frontmatter for SEO.
- Interactivity: Add Alpine.js only where needed (accordion FAQs, mobile nav, modals).
- Optimize: Compress images, set
preload
for hero, check CLS with fixed sizes. - Preview: Open a PR; Netlify generates a preview URL.
- Review: Stakeholders test on mobile and desktop; fix nits quickly.
- Ship: Merge to main; Netlify deploys to production edge.
- Track: Watch Web Vitals, analytics, and real user feedback.
Once you’ve done this twice, it becomes muscle memory.
Pitfalls and Anti-Patterns
Over-Hydration, CSS Bloat, and CMS Sprawl
- Over-Hydration: If a component can render server-side, let it. Only hydrate interactive parts.
- CSS Bloat: Don’t sprinkle random utility classes in CMS content without a plan; use prose classes and a safelist.
- CMS Sprawl: Keep Collections tight. Fewer content types, well-named fields, better governance.
Roadmap for 2025+
What I’m Watching Next
- Edge personalization patterns that don’t torpedo caching.
- MDX component kits for rich editorial experiences without a design debt explosion.
- AI-assisted content QA (tone, accessibility, SEO checks) wired into PRs—helpful suggestions, not gatekeeping.
Conclusion
This stack is opinionated: Astro for speed and sanity; Tailwind for a consistent visual language; Alpine for just-enough interactivity; Decap for a writer-friendly, Git-true CMS; Netlify for a ridiculously smooth build-to-edge pipeline; and ChatGPT5 for the creative lift that turns a rough idea into a clear, shippable shape. It’s fast, maintainable, and fun to work with. Whether you’re shipping a personal site or a content-heavy brand, you get craftsmanship without complexity—and performance without heroics.
FAQs
Q1: Can this stack handle dynamic features like search or authenticated dashboards? Yes. Keep the site static for speed, then attach dynamic pieces with Netlify Functions or an external API. For search, consider a prebuilt index (lunr/mini-search) or a hosted service. For auth/dashboards, place them under a separate route or subdomain with a lightweight server.
Q2: How do I prevent Tailwind from purging classes used by CMS content?
Use a safelist in tailwind.config.js
for known dynamic classes (e.g., color utilities, prose-*
). Prefer well-scoped prose styling and avoid string-constructed class names.
Q3: When should I choose Alpine.js over a larger framework? If your interactivity is “sprinkles” (disclosure widgets, menus, tabs, light forms), Alpine is perfect. When state spans multiple pages, requires complex routing, or you need deep client-side data fetching, reach for a framework—but only where it’s justified.
Q4: What’s the migration path if I outgrow Decap CMS? You’re in good shape. Content is files in Git. You can map frontmatter to any headless CMS with an import script, or keep Decap for simple content and integrate a headless endpoint only for complex features.
Q5: How does ChatGPT5 actually improve delivery speed? It accelerates ideation, drafts boilerplate, and explains tradeoffs so you make confident calls faster. Combined with linting, tests, and code review, it shortens cycles without compromising quality.
Enjoying this? 👉 Tip a coffee and keep posts coming