Stream Facility

Development Log

A running record of what's been built, what's underway, and what's on the horizon. Updated as the platform grows.

Last updated 2026-09-01

99

Features built

0

In progress

5

Planned

DesktopBuilt
2026-07

Stream Facility Studio v2.0.2 — Sync & Nav Fixes

Studio v2.0.2 fixes manuscript sync and the in-app navigation. Pulling from the cloud now correctly downloads your acts, chapters, and scenes — previously they were silently skipped because Studio sub-documents are indexed by draft, not by author. The nav is also cleaner: web-only links (Lobby, Library, Beta) are hidden inside the app, and the Help link goes to the live help centre.

  • ·story_acts, story_chapters, and story_scenes now sync correctly — the pull endpoint fetches them via draftId rather than authorId, which is how Studio structures its data
  • ·Desktop nav hides web-only items (Lobby, Library, Beta, Inbox, Notifications) and shows a Sync shortcut instead of the download page
  • ·Pro plan badge displays correctly on first launch before the first sync, using a local fallback rather than an empty author query
  • ·Sign Out in the desktop app now calls the Tauri IPC command directly instead of routing through NextAuth
  • ·Sync error messages are now surfaced properly — a crash in the write loop previously returned an empty response that showed as a JSON parse error
DesktopBuilt
2026-07

Stream Facility Studio — Phase 5: AI Settings & Local Providers

AI provider configuration is now built into the Studio app at /dashboard/desktop/ai. Choose Anthropic, OpenAI, or OpenRouter and paste an API key once — it's stored in the OS keychain and never written to disk or sent to the platform. Ollama and LocalAI users get automatic local-server detection at startup with a live re-detect button in settings.

  • ·Five providers: Anthropic, OpenAI, OpenRouter (cloud) + Ollama, LocalAI (local — no API key required)
  • ·API keys stored in OS keychain via Tauri keyring crate — never in SQLite, never in any plaintext file
  • ·At Studio startup, local AI servers are automatically detected; local providers configure without any API key required
  • ·Key presence is exposed as a boolean flag only — actual key values are never returned to the UI; a live re-detect option is available on demand
  • ·aiProvider-local.ts replaces aiProvider.ts via next.config.ts webpack alias — all existing AI routes (chat, generate, summarize) work offline without any changes
  • ·Settings page also shows the signed-in account and provides a Sign Out button wired to the Tauri sign_out_desktop command
  • ·Account section, provider grid, model datalist with curated suggestions, write-only key input — all in one page at /dashboard/desktop/ai
DesktopBuilt
2026-07

Stream Facility Studio — Phase 4: Bidirectional Sync Engine

The full platform — worlds, codex, series, books, drafts, and scenes — now syncs between the Studio desktop app and your Stream Facility account. Pull your entire library down to SQLite for offline use. Push scene content back when you're ready. Everything is triggered manually from /dashboard/sync so you decide when data moves.

  • ·Full library synced on pull: worlds, series, books, all codex entity types (characters, locations, items, creatures, organizations, concepts, lore, governments, magic systems, languages, religions, regions, planes), eras, world events, entity pages, and all story structure (drafts, acts, chapters, scenes)
  • ·Pull is full-replace: local SQLite cleared and repopulated from the live platform in one operation — no conflict tracking needed for read-only codex data
  • ·Push sends scene content only (last-write-wins) — draft structure is read-only offline to keep things simple
  • ·An authenticated bulk sync endpoint returns the full library in one call; the desktop session token is sent in the Authorization header
  • ·Sync state (lastPullAt, lastPushAt) stored in a local desktop_meta SQLite collection and displayed on the sync page
  • ·Sync credentials and the platform URL are injected at launch — sync routes call the live platform directly without any browser involvement
DesktopBuilt
2026-07

Stream Facility Studio — Phase 3: Local Auth & License

Sign in once and stay signed in. Studio stores a 90-day session token in the OS keychain and verifies your license file on every launch — no internet connection required after the initial activation. Expired licenses still let you write forever; only sync is gated.

  • ·Session JSON (userId, email, name, syncToken) stored in OS keychain via keyring crate — survives app restarts, OS updates, and reboots
  • ·License file is a cryptographically signed payload — the verification secret is compiled into the binary, never readable from disk or environment variables at runtime
  • ·Perpetual model: expired license shows a banner but the full writing experience remains unlocked indefinitely
  • ·Activation flow: frameless 480×480 HTML window posts credentials to /api/desktop/activate, verifies the returned license, saves to keychain, spawns the Next.js sidecar, closes itself
  • ·Sign out (IPC command sign_out_desktop): kills the sidecar, deletes session from keychain, deletes license from disk, closes the main window, reopens the activation form
  • ·auth-local.ts reads session variables injected at launch — all dashboard auth checks pass without any cloud auth or database calls
  • ·Long-lived session tokens are issued for the desktop app and used to authenticate sync calls to the live platform
DesktopBuilt
2026-07

Stream Facility Studio — Phase 2: Tauri v2 Shell

The desktop app is a thin Tauri v2 Rust wrapper around the full Stream Facility web platform, running locally. The Tauri binary spawns a Node.js sidecar, waits for it to start, then opens a WebView pointed at localhost. Everything in the web dashboard — worlds, codex, studio, beta — works offline from the same codebase.

  • ·No bundled JS frontend: the WebView is http://localhost:{port}/dashboard — the actual Next.js app running on the machine
  • ·Rust do_launch() picks a free port, resolves the sidecar path, injects the full env block, spawns Node, polls for TCP-ready, creates the main WebviewWindow, closes the splashscreen
  • ·Splashscreen is a pure-CSS animated HTML file in desktop/dist/ — zero JS, zero bundler
  • ·withGlobalTauri: true exposes window.__TAURI__.core.invoke in all windows; dangerousRemoteDomainIpcAccess allows http://localhost to call Tauri commands
  • ·On main window close, Tauri kills and awaits the Node.js child process — no orphaned server processes
  • ·find_server_js() resolution priority: SFSTUDIO_SERVER_PATH env var → production bundle in resource_dir → dev .next/standalone path
  • ·desktop/ is a second Tauri app alongside the legacy desktop-legacy/ folder — both coexist in the repo
DesktopBuilt
2026-07

Stream Facility Studio — Phase 1: Next.js Sidecar Architecture

The desktop app now runs the full web platform locally instead of maintaining a separate native codebase. A Next.js standalone build becomes the sidecar — one build command produces both a Vercel deployment and a self-contained Node.js bundle the Tauri shell can spawn. Every dashboard page works offline without a line of duplicate code.

  • ·DESKTOP_BUILD=true build flag switches Next.js to standalone output and activates four webpack server-bundle aliases
  • ·mongodb.ts → mongodb-local.ts: SQLite-backed MongoDB Db surface using the node:sqlite built-in (Node 22.5+); documents stored as JSON blobs with indexed author_id and world_id columns
  • ·auth.ts → auth-local.ts: reads session variables injected at launch by Tauri, returns a Pro-tier session; stubs signIn/signOut; middleware allows all requests unconditionally
  • ·proxy.ts → auth-local.ts: same stub handles the NextAuth middleware handler import path
  • ·aiProvider.ts → aiProvider-local.ts: reads AI config from variables injected at launch by Tauri rather than querying the cloud database
  • ·No native compilation, no better-sqlite3, no Electron — node:sqlite is built into Node 22 and requires no install step
  • ·Web platform on Vercel never loads any -local.ts file; aliases only activate when DESKTOP_BUILD=true is set at build time
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 4H: Era Codex Sync, Timelines Nav & Draft Import

Fixes three issues discovered after first world import. Eras now appear in the Codex list — sync writes to both the eras table (for calendar use) and the entities table (for display). The sidebar has a dedicated Timelines section grouping Eras and Events. The Studio page gains an '↓ From Platform' button that fetches remote drafts and imports the full content (acts, chapters, scenes) into local SQLite in one step.

DesktopBuilt
2026-07

Stream Facility Desktop — Phase 4G: Full Codex Sync & Tabbed Entity View

The desktop now syncs the complete set of codex data from the platform — physical details, skills, aliases, connections, timeline entries, images, eras, and book genre — and displays it in the same tabbed layout authors see on the web (Profile, Physical, Skills, Aliases, Connections, Timeline, Extra). Previously only name, aliases, and a truncated summary were imported.

  • ·New desktop-authenticated API routes for eras, connections, and timeline data
  • ·Fixed root cause of era import failure: /api/eras uses session auth, so desktop token was silently rejected; new dedicated eras route fixes this
  • ·Entities route expanded to return all character fields: role, bio, portraitUrl, heroImageUrl, age, lifeStatus, gender, race, eyeColor, hairColor, height, weight, build, distinguishingFeatures, appearance, skills, roles, traits, extra
  • ·Alias bug fixed: MongoDB stores aliases as {name,...} objects; Rust now extracts just the name string, ending the [object Object] display issue
  • ·Connections and timeline entries are bulk-fetched per world and embedded in each entity's fields JSON blob — no SQLite migration needed
  • ·CodexDetail page rebuilt as a fully tabbed component matching the web platform; characters get Profile/Physical/Skills/Aliases/Connections/Timeline/Extra; other entity types get Details/Aliases/Extra
  • ·Portrait and hero banner images display inline from Cloudinary/Vercel Blob URLs — no local download required
  • ·Connections and Timeline tabs are read-only on desktop with a clear note directing authors to the platform for edits
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 4F: Connect from Launcher

Authors who already have a platform world no longer need to create a blank local file first. A new 'or connect to a platform world →' path in the Launcher opens a self-contained flow: sign in, pick a world, preview the content, choose where to save the .sfstudio file, and import — all in one sequence.

  • ·Five-state ConnectPlatformFlow component: checking → login → pick-world → confirm → saving; replaces the entire Launcher UI while active
  • ·Reuses the existing preview_world_pull and pull_world_full Rust commands — no new backend code needed
  • ·Confirm step shows the same series/books/entities/eras preview as WorldSyncPanel so authors know what they're importing
  • ·File save dialog pre-fills the world name as the default filename (e.g. MyWorld.sfstudio)
  • ·Retry Import button appears if the pull fails after the project file was created, so authors can recover without starting over
  • ·No changes to WorldSyncPanel — both flows coexist; Launcher flow is for first-time import, WorldSyncPanel is for re-sync from WorldHome
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 4E: Bidirectional World Sync

The desktop app now imports all content from a linked web platform world — series, books, codex entities, and eras — with a preview-then-confirm flow before any data is written. Both directions are manually triggered by the author. A WorldSyncPanel in the World Overview provides connection status, a world picker, a full import preview with counts, and an amber warning when local data already exists.

  • ·Five-state panel: status → login → pick-world → confirm → done; preview step shows series names, book titles (capped at 4 + count), entity count, era count before any writes
  • ·Amber warning block when local series/books/entities already exist — platform records update matching items, local-only items remain intact
  • ·FK-safe upsert for series: INSERT OR IGNORE preserves existing local integer PK; UPDATE patches fields in place; SELECT builds remote→local ID map used when linking books
  • ·New desktop-authenticated API routes for series and books metadata
  • ·Three new Rust commands: get_remote_world_id (connection status), preview_world_pull (fetch without writing), pull_world_full (fetch + write + set sync_config.remote_world_id)
  • ·WorldHome stats grid (Series, Books) reloads automatically after a successful sync via onSynced callback and syncKey increment
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 3C: Full Codex, Series & Books

Codex entity editing expanded from pull-only to full local CRUD. Series and books are now managed locally in the desktop app with their own page. Migration 0003 adds the series and books tables and expands the entities table for local authoring. The activation flow was redesigned from importing a license file to a simple sign-in form.

  • ·SQLite migration 0003: entities table gains dirty/description/fields/tags columns; new series table (title, genre, status); new books table with series_id FK (ON DELETE SET NULL); drafts gains local_book_id
  • ·CodexList.tsx and CodexDetail.tsx pages — type-filtered list with inline search, full edit form with type-specific fields from entityTypes config, Saved ✓ confirmation, delete with confirm
  • ·SeriesBooks.tsx — Series section with nested books, Standalone Books section; inline create/edit forms per item with genre and status dropdowns
  • ·Activation redesign: LicenseGate replaced with sign-in form; activate_desktop Rust command fetches auth token + license in one step — no manual file download
  • ·Launcher and LicenseGate both display current app version (vX.Y.Z) via @tauri-apps/api/app getVersion()
  • ·Settings multi-provider AI: four tabs — Anthropic, Ollama (local, auto-detects models), OpenAI/compat (configurable base URL), OpenRouter (300+ models, searchable); active provider dot indicator; Check for Updates fetches GET /api/desktop/version from the platform
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 4C: Era Date Anchoring

The desktop app now matches the web platform's in-world date anchoring system. Chapters can be pinned to an era and date range from the Plan view. Eras sync from the web platform alongside codex entities. A new SQLite migration adds era columns to acts, chapters, and scenes — tracked by a new schema_migrations table so ALTER TABLE never re-runs on an existing database.

  • ·SQLite migration 0004: 6 era columns added to acts, chapters, and scenes (era_id, era_name, in_world_begins/ends_date and label); new local eras cache table
  • ·Migration runner upgraded: schema_migrations table bootstraps itself first, then checks and records each version — ALTER TABLE ADD COLUMN is safe on existing databases
  • ·pull_eras / list_eras Rust commands sync eras from /api/eras?worldId=..., stored locally; pull_eras called automatically alongside pull_entities in SyncPanel (best-effort)
  • ·update_node_dates / clear_node_dates Rust commands dispatch to acts, chapters, or scenes by entity_type
  • ·WorldDateInput and worldDate.ts ported from the web platform: zero Next.js imports, direct relative paths — the same calendar-aware date input used on the web
  • ·InlineDatePanel in desktop PlanView: era picker from local eras table, WorldDateInput for begins/ends dates, calendar-aware labels via worldDateToLabel / realWorldDateLabel
  • ·WorldDateBadge pill shows in_world_begins_date_label inline on chapter rows; ◷ clock icon toggles the panel
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 4A: License & Distribution

The desktop app now ships with a full license system: a signed license file downloaded from your account page, verified cryptographically at startup, and stored in the OS app data directory. Missing license shows a gate screen; expired license shows a banner but writing keeps working forever.

  • ·License file: a cryptographically signed payload containing account info, app version, and a 1-year validity window; verified at startup against a secret compiled into the binary
  • ·The verification secret is embedded at compile time — never read from environment variables or disk at runtime; dev builds use a safe placeholder automatically
  • ·Startup check: Missing → LicenseGate screen (Get License opens browser, Import License File opens file dialog); Expired → crimson banner, full writing still works, sync disabled; Active → normal app
  • ·Web: GET /api/desktop/license generates and serves the signed file as a browser download; /dashboard/desktop page with OS download links and the Download License button
  • ·Import flow verifies HMAC before writing the file — no restart needed, React state updates immediately after import
  • ·Desktop nav link added to the inside nav bar
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 4D: Full-text Search

Search across all scenes in a draft from the Plan view. A 320px search panel slides in from the right, debounces input at 300ms, and shows up to 50 hits with a context snippet and direct navigate-to-scene on click.

  • ·SQL LIKE query on TipTap JSON content — no FTS5 migration needed; fast enough for typical draft sizes
  • ·Rust recursively extracts plain text from TipTap JSON nodes and builds a ~160-char snippet centred on the match
  • ·Results grouped and ordered by chapter → scene; each hit shows chapter name, scene name, snippet, and word count
  • ·Search and Sync panels are mutually exclusive — opening one closes the other
  • ·Click any result to navigate directly to that scene in Write view
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 4B: Settings & Planning Notes

A dedicated Settings page consolidates account info, platform URL, AI key management, and Write view typography preferences. Separately, chapter summaries and scene notes — fields that existed in the schema but were never shown — now appear as inline text areas in the Plan view on both desktop and web.

  • ·Settings page: Account (email + sign out), Platform (editable URL saved to preferences.json), AI Assist (key status, set/remove), Write View (font size and line spacing toggles)
  • ·Font size (Small/Medium/Large) and line spacing (Normal/Relaxed/Loose) stored in preferences.json; WriteView reads on mount and applies as CSS custom properties --write-font-size and --write-line-height
  • ·Gear ⚙ icon added to Studio and Plan view toolbars
  • ·Chapter summary: two-row textarea below chapter header, save-on-blur
  • ·Scene notes: single-row textarea below each scene row, save-on-blur
  • ·Web platform: new PATCH /api/studio/[draftId]/chapters/[chapterId] route for chapter summaries; both views updated
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 3B: AI Write Assist

A ✦ Assist panel slides in on the right side of the Write view. Four modes — Continue, Improve, Brainstorm, Custom — send selected text or the full scene to Claude and return a response. The Anthropic API key is stored securely in the OS keychain, never on disk.

  • ·Four modes: Continue (1–3 paragraph continuation), Improve (rewrite for clarity and rhythm), Brainstorm (3–5 concrete next ideas), Custom (author-specified instruction)
  • ·Selected text used as focus if present; full scene text always included as context — no character limit
  • ·Anthropic API key stored in OS keychain via the keyring crate — same keychain service as the sync auth token
  • ·Insert at cursor inserts the response directly into the focused TipTap editor at cursor position
  • ·Copy button for using the response outside the app; ✕ to dismiss without inserting
  • ·Remove API key option in the panel footer resets to the key-setup view
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 3A: Entity Sync & Markdown Export

Codex entities from the web platform sync to the desktop app and appear as amber highlights in the Write view. Clicking a highlighted name shows a popup with the entity's type, name, and summary. Drafts can be exported to Markdown with a native save dialog.

  • ·Entity sync: authenticated desktop endpoints list the author's worlds and return entities for all codex types
  • ·Entities stored locally in a SQLite entities table — name, aliases (JSON), summary, entity_type, world_id
  • ·Entity mention plugin ported from the web platform: ProseMirror decoration overlay highlights entity names in amber in Write view without changing stored TipTap JSON
  • ·EntityPopup: click any highlighted entity name to see a fixed-position popup with type badge, name, and summary
  • ·SyncPanel world picker: Sync Entities button opens a world list; selecting a world pulls entities into SQLite
  • ·Markdown export: PlanView Export button opens a native save dialog; Rust tiptap_to_markdown() handles paragraph, heading, blockquote, lists, hr, and all inline marks
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 2: Core Writing Loop

The full writing loop is working in the native desktop app: plan your draft structure, write in a continuous-scroll TipTap canvas, save version snapshots, and sync to the web platform. PlanView has full drag-and-drop reordering of acts, chapters, and scenes.

  • ·PlanView: Acts → Chapters → Scenes hierarchy with @dnd-kit drag-and-drop, inline rename, collapse/expand, word count totals, Expand All / Collapse All
  • ·WriteView: continuous-scroll TipTap canvas — all scenes render simultaneously; toolbar applies to the focused scene; Scene Break and Chapter Break insertable at cursor
  • ·Scene version control: ⎘ Save Version and ⎇ Version History per scene; ⎘ Save Manuscript Version for a bulk snapshot across all scenes
  • ·Sync panel: sign in with Stream Facility credentials, link local draft to a web draft, push dirty scenes, pull updates
  • ·Authenticated desktop API routes on the web platform: session token issuance, draft listing, and scene sync endpoints
  • ·Entity mention plugin registered from launch with a live entity list — highlights update after every entity sync
DesktopBuilt
2026-07

Stream Facility Desktop — Phase 1: Foundation

A native desktop writing app built with Tauri v2 — roughly 5 MB vs Electron's 150 MB. A .sfstudio SQLite file is created or opened at launch. The Launcher screen handles New World, Open World, and a Recent Worlds list. All draft, chapter, scene, revision, and sync tables initialise on first open.

  • ·Tauri v2 + React + Vite + TypeScript — one binary, no Electron, no Chromium bundle
  • ·SQLite schema with WAL mode: drafts, acts, chapters, scenes, scene_revisions, sync_config — mirrors web platform MongoDB collections
  • ·Project stored as a portable .sfstudio file (SQLite database) — copy the file to move the project
  • ·Launcher: New World / Open World dialogs via Tauri file dialog; Recent Worlds list in the sidebar
  • ·Full type-safe Rust command layer in src-tauri/src/commands/ with tauri-commands.ts wrapper on the frontend
  • ·Same sf-* design tokens as the web platform via a copied @theme {} block — zero UI divergence

This log tracks platform features, not individual content. For questions or feedback, get in touch.