A minimal Astro personal site template with a sidebar layout, blog, projects, newsletter, and full-text search. Built on Astro 5, Tailwind CSS 4, and basecoat-css.
bun create astro@latest --template github:frankievalentine/minastroThen follow the prompts. Once installed:
cd your-project
bun install
bun run build # required once to generate the Pagefind search index
bun run dev- Blog — Markdown and MDX posts with reading-time estimates, tag badges, and a back-to-top button
- Projects — a dedicated projects page and a featured projects section on the home page
- Newsletter — a subscribe form wired to a configurable endpoint
- Search — Pagefind full-text search via
⌘Kdialog - RSS feed — at
/rss.xml, auto-generated from your posts - Sitemap — auto-generated by
@astrojs/sitemap - Dark/light toggle — in the sidebar popover, persisted to
localStorage - View Transitions — smooth page navigation via Astro's
ClientRouter - Analytics — opt-in via Partytown; disabled by default
Everything personal is in one file: src/site.config.ts
export const siteConfig: SiteConfig = {
name: "Your Name",
title: "Your Name",
description: "Your Name's personal website.",
url: "https://your-domain.com",
avatar: "/avatar.svg",
location: "Your City",
roles: ["Software Engineer", "Open Source", "Builder"],
bio: "A short bio shown on the about page.",
social: {
github: "https://github.com/yourusername",
twitter: "https://x.com/yourusername",
email: "hello@your-domain.com",
// linkedin: "https://linkedin.com/in/yourusername",
},
newsletter: {
enabled: true,
formUrl: "https://your-newsletter-service.com/subscribe",
description: "Occasional notes on engineering and ideas.",
},
analytics: {
enabled: false, // set to true to activate
url: "https://your-analytics.com/api/script.js",
domain: "your-domain.com",
},
nav: [
{ label: "About", href: "/" },
{ label: "Posts", href: "/posts" },
{ label: "Projects", href: "/projects" },
{ label: "Newsletter", href: "/newsletter" },
],
};All fields are typed via the SiteConfig interface — TypeScript will catch anything missing.
Replace public/avatar.svg with your own image (.jpg, .png, .svg, or .webp). Update the avatar field in siteConfig to match the filename.
Create .md or .mdx files in src/content/posts/:
---
title: My Post Title
description: A one-sentence summary used for SEO and the post list.
date: 2025-03-01
tags: [engineering, notes]
---
Your content here.Create .md files in src/content/projects/:
---
title: my-project
description: What this project does in a sentence or two.
github: https://github.com/you/my-project
url: https://my-project.com # optional
tags: [typescript, cli]
featured: true # show on home page
status: active # active | wip | archived
date: 2025-01-01
---Projects marked featured: true appear in the Projects card on the home page. All projects appear on /projects.
| Path | Description |
|---|---|
src/site.config.ts |
All site identity and feature configuration |
src/content/posts/ |
Blog posts (.md and .mdx) |
src/content/projects/ |
Project entries (.md) |
src/layouts/Layout.astro |
Sidebar shell used by all pages |
src/pages/ |
Routes: index, posts, projects, newsletter, rss, 404 |
src/components/ |
Search dialog, BackToTop button |
src/styles/global.css |
Tailwind + basecoat imports |
src/utils.ts |
formatDate, readingTime utilities |
public/ |
Static assets: favicon, avatar, manifest, robots.txt |
| Command | Action |
|---|---|
bun run dev |
Start local dev server at localhost:4321 |
bun run build |
Build to ./dist/ and generate Pagefind index |
bun run preview |
Preview the production build locally |
bun run cfpreview |
Preview against Cloudflare Pages via Wrangler |
bun run cfdeploy |
Deploy to Cloudflare Pages |
bun run check |
Type-check and lint (astro check + ESLint) |
bun run fix |
Auto-fix ESLint issues |
Search only works after
bun run build— Pagefind generates its index at build time. In dev, the search dialog will open but return no results.
The template ships with the Cloudflare adapter. To deploy:
bunx wrangler login
bun run build
bun run cfdeployOr connect your GitHub repo in the Cloudflare Pages dashboard and set the build command to bun install && bun run build and the output directory to dist.
A Dockerfile is included for self-hosted deployments. It builds the static site with Bun and serves it via nginx:
docker build -t minastro .
docker run -p 8080:80 minastroThe site will be available at http://localhost:8080. The image uses a multi-stage build — the Bun builder stage produces ./dist/, and the nginx stage serves it with no runtime dependencies.
To deploy to Vercel, Netlify, or Node.js, swap out the adapter in astro.config.mjs. See the Astro adapters docs for details. Remove wrangler.jsonc and @astrojs/cloudflare from package.json if you switch.
- Astro 5
- Tailwind CSS 4
- basecoat-css — sidebar, cards, buttons, popovers, command dialog
- Pagefind — static full-text search
- Expressive Code — syntax-highlighted code blocks
- @astrojs/partytown — off-thread analytics
- Cloudflare Pages — default deployment target