Merge pull request #21 from BlackRoad-OS/codex/update-blackroad-os-docs-frontend-service

Convert docs portal to Next.js with core pages and APIs
This commit is contained in:
Alexa Amundson
2025-11-20 21:04:08 -06:00
committed by GitHub
16 changed files with 591 additions and 17958 deletions

View File

@@ -1,9 +1,9 @@
OS_ROOT=https://blackroad.systems OS_ROOT=https://blackroad.systems
SERVICE_BASE_URL=https://docs.blackroad.systems SERVICE_BASE_URL=https://docs.blackroad.systems
NEXT_PUBLIC_OS_ROOT=https://blackroad.systems NEXT_PUBLIC_OS_ROOT=https://blackroad.systems
NEXT_PUBLIC_SERVICE_ID=docs NEXT_PUBLIC_SERVICE_ID=docs
NEXT_PUBLIC_SERVICE_NAME="BlackRoad OS Docs" NEXT_PUBLIC_SERVICE_NAME="BlackRoad OS Docs"
NEXT_PUBLIC_CONSOLE_URL=https://console.blackroad.systems NEXT_PUBLIC_CONSOLE_URL=https://console.blackroad.systems
NEXT_PUBLIC_WEB_URL=https://blackroad.systems NEXT_PUBLIC_WEB_URL=https://blackroad.systems
NEXT_PUBLIC_API_URL=https://api.blackroad.systems NEXT_PUBLIC_API_URL=https://api.blackroad.systems
PUBLIC_DOCS_URL=https://docs.blackroad.systems

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
node_modules node_modules
build build
.docusaurus .docusaurus
.next
.DS_Store .DS_Store
.env .env
.env.local .env.local

View File

@@ -9,12 +9,9 @@ FROM node:18-alpine AS runner
WORKDIR /app WORKDIR /app
COPY package*.json ./ COPY package*.json ./
RUN npm install --omit=dev RUN npm install --omit=dev
COPY --from=builder /app/build ./build COPY --from=builder /app/.next ./.next
COPY --from=builder /app/static ./static COPY --from=builder /app/public ./public
COPY --from=builder /app/docusaurus.config.js ./ COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/sidebars.js ./
COPY --from=builder /app/src ./src
COPY --from=builder /app/README.md ./
ENV PORT=8080 ENV PORT=8080
EXPOSE 8080 EXPOSE 8080
CMD ["npm", "start"] CMD ["npm", "start"]

View File

@@ -3,7 +3,7 @@
Documentation portal for the BlackRoad Operating System. Documentation portal for the BlackRoad Operating System.
## Stack ## Stack
- Docusaurus v3 + React - Next.js + React
- JavaScript - JavaScript
## Running locally ## Running locally
@@ -11,22 +11,22 @@ Documentation portal for the BlackRoad Operating System.
npm install npm install
npm run dev npm run dev
``` ```
Visit http://localhost:3000 (or the port set in the env). Visit http://localhost:3000.
## Build & start ## Build & start
```bash ```bash
npm run build npm run build
npm start npm start
``` ```
The start command serves the static build on port 8080 by default. The start command serves the production build on port 8080.
## Key routes ## Key routes
- `/` docs homepage - `/` docs homepage
- `/getting-started` introduction and onboarding checklist - `/getting-started` introduction and onboarding checklist
- `/architecture` high-level architecture overview - `/architecture` high-level architecture overview
- `/services` service catalog - `/services` service catalog
- `/api/health` static health payload - `/api/health` health payload
- `/api/info` static service metadata - `/api/info` service metadata
## Railway deployment ## Railway deployment
- Port: 8080 - Port: 8080

7
next.config.js Normal file
View File

@@ -0,0 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
output: 'standalone',
};
module.exports = nextConfig;

17927
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,18 +4,13 @@
"private": true, "private": true,
"description": "Official documentation hub for BlackRoad OS", "description": "Official documentation hub for BlackRoad OS",
"scripts": { "scripts": {
"dev": "docusaurus start", "dev": "next dev",
"build": "npm run generate:meta && docusaurus build", "build": "next build",
"start": "docusaurus serve --dir build --host 0.0.0.0 --port ${PORT:-8080}", "start": "next start -p 8080",
"serve": "npm run start", "lint": "next lint"
"test": "npm run build",
"generate:meta": "node scripts/generateMeta.js"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "^3.5.2", "next": "14.2.4",
"@docusaurus/preset-classic": "^3.5.2",
"@mdx-js/react": "^3.0.1",
"clsx": "^2.1.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1" "react-dom": "^18.3.1"
} }

View File

@@ -1,20 +1,13 @@
const SERVICE_ID = 'docs'; export const SERVICE_ID = 'docs';
const SERVICE_NAME = 'BlackRoad OS Docs'; export const SERVICE_NAME = 'BlackRoad OS Docs';
const SERVICE_BASE_URL = process.env.SERVICE_BASE_URL || 'https://docs.blackroad.systems'; export const SERVICE_BASE_URL = process.env.SERVICE_BASE_URL || 'https://docs.blackroad.systems';
const OS_ROOT = process.env.OS_ROOT || 'https://blackroad.systems'; export const OS_ROOT = process.env.OS_ROOT || 'https://blackroad.systems';
const serviceConfig = { export const serviceConfig = {
SERVICE_ID, SERVICE_ID,
SERVICE_NAME, SERVICE_NAME,
SERVICE_BASE_URL, SERVICE_BASE_URL,
OS_ROOT, OS_ROOT,
}; };
module.exports = { export default serviceConfig;
SERVICE_ID,
SERVICE_NAME,
SERVICE_BASE_URL,
OS_ROOT,
serviceConfig,
default: serviceConfig,
};

5
src/pages/_app.jsx Normal file
View File

@@ -0,0 +1,5 @@
import '../styles/globals.css';
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}

7
src/pages/api/health.js Normal file
View File

@@ -0,0 +1,7 @@
export default function handler(req, res) {
res.status(200).json({
ok: true,
service: 'docs',
ts: new Date().toISOString(),
});
}

11
src/pages/api/info.js Normal file
View File

@@ -0,0 +1,11 @@
import { serviceConfig } from '../../config/serviceConfig';
export default function handler(req, res) {
res.status(200).json({
name: serviceConfig.SERVICE_NAME,
id: serviceConfig.SERVICE_ID,
baseUrl: serviceConfig.SERVICE_BASE_URL,
osRoot: serviceConfig.OS_ROOT,
ts: new Date().toISOString(),
});
}

View File

@@ -1,35 +1,55 @@
import Layout from '@theme/Layout'; import Head from 'next/head';
import React from 'react';
const layers = [
{
title: 'Frontends',
description: 'web (public site), console (Prism console), docs (this portal). These shape the user experience.',
},
{
title: 'Backends',
description: 'api (public gateway), core (engine and ledger), operator (workers and background jobs).',
},
{
title: 'Infrastructure',
description: 'Railway for deployment, Cloudflare and managed domains under *.blackroad.systems.',
},
];
export default function Architecture() { export default function Architecture() {
return ( return (
<Layout title="Architecture" description="High-level architecture for BlackRoad OS"> <>
<main className="container margin-vert--lg"> <Head>
<header className="margin-bottom--lg"> <title>Architecture | BlackRoad OS Docs</title>
<h1>Architecture</h1> </Head>
<p className="subtitle">How users, frontends, and backends flow together in BlackRoad OS.</p> <header className="hero">
</header> <h1>Architecture</h1>
<p>Understand how the system layers connect users to core capabilities.</p>
<section className="margin-bottom--lg"> </header>
<h2>System flow</h2> <main className="main">
<p>The following text diagram highlights the primary request paths:</p> <section className="section">
<pre> <h2>System layers</h2>
Users & Agents Web & Console <div className="card-grid">
Web Public API Core {layers.map((layer) => (
Console API Core + Operator <div key={layer.title} className="card">
Operator async tasks, queues, workflows <h3>{layer.title}</h3>
</pre> <p className="subtle">{layer.description}</p>
</div>
))}
</div>
</section> </section>
<section className="margin-bottom--lg"> <section className="section">
<h2>Platform layers</h2> <h2>Flow</h2>
<ul> <div className="card">
<li><strong>Frontends</strong>: public web experience, Prism Console, and this docs site.</li> <pre style={{ whiteSpace: 'pre-wrap', margin: 0, fontFamily: 'monospace' }}>
<li><strong>Backends</strong>: Core for the ledger and main business logic; API for the external gateway; Operator for asynchronous orchestration.</li> {`Users → Web / Console / Docs → API → Core / Operator`}
<li><strong>Shared infrastructure</strong>: Railway hosts the services, Cloudflare fronts the domains, and <code>blackroad.systems</code> anchors the URLs.</li> </pre>
</ul> <p className="subtle" style={{ marginTop: '12px' }}>
Traffic starts at frontends, funnels through the API gateway, and lands on core systems and operators.
</p>
</div>
</section> </section>
</main> </main>
</Layout> </>
); );
} }

View File

@@ -1,55 +1,65 @@
import Layout from '@theme/Layout'; import Head from 'next/head';
import Link from '@docusaurus/Link';
import React from 'react'; const services = [
import serviceConfig from '../config/serviceConfig'; { name: 'core', description: 'Internal engine, ledger, and foundational backend services.' },
{ name: 'api', description: 'Public gateway that fronts the platform APIs.' },
{ name: 'operator', description: 'Job workers and background orchestration.' },
{ name: 'console', description: 'Prism console for operators and administrators.' },
{ name: 'web', description: 'Public marketing site for BlackRoad OS.' },
{ name: 'docs', description: 'This documentation portal.' },
];
const firstSteps = [
{ label: 'Visit web', url: 'https://blackroad.systems' },
{ label: 'Open console', url: 'https://console.blackroad.systems' },
{ label: 'Ping API health', url: 'https://api.blackroad.systems/health' },
{ label: 'Open docs', url: '/' },
];
export default function GettingStarted() { export default function GettingStarted() {
return ( return (
<Layout title="Getting Started" description="Start using the BlackRoad Operating System"> <>
<main className="container margin-vert--lg"> <Head>
<header className="margin-bottom--lg"> <title>Getting Started | BlackRoad OS Docs</title>
<h1>Getting Started</h1> </Head>
<p className="subtitle">Understand the BlackRoad Operating System and take your first steps.</p> <header className="hero">
</header> <h1>Getting Started</h1>
<p>Understand what BlackRoad OS is and how to take your first steps.</p>
<section className="margin-bottom--lg"> </header>
<main className="main">
<section className="section">
<h2>What is BlackRoad OS?</h2> <h2>What is BlackRoad OS?</h2>
<p> <p className="subtle">
BlackRoad OS is the platform layer for orchestrating digital logistics and operational workflows. It brings together BlackRoad OS is an operating layer for orchestrating financial and operational workflows. It brings
public-facing frontends, operator consoles, and backend services into a single, reliable surface. together frontends, APIs, and workers under a consistent domain family and deployment strategy.
</p> </p>
</section> </section>
<section className="margin-bottom--lg"> <section className="section">
<h2>Core services</h2> <h2>Core services</h2>
<ul> <div className="card-grid">
<li><strong>core</strong> Ledger and core API that acts as the system of record.</li> {services.map((service) => (
<li><strong>api</strong> Public gateway that fronts the core for external access.</li> <div key={service.name} className="card">
<li><strong>operator</strong> Workers, queues, and background orchestration.</li> <h3>{service.name}</h3>
<li><strong>console</strong> Prism Console for operators and administrators.</li> <p className="subtle">{service.description}</p>
<li><strong>web</strong> Public-facing site for users and partners.</li> </div>
<li><strong>docs</strong> This documentation site that explains how everything connects.</li> ))}
</ul> </div>
</section> </section>
<section className="margin-bottom--lg"> <section className="section">
<h2>Environments</h2>
<p>
Services are hosted on Railway and published under the <code>blackroad.systems</code> domain family. Use HTTPS endpoints
in each environment for predictable connectivity.
</p>
</section>
<section className="margin-bottom--lg">
<h2>First steps checklist</h2> <h2>First steps checklist</h2>
<ol> <div className="card">
<li>Visit the public site: <Link to="https://blackroad.systems">blackroad.systems</Link>.</li> <ol>
<li>Open the console: <Link to="https://console.blackroad.systems">console.blackroad.systems</Link>.</li> {firstSteps.map((step) => (
<li>Hit the API probe: <Link to="https://api.blackroad.systems/health">api.blackroad.systems/health</Link>.</li> <li key={step.label} style={{ marginBottom: '10px' }}>
<li>Stay in the docs: <Link to={serviceConfig.SERVICE_BASE_URL}>Docs homepage</Link>.</li> <strong>{step.label}:</strong> <a href={step.url}>{step.url}</a>
</ol> </li>
))}
</ol>
</div>
</section> </section>
</main> </main>
</Layout> </>
); );
} }

View File

@@ -1,76 +1,64 @@
import Link from '@docusaurus/Link'; import Link from 'next/link';
import Layout from '@theme/Layout'; import Head from 'next/head';
import React from 'react'; import { serviceConfig } from '../config/serviceConfig';
import serviceConfig from '../config/serviceConfig';
const quickLinks = [ const links = [
{ href: '/getting-started', label: 'Getting Started' }, { href: '/getting-started', title: 'Getting Started', description: 'Kick off with core concepts, environment access, and first checks.' },
{ href: '/architecture', label: 'Architecture' }, { href: '/architecture', title: 'Architecture', description: 'See how frontends, gateways, and workers fit together inside BlackRoad OS.' },
{ href: '/services', label: 'Services' }, { href: '/services', title: 'Services', description: 'Service catalog with IDs, base URLs, and responsibilities.' },
]; ];
export default function Home() { export default function Home() {
return ( return (
<Layout title="BlackRoad OS Documentation" description="Architecture, services, and integration guides for BlackRoad OS."> <>
<header className="hero hero--primary homepage-hero"> <Head>
<div className="container"> <title>BlackRoad OS Documentation</title>
<h1 className="hero__title">BlackRoad OS Documentation</h1> <meta
<p className="hero__subtitle">Architecture, services, and integration guides for BlackRoad OS.</p> name="description"
<div className="buttons"> content="Reference for architecture, services, and integration of BlackRoad OS."
{quickLinks.map((link) => ( />
<Link key={link.href} className="button button--secondary button--lg" to={link.href}> </Head>
{link.label} <header className="hero">
</Link> <h1>BlackRoad OS Documentation</h1>
<p>Reference for architecture, services, and integration of BlackRoad OS.</p>
</header>
<main className="main">
<section className="section">
<h2>Start exploring</h2>
<div className="card-grid">
{links.map((link) => (
<div key={link.href} className="card">
<h3>{link.title}</h3>
<p className="subtle">{link.description}</p>
<p>
<Link href={link.href}>Open {link.title} </Link>
</p>
</div>
))} ))}
</div> </div>
</div>
</header>
<main className="container margin-vert--lg">
<section className="row">
<div className="col col--6">
<h2>What you will find here</h2>
<ul>
<li>How the BlackRoad Operating System fits together across frontends, APIs, and workers.</li>
<li>Environment and deployment notes for Railway and the <code>blackroad.systems</code> domain family.</li>
<li>Service-by-service responsibilities with links to deeper docs in each section.</li>
</ul>
</div>
<div className="col col--6">
<h2>Quick navigation</h2>
<ul>
{quickLinks.map((link) => (
<li key={link.href}>
<Link to={link.href}>{link.label}</Link>
</li>
))}
</ul>
</div>
</section> </section>
<section className="margin-top--lg"> <section className="section">
<h2>Service metadata</h2> <h2>Service metadata</h2>
<p className="margin-bottom--sm">Values pulled from the shared service configuration.</p> <p className="subtle">Values provided via shared configuration.</p>
<div className="card"> <ul className="list-inline">
<div className="card__body"> <li>
<ul> <strong>Service ID:</strong> {serviceConfig.SERVICE_ID}
<li> </li>
<strong>Service ID:</strong> {serviceConfig.SERVICE_ID} <li>
</li> <strong>Service Name:</strong> {serviceConfig.SERVICE_NAME}
<li> </li>
<strong>Service Name:</strong> {serviceConfig.SERVICE_NAME} <li>
</li> <strong>Service Base URL:</strong> {serviceConfig.SERVICE_BASE_URL}
<li> </li>
<strong>Service Base URL:</strong> {serviceConfig.SERVICE_BASE_URL} <li>
</li> <strong>OS Root:</strong> {serviceConfig.OS_ROOT}
<li> </li>
<strong>OS Root:</strong> {serviceConfig.OS_ROOT} </ul>
</li>
</ul>
</div>
</div>
</section> </section>
<div className="footer">BlackRoad OS Docs stay aligned across frontends, APIs, and operators.</div>
</main> </main>
</Layout> </>
); );
} }

View File

@@ -1,78 +1,84 @@
import Layout from '@theme/Layout'; import Head from 'next/head';
import React from 'react';
import serviceConfig from '../config/serviceConfig';
const services = [ const services = [
{ {
name: 'BlackRoad OS Core', name: 'BlackRoad OS Web',
id: 'core',
baseUrl: 'https://core.blackroad.systems',
role: 'Ledger and primary business logic that anchors the OS.',
},
{
name: 'Public API Gateway',
id: 'api',
baseUrl: 'https://api.blackroad.systems',
role: 'Externally facing entry point that fronts the core.',
},
{
name: 'Operator',
id: 'operator',
baseUrl: 'https://operator.blackroad.systems',
role: 'Workers and background jobs that coordinate async workflows.',
},
{
name: 'Prism Console',
id: 'console',
baseUrl: 'https://console.blackroad.systems',
role: 'Operational console for teams to manage the platform.',
},
{
name: 'Web',
id: 'web', id: 'web',
baseUrl: 'https://blackroad.systems', baseUrl: 'https://blackroad.systems',
role: 'Public web experience for users and partners.', description: 'Public-facing site for the platform.',
}, },
{ {
name: 'Docs', name: 'BlackRoad OS Console',
id: serviceConfig.SERVICE_ID, id: 'console',
baseUrl: serviceConfig.SERVICE_BASE_URL, baseUrl: 'https://console.blackroad.systems',
role: 'Documentation portal describing architecture, services, and integration guides.', description: 'Prism console for operators and administrators.',
},
{
name: 'BlackRoad OS API',
id: 'api',
baseUrl: 'https://api.blackroad.systems',
description: 'Public gateway that exposes platform capabilities.',
},
{
name: 'BlackRoad OS Core',
id: 'core',
baseUrl: 'https://core.blackroad.systems',
description: 'Engine, ledger, and internal backbone.',
},
{
name: 'BlackRoad OS Operator',
id: 'operator',
baseUrl: 'https://operator.blackroad.systems',
description: 'Workers and background jobs.',
},
{
name: 'BlackRoad OS Docs',
id: 'docs',
baseUrl: 'https://docs.blackroad.systems',
description: 'This documentation portal.',
}, },
]; ];
export default function Services() { export default function Services() {
return ( return (
<Layout title="Services" description="Service catalog for BlackRoad OS"> <>
<main className="container margin-vert--lg"> <Head>
<header className="margin-bottom--lg"> <title>Services | BlackRoad OS Docs</title>
<h1>Services</h1> </Head>
<p className="subtitle">Overview of the platform surfaces and their responsibilities.</p> <header className="hero">
</header> <h1>Services</h1>
<p>Catalog of core services with IDs, base URLs, and responsibilities.</p>
<div className="table-container"> </header>
<table className="table"> <main className="main">
<thead> <section className="section">
<tr> <div className="card">
<th>Name</th> <table className="table">
<th>ID</th> <thead>
<th>Base URL</th> <tr>
<th>Role</th> <th>Name</th>
</tr> <th>ID</th>
</thead> <th>Base URL</th>
<tbody> <th>Description</th>
{services.map((service) => (
<tr key={service.id}>
<td>{service.name}</td>
<td>{service.id}</td>
<td>{service.baseUrl}</td>
<td>{service.role}</td>
</tr> </tr>
))} </thead>
</tbody> <tbody>
</table> {services.map((service) => (
</div> <tr key={service.id}>
<td>{service.name}</td>
<td>
<span className="badge">{service.id}</span>
</td>
<td>
<a href={service.baseUrl}>{service.baseUrl}</a>
</td>
<td>{service.description}</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
</main> </main>
</Layout> </>
); );
} }

132
src/styles/globals.css Normal file
View File

@@ -0,0 +1,132 @@
:root {
--bg: #0b1021;
--panel: #111831;
--text: #e8ecf1;
--muted: #a4adbd;
--accent: #3b82f6;
--border: #1f2a44;
--green: #22c55e;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: radial-gradient(circle at 20% 20%, rgba(59, 130, 246, 0.08), transparent 25%),
radial-gradient(circle at 80% 0%, rgba(34, 197, 94, 0.08), transparent 25%),
var(--bg);
color: var(--text);
min-height: 100vh;
}
a {
color: var(--accent);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.main {
max-width: 960px;
margin: 0 auto;
padding: 48px 20px 80px;
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
margin-top: 24px;
}
.card {
background: rgba(17, 24, 49, 0.7);
border: 1px solid var(--border);
border-radius: 12px;
padding: 16px;
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.2);
}
.card h3 {
margin-top: 0;
margin-bottom: 8px;
}
.hero {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.25), rgba(17, 24, 49, 0.8));
border-bottom: 1px solid var(--border);
padding: 48px 20px;
text-align: center;
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
}
.hero h1 {
margin: 0 0 12px;
font-size: clamp(28px, 4vw, 40px);
}
.hero p {
margin: 0;
color: var(--muted);
}
.section {
margin-top: 40px;
}
.table {
width: 100%;
border-collapse: collapse;
margin-top: 16px;
}
.table th,
.table td {
border: 1px solid var(--border);
padding: 12px;
text-align: left;
}
.table th {
background: rgba(59, 130, 246, 0.1);
}
.badge {
display: inline-block;
padding: 4px 10px;
border-radius: 999px;
background: rgba(34, 197, 94, 0.15);
color: var(--green);
font-weight: 600;
border: 1px solid rgba(34, 197, 94, 0.4);
}
.list-inline {
display: grid;
gap: 10px;
list-style: none;
padding: 0;
}
.list-inline li {
background: rgba(17, 24, 49, 0.6);
border: 1px solid var(--border);
border-radius: 10px;
padding: 12px;
}
.subtle {
color: var(--muted);
}
.footer {
margin-top: 48px;
color: var(--muted);
font-size: 14px;
text-align: center;
}