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

Jamdesk
December 4, 2025
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:

  1. Scaffold a Next.js app
  2. Add a tiny “docs engine” with a docs list
  3. 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-site

You 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 marked

This 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 dev

Visit:

  • / → 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