Build a Tiny Docs Site with Next.js in Under an Hour

A full-blown documentation platform (Docusaurus, Mintlify, etc.) is great when you’re at scale, but sometimes you just need something tiny. Let’s build a minimal docs site using Next.js + Markdown.
We’ll:
- Scaffold a Next.js app
- Add a tiny “docs engine” with a docs list
- Render docs pages from Markdown
Create a Next.js App
From your project folder:
npx create-next-app@latest simple-docs-site
cd simple-docs-siteYou can accept the defaults. We’ll assume the App Router (app/ directory) is enabled, which is the default in newer Next.js versions.
Add Some Docs Data
We’ll keep this simple: a tiny “database” as a TypeScript file with Markdown strings.
// lib/docs.ts
export type Doc = {
slug: string;
title: string;
content: string; // markdown
};
export const docs: Doc[] = [
{
slug: "getting-started",
title: "Getting Started",
content: `
# Getting Started
Welcome to our docs site! 🎉
This is a simple markdown-powered page.
## What you can do
- Learn the basics
- Click around
- Extend it later with a real CMS
\`\`\`bash
npm install
npm run dev
\`\`\`
`,
},
{
slug: "api-reference",
title: "API Reference",
content: `
# API Reference
Here's a fake API:
\`\`\`http
GET /api/users
\`\`\`
Returns a list of users.
`,
},
];
export function getAllDocs() {
return docs;
}
export function getDocBySlug(slug: string) {
return docs.find((doc) => doc.slug === slug);
}This gives us:
- A list of docs (docs)
- A helper to get them all
- A helper to get a single doc by slug
Later, you can swap this with a real CMS (Ghost, Contentful, etc.) without changing your pages much.
Install a Markdown Renderer
npm install markedThis converts Markdown into HTML inside your Next.js pages.
Create the Docs List Page
Replace your app/page.tsx with the following:
import Link from "next/link";
import { getAllDocs } from "@/lib/docs";
export default function HomePage() {
const allDocs = getAllDocs();
return (
<main className="max-w-2xl mx-auto py-10">
<h1 className="text-3xl font-bold mb-4">Simple Docs</h1>
<p className="mb-6 text-gray-600">
A tiny docs site powered by Next.js and Markdown.
</p>
<ul className="space-y-3">
{allDocs.map((doc) => (
<li key={doc.slug}>
<Link
href={`/docs/${doc.slug}`}
className="text-blue-600 hover:underline"
>
{doc.title}
</Link>
</li>
))}
</ul>
</main>
);
}This displays a list of your docs with links.
Create the Dynamic Docs Page
Create app/docs/[slug]/page.tsx:
import { notFound } from "next/navigation";
import { marked } from "marked";
import { getAllDocs, getDocBySlug } from "@/lib/docs";
type DocPageProps = {
params: { slug: string };
};
export default function DocPage({ params }: DocPageProps) {
const doc = getDocBySlug(params.slug);
if (!doc) {
return notFound();
}
const html = marked.parse(doc.content);
return (
<main className="max-w-2xl mx-auto py-10">
<a href="/" className="text-sm text-gray-500 hover:underline">
← Back to docs
</a>
<h1 className="text-3xl font-bold mt-4 mb-6">{doc.title}</h1>
<article
className="prose prose-sm sm:prose lg:prose-lg"
dangerouslySetInnerHTML={{ __html: html }}
/>
</main>
);
}
export async function generateStaticParams() {
const docs = getAllDocs();
return docs.map((doc) => ({ slug: doc.slug }));
}This:
- Looks up the doc by slug
- Converts Markdown → HTML
- Renders it in the page
Run the Project
npm run devVisit:
- / → Docs list
- /docs/getting-started → Individual doc page
Next Steps
You can extend this simple docs site by:
- Moving docs into real .md files
- Pulling content from Ghost using its Content API
- Adding a sidebar or search
- Deploying instantly on Vercel