A personal website is one of those projects that looks simple until you try to finish it. The homepage may only need a short introduction and a list of posts, but a site that is ready to publish also needs metadata, feeds, social previews, sensible typography, and a deployment story.
I maintain [Portfolio Starter Kit]1 to make that starting point less repetitive. It is a compact, open-source foundation for building a personal website and MDX blog with modern Next.js tooling. This website is built from the same foundation.
Why another starter kit?
The main reason I maintain Portfolio Starter Kit is that active maintenance of the original Vercel template has slowed.2 The example remains a useful foundation, but it now receives less attention while Next.js continues to change quickly.
A starter kit is not only a collection of files; it is also a set of decisions about routing, rendering, content, dependencies, and deployment. As framework APIs and build tooling evolve, an infrequently updated template gradually accumulates friction. New users can end up performing a migration before they have written their first post.
I was already making those updates for my own use. Rather than keep the fixes in a private copy, I turned that work into an independently maintained project: small enough to understand in one sitting, complete enough to deploy as a real website, and current enough to remain a useful starting point.
Portfolio Starter Kit is therefore less a visual reinvention than a maintained continuation. Its purpose is to preserve what made the original example useful while keeping the foundation aligned with the modern Next.js ecosystem.
What it includes
The project uses the Next.js App Router and React Server Components as its foundation.3 Blog posts live in local MDX files, keeping the writing workflow close to plain text and the entire site inside one repository.
The starter includes:
- a homepage with writing, projects, and work experience sections
- build-time, type-safe content through Content Collections and Zod
- MDX and GitHub Flavored Markdown, including tables, task lists, and footnotes
- inline and display math rendered with KaTeX
- dual-theme Shiki syntax highlighting, code annotations, and copy buttons
- optimized local Markdown images with inferred dimensions and responsive sizing
- draft posts, update dates, and optional social images
- generated metadata, canonical URLs, and JSON-LD structured data
- dynamic Open Graph images, an RSS feed, sitemap, and robots.txt
- a root-level
llms.txtindex for machine-readable site discovery - responsive Tailwind CSS styling, dark mode, and optimized Geist fonts
- optional Vercel Analytics and Speed Insights integration
None of these features is unusual by itself. The value is that they already work together while the codebase remains small.
A writing workflow that stays out of the way
I prefer keeping articles as files rather than placing them behind a content management system. A post is an MDX document with a small frontmatter block:
---
title: "My Post"
publishedAt: "2026-08-08"
updatedAt: "2026-08-12"
summary: "A short description of the article."
image: "/images/blog/my-post/cover.png"
draft: false
---Only the title, publication date, and summary are required. Content Collections validates the frontmatter, compiles the MDX at build time, and generates the types consumed by the application. Published posts automatically receive a route, appear in the writing index, enter the RSS feed and sitemap, and provide the metadata needed for search engines and social sharing. Setting draft: true keeps unfinished work out of those public surfaces.
The project supports GitHub Flavored Markdown through remark-gfm.4 That means tables, task lists, strikethrough, autolinks, and footnotes can remain part of the writing format instead of becoming custom React components. Mathematical notation is handled by KaTeX, while Shiki highlights code during the content build so readers do not need to download a client-side highlighter.
Local images follow the same low-friction model. Place them under public, reference them with standard Markdown syntax, and the content pipeline infers their dimensions and renders them responsively. The source remains ordinary Markdown while the result gets the layout stability expected from an optimized image component.
This approach has a useful property: the content stays portable. The articles are readable in a text editor, reviewable in Git, and not locked to a hosted editor or proprietary export format.
Small enough to understand
I do not want the starter to grow into a general-purpose publishing platform. Its job is narrower: provide a dependable base for a portfolio and technical blog.
The code is organized around a few clear responsibilities. The App Router handles pages and metadata. Content Collections validates frontmatter and compiles MDX. A shared MDX component map controls how prose, links, images, and code blocks render. Route handlers generate RSS, Open Graph images, and the site-level llms.txt file. Everything else is ordinary React and CSS.
This makes customization direct. Changing the navigation does not require learning a theme system. Updating the homepage does not involve overriding a package. The source is the product, so users can edit it with the same tools they already use for application code.
One source for portfolio data
The homepage is divided into writing, projects, and work experience instead of treating a portfolio as only a blog index. Projects and work history live in a small typed data module, so changing the site means editing data rather than duplicating cards or markup.
That data is also reused by the root-level llms.txt route. The machine-readable index lists the main pages, published writing, projects, work experience, RSS feed, and sitemap without creating a second content system. Blog metadata still comes from Content Collections, while portfolio metadata comes from the same source that renders the homepage.
Relationship to the original Vercel example
Portfolio Starter Kit began as an adaptation of the open-source Portfolio Blog Starter in the vercel/examples repository.2 That project provided the original foundation, and its copyright notice remains preserved under the MIT License.5
As upstream maintenance slowed, I separated the ongoing upgrade work into this repository. I have since updated the dependency stack, introduced a typed content pipeline, expanded Markdown and math support, improved code and image rendering, added structured portfolio sections, and refreshed the publishing and discovery features.
The distinction is important: Portfolio Starter Kit is not sponsored, endorsed, maintained, or distributed by Vercel. Vercel is one possible deployment provider, and the original example is credited as the historical upstream, but this repository is developed and maintained by me.
Getting started
The project requires Node.js 20.9 or newer and pnpm 11. To run it locally:
git clone https://github.com/qiyangdev/portfolio-starter-kit.git
cd portfolio-starter-kit
pnpm install
pnpm devThe repository also includes a one-click Vercel deployment option, but the application remains a standard Next.js project. The deployment button is a convenience, not a requirement.
Before publishing changes, the project provides three basic checks:
pnpm lint
pnpm typecheck
pnpm buildThey are intentionally ordinary. A starter should make the correct path obvious without inventing a separate workflow that users have to memorize.
Who it is for
Portfolio Starter Kit is a good fit for developers who want a personal site, a small technical blog, or a clean starting point for learning how a content-focused Next.js application fits together.
It is less suitable for teams that need editorial roles, scheduled publishing, a visual page builder, or a large content operation. Those requirements usually justify a CMS and a more elaborate architecture. This project deliberately optimizes for one person, one repository, and a straightforward publishing loop.
Maintaining the foundation
My goal is not to add every possible feature. I want to keep the project current, understandable, and useful without turning it into a framework of its own.
That means updating dependencies deliberately, following changes in Next.js rather than preserving obsolete conventions forever, and treating metadata, feeds, and accessibility as part of the baseline rather than optional polish. It also means saying no when a feature would make the starter harder to understand for everyone else.
A starter kit is successful when people stop thinking about the starter kit and begin making the site their own. Portfolio Starter Kit is the foundation I wanted for my own work, and maintaining it publicly gives that work a chance to be useful to someone else as well.
You can explore the source on [GitHub]1 or view the [live preview]6.