feat: bootstrap Eldorado documentation and Pages publication
Build and publish Eldorado documentation / build (push) Successful in 30s

This commit is contained in:
jarvis-at-skic committed 2026-10-02 10:03:16 +00:00
1 parent dceabb9514
commit 98a0cb088f
17 files changed
+12749 -2

No files matched your search

+55
View File
@@ -0,0 +1,55 @@
name: Build and publish Eldorado documentation
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: eldorado-documentation-${{ gitea.ref }}
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10.15.1
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Validate source contracts
run: pnpm verify
- name: Typecheck
run: pnpm typecheck
- name: Build site
run: pnpm build
- name: Validate built routes, search and fonts
run: pnpm verify:build
- name: Record deployed revision
shell: bash
run: git rev-parse HEAD > build/revision.txt
- name: Publish to LEGO Cloud Pages
if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main'
shell: bash
run: |
set -euo pipefail
ORG_REPO='${{ gitea.repository }}'
case "$ORG_REPO" in */*) ;; *) exit 1 ;; esac
case "$ORG_REPO" in *..*|/*|*/|*//* ) exit 1 ;; esac
test "$ORG_REPO" = 'eldorado-v1/documentation'
test -f build/index.html
pages_root='/gondor-v1-gitea-pages'
mountpoint -q "$pages_root" || { echo "$pages_root is not a persistent mount" >&2; exit 1; }
destination="$pages_root/$ORG_REPO"
rm -rf -- "$destination"
mkdir -p "$destination"
cp -a build/. "$destination/"
+7
View File
@@ -0,0 +1,7 @@
node_modules/
build/
.docusaurus/
.cache/
.env
.env.*
!.env.example
+1
View File
@@ -0,0 +1 @@
22
+29 -2
View File
@@ -1,3 +1,30 @@
# documentation # Eldorado documentation
Eldorado documentation foundation · Docusaurus · LEGO Cloud Pages A Docusaurus foundation. The documentation’s purpose and audience are intentionally undecided.
- Site: https://pages.apps.lego-cloud.eu/eldorado-v1/documentation/
- Repository: https://gitea.lego-cloud.eu/eldorado-v1/documentation (private)
- Channel: https://discord.com/channels/1518726359512387766/1555510466904727622
## Development
Use Node.js 22+ and pnpm 10.15.1.
```sh
pnpm install --frozen-lockfile
pnpm start
pnpm verify
pnpm typecheck
pnpm build
pnpm verify:build
```
## CI and publication
Pull requests validate only. Pushes to `main` validate, build, and publish to the persistent runner mount at `/gondor-v1-gitea-pages/eldorado-v1/documentation/`, following `corp-v1/portal`. Publication fails if that mount is unavailable. The Pages platform controls user authentication independently of repository visibility. No infrastructure or authentication changes are required.
After publication, verify the exact commit’s Actions task and deployed page body; an OAuth redirect is not content verification. Future changes should use pull requests. Never commit credentials or edit generated `build/` output.
## Design
Inspired by https://www.eldorado.gg/: Lato, near-black navigation, charcoal, gold `#ffc950`, light panels, bold headings. Original documentation artwork and square panels; no official marketplace assets or business claims. See `docs/reference.md`.
+39
View File
@@ -0,0 +1,39 @@
---
title: How to update and publish the site
description: Preview documentation changes, validate them, and publish through Gitea Actions.
slug: /maintain
---
## What you need
Node.js 22 or later, pnpm 10.15.1, and write access to the private [documentation repository](https://gitea.lego-cloud.eu/eldorado-v1/documentation).
## Preview locally
```sh
pnpm install --frozen-lockfile
pnpm start
```
Open the development server address printed in the terminal. The site uses the `/eldorado-v1/documentation/` base path.
## Add or change a page
Edit Markdown in `docs/`. Include `title` and `description` frontmatter and add the page ID to `sidebars.ts`. Keep the documentation’s future scope open until it is agreed.
## Validate the change
```sh
pnpm verify
pnpm typecheck
pnpm build
pnpm verify:build
```
The build fails on broken internal links. The built-output checks verify routes, locally bundled fonts, search content, and the expected site base path.
## Publish
Open a pull request for subsequent changes. Gitea Actions validates pull requests without publishing. Once a change is merged to `main`, the workflow builds and copies the site to the persistent Pages mount at `/gondor-v1-gitea-pages/eldorado-v1/documentation/`.
Check the Actions result for that exact commit, then open [the published site](https://pages.apps.lego-cloud.eu/eldorado-v1/documentation/). Pages access follows the platform’s existing authentication policy; a sign-in redirect is not a failed build.
+21
View File
@@ -0,0 +1,21 @@
---
title: Explore the starting point
description: Understand what this documentation foundation includes and what is still undecided.
slug: /overview
---
This is the starting point for **Eldorado v1 documentation**. The purpose, audience, and content structure will be defined later.
## What is included
- A Docusaurus site with responsive navigation and local search.
- An Eldorado-inspired visual theme with a dark header, gold accents, and Lato typography.
- Automated checks on pull requests and publication to LEGO Cloud Pages after a push to `main`.
## What remains open
The documentation’s goals, ownership model, subject matter, and final information architecture are not yet agreed. This starter does not introduce product requirements, business claims, or a delivery roadmap.
## Work on the foundation
[Maintain and publish the site](./maintain.md) or [look up its configuration](./reference.md).
+39
View File
@@ -0,0 +1,39 @@
---
title: Site configuration reference
description: Look up source locations, tool versions, styling choices, and publication settings.
slug: /reference
---
## Repository layout
| Path | Responsibility |
| --- | --- |
| `docs/` | Documentation Markdown |
| `src/pages/index.tsx` | Homepage |
| `src/css/custom.css` | Eldorado-inspired theme |
| `static/img/docs-mark.svg` | Original documentation icon |
| `docusaurus.config.ts` | Routes, metadata, navigation, and search |
| `sidebars.ts` | Documentation navigation |
| `scripts/verify.mjs` | Source and built-output contract checks |
| `.gitea/workflows/pages.yml` | Validation and Pages publication |
## Runtime and publication
| Setting | Value |
| --- | --- |
| Framework | Docusaurus 3.10.2 |
| Node.js | 22 or later; CI uses 22 |
| Package manager | pnpm 10.15.1 |
| Base path | `/eldorado-v1/documentation/` |
| Repository | `eldorado-v1/documentation` (private) |
| Publication branch | `main` |
| Pages mount | `/gondor-v1-gitea-pages` |
| Search | Local build-generated index; no external search service |
## Visual reference
The theme adapts [Eldorado’s website](https://www.eldorado.gg/): near-black navigation, charcoal surfaces, gold `#ffc950` accents, light `#f6f6f6` backgrounds, and Lato type. Gold buttons use dark text; light-mode text links use a darker gold for contrast. Fonts are bundled locally.
The documentation uses original page artwork and a document icon, not marketplace imagery, commercial copy, or the official logo. Square panels follow the workspace’s existing design preference. This is a documentation workspace, not the public Eldorado marketplace.
The publication workflow follows the persistent-mount pattern in [corp-v1/portal](https://gitea.lego-cloud.eu/corp-v1/portal/src/branch/main/.gitea/workflows/pages.yml).
+38
View File
@@ -0,0 +1,38 @@
import type {Config} from '@docusaurus/types';
import type * as Preset from '@docusaurus/preset-classic';
const config: Config = {
title: 'Eldorado Documentation',
tagline: 'A home for what comes next.',
favicon: 'img/docs-mark.svg',
url: 'https://pages.apps.lego-cloud.eu',
baseUrl: '/eldorado-v1/documentation/',
organizationName: 'eldorado-v1',
projectName: 'documentation',
trailingSlash: true,
onBrokenLinks: 'throw',
markdown: {hooks: {onBrokenMarkdownLinks: 'throw'}},
presets: [['classic', {
docs: {sidebarPath: './sidebars.ts', routeBasePath: 'docs', editUrl: 'https://gitea.lego-cloud.eu/eldorado-v1/documentation/_edit/main/'},
blog: false,
theme: {customCss: './src/css/custom.css'},
} satisfies Preset.Options]],
themes: [['@easyops-cn/docusaurus-search-local', {
hashed: 'filename', indexDocs: true, indexBlog: false, indexPages: true,
docsRouteBasePath: 'docs', language: ['en'], highlightSearchTermsOnTargetPage: true,
}]],
themeConfig: {
colorMode: {defaultMode: 'light', respectPrefersColorScheme: true},
navbar: {
title: 'Eldorado', logo: {alt: 'Documentation home', src: 'img/docs-mark.svg'},
items: [
{to: '/docs/overview/', label: 'Documentation', position: 'left'},
{to: '/docs/maintain/', label: 'Maintainer guide', position: 'left'},
{href: 'https://gitea.lego-cloud.eu/eldorado-v1/documentation', label: 'Repository', position: 'right'},
],
},
footer: {style: 'dark', copyright: 'Eldorado v1 · Documentation workspace · Purpose to be defined'},
docs: {sidebar: {hideable: true}},
} satisfies Preset.ThemeConfig,
};
export default config;
+47
View File
@@ -0,0 +1,47 @@
{
"name": "eldorado-documentation",
"version": "0.1.0",
"private": true,
"packageManager": "pnpm@10.15.1",
"engines": {
"node": ">=22"
},
"scripts": {
"start": "docusaurus start",
"build": "docusaurus build",
"serve": "docusaurus serve",
"typecheck": "tsc --noEmit",
"verify": "node scripts/verify.mjs",
"verify:build": "node scripts/verify.mjs --build"
},
"dependencies": {
"@docusaurus/core": "3.10.2",
"@docusaurus/preset-classic": "3.10.2",
"@easyops-cn/docusaurus-search-local": "0.55.3",
"@fontsource/lato": "5.2.6",
"@mdx-js/react": "3.1.1",
"clsx": "2.1.1",
"prism-react-renderer": "2.4.1",
"react": "19.1.1",
"react-dom": "19.1.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.10.2",
"@docusaurus/tsconfig": "3.10.2",
"@docusaurus/types": "3.10.2",
"@types/react": "19.1.13",
"typescript": "5.9.3"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 3 chrome versions",
"last 3 firefox versions",
"last 5 safari versions"
]
}
}
+12288
View File
File diff suppressed because it is too large. Load diff
+5
View File
@@ -0,0 +1,5 @@
packages:
- '.'
onlyBuiltDependencies:
- core-js
- core-js-pure
+31
View File
@@ -0,0 +1,31 @@
import assert from 'node:assert/strict';
import {readFileSync, readdirSync, existsSync} from 'node:fs';
import {join} from 'node:path';
const read = p => readFileSync(p, 'utf8');
const config = read('docusaurus.config.ts');
assert(config.includes("baseUrl: '/eldorado-v1/documentation/'"));
assert(config.includes("onBrokenLinks: 'throw'"));
assert(config.includes("hashed: 'filename'"));
for (const file of readdirSync('docs')) {
const doc = read(join('docs', file));
assert(/^---\n[\s\S]*?title: .+\n[\s\S]*?description: .+\n/.test(doc), `Missing metadata: ${file}`);
}
const css = read('src/css/custom.css');
assert(css.includes('#ffc950') && css.includes('@fontsource/lato/400.css'));
const workflow = read('.gitea/workflows/pages.yml');
assert(workflow.includes('mountpoint -q'));
assert(workflow.includes("gitea.event_name == 'push' && gitea.ref == 'refs/heads/main'"));
if (process.argv.includes('--build')) {
for (const route of ['index.html','docs/overview/index.html','docs/maintain/index.html','docs/reference/index.html','404.html']) {
assert(existsSync(join('build',route)), `Missing route: ${route}`);
}
const home = read('build/index.html');
assert(home.includes('A home for') && home.includes('what comes next.'));
assert(home.includes('/eldorado-v1/documentation/assets/'));
const search = readdirSync('build').filter(f => /^search-index.*\.json$/.test(f));
assert(search.length > 0, 'Missing search index');
assert(search.some(f => read(join('build',f)).includes('publish')), 'Missing indexed content');
assert(readdirSync('build/assets/fonts').some(f => f.endsWith('.woff2')), 'Missing bundled fonts');
assert(!home.includes('Docusaurus tutorial'));
}
console.log('PASS: ' + (process.argv.includes('--build') ? 'source + built routes, search and fonts' : 'source contracts'));
+3
View File
@@ -0,0 +1,3 @@
import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
const sidebars: SidebarsConfig = {docsSidebar: ['overview', 'maintain', 'reference']};
export default sidebars;
+99
View File
@@ -0,0 +1,99 @@
@import '@fontsource/lato/400.css';
@import '@fontsource/lato/700.css';
@import '@fontsource/lato/900.css';
:root {
--ifm-font-family-base: 'Lato', sans-serif;
--ifm-heading-font-weight: 900;
--ifm-color-primary: #805b00;
--ifm-color-primary-dark: #735200;
--ifm-color-primary-darker: #6d4d00;
--ifm-color-primary-darkest: #594000;
--ifm-color-primary-light: #8d6400;
--ifm-color-primary-lighter: #936900;
--ifm-color-primary-lightest: #a67600;
--ifm-background-color: #f6f6f6;
--ifm-background-surface-color: #fff;
--ifm-color-content: #14131a;
--ifm-global-radius: 0;
--ifm-code-border-radius: 0;
--ifm-button-border-radius: 0;
--ifm-navbar-height: 76px;
--ifm-line-height-base: 1.7;
--gold: #ffc950;
--surface: #fff;
--muted: #62616b;
--line: #dedee3;
}
[data-theme='dark'] {
--ifm-color-primary: #ffc950;
--ifm-color-primary-dark: #ffc035;
--ifm-color-primary-darker: #ffb91e;
--ifm-color-primary-darkest: #efaa00;
--ifm-color-primary-light: #ffd46d;
--ifm-color-primary-lighter: #ffdc86;
--ifm-color-primary-lightest: #ffe6a6;
--ifm-background-color: #14131a;
--ifm-background-surface-color: #222127;
--ifm-color-content: #f6f6f6;
--surface: #222127;
--muted: #b8b7c0;
--line: #37363f;
}
.navbar {background: #101014; border-bottom: 1px solid #35343d; box-shadow: none; padding: 0 2rem;}
.navbar__title {font-size: 1.7rem; color: #fff; letter-spacing: -.6px;}
.navbar__logo {height: 38px; margin-right: .75rem;}
.navbar__link {color: #d5d4dc; font-weight: 700; font-size: .95rem;}
.navbar__link:hover, .navbar__link--active {color: var(--gold);}
.navbar__toggle, .navbar button {color: #fff;}
.navbar-sidebar {background: #1f1f29; --ifm-menu-color: #eee; --ifm-menu-color-active: #ffc950; --ifm-menu-color-background-active: #303039;}
.navbar-sidebar__back {color: #fff;}
.navbar input {background-color: #28272e; color: #fff; border: 1px solid #41404c; border-radius: 0;}
.navbar input::placeholder {color: #cccbd1;}
.docs-hero {overflow: hidden; color: #fff; background: #1f1f29; border-bottom: 4px solid var(--gold);}
.hero-inner {max-width: 1240px; margin: auto; padding: 76px 40px 82px; display: grid; grid-template-columns: 1.15fr 1fr; gap: 50px; align-items: center;}
.eyebrow {font-size: .75rem; font-weight: 900; letter-spacing: .16em; margin-bottom: 18px;}
.hero-copy .eyebrow {color: var(--gold);}
.hero-copy h1 {font-size: clamp(2.8rem, 4.7vw, 4.2rem); letter-spacing: -.045em; line-height: 1.08; margin-bottom: 24px;}
.hero-copy h1 span {color: var(--gold);}
.hero-description {font-size: 1.17rem; color: #d1d0d8; max-width: 410px; margin-bottom: 28px;}
.button--primary {background: var(--gold); border-color: var(--gold); color: #14131a; font-weight: 900;}
.button--primary:hover {background: #ffd778; border-color: #ffd778; color: #14131a;}
.button--primary span {padding-left: 24px;}
.hero-note {font-size: .8rem; margin: 14px 0 0; color: #b1b0bc;}
.hero-art {position: relative; height: 340px;}
.art-grid {position: absolute; inset: -25px; background-image: linear-gradient(#ffffff09 1px,transparent 1px),linear-gradient(90deg,#ffffff09 1px,transparent 1px); background-size: 36px 36px; transform: rotate(-8deg);}
.document-sheet {position: absolute; width: 245px; height: 292px; left: 50%; top: 8px;}
.sheet-back {background: #87682e; transform: translateX(-36%) rotate(10deg); border: 1px solid #c39335;}
.sheet-front {background: var(--gold); color: #14131a; transform: translateX(-60%) rotate(-7deg); padding: 25px; box-shadow: 14px 20px 0 #0002;}
.sheet-tag {font-size: .65rem; font-weight: 900; letter-spacing: .14em;}
.sheet-title {display: block; font-weight: 900; font-size: 2.5rem; letter-spacing: -.055em; line-height: 1.1; margin: 30px 0 23px;}
.sheet-line {display: block; height: 3px; background: #14131a5c; margin: 10px 0; width: 85%;}
.sheet-line.short {width: 58%;}
.sheet-number {display: block; font-size: .6rem; font-weight: 900; margin-top: 25px; letter-spacing: .08em;}
.art-label {position: absolute; bottom: -1px; left: 8%; right: 3%; background: #101014; border: 1px solid #4b4850; padding: 14px 18px; font-size: .62rem; letter-spacing: .12em; font-weight: 700;}
.art-label span {float: right; color: var(--gold); font-size: 1rem;}
.start-section {max-width: 1240px; padding: 48px 40px 64px;}
.section-heading {display: flex; justify-content: space-between; align-items: center; gap: 20px; margin-bottom: 25px;}
.section-heading .eyebrow {color: var(--muted); margin-bottom: 8px;}
.section-heading h2 {font-size: 1.8rem; letter-spacing: -.03em; margin: 0;}
.foundation-badge {font-size: .75rem; border: 1px solid var(--line); padding: 5px 12px; color: var(--muted); white-space: nowrap;}
.start-grid {display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;}
.start-card {display: flex; flex-direction: column; padding: 27px; background: var(--surface); border: 1px solid var(--line); color: var(--ifm-color-content); transition: border-color .15s, transform .15s;}
.start-card:hover {color: var(--ifm-color-content); text-decoration: none; border-color: #b88719; transform: translateY(-3px);}
.card-number {font-size: .65rem; font-weight: 900; letter-spacing: .11em; color: var(--muted); margin-bottom: 23px;}
.start-card h3 {font-size: 1.4rem; margin-bottom: 10px;}
.start-card p {color: var(--muted); font-size: .95rem; flex: 1;}
.card-action {font-weight: 700; font-size: .85rem; border-top: 1px solid var(--line); padding-top: 17px; margin-top: 10px;}
.card-action span {float: right;}
.scope-note {margin-top: 28px; padding: 22px 25px; display: flex; gap: 18px; border-left: 3px solid var(--gold); background: var(--surface);}
.scope-symbol {font-size: 1.65rem; color: var(--ifm-color-primary);}
.scope-note p {color: var(--muted); font-size: .9rem; margin: 3px 0 0;}
.footer {background: #101014; color: #afadb9; font-size: .8rem; padding: 27px;}
.theme-doc-markdown {max-width: 850px;}
.theme-doc-markdown h1 {letter-spacing: -.035em;}
.pagination-nav__link, .menu__link, .theme-admonition, pre {border-radius: 0;}
a:focus-visible, button:focus-visible {outline: 3px solid #b88719; outline-offset: 4px;}
@media (max-width: 996px) {.navbar {padding: 0 1rem;} .hero-inner {gap: 15px; padding: 55px 25px;} .hero-art {transform: scale(.85);} .start-section {padding: 35px 25px;} .start-card {padding: 20px;}}
@media (max-width: 700px) {.hero-inner {grid-template-columns: 1fr; padding: 45px 24px;} .hero-art {display: none;} .hero-copy h1 {font-size: 3rem;} .start-grid {grid-template-columns: 1fr;} .section-heading {align-items: flex-start;} .foundation-badge {display: none;} .start-section {padding: 32px 20px;} .navbar__title {font-size: 1.45rem;} .navbar__logo {height: 31px;} .navbar input {max-width: 145px;} .button--lg {font-size: .95rem;} .button--primary span {padding-left: 10px;}}
@media (prefers-reduced-motion: reduce) {.start-card {transition: none;} .start-card:hover {transform: none;}}
+36
View File
@@ -0,0 +1,36 @@
import React from 'react';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';
export default function Home(): React.ReactElement {
return <Layout title="Home" description="The starting point for Eldorado documentation. Purpose and audience will be defined next.">
<main>
<section className="docs-hero">
<div className="hero-inner">
<div className="hero-copy">
<p className="eyebrow">ELDORADO / DOCUMENTATION</p>
<h1>A home for<br/><span>what comes next.</span></h1>
<p className="hero-description">The foundation is here. The story is still yours to define.</p>
<Link className="button button--primary button--lg" to="/docs/overview/">Explore the documentation <span aria-hidden="true">→</span></Link>
<p className="hero-note">A starting point. Not a finished knowledge base.</p>
</div>
<div className="hero-art" aria-hidden="true">
<div className="art-grid"/>
<div className="document-sheet sheet-back"/>
<div className="document-sheet sheet-front"><span className="sheet-tag">ELDORADO V1</span><span className="sheet-title">An open<br/>chapter.</span><span className="sheet-line"/><span className="sheet-line short"/><span className="sheet-number">01 / DOCUMENTATION</span></div>
<div className="art-label">SPACE FOR YOUR NEXT IDEA <span>↗</span></div>
</div>
</div>
</section>
<section className="start-section container" aria-labelledby="start-title">
<div className="section-heading"><div><p className="eyebrow">START HERE</p><h2 id="start-title">A clear place to begin.</h2></div><span className="foundation-badge">Foundation · v1</span></div>
<div className="start-grid">
<Link className="start-card" to="/docs/overview/"><span className="card-number">01 / OVERVIEW</span><h3>What’s here</h3><p>Understand the starting point and what remains to be decided.</p><span className="card-action">Read the overview <span aria-hidden="true">↗</span></span></Link>
<Link className="start-card" to="/docs/maintain/"><span className="card-number">02 / MAINTENANCE</span><h3>Make it your own</h3><p>Add a page, preview a change, and publish through the existing pipeline.</p><span className="card-action">Open the guide <span aria-hidden="true">↗</span></span></Link>
<Link className="start-card" to="/docs/reference/"><span className="card-number">03 / REFERENCE</span><h3>Under the hood</h3><p>Find the repository layout, build commands, and publication details.</p><span className="card-action">View the reference <span aria-hidden="true">↗</span></span></Link>
</div>
<aside className="scope-note"><span className="scope-symbol" aria-hidden="true">✦</span><div><strong>Ready for direction.</strong><p>The documentation’s purpose, audience, and content structure will be agreed later. No product scope is implied by this starter.</p></div></aside>
</section>
</main>
</Layout>;
}
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><rect width="48" height="48" fill="#ffc950"/><path d="M13 11h22v26H13z" fill="none" stroke="#14131a" stroke-width="3"/><path d="M19 19h10m-10 6h10m-10 6h6" stroke="#14131a" stroke-width="3"/></svg>

After

Width:  |  Height:  |  Size: 258 B

+10
View File
@@ -0,0 +1,10 @@
{
"extends": "@docusaurus/tsconfig",
"compilerOptions": {
"baseUrl": "."
},
"exclude": [
"build",
"node_modules"
]
}