11 Commits

Author SHA1 Message Date
stephan
ab897b8a81 Wire Google Analytics 4 (G-V8QWB45G6X) alongside Umami
Adds gtag.js to the production head so Search Console can cross-reference
GA traffic. Same gating as Umami — production builds only, never injected
on dev. Three head entries:

  1. Umami (kept) — self-hosted, DNT-aware, GDPR-light
  2. Google's gtag loader (async)
  3. Inline init: window.dataLayer + gtag('config', 'G-V8QWB45G6X')

Both analytics run side-by-side; pick one or both in the GA dashboard.
A GDPR consent banner is not added — configure IP anonymisation +
consent mode v2 in the GA property settings if you intend to serve EU
visitors without explicit cookie acceptance.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 20:02:45 +02:00
stephan
937b4e40a8 Add BingSiteAuth.xml for Bing Webmaster Tools site verification
Bing's verifier probes /BingSiteAuth.xml at the apex. Anything in
docs/public/ is copied verbatim to the site root by Astro, so this lands
at https://nibiru-framework.com/BingSiteAuth.xml after the next
production rebuild.

Token: 0907F98391491C32C3B25FD8810BBDC2

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:45:49 +02:00
stephan
47bd4bf53f Expose /sitemap.xml for Bing + IndexNow
Astro's sitemap integration emits /sitemap-index.xml + /sitemap-0.xml. Bing
Webmaster Tools and IndexNow probe /sitemap.xml literally, so a request
for the canonical name was 404'ing. Two changes:

- astro.config.mjs: add a 301 redirect /sitemap.xml → /sitemap-index.xml
  (alongside the existing / → /en/ redirect)
- public/robots.txt: list both Sitemap URLs so any crawler that reads
  robots.txt finds an entry it can use directly

After production redeploys (`docker compose up -d --build`), submit
https://nibiru-framework.com/sitemap.xml in Bing Webmaster Tools — it'll
follow the 301 and ingest the index.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:42:22 +02:00
stephan
f8f58c4ab9 Sweep: link fixes, splash i18n parity, neuronetz badge, mobile, training source
LINK AUDIT — every internal link now resolves to a real page:
  - BrandHeader doc-nav 'Showcase' target → /{locale}/showcase/projects/
    (the showcase/ directory has no index, only patterns/projects)
  - Translated-slug bugs across de/es/fr/ja: ~30 broken links from the
    overnight translator that auto-localised path segments. Mapped back to
    the actual English slugs:
      de:  warum-nibiru → why-nibiru, kuenstliche-intelligenz/orakel → ai/oracle,
           kI/modul/* → ai/module/*, praesentation/projekte → showcase/projects
      es:  ai/modulo/* → ai/module/*, diseno/* → design/*,
           porque-nibiru / por-que-nibiru → why-nibiru,
           presentacion/proyectos → showcase/projects
      fr:  ia/module/* → ai/module/*, ia/module/formation → ai/module/training,
           pourquoi-nibiru → why-nibiru, presentation/projets → showcase/projects
      ja:  ai/milestones → ai/roadmap
  - Cross-locale leaks: bare `/ai/oracle` (no locale) → `/{locale}/ai/oracle/`
    in de/index.mdx, fr/index.mdx, fr/ai/module/overview.md, en/ai/corpus.md
  - `/en/start/` (which 404s — start/ has no index) was hardcoded in five
    design/components.md atelier-button hrefs across all locales →
    `/{locale}/start/installation/`
  - `/en/reference` removed from en/downloads.mdx — the reference doc tree
    isn't built yet; replaced with a github link to the v2 markdown source
  - Collapsed stray double-slashes (`/de/why-nibiru//` etc.) introduced by
    the slug-replacement sed sweep

Final audit shows 0 broken internal links (down from ~37).

TRAINING SOURCE NOW SHIPS — root cause of "I cannot find the training data
in the repository": the curated source files were gitignored.
  - .gitignore at scripts/extraction/ now whitelists framework-reference-v2.md
    and lora-augmentation.summary.txt alongside lora-augmentation.jsonl
  - The 1620-line v2 reference, the 323-record augmentation jsonl, and the
    summary report all enter the repo so the production Docker build sees
    them and contributors can find them by browsing gitea

NEURONETZ AI DEEPLINK BADGE — small "AI by Neuronetz ↗" pill in the splash
footer's bottom strip. Logo mark mirrored locally to
public/img/external/neuronetz-mark.svg (pulled from neuronetz.ai/favicon.svg)
so the page doesn't hot-link off-domain on every paint. Magenta border on
hover; opens neuronetz.ai in a new tab with rel=noopener.

SPLASH I18N PARITY — de/es/fr/ja index.mdx now import + render the same
component stack as en (CometTrail · MmvcStage · MissionControl · LaunchSequence
· SpacecraftGrid · EditorialContent · LandingFooter · ToTop · LandingScripts),
so every locale shows the full splash structure. The component bodies
themselves are still English (proper i18n is the next step); for now this
brings structural parity.

MOBILE RESPONSIVE SWEEP:
  - LandingFooter: 4-col grid stacks 2-col @ 768px and 1-col @ 480px;
    bottom strip wraps vertical at 480px
  - MmvcStage: 5-step progress rail tightens its gaps under 720px and
    drops the bar segments entirely under 480px so the labels fit
  - Docs bridge §11: tighter H1/H2 spacing, breadcrumbs/doc-meta on
    narrow viewports, pagination cards stack 1-col, help-strip stacks
    vertical, tables get horizontal-scroll on overflow
  - Doc-header: nav-version chip hides under 480px so the search-pill
    + brand fit comfortably

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 19:36:25 +02:00
stephan
22392161ba LoRA augmentation: 196 → 323 records (full agent run)
Earlier commit captured a partial 196-record file because the background
research agent was still writing when the commit landed. The agent has
since completed with 323 high-quality records.

New distribution by kind:
  121 code-recall · 97 workflow · 29 inikey · 26 comparison
   16 gotcha · 16 debug · 15 edge-case · 3 refactor

All 323 lines are valid JSON, all carry instruction/input/output plus
metadata.{language, source, section, kind, citations}. Every answer has
a real file:line citation or quoted code from framework-reference-v2.md
(no hedging language allowed in agent output).

Effect on en-language corpus:
  before: 1264 records per format
  after:  ~1545 records per format (+281 from augmentation × ~1)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:31:18 +02:00
stephan
83d99eff60 Whitelist lora-augmentation.jsonl in extraction/ .gitignore
The inner .gitignore at docs/scripts/extraction/.gitignore blanket-ignored
*.md/*.json/*.jsonl so research-agent transcripts wouldn't drift in. The
curated augmentation file needs an explicit exception so the Docker build
step on production can read it during `node scripts/build-corpus.mjs`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:26:26 +02:00
stephan
f4ccc45a3b Strip api.neuronetz.ai from documentation; chat config stays in env
The Ollama URL was leaking via:
  - prose in /en/, /de/, /ja/, /es/, /fr/ docs (oracle, deployment,
    local-testing, ai/module/{overview,embed,training})
  - code blocks teaching users to curl the host directly
  - .env.example, Dockerfile, docker-compose.yml defaults
  - providers.mjs, translate-docs.mjs, build-oracle-index.mjs defaults
  - LandingScripts.astro comment
  - lora-runbook.md prose + SSH host
  - the GET handler at /api/oracle which echoed `ollamaUrl` back to public callers
  - the "Oracle is silent" fallback message at /api/oracle POST

Replacements:
  - prose: "neuronetz.ai" → "your Ollama instance"
  - example URLs in code blocks: https://api.neuronetz.aihttps://your-ollama-host.example
  - code-level defaults: → http://localhost:11434 (Ollama's standard local port)
  - GET /api/oracle: dropped the `ollamaUrl` field; provider + model still exposed
  - runbook SSH host: neuronetz@cloud.neuronetz.ai → <gpu-user>@<gpu-host>

Production chat is unaffected: docs/.env (gitignored) on the production
host still pins OLLAMA_BASE_URL=https://api.neuronetz.ai. The only
change in the running container is that the GET handler no longer
echoes the URL.

analytics.neuronetz.ai (Umami tracking) is intentionally left intact —
it's a public, brand-owned subdomain meant to be visible.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:14:17 +02:00
stephan
9b7fd15ca1 Drop nested location blocks from nginx vhost overrides — they 404 assets
The first version of vhost.d/<host>_location nested four `location { … }`
blocks (for /_astro/, images, /sw.js, /llms.txt) inside the proxy's
generated `location / { … }` to set Cache-Control. nginx accepts the
syntax, but a nested location with no `proxy_pass` directive falls through
to filesystem root and 404s the asset — which is why CSS / JS / images
were missing on the live site even though the HTML loaded fine.

Astro already emits sensible Cache-Control on hashed _astro bundles, so
we don't need the proxy to set them. Removed all four nested blocks; the
vhost.d files now only carry proxy headers, gzip, and security headers,
all of which are valid inside a location {} block without proxy_pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 16:23:11 +02:00
stephan
a44df81b71 Split docs into apex + www containers, add nginx vhost overrides
The acme-companion on the production host doesn't accept comma-separated
VIRTUAL_HOST / LETSENCRYPT_HOST values, so cert issuance was failing for
the combined `nibiru-framework.com,www.nibiru-framework.com` entry.

docker-compose.yml — now defines two services sharing the same image:
  - docs      → VIRTUAL_HOST=nibiru-framework.com (apex)
  - docs-www  → VIRTUAL_HOST=www.nibiru-framework.com (built once, reused)
A YAML anchor (x-docs-shared-env) keeps the Oracle/LLM/Anthropic config in
lockstep so the two containers can never drift.

docs/nginx/vhost.d/ — per-host nginx-proxy overrides applied at the
location-block level by jwilder/nginx-proxy. Both files set:
  - X-Forwarded-* trust + buffering off (Oracle SSE streaming)
  - HSTS / X-Content-Type / X-Frame / Referrer-Policy / Permissions-Policy
  - gzip with the right MIME set for Astro/Starlight assets
  - Aggressive cache on /_astro/ (immutable hashed bundles)
  - 30-day cache on images/fonts
  - no-store on /sw.js (so PWA updates land)
  - 24-hour cache on /llms.txt for AI crawlers
docs/nginx/README.md explains how to mount these into an existing
nginx-proxy (bind-mount + reload, or bake into the proxy image).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:45:02 +02:00
stephan
5be20ebd08 Add docs/.npmrc so the Docker build COPY succeeds
The Dockerfile's `COPY package.json package-lock.json .npmrc ./` requires
the file to exist; the build was failing on a fresh clone with
`failed to compute cache key … "/.npmrc": not found`.

Contents are intentionally minimal: silence npm's audit/funding chatter
during CI/Docker builds and enable legacy-peer-deps so Astro 6 + Starlight
0.38 + @vite-pwa/astro can install together without npm's strict peer
resolver rejecting the lockfile.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:35:54 +02:00
stephan
48c839d927 Initial public push: docs cosmos v4 + AI module + framework groundwork
This is the snapshot the production landing site (nibiru-framework.com) is
deployed from. Brings together the recent splash + docs migration to the v4
"Cosmos" design system, the new in-framework AI module, and the framework
groundwork that backs the framework-reference extraction.

What lands:
- docs/: Astro + Starlight site with the v4 dark cosmic palette, GalaxyHero
  canvas constellation, Mission Control chat (wired to /api/oracle →
  api.neuronetz.ai via providers.mjs Ollama), 5-panel MMVC stage
  (Model · AI · Module · Controller · View), translated EN/DE/JA/ES/FR
  content, PWA + sitemap + llms.txt + Umami analytics.
- docs/design-system/: canonical mockup bundle (source/index-v2.html for
  splash, source/docs-system.html + preview/ for docs, SPEC.md, tokens).
- docs/scripts/extraction/framework-reference-v2.md: deep framework
  reference (~1.6k lines, file:line citations, every public factory and
  idiom — basis for the LoRA training corpus.
- application/module/ai/: AI module with chat / embed / RAG / agent
  plugins, plus pdoQuery / httpGet / fileRead tools and Modelfile +
  smoke-test in training/.
- application/module/users/: user / ACL / form-factory traits used as the
  reference plugin pattern for the framework docs.
- application/settings/config/database/: schema + seed migrations
  including the AI module tables (200–203).
- Form factory + autogenerator changes the framework-reference-v2 covers.

Production secrets stay out: docs/.env, settings.production.ini and
ai.production.ini are all gitignored (.example files are in tree).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:22:18 +02:00