@galaxy/docs — the galaxy-docs reading site
engineering-apps-docs-readme · in engineering/apps/docs · org-wide · updated 2026-06-01 10:19
Frontmatter
- lang
- en
- imported_at
- 2026-06-01T10:19:40.086Z
- source_path
- productgalaxy/apps/docs/README.md
- source_repo
- productgalaxy
@galaxy/docs — the galaxy-docs reading site
Astro 6 + Starlight + Tailwind 4 public READING surface for the 5th product
(galaxy-docs). Fetches notes from Galaxy's /api/v1/notes at request time via
Astro 6 live content collections, with a build-time snapshot for fast first paint.
- Authoring happens in the Galaxy admin UI at
/admin/notes/(Next.js, owned by the Phase 4.5 agent). - Reading happens here, at
docs.galaxy.example.com. - Vault export / import for Obsidian round-trip is owned by the Phase 4.6 agent.
This app is server-rendered (output: 'server', Node adapter). Live content
collections + Caddy/Cloudflare cache headers give us ISR-style behavior — fresh on
edit, snappy on repeat hits.
Quick start (local)
# From the monorepo root:
cp apps/docs/.env.example apps/docs/.env
# Then edit apps/docs/.env to set GALAXY_API_URL + GALAXY_DOCS_API_TOKEN.
pnpm install
pnpm --filter @galaxy/docs dev
# → http://localhost:4321
To point at the staging Galaxy API without running a local Galaxy:
# In apps/docs/.env:
GALAXY_API_URL=https://staging-api.galaxy.example.com
GALAXY_DOCS_API_TOKEN=<bearer-jwt-from-the-staging-galaxy-docs-site-oauth-client>
The token is a short-lived JWT issued by the galaxy-docs-site OAuth client
(Client Credentials Flow). Refresh every 15 min — the loader handles refresh
automatically when given a refresh token in a future iteration. For now, generate
a fresh token before each long dev session:
curl -sX POST $GALAXY_API_URL/oauth/token \
-d 'grant_type=client_credentials' \
-d "client_id=galaxy-docs-site" \
-d "client_secret=$GALAXY_DOCS_SITE_CLIENT_SECRET" \
| jq -r .access_token
Build & preview
pnpm --filter @galaxy/docs build # → apps/docs/dist/
pnpm --filter @galaxy/docs preview # → http://localhost:4321 (production preview)
The build snapshots up to GALAXY_DOCS_BUILD_SNAPSHOT_LIMIT (default 500) notes
into a build-time index that pages can consult without a network round-trip. Live
content collections handle everything else at request time.
If Galaxy is unreachable at build time, the snapshot is skipped (logged warning, no error). The site still serves correctly — it just falls back to live fetches for everything.
Deploy via docker-compose
The docs service is declared in
/Users/parhumm/Projects/SabaIdea/productgalaxy/docker-compose.yml. Image build
is multi-stage from apps/docs/Dockerfile.
# Build + bring up the docs container (plus its app + postgres dependencies):
docker compose build docs
docker compose up -d docs
# Tail logs:
docker compose logs -f docs
# Restart after env change (Compose picks up .env changes automatically):
docker compose up -d --force-recreate docs
Production deploys go through Haloy CLI (/Users/parhumm/Projects/SabaIdea/productgalaxy/CLAUDE.md
§15: "Zero-downtime deploys via Haloy CLI (layer-only image push + atomic swap)").
Do NOT use docker compose up directly in production.
Layout
apps/docs/
├── astro.config.mjs # Astro 6 + Starlight + Tailwind 4 + sitemap, SSR
├── astro.starlight.config.ts # Starlight options (sidebar, i18n, pagefind)
├── tailwind.config.mjs # Tailwind 4 minimal config (tokens live in CSS)
├── tsconfig.json
├── env.d.ts
├── package.json
├── Dockerfile # multi-stage build
├── .env.example
├── README.md # ← you are here
└── src/
├── live.config.ts # Astro 6 LIVE content collection (request-time)
├── content.config.ts # Build-time snapshot collection
├── middleware.ts # Loads businesses + active-business cookie
├── loaders/
│ ├── galaxy.ts # Axios HTTP client (retry, RFC 9457, typed wrappers)
│ └── sidebar-plugin.ts # Starlight plugin: API-driven sidebar tree
├── components/
│ ├── Backlinks.astro # SSR backlinks panel
│ └── WikilinkRenderer.astro# Renders content_html_cache + cross-domain links
├── pages/
│ ├── index.astro # Home: recent + folders + tags + search
│ ├── health.ts # /health liveness probe
│ ├── api/
│ │ ├── business-switcher.ts # POST cookie-set
│ │ └── search.ts # GET → /api/v1/notes/search proxy
│ └── [business]/
│ ├── index.astro # Per-business landing
│ ├── [...slug].astro # Per-note view (title + body + backlinks)
│ ├── folder/[...folder].astro # Folder index view
│ └── tag/[tag].astro # Tag index view
├── styles/
│ └── global.css # Tailwind 4 import + Starlight token overrides + RTL
└── content/
└── static/welcome.md # Curated in-repo page (survives Galaxy outage)
Operator FAQ
The sidebar is empty / says "businesses fetch failed".
The galaxy-docs-site OAuth client either isn't issued yet or lacks
businesses:read scope. Re-issue via Galaxy admin → OAuth clients → rotate.
Persian (fa) notes show in the wrong direction.
Ensure frontmatter.lang: fa is set on the note. The reader uses
frontmatter.lang (NOT a separate column) to flip dir="rtl".
Wikilink [[issue:TVK-AI-008]] is not clickable.
Check that PUBLIC_PRODUCT_AUDITS_URL is set in .env. The reader rewrites the
cross-domain placeholder href to that target.
Search returns 0 hits for a recently-added note.
Pagefind indexes only the build-time snapshot. For live notes, the search box
falls back to /api/search (which proxies /api/v1/notes/search). Confirm the
endpoint is reachable: curl $GALAXY_API_URL/api/v1/notes/search?q=hello -H "Authorization: Bearer …".
I edited a note in admin but the docs site still shows the old version.
Live content cache TTL is 60s by default (GALAXY_DOCS_CACHE_TTL). Hit refresh
after the TTL or set GALAXY_DOCS_CACHE_TTL=0 for instant updates during edit
sessions.
Related
- Plan:
/Users/parhumm/.claude/plans/now-plan-to-new-spicy-dragonfly.md§ "2. Reading surface — dedicated docs siteapps/docs/". - Research:
/Users/parhumm/Projects/SabaIdea/productgalaxy/jaan-to/outputs/pm-research/docs-research.md. - Architecture:
/Users/parhumm/Projects/SabaIdea/productgalaxy/docs/architecture/ADR-003-batch-3-stack-lockin.md. - Docs cache (libraries used here):
jaan-to/outputs/docs-cache/astro-6/jaan-to/outputs/docs-cache/astro-live-content-collections/jaan-to/outputs/docs-cache/starlight/jaan-to/outputs/docs-cache/portaljs-remark-wiki-link/