System Architecture Overview
Relevant source files
The following files were used as context for generating this wiki page:The Railway Documentation project is a modern, statically-generated documentation website built with Next.js. Its primary purpose is to host and serve all documentation related to the Railway platform. The architecture is designed for performance, excellent developer experience, and powerful search capabilities.
The system leverages a Git-based content workflow where documentation is written in Markdown. Contentlayer processes these files during the build step, transforming them into structured data accessible within the Next.js application. Pages are primarily pre-rendered using Static Site Generation (SSG) for fast load times, with specific routes handled by Server-Side Rendering (SSR) for dynamic content delivery. Search functionality is powered by Meilisearch, which indexes the content via a dedicated scraper.
Core Framework & Technologies
The application is built on a foundation of modern web technologies, defined primarily in the package.json file.
| Technology / Library | Version | Purpose | Source |
|---|---|---|---|
next | ^15.5.9 | Core React framework for SSG, SSR, and API routes. | package.json:20 |
react | ^18.3.1 | UI library for building components. | package.json:24 |
contentlayer | ^0.3.4 | Manages and validates content from Markdown files. | package.json:16 |
meilisearch | ^0.32.3 | Powers the site's search functionality. | package.json:19 |
twin.macro | ^3.1.0 | Integrates Tailwind CSS with CSS-in-JS (Styled Components). | package.json:30 |
typescript | ^4.2.4 | Provides static typing for the codebase. | package.json:45 |
Sources: package.json
Styling
The UI is styled using Tailwind CSS, with twin.macro enabling its use alongside Styled Components. The configuration in tailwind.config.js defines custom colors, fonts, and extends the base theme. It also configures the @tailwindcss/typography plugin to style the Markdown content rendered by Contentlayer.
Sources: tailwind.config.js, package.json:30, 50
Content Management & Rendering
The system's content pipeline is designed to transform Markdown files into performant, statically-generated web pages.
Content Processing with Contentlayer
Contentlayer is central to the content pipeline. It reads Markdown files from the src/docs directory, validates them against a defined schema, and generates typed data and JSON files that the Next.js application can import.
The diagram below illustrates the Contentlayer build process.
Sources: package.json:10, contentlayer.config.ts:24-25
The schema for documentation pages is defined in contentlayer.config.ts.
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | The title of the page. |
description | string | Yes | The description of the page for SEO. |
url | string | No (Computed) | The URL path, resolved from the file path. |
Sources: contentlayer.config.ts:8-22
Page Rendering
The application employs a hybrid rendering strategy, using both Static Site Generation (SSG) and Server-Side Rendering (SSR).
Static Site Generation (SSG)
The majority of documentation pages are pre-rendered at build time using SSG. The file src/pages/[...slug].tsx is responsible for this.
getStaticPaths: This function reads all page URLs generated by Contentlayer and tells Next.js which paths to pre-render.getStaticProps: For each path, this function fetches the corresponding page data from Contentlayer's output.- The
PostPagecomponent receives the page data and renders the MDX content usinguseMDXComponent.
Sources: src/pages/[...slug].tsx:69-87
Dynamic Rendering (SSR) & Markdown Format
A special dynamic route, src/pages/dynamic/[...slug].tsx, handles requests that require server-side rendering. This is primarily used to serve the raw Markdown content of a page.
The middleware.ts file intercepts all incoming requests and, based on the Accept header, a .md extension, or a ?format=md query parameter, it can rewrite the URL to this dynamic route. The getServerSideProps function in dynamic/[...slug].tsx then checks for the format=md query and, if present, returns the raw Markdown content with the appropriate text/markdown content type.
Sources: src/middleware.ts:18-35, src/pages/dynamic/[...slug].tsx:60-84
Request Handling & Routing
Next.js middleware plays a crucial role in routing and content negotiation.
Middleware Logic
The middleware function in src/middleware.ts intercepts requests to determine if a user or client is requesting a Markdown version of a documentation page.
This sequence diagram shows how a request for a Markdown file is handled.
Sources: src/middleware.ts:18-35
API Routes
LLM Content Generation (/api/llms-docs.md.ts)
This API endpoint is designed to generate a single, large text file containing the entire documentation content, structured for consumption by Large Language Models (LLMs).
The process is as follows:
- It retrieves the complete page structure from
sidebarContent. - It iterates through each page defined in the sidebar.
- For each page, it reads the corresponding Markdown file from
src/docs. - It uses
gray-matterto parse the frontmatter and content. - It strips out complex Markdown (like code blocks and links) to create a clean text version.
- All content is concatenated into a single string and sent as a
text/plainresponse.
Sources: src/pages/api/llms-docs.md.ts
Search Functionality
Search is powered by Meilisearch and is implemented through a combination of an external scraper and a client-side UI.
Indexing with Meilisearch
The meilisearch-docs-scraper.config.json file configures a scraper that crawls the production documentation site. It extracts content based on a set of CSS selectors and sends it to a Meilisearch index named docs_railway_app_production.
The scraper configuration specifies which parts of the HTML correspond to the document hierarchy and main text content.
| Selector | CSS Selector | Purpose |
|---|---|---|
lvl0 | .sidebar .current-section | The main section title (e.g., "Guides"). |
lvl1 | .docs-content h1 | The page title. |
lvl2 | .docs-content h2 | Section headings. |
lvl3 | .docs-content h3 | Subsection headings. |
text | .docs-content p, .docs-content li, ... | The main text content to be indexed. |
Sources: meilisearch-docs-scraper.config.json:9-20
The configuration also defines synonyms to improve search relevance, such as mapping "postgres" to "postgresql".
Sources: meilisearch-docs-scraper.config.json:23-29
Search UI
The src/components/Search/Results.tsx component is responsible for rendering the search results returned from Meilisearch. It handles keyboard navigation (ArrowUp, ArrowDown, Enter) and displays results grouped by their top-level category.
Sources: src/components/Search/Results.tsx
SEO & Metadata
The project has a robust SEO implementation to ensure content is discoverable and well-represented on search engines and social media.
SEO Component & Structured Data
The src/components/SEO.tsx component is the core of the SEO strategy. It leverages next-seo to manage standard meta tags and generates several types of structured data (JSON-LD) to provide rich context to search engines.
Generated schemas include:
Organization: Information about Railway.BreadcrumbList: The navigation path to the current page, built by thebuildBreadcrumbsutility.ItemList(Table of Contents): A list of all headers on the page, extracted byextractHeadersFromMarkdown.Article: Metadata about the documentation page itself, including author, publisher, and modification dates.FAQPage: If the page contains headers ending in a question mark, this schema is generated to mark them as questions for rich results.
This diagram shows the flow of data into the SEO component.
Sources: src/components/SEO.tsx, src/utils/seo.ts