noz-studio/CLAUDE.md
kryptomrx 3f9553cff4 feat: initial commit — noz-studio web editor
Full-featured web editor PWA for noz, built with Next.js and CodeMirror 6.

Editor:
- CM6-based Markdown editor with iA Writer aesthetic and Typora-style marker hiding
- Live preview with KaTeX math, highlight.js syntax highlighting, wikilink rendering
- Wikilink autocomplete via server note graph ([[  triggers suggestion list)
- Floating selection toolbar, format toolbar, status bar
- Split / editor-only / preview-only view modes with resizable panels
- Visual frontmatter panel (no raw YAML editing required)

Navigation:
- Folder tree with topics, sub-topics, drafts section
- Create / rename / move / delete notes and folders
- Diagram editor (TOML definition → canvas visualization)

Search:
- ⌘K command palette with scoped search (@topic, @web, @draft)

Preview:
- Broken wikilink detection with visual indicator and toast notification
- Fragment links: [[note#section]] navigates and scrolls to heading
- In-page links: [[#section]] scrolls without switching notes
- Heading anchors auto-generated from heading text

Auth:
- Token / Authentik SSO / both — driven by noosphere.toml
- sessionStorage only (no localStorage — prevents credential leaks on shared devices)

i18n: German + English
2026-05-18 16:05:11 +02:00

9.1 KiB
Raw Blame History

noz-studio — Projektübersicht für Claude

Kommunikation: Deutsch. Alle Konversationen, Commit-Messages, Kommentare und UI-Labels auf Deutsch.

Was ist noz-studio?

noz-studio ist der Web-Editor für noz — ein vollständiger Markdown-Editor als PWA, optimiert für Desktop und Mobile (Touch). Gedacht für Situationen wo noz-cli nicht verfügbar ist (Arbeit, unterwegs, fremdes Gerät).

noz-studio ist ein Client. Es schreibt keinen eigenen Content-Store — es spricht ausschließlich gegen die noz-API. Die einzige Verbindung zwischen noz und noz-studio sind API-Endpunkte.

noz (Server + API)  ←──────────────────────────
        ↑                  ↑              ↑
    noz-cli            noz (public)   noz-studio
   (Terminal)          (Leser)        (Web-Editor)

Stack

  • Next.js (App Router) — gleicher Stack wie noz
  • CodeMirror 6 — Editor-Engine (MIT-Lizenz) — NUR als Engine, alles außen rum ist custom
  • Tailwind CSS v4 — OKLCH-Farben, gleiche Palette wie noz aber eigene Design-Sprache
  • PWAmanifest.json + Service Worker — installierbar auf iOS/Android/Desktop

Design-Prinzipien

  • iA Writer-Feel — fokussiert, clean, Typografie im Vordergrund
  • Affine-like — immer offen, kein "speichern"-Stress
  • Kein localStorage für Credentials — Token in sessionStorage (Tab zu → Token weg, kein Datenleak auf Arbeitsrechnern)
  • noosphere.toml als Single Source of Truth — Studio liest Config vom Server, nie hardcoden
  • CM6 ist swappable — EditorEngine-Interface abstrahiert die Implementierung

Auth-System

Konfiguriert in noosphere.toml des noz-Servers:

[studio]
auth         = "token"      # "token" | "authentik" | "both"
allow_delete = true
allow_push   = true
allow_rebuild = false

Studio macht beim Start einen public Request ohne Token:

GET /api/studio/config  →  { auth: "token" | "authentik" | "both", name: "...", lang: "..." }

Daraufhin zeigt der Login-Screen die passende UI (Token-Formular, Authentik-SSO-Button, oder beides).

Token-Handling:

  • Gespeichert in sessionStorage — nie localStorage
  • Tab schließen = Token weg = kein Datenleak auf fremden Geräten
  • Gleicher Token wie [cli] in noosphere.toml

Draft-System (3 Stufen)

[ Draft ]  →  [ In Review ]  →  [ Live ]
Stufe Speicherort Sichtbar auf noz? Wer sieht es?
Draft content/noosphere/_drafts/notiz.md Nein (Index-Builder überspringt _-Ordner) Nur Studio
In Review content/noosphere/topic/notiz.md + draft: true im Frontmatter Nur via Authentik/Vault Eingeloggte User
Live content/noosphere/topic/notiz.md (kein draft-Flag) Ja, öffentlich Alle

Der Draft-Button im Editor-StatusBar toggelt zwischen den Stufen. Studio kümmert sich um:

  • Datei verschieben (_drafts/ → topic-Ordner)
  • Frontmatter draft: true/false setzen
  • Index-Rebuild triggern (wenn allow_rebuild = true)

EditorEngine-Interface (CM6 swappable)

// src/components/editor/engine.ts
interface EditorEngine {
  getValue(): string
  setValue(content: string): void
  onSave(callback: (value: string) => void): void
  focus(): void
  destroy(): void
}
// src/components/editor/cm6-adapter.ts
class CM6Adapter implements EditorEngine { ... }
// src/components/editor/editor-wrapper.tsx
// Kennt nur EditorEngine, nie direkt CM6

Wenn CM6 irgendwann getauscht wird → nur cm6-adapter.ts anfassen.


Projektstruktur

noz-studio/
  src/
    app/
      page.tsx                  # → redirect /editor oder /login
      login/
        page.tsx                # Login-Screen (token | authentik | both — je nach config)
      editor/
        page.tsx                # Haupt-Editor: Sidebar + Editor + Preview
    components/
      editor/
        engine.ts               # EditorEngine Interface
        cm6-adapter.ts          # CM6 implementiert EditorEngine
        editor-wrapper.tsx      # React Component — bindet Adapter ein
        toolbar.tsx             # Formatting-Toolbar (Bold, Italic, Link, Bild...)
        status-bar.tsx          # Wortanzahl, Status-Badge, Draft-Button, Sprache
      sidebar/
        folder-tree.tsx         # Topic/Folder Navigation (wie noz Folder-View)
        note-list.tsx           # Notes im aktuellen Ordner
        draft-badge.tsx         # Visueller Draft-Indikator
      preview/
        preview.tsx             # Live-Preview (KaTeX, Wikilinks, Bilder, Tabellen)
      auth/
        token-form.tsx          # Token-Login Formular
        authentik-button.tsx    # Authentik SSO Button
    lib/
      api.ts                    # Alle API-Calls zu noz (einzige Stelle die fetch aufruft)
      auth.ts                   # Token lesen/schreiben (sessionStorage)
      config.ts                 # Studio-Config vom Server cachen
    hooks/
      use-notes.ts              # Notes laden, CRUD
      use-editor.ts             # Editor-State, Auto-Save
      use-config.ts             # noosphere.toml Config
  public/
    manifest.json               # PWA Manifest
    icons/                      # App-Icons (512x512, 192x192, maskable)
  next.config.ts

Features

Editor — gebaut ✓

  • Markdown-Editor (CM6, iA Writer-Feel)
  • Live-Preview (rechts, togglebar — raw / split / rendered)
  • KaTeX Math ($...$ und $$...$$)
  • Syntax-Highlighting für Code-Blöcke (highlight.js)
  • Formatierungs-Toolbar (Bold/Italic/Strike/H1H3/Link/Code/Bild/Mathe/Wikilink/…)
  • Floating Selection-Toolbar (erscheint bei Textauswahl)
  • Einstellungs-Modal (Affine-Stil, vollseitig)
  • ⌘K Command Palette (Scoped Search: @topic, @web, @draft)
  • Resizable Sidebar (160360px) + Resizable Preview (200640px)
  • Glassmorphism Navbar (vereint Format-Toolbar + View-Toggle + Suche)

Editor — geplant

  • Typora-Style: **fett** sofort fett (CM6 Decorations)
  • / Slash-Command-Menü (wie Notion/AFFiNE)
  • Wikilink-Autocomplete ([[ → Vorschläge)
  • Bild-Upload (Drag & Drop → Upload → ![](url))

Navigation — gebaut ✓

  • Folder-Tree (Topics → Notes, Unterordner-Unterstützung via subTopics)
  • Draft-Bereich (eigener _drafts-Bereich)
  • Note umbenennen (inline, im Tree)
  • Ordner erstellen (root + Unterordner)
  • Ordner umbenennen (inline)
  • Note verschieben (Kontextmenü → Ordner-Auswahl)

Navigation — geplant

  • Meilisearch-Integration (/api/search)
  • Note löschen (mit Bestätigungs-Dialog)

Verwaltung — geplant

  • Neue Notiz (Frontmatter-Wizard)
  • 3-Stufen Draft-Button (Draft → In Review → Live)
  • Frontmatter visuell editieren

PWA / Mobile — geplant

  • Installierbar (manifest.json)
  • Touch-optimiert (Bottom-Navigation auf Mobile)

Verbindung zu noz

noz-studio braucht neue API-Routen in noz (noch nicht gebaut — werden nach dem Studio-Design spezifiziert):

GET    /api/studio/config              # public — Auth-Methode + Site-Config
GET    /api/cli/notes                  # alle Notes (meta)
GET    /api/cli/notes/:slug            # Raw Markdown
POST   /api/cli/notes                  # neue Note — { slug, title, topic, status, lang, content }
PUT    /api/cli/notes/:slug            # Note aktualisieren
DELETE /api/cli/notes/:slug            # Note löschen
POST   /api/cli/notes/:slug/rename     # umbenennen — { newTitle } — Server rewritet Wikilinks
POST   /api/cli/notes/:slug/move       # Note verschieben — { newTopic } — Server rewritet Wikilinks
GET    /api/cli/templates              # Templates
POST   /api/cli/rebuild                # build:index triggern

POST   /api/cli/folders                # Neuer Ordner — { slug, parent? } — legt _index.md an
PUT    /api/cli/folders/:slug          # Ordner umbenennen — { newSlug } — Server rewritet ALLE internen Links
DELETE /api/cli/folders/:slug          # Ordner löschen (nur wenn leer — sonst 409)

Alle außer /api/studio/config erfordern Authorization: Bearer <token>.

Wenn eine Note verschoben wird (/move) oder ein Ordner umbenannt wird (PUT /folders):

  1. Datei/Verzeichnis physisch verschieben
  2. In allen .md-Dateien des Content-Stores Wikilinks ersetzen:
    • Note-Move: [[alter-topic/note-slug]][[neuer-topic/note-slug]]
    • Folder-Rename: [[alter-ordner/...]][[neuer-ordner/...]]
  3. Index-Rebuild triggern (wenn allow_rebuild = true)

Kurzform: [[slug]] ohne Topic-Prefix bleibt unverändert — nur vollqualifizierte Slugs werden rewritten.


Design-System

Gleiche OKLCH-Palette wie noz (globals.css), aber eigene Layout-Sprache:

  • Dark by default (Editor-Feeling)
  • Newsreader für Headings (italic), Inter für UI, JetBrains Mono im Editor
  • Kein Prose-Layout — Editor ist das Zentrum

Layouts:

  • Desktop: [Sidebar 260px] [Editor flex] [Preview flex]
  • Mobile: Bottom-Nav + Fullscreen-Editor + Swipe zwischen Editor/Preview