Skip to main content
All blog posts in next-dev-portfolio live in a single JSON file: src/data/collections/posts/posts.json. The file is a keyed object where each top-level key is the post’s slug, and each value is a fully typed post record validated by a Zod schema at build time. Adding a new post is as simple as appending a new key-value pair to that object and running a rebuild.

File Location

Data Structure

The top-level object is a map of slug → post. This makes look-ups O(1) and keeps the dynamic route /blog/[slug] simple — the renderer reads the key that matches the URL parameter.

Required Fields

Every post record must include all of the following fields. The Zod schema will reject the build if any required field is missing or has the wrong type.

Optional Fields

The body Field

The body field accepts GitHub-flavored Markdown rendered via remark-gfm. You can use all standard GFM features inside it:
  • Headings (##, ###)
  • Fenced code blocks with language tags
  • Tables
  • Task lists
  • Bold, italic, inline code, and blockquotes
Write the Markdown as a JSON string, using \n for newlines and \n\n for paragraph breaks.

The image Object

When provided, the cover image object requires two sub-fields:
Use Unsplash source URLs and always append ?w=1600&q=80 to serve a web-optimized 1600 px wide JPEG. This keeps page weight low while preserving sharpness on retina displays.

How Posts Are Displayed

Posts surface in two places in the default layout:

Blog list page — /blog

The posts-list section on src/data/pages/blog.json renders every post in reverse-chronological order. Tags are shown as clickable filter chips.

Home page — recent posts

The recent-posts section on src/data/pages/home.json shows the most recent N posts. Control the count with the limit field in that section’s data object.
To change how many posts appear in the home page teaser, open src/data/pages/home.json and update the limit value in the recent-posts section:

Dynamic Route

Every post is accessible at /blog/[slug], where [slug] is the top-level key in posts.json. The template file at src/data/pages/blog/[slug].json configures the post-detail section that renders the full article body.
The slug key and the id field must always match. Mismatched values will cause the detail page to fail its schema validation at build time.

Adding a New Post

1

Open posts.json

Open src/data/collections/posts/posts.json in your editor.
2

Append a new entry

Copy an existing post object, paste it as a new key-value pair at the end of the top-level object, and update every field. Choose a slug that is URL-safe: lowercase letters, numbers, and hyphens only.
3

Rebuild the site

The build pipeline validates every post against the Zod schema. If a required field is missing or a type is wrong, you’ll see a descriptive error pointing to the exact field.

Removing a Post

Delete the entire key-value pair from posts.json, then rebuild. The post will no longer appear in listings or be accessible at its /blog/[slug] URL.
Removing a post that is linked from another page (for example, a hand-crafted link in a cta-band section) will produce a broken link. Search for the slug across your src/data/pages/ files before deleting.

Complete Post Example