Notes Site Starter is an independent open-source project developed and maintained solely by Qiyang. It provides a modern personal site and MDX blog foundation with an upgraded dependency stack, strict type safety, and current Next.js tooling.
The project was initially adapted from the open-source Portfolio Blog Starter. This historical origin does not imply any affiliation with Vercel. Vercel does not sponsor, endorse, maintain, or distribute this project.
|
|
- Next.js App Router with React Server Components
- Build-time, type-safe article collections powered by Content Collections and Zod
- MDX and GitHub Flavored Markdown with tables, task lists, and footnotes
- KaTeX-powered inline and display math
- Optimized local Markdown images with automatic dimensions and responsive sizing
- SEO metadata, sitemap, robots.txt, and JSON-LD
- RSS feed and dynamic Open Graph images
- Syntax-highlighted code blocks with copy buttons
- Responsive prose styles with light and dark mode support
- Tailwind CSS v4
- Optional Vercel Analytics and Speed Insights integration
- Optimized Geist fonts
- Node.js 20.9 or newer
- pnpm 11
Vercel is one optional deployment provider. The button creates a new Vercel project from this repository and clones it into your Git provider account.
Clone this repository and install its dependencies:
git clone https://github.com/qiyangdev/notes-site-starter.git
cd notes-site-starter
pnpm install
pnpm devOpen http://localhost:3000 in your browser.
After cloning the repository, replace the starter identity before deploying:
- Set the production
baseUrlinapp/sitemap.ts. - Update the site metadata and language in
app/layout.tsx. - Rewrite the homepage, navigation, and footer.
- Replace the article author, profile URL, and RSS channel details.
- Add your own
.mdxposts underapp/blog/posts. - Customize fonts, colors, social previews, and analytics as needed.
See the complete personalization guide for file-by-file instructions, examples, and a pre-deployment checklist.
Add .mdx files under app/blog/posts. Content Collections validates each file against the schema in content-collections.ts, compiles its MDX, and generates the TypeScript data consumed by the blog, RSS feed, and sitemap.
Every post starts with frontmatter:
---
title: 'My Project'
publishedAt: '2026-08-09'
updatedAt: '2026-08-10'
summary: 'A short description used in metadata, feeds, and previews.'
draft: false
image: '/images/blog/my-project-social.png'
---updatedAt, draft, and image are optional. Omit updatedAt until an article receives a meaningful update; when present, it cannot be earlier than publishedAt. Drafts default to false, while setting draft: true excludes the post from article routes, lists, RSS, and the sitemap. The image field defines an optional social preview image.
Store article images under public/images/blog and reference them with standard Markdown:
The shared MDX image component reads local image dimensions during static rendering and renders them through next/image with responsive sizing, rounded corners, a theme-aware border, and consistent vertical spacing.
The blog can be populated by syncing a folder of notes from Apple Notes into MDX posts. The sync is one-way: the chosen Apple Notes folder is the source of truth, and each run regenerates the corresponding app/blog/posts/*.mdx files and their images.
pnpm sync:notes # lists folders and prompts for a choice
pnpm sync:notes --folder Writing # sync a folder by name, no prompt
pnpm sync:notes --list # list folders and exitRunning without options prints every folder (nested folders included) with its note count and asks which one to sync. --folder <name> selects by folder name for scripts and CI.
How it works:
scripts/sync-notes.mtsreads the chosen folder via AppleScript automation (JXA), so it requires macOS and Automation permission for your terminal (grant it when prompted, or in System Settings → Privacy & Security → Automation → Notes). Checklist checkbox state is read directly from the local Notes database (NoteStore.sqlite).- Notes body HTML is converted to GitHub Flavored Markdown: paragraphs, ordered and unordered lists, checklists (
- [ ]/- [x]task lists), fenced code blocks, and inline formatting are preserved. - Inline images are extracted to
public/images/blog/notes/with content-hash filenames (deduplicated across posts) and referenced as/images/blog/notes/<hash>.<ext>. - Frontmatter is derived from each note:
titlefrom the note name,publishedAtfrom the note's creation date,updatedAtfrom the modification date (only when a later day),summaryfrom the first paragraph, anddraft: false. - A manifest at
scripts/notes-manifest.jsontracks the generated posts and images so stale files are removed when notes are renamed or deleted, and so switching folders replaces the previously synced posts. Manually written posts (for examplepersonalize-notes-site-starter.mdx) are left untouched.
Because the sync is one-way, edit articles in Apple Notes — any changes made directly to the generated .mdx files are overwritten on the next run. The Recently Deleted folder is never offered as a source.
Before deploying or opening a pull request, run:
pnpm lint
pnpm typecheck
pnpm buildThe initial codebase was adapted from the MIT-licensed Portfolio Blog Starter in the vercel/examples repository. This reference is provided solely for attribution. Vercel has no involvement in the development or maintenance of this project, and its original copyright notice is preserved in the license.
Distributed under the MIT License. Copyright for the original template remains with Vercel, Inc.; subsequent modifications are copyright Qiyang.

