Build a Documentation Site on Private GitHub Pages from Day 1

Tadashi Shigeoka ·  Fri, April 3, 2026

When a new project kicks off, what do you set up first? Repository creation, CI configuration, development environment. The list is long.

“Documentation site” rarely makes it onto that initial priority list. You figure the README is enough, or maybe a Notion page will do. So it gets deferred.

But if you set up a documentation site on Day 1, knowledge sharing within your team becomes remarkably smoother from that point on. Setup guides, architecture decisions, API specifications, operational procedures. Having all of this in a searchable site with sidebar navigation eliminates the constant “where was that info again?” problem.

Why Private GitHub Pages

GitHub Pages lets you host a documentation site directly from your repository. Organizations on GitHub Enterprise Cloud can set GitHub Pages visibility to private.

The reasons to use Private GitHub Pages are straightforward:

  • No separate access control needed: Only members with repository read access can view the site. No authentication layer to build or maintain
  • Simple deployment: Push to main, GitHub Actions deploys automatically. No external service integrations required
  • Collocated with code: Documentation source lives in the same repository, so code changes and doc updates can be reviewed in the same PR
  • No additional cost: If your organization already has GitHub Enterprise Cloud, there is nothing extra to pay

Notion and Confluence have their own page history features, but Git-based management is different in nature. With Git, you can review diffs, run PR-based reviews, and include code changes and documentation updates in the same commit.

Note that Private GitHub Pages is exclusive to GitHub Enterprise Cloud. It is not available on Free, Pro, or Team plans. If your organization does not have Enterprise Cloud, you can still use GitHub Pages publicly and add an authentication layer using a service like Cloudflare Access.

Two Fast-Building Options

There are many SSGs for documentation sites. In terms of raw build speed, Go-based Hugo and Rust-based mdBook are at the top. Rspress, which uses a Rust-based bundler, is also fast.

However, if your project’s tech stack is centered on TypeScript, keeping the documentation site in the same ecosystem makes it easier to maintain. Config file syntax, component extension, build toolchain knowledge: everything becomes an extension of what the team already knows.

With that in mind, I picked two fast-building options from the TypeScript ecosystem.

VitePress: Simple with Markdown

VitePress is a Vite-powered SSG that turns Markdown files into a static site.

Key features

  • Markdown (.md) based, simple structure
  • Fast builds and hot reload powered by Vite
  • Default theme optimized for documentation sites
  • Sidebar, search, and navigation configurable from a single config file
  • Vue components usable inside Markdown

Setup

npm add -D vitepress
npx vitepress init

Answer the setup wizard prompts and your documentation site scaffold is ready.

Configuration example

// docs/.vitepress/config.mts
import { defineConfig } from "vitepress";
 
export default defineConfig({
  title: "Project Docs",
  description: "Internal documentation",
  base: "/repo-name/",
  themeConfig: {
    nav: [{ text: "Home", link: "/" }],
    sidebar: [
      {
        text: "Getting Started",
        items: [
          { text: "Setup", link: "/setup" },
          { text: "Architecture", link: "/architecture" },
        ],
      },
    ],
    search: { provider: "local" },
  },
});

In a real project, the entire VitePress setup through GitHub Pages deployment was completed in a single PR. Build time was about 1 second. Existing Markdown files in the docs/ directory were used as-is, so no content migration was needed.

Starlight: Feature-Rich with MDX

Starlight is an Astro-based documentation theme for building feature-rich documentation sites.

Key features

Setup

npm create astro@latest -- --template starlight

Configuration example

// astro.config.mjs
import { defineConfig } from "astro/config";
import starlight from "@astrojs/starlight";
 
export default defineConfig({
  site: "https://your-org.github.io",
  base: "/repo-name",
  integrations: [
    starlight({
      title: "Project Docs",
      defaultLocale: "en",
      locales: {
        en: { label: "English", lang: "en" },
        ja: { label: "日本語", lang: "ja" },
      },
      sidebar: [
        {
          label: "Getting Started",
          items: [
            { slug: "en/setup" },
            { slug: "en/architecture" },
          ],
        },
      ],
    }),
  ],
});

In a real project, about 100 pages built successfully, with Pagefind search working correctly for both English and Japanese content.

Automatic Deployment with GitHub Actions

The official documentation for both VitePress and Starlight shows workflows that deploy via the GitHub Actions Pages source. However, in my projects I use the Deploy from a branch source, pushing build artifacts to a gh-pages branch.

The reason is compatibility with GitHub’s organization-level Actions policy for SHA pinning. This policy can enforce that all action references in workflows use full commit SHAs. When using the GitHub Actions Pages source, you depend on actions like actions/deploy-pages, and the SHA pinning policy can interfere with how these are referenced, causing Pages deployments to break. With branch-based deployment, you simply git push build output to a branch, avoiding this constraint entirely.

VitePress

# .github/workflows/deploy-docs.yml
name: Deploy Docs
 
on:
  push:
    branches: [main]
    paths:
      - "docs/**"
      - ".github/workflows/deploy-docs.yml"
  workflow_dispatch:
 
permissions:
  contents: write
 
concurrency:
  group: pages
  cancel-in-progress: false
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
      - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
        with:
          node-version: 24
          cache: npm
      - run: npm ci
      - run: npm run docs:build
      - name: Deploy to gh-pages
        run: |
          cd docs/.vitepress/dist
          git init
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add -A
          git commit -m "deploy: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
          git push -f "https://x-access-token:${{ github.token }}@github.com/${{ github.repository }}.git" HEAD:gh-pages

Starlight (Astro)

# .github/workflows/deploy-docs.yml
name: Deploy Docs
 
on:
  push:
    branches: [main]
    paths:
      - "docs/**"
      - ".github/workflows/deploy-docs.yml"
  workflow_dispatch:
 
permissions:
  contents: write
 
concurrency:
  group: pages
  cancel-in-progress: false
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
      - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
        with:
          node-version: 24
          cache: npm
      - run: npm ci
      - run: npm run build
      - name: Deploy to gh-pages
        run: |
          cd dist
          touch .nojekyll
          git init
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add -A
          git commit -m "deploy: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
          git push -f "https://x-access-token:${{ github.token }}@github.com/${{ github.repository }}.git" HEAD:gh-pages

The workflows are nearly identical. The only differences are the build command and the output directory.

After deployment, set Settings > Pages > Source to Deploy from a branch and select gh-pages as the branch.

Choosing Between VitePress and Starlight

Both tools build fast and cover the features you need for a documentation site. Here is how to decide.

AspectVitePressStarlight
FormatMarkdown (.md)Markdown (.md) + MDX (.mdx)
InternationalizationPlugin-basedBuilt-in
SearchLocal search (built-in)Pagefind (CJK-aware)
ComponentsVue componentsAstro components + built-in UI
ConfigurationVery simpleMore feature-rich
Best forSingle-language, straightforward docsMultilingual or heavily customized docs

Choose VitePress when: You want to write documentation in plain Markdown with minimal configuration, or you want to leverage the Vue ecosystem.

Choose Starlight when: You need MDX for rich content, built-in multilingual support, or want built-in components like cards, tabs, and badges out of the box.

Either way, the Day 1 setup fits in a single PR. If you are unsure, use this rule of thumb: if plain .md files are enough, go with VitePress. If you want MDX or i18n, go with Starlight.

What to Write on Day 1

Once the documentation site is up, what should you write first? From experience, these documents pay off the most when written on Day 1:

  1. Development environment setup: The steps from cloning the repository to running the application locally. When this lives only in the README, it gets buried as the project grows
  2. Architecture overview: Why the tech stack was chosen, what the directory structure looks like. Writing down “why this design” helps new team members ramp up faster
  3. Deployment procedure and configuration: CI/CD pipeline structure, environment variable management. The kind of information that usually gets passed around verbally

You do not need perfect documentation. Bullet points are fine to start. What matters is that the “place to write” exists from Day 1. When there is a place, team members naturally start adding documentation.

Conclusion

Setting up a documentation site on Private GitHub Pages from Day 1 accelerates knowledge sharing across your team.

  • Private GitHub Pages: Only accessible to members with repository read access. No separate authentication required
  • VitePress: Markdown-based and simple. Minimal configuration, fast builds
  • Starlight: MDX support, built-in i18n, rich built-in components. Suited for feature-rich documentation sites
  • Both: Deployable via GitHub Actions, with the entire setup fitting in a single PR

Documentation that gets “deferred until later” almost never gets written. Setting up a documentation site on Day 1 creates the state of “there is a place to write.” That alone fundamentally changes your team’s documentation culture.

That’s all from someone who sets up documentation sites on project Day 1. From the gemba.

References