My personal blog and portfolio, built with AstroJS, Starwind components, Tailwind CSS, and deployed to Cloudflare Workers.
- Astro 6 with server output
- @astrojs/cloudflare for Cloudflare Workers deployment
- Tailwind CSS 4 via the Vite plugin
- Starwind components in
src/components/starwind - Astro content collections for pages, posts, projects, and experience entries
astro-expressive-codefor code block renderingsatoriand@resvg/resvg-jsfor generated Open Graph imagesultracite, Biome, TypeScript, commitlint, and lefthook for local quality checks
/- About page assembled fromsrc/content/pages/about.md, skills, and experience entries./now- Current tools, GitHub activity, and recent posts./projectsand/projects/[slug]- Project index and detail pages fromsrc/content/projects./blogand/blog/[slug]- Blog index and post pages fromsrc/content/posts./contact- Contact form and social links./feed.xml- RSS feed generated from published blog posts./openapi.json- OpenAPI metadata for public API and discovery endpoints./api/health- Health endpoint for uptime checks./.well-known/*- Agent, OAuth, OpenID, API catalog, and MCP discovery metadata.
The root layout provides the sidebar navigation, theme switcher, social links, RSS link, CV download, SEO metadata, JSON-LD support, and WebMCP tool registration.
Content is managed with Astro content collections in src/content.config.ts.
- Pages:
src/content/pages/*.md - Blog posts:
src/content/posts/*.md - Projects:
src/content/projects/*.md - Experience entries:
src/content/experiences/*.md
Blog posts support draft, featured, tags, coverImage, publishedAt, and updatedAt frontmatter. Draft posts are filtered out by the post utilities before rendering feeds and public pages.
Project entries support technologies, live URLs, repository URLs, and cover images. Experience entries drive the work history on the homepage.
- Node.js
>=24.11.0 - pnpm
11.2.1
Install dependencies:
pnpm installpnpm devStarts the Astro dev server at http://localhost:4321.
Run quality checks:
pnpm check
pnpm typecheckApply automated formatting and fixes:
pnpm fixOpen Graph images are generated before production builds:
pnpm build:ogThe generator reads blog posts and projects from src/content, then writes PNG cards to public/opengraph-image.png and public/social-cards.
To regenerate existing cards, pass --force directly to the script:
node scripts/opengraph/generate.ts --forcepnpm build
pnpm previewpnpm build runs the Open Graph generator first, then builds the Astro site using the Cloudflare adapter.
For bundle inspection:
pnpm analyzeThe site is configured for Cloudflare Workers with static assets in wrangler.jsonc.
Deploy with Wrangler:
pnpm deployThis runs a production build and then publishes via:
wrangler deployCloudflare observability is enabled, and the Worker is configured to run before assets so Astro server routes, middleware, and well-known endpoints are handled correctly.