Test commit.
A modern personal blog built with Next.js and FastAPI, featuring markdown-based content, tag filtering, and responsive design.
2026 May 22 - ran new Next/FastAPI app. removed old gatsby files, removed redundant readme markdowns. soon deploy to Vercel.
- π Markdown Blog Posts - Write posts in markdown with frontmatter
- π·οΈ Tag System - Organize and filter posts by tags
- πΌοΈ Image Support - Optimized image handling and serving
- π± Responsive Design - Mobile-first, works on all devices
- β‘ Fast Performance - Static generation with incremental updates
- π SEO Optimized - Built-in metadata and Open Graph support
- π¨ Modern UI - Clean design with CSS Modules
- π Easy Deployment - Optimized for Vercel
βββββββββββββββββββββββββββββββββββββββββββ
β Vercel β
βββββββββββββββββββββββββββββββββββββββββββ€
β Next.js Frontend ββββΊ FastAPI Backendβ
β (React + TypeScript) (Python) β
βββββββββββββββββββββββββββββββββββββββββββ
- Frontend: Next.js 14+ with App Router and TypeScript
- Backend: FastAPI serving blog content via REST API
- Deployment: Vercel with automatic HTTPS and global CDN
- Node.js 18+
- Python 3.11+
- npm or yarn
./start-dev.shThis starts both the frontend and backend servers. Visit:
- Frontend: http://localhost:3000
- Backend API: http://localhost:8000
- API Docs: http://localhost:8000/docs
Backend:
cd backend
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
uvicorn main:app --reloadFrontend:
cd frontend
npm install
npm run devQUICK-START.md for more details.
willcapio-old/
βββ frontend/ # Next.js application
β βββ app/ # App Router pages
β βββ components/ # React components
β βββ lib/ # Utilities (API, theme)
β βββ public/ # Static assets
β
βββ backend/ # FastAPI application
β βββ main.py # API server
β βββ content/ # Markdown blog posts
β βββ requirements.txt
β
βββ vercel.json # Deployment configuration
- Next.js 14+ (App Router)
- TypeScript
- CSS Modules
- React 18
React components are in frontend/components/ with CSS Modules for styling.
Edit frontend/lib/theme.ts to change colors, fonts, and styles.
- FastAPI
- Python Markdown
- Frontmatter parsing
- Uvicorn (ASGI server)
| Endpoint | Description |
|---|---|
GET /api/posts |
List all blog posts |
GET /api/posts/{slug} |
Get single post |
GET /api/tags |
Get all tags |
GET /api/posts/tag/{tag} |
Filter by tag |
GET /api/site-config |
Site configuration |
GET /docs |
API documentation |
All API logic is in backend/main.py. Easy to extend with new endpoints. Much of this is only used during build time.
-
Create a new directory in
backend/content/posts/:mkdir backend/content/posts/2024-12-19
-
Create
index.mdwith frontmatter:--- title: "My New Post" date: "2024-12-19" tags: ["tech", "blog"] cover: "./cover-image.jpg" --- Your post content here...
-
Add images to the same directory
-
Restart the backend to see changes
see DEPLOYMENT.md
Set NEXT_PUBLIC_API_URL in Vercel:
- Development:
http://localhost:8000 - Production:
https://your-domain.vercel.app
- Quick Start Guide - Get up and running fast
- Deployment Guide - Deploy to Vercel
- Project Overview - Full technical overview
- Migration Summary - What was changed (originally built with Gatsby v2 and migrated to Next.js and FastAPI)
The reason you're only seeing :8000 image calls in the Network tab is because the text/post data calls happen server-side β Next.js fetches from the API at build/render time on the server (note next: { revalidate: 3600 } in lib/api.ts), so they never appear in the browser's network inspector. Only the image src URLs embedded in the rendered HTML end up making client-side requests to :8000.
Both pages use force-static, meaning Next.js calls the FastAPI backend at build time (npm run build), bakes all the post data into static HTML files, and serves those pre-rendered pages. So:
When you hit localhost:3000 for the first time, the HTML you get back already contains all the text β no API call happens in the browser at all generateStaticParams() on the blog page means every post slug is also pre-rendered to its own static HTML page at build time The :8000 image calls you see in the Network tab are the only runtime requests, because image URLs are embedded as src attributes and the browser fetches those client-side The FastAPI backend only needs to be running during npm run build (or when Next.js revalidates after 1 hour). In production you'd need the backend running continuously for revalidation, but the page loads themselves are just static file serving.
First deploy to Vercel failed...I think the vercel functions serving images, weren't working. so updated app to find them locally on filesystem. then that broke local running, even though Vercel deploy worked:
The images are requesting localhost:3000/images/... but FastAPI is on localhost:8000. Locally, Next.js doesn't proxy /images/* to FastAPI β that routing only exists in vercel.json for Vercel. Fix is to add a dev rewrite in next.config.ts.
Edited next.config.ts +15 -0 This proxies /images/* and /api/* to FastAPI at localhost:8000 in dev only. On Vercel, vercel.json handles the routing instead.
Make sure FastAPI is running (cd backend && uvicorn main:app --reload), then restart the Next.js dev server and the images should load. Want me to commit and push this fix too?
# Test the API
./test-api.sh
# Test frontend build
cd frontend && npm run build- β CORS properly configured
- β Environment variables for configuration
- β No sensitive data in code
- β HTTPS on Vercel
- β‘ Static Site Generation (SSG)
- π Incremental Static Regeneration (ISR)
- πΌοΈ Optimized image loading
- π Global CDN distribution
- π± Mobile-first responsive design
This is a personal blog, but feel free to fork and adapt for your own use!
MIT