This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
verifiedsoftware.dev — a content-driven landing page and newsletter about formally verified software. Built with Astro 5, Tailwind CSS 4, and deployed to Cloudflare Pages with a D1 database for subscriber storage.
npm install # Install dependencies
npm run dev # Dev server at http://localhost:4321
npm run build # Production build to dist/
npm run preview # Preview production build locallyNo test framework is configured. No linter is configured.
- Push to
maintriggers GitHub Actions (.github/workflows/deploy.yml) - Uses
wrangler pages deployviacloudflare/wrangler-action@v3 - Requires
CLOUDFLARE_API_TOKENandCLOUDFLARE_ACCOUNT_IDas GitHub secrets
Static site (Astro) with one serverless function:
src/pages/— Astro pages (index, about, subscribe, blog/index, blog/[...slug])src/layouts/—BaseLayout.astro(shell with SEO/OG/analytics) andBlogPost.astrosrc/components/— Astro components (Nav, Footer, NewsletterSignup, StatStrip, ProofBlock, EcosystemGrid, Roadmap)src/styles/global.css— Design system (colors, typography, animations via CSS custom properties)src/content/blog/— Markdown blog posts (content collection)src/content.config.ts— Blog schema: title, description, date, author, tags, draftfunctions/api/subscribe.js— Cloudflare Pages Function: email subscription endpoint storing to D1, with CORS origin check, rate limiting, and email validation
Cloudflare D1 (wrangler.toml): Database binding DB for verifiedsoftware-subscribers. Tables: subscribers (email, subscribed_at), rate_limits (ip, ts).
Tailwind CSS 4: Configured via Vite plugin in astro.config.mjs (not PostCSS).
Create src/content/blog/<slug>.md with frontmatter:
---
title: "Post Title"
description: "Description"
date: 2026-03-15
author: "Brendan"
tags: ["verification", "lean"]
draft: false
---Set draft: true to exclude from production.
- The README references Buttondown for newsletter, but the subscribe function was migrated to use Cloudflare D1 directly — no external API keys needed
.env.exampleconfirms no external API keys are required- Analytics: Plausible (cookieless), loaded in BaseLayout.astro
.fade-upCSS class + IntersectionObserver in BaseLayout provides scroll-triggered animations