Skip to main content
The docs.github.com application is a dynamic Node.js web server built on Express and Next.js. This page describes how the application is structured, what each major directory does, and how to run it locally.

History

1

Ruby on Rails

The site started as a Ruby on Rails web application.
2

Jekyll

It was converted to a static site powered by Jekyll, a Ruby static site generator. Many authoring conventions from this era are still in use today: Markdown content files, Liquid templating, frontmatter, and redirect_from support.
3

Nanoc

The site migrated to Nanoc, another Ruby static site generator.
4

Node.js + Express + Next.js (current)

Today the site is a dynamic Node.js server powered by Express. Middleware handles HTTP redirects, language header detection, and dynamic content generation across all flavors of GitHub product documentation.

Technology stack

The application runs on Node.js (v24+) with the following core frameworks:
  • Express — HTTP server and middleware pipeline
  • Next.js — React rendering and routing (currently transitioning from the pages router to the app router)
  • React — UI components
  • TypeScript — used throughout src/
The entry point is src/frame/server.ts, which calls src/frame/start-server.ts to initialize the Express app.

Subject folder pattern

The src/ directory is organized by subject rather than by technical role (client, server, stylesheet, etc.). Each subject folder represents a major capability of the site and contains all the code for that capability in one place: middleware, components, scripts, tests, and documentation.
src/
  xsubject/
    README.md
    lib/
    middleware/
    components/
    pages/
    stylesheets/
    scripts/
    tests/
A subject folder is created when a capability has its own specific tests. Not every element listed above is required — use only what the subject needs.
Two broad folders exist for code that is difficult to assign to a specific subject:
  • src/frame/ — cross-cutting infrastructure (header, footer, global sidebar, middleware orchestration)
  • src/workflows/ — process automation rather than production application code

Key src/ directories

src/frame/

The “spine” of the application. Handles Express server setup, the full middleware pipeline, shared React layout components (header, footer, global sidebar), the req.context object, and Next.js integration. Code belongs here only when it is truly cross-cutting — used by three or more subjects — or is fundamental infrastructure.

src/content-render/

Markdown rendering pipeline. Transforms raw Markdown files (with Liquid templating) into HTML served to the client. Includes remark/rehype plugins for GFM, syntax highlighting, and custom GitHub Docs extensions.

src/search/

Elasticsearch-backed search. Exposes the /api/search/v1 and /api/search/ai-search-autocomplete/v1 endpoints, browser-side search components, and the scraping and indexing scripts used to populate the search index.

src/rest/

REST API reference documentation pipeline. Auto-generates Markdown in content/rest/ from the OpenAPI description in github/rest-api-description. Contains the sync script, generated data files, and config.

src/graphql/

GraphQL API reference documentation. Similar pipeline to REST — syncs schema data and generates documentation pages for the GraphQL API.

src/webhooks/

Webhook event reference documentation. Shares the sync pipeline with REST and GitHub Apps (sync-openapi.yml).

src/content-linter/

Content quality checking. Runs markdownlint rules and custom rules against Markdown files in content/ and data/. Used in CI and as a pre-commit hook.

src/languages/

Internationalization. Language detection middleware, translation file management, and the ENABLED_LANGUAGES configuration that controls which languages the server serves.

src/versions/

Version management. Detects the requested GitHub product version from URLs and populates req.context with version information for conditional rendering.

src/redirects/

URL redirect handling. Builds and serves the redirect map derived from redirect_from frontmatter and other redirect sources.

Middleware pipeline

The middleware pipeline is defined in src/frame/middleware/index.ts and executes in this order for every request:
  1. Connection management — timeout handling and abort detection
  2. Security and headers — Helmet, CORS
  3. Language detection — parses Accept-Language headers and URL language prefix
  4. Context initialization — builds the base req.context object
  5. URL normalization and redirects — resolves redirect rules before serving content
  6. Page finding — locates the matching page in the site tree
  7. Subject-specific middleware — version detection, feature flags, breadcrumbs, TOC
  8. Page rendering — renders Markdown to HTML and sends the response
  9. Error handling — 404 and 500 error pages
Each subject registers its middleware into this pipeline. When adding new middleware, decide first whether it belongs in a specific subject directory.

Build and run

npm ci          # Clean install of dependencies
npm run build   # Next.js build with webpack (run once per branch)
npm start       # Start dev server with nodemon on port 4000
The development server starts with NODE_ENV=development and ENABLED_LANGUAGES=en. It uses nodemon to reload on changes to .ts, .json, .yml, .md, .html, and .scss files.Visit http://localhost:4000 when the server is running.
To enable additional languages locally, edit the start script in package.json and update ENABLED_LANGUAGES. For example, set ENABLED_LANGUAGES='en,ja,pt' to add Japanese and Portuguese. Restart the server for the change to take effect.

Adding a new subject folder

When a new capability grows to the point of having its own tests, create a subject folder under src/:
1

Create the folder structure

Create src/mysubject/ with at minimum a README.md and tests/ directory.
2

Add tests to the workflow

Open .github/workflows/test.yml and add an entry for your test files. This file is manually maintained — new test files do not run automatically.
3

Add to branch protection

After your entry in test.yml merges to main, add it to the branch protection required checks so it gates pull requests.
4

Register middleware (if needed)

If your subject has Express middleware, import it into src/frame/middleware/index.ts at the appropriate position in the pipeline.

Build docs developers (and LLMs) love