openscribe/site/pages/how-it-works.html
Laurence 8fd9b694f8
Some checks failed
ci / firmware (pull_request) Failing after 31s
ci / openapi (pull_request) Failing after 33s
ci / emulator (pull_request) Failing after 24s
ci / server (pull_request) Failing after 37s
docs+site: Nightjar brand, hosted service, infrastructure plan, saved site
Persists the branding/commercial/infrastructure work (previously only in chat and
on the live site) into version control.

What changed:
- docs/naming.md: due-diligence and the decision to brand the product Nightjar
  (OpenScribe domain/GitHub/trademark collisions; alternatives screened; why Nightjar).
- docs/hosted-service.md: the commercial model - plan tiers (Self-host / Cloud
  Starter / Cloud Pro / Private), indicative pricing, backend mapping, and the
  build-to-sell roadmap (metering, billing, provisioning, DPA).
- docs/infrastructure.md: backend infra plan. Primary option = self-host on the
  3x Minisforum MS-02 cluster (one with an RTX 3050 6GB) fronted by a Cloudflare
  Tunnel, with node roles, the 3050 capacity reality, caveats, and a Hetzner cloud
  fallback. Provision-later.
- site/: reproducible marketing-site source - block content for all 11 pages
  (rebranded to Nightjar), the navigation, the Contact Form 7 config (honeypot),
  the ApisCP SOAP helper (tools/apiscp.php, no secret), and a README on how the
  WordPress site is built and managed via the API.
- state/: DECISIONS (Nightjar rebrand, hosted service, MS-02 backend), PROJECT
  (brand + commercial section), TODO (rename decision, trademark, mailbox, pricing,
  hosted-service build, infra provisioning).

Why:
- User asked to save everything to the repo. Captures the product rebrand, the
  commercialisation plan, and the infrastructure decision so a cold session has the
  full picture.

Notes:
- The repo is still named `openscribe`; the product/brand is Nightjar. A full
  codebase rename is deferred (tracked in TODO + docs/naming.md).
- No secrets committed: the ApisCP API key is read from a local scratch file, never
  the repo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 22:24:24 +01:00

74 lines
11 KiB
HTML

<!-- wp:heading {"level":1} --><h1 class="wp-block-heading">How Nightjar works</h1><!-- /wp:heading --><!-- wp:paragraph {"fontSize":"large"} --><p class="has-large-font-size">From a press of a button to a searchable, summarised transcript, every step runs on hardware and services you control. Here is the whole workflow, end to end.</p><!-- /wp:paragraph -->
<!-- wp:heading --><h2 class="wp-block-heading">The workflow at a glance</h2><!-- /wp:heading -->
<!-- wp:html -->
<figure style="margin:0 0 8px;overflow-x:auto">
<svg viewBox="0 0 980 210" width="100%" role="img" aria-label="Nightjar workflow: record, sync, transcribe, summarise, export" xmlns="http://www.w3.org/2000/svg" style="font-family:ui-sans-serif,system-ui,sans-serif;max-width:980px">
<defs><marker id="ar" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto"><path d="M0,0 L7,3 L0,6 Z" fill="#a1a1aa"/></marker></defs>
<g>
<rect x="16" y="55" width="160" height="100" rx="12" fill="#fafafa" stroke="#e4e4e7"/>
<text x="96" y="92" text-anchor="middle" font-size="16" font-weight="700" fill="#18181b">1. Record</text>
<text x="96" y="115" text-anchor="middle" font-size="12" fill="#52525b">One button, to</text>
<text x="96" y="131" text-anchor="middle" font-size="12" fill="#52525b">microSD. No limit.</text>
<rect x="220" y="55" width="160" height="100" rx="12" fill="#fafafa" stroke="#e4e4e7"/>
<text x="300" y="92" text-anchor="middle" font-size="16" font-weight="700" fill="#18181b">2. Sync</text>
<text x="300" y="115" text-anchor="middle" font-size="12" fill="#52525b">BLE, WiFi, or</text>
<text x="300" y="131" text-anchor="middle" font-size="12" fill="#52525b">on-charge upload</text>
<rect x="424" y="55" width="160" height="100" rx="12" fill="#fff7ed" stroke="#fdba74"/>
<text x="504" y="92" text-anchor="middle" font-size="16" font-weight="700" fill="#9a3412">3. Transcribe</text>
<text x="504" y="115" text-anchor="middle" font-size="12" fill="#7c2d12">Your server +</text>
<text x="504" y="131" text-anchor="middle" font-size="12" fill="#7c2d12">your chosen AI</text>
<rect x="628" y="55" width="160" height="100" rx="12" fill="#fff7ed" stroke="#fdba74"/>
<text x="708" y="92" text-anchor="middle" font-size="16" font-weight="700" fill="#9a3412">4. Summarise</text>
<text x="708" y="115" text-anchor="middle" font-size="12" fill="#7c2d12">Overview, points,</text>
<text x="708" y="131" text-anchor="middle" font-size="12" fill="#7c2d12">action items</text>
<rect x="832" y="55" width="132" height="100" rx="12" fill="#fafafa" stroke="#e4e4e7"/>
<text x="898" y="92" text-anchor="middle" font-size="16" font-weight="700" fill="#18181b">5. Export</text>
<text x="898" y="115" text-anchor="middle" font-size="12" fill="#52525b">Audio, TXT, SRT,</text>
<text x="898" y="131" text-anchor="middle" font-size="12" fill="#52525b">VTT, MD, JSON</text>
<line x1="180" y1="105" x2="214" y2="105" stroke="#a1a1aa" stroke-width="2" marker-end="url(#ar)"/>
<line x1="384" y1="105" x2="418" y2="105" stroke="#a1a1aa" stroke-width="2" marker-end="url(#ar)"/>
<line x1="588" y1="105" x2="622" y2="105" stroke="#a1a1aa" stroke-width="2" marker-end="url(#ar)"/>
<line x1="792" y1="105" x2="826" y2="105" stroke="#a1a1aa" stroke-width="2" marker-end="url(#ar)"/>
</g>
</svg>
</figure>
<!-- /wp:html -->
<!-- wp:heading {"level":3} --><h3 class="wp-block-heading">1. Record</h3><!-- /wp:heading --><!-- wp:paragraph --><p>The device is a small ESP32-S3 board with a digital MEMS microphone and a microSD card. A single button starts and stops recording; a status light shows what it is doing. Audio is written straight to the card as it is captured, so there is no length limit and nothing needs a network connection just to start recording. Each recording is saved with a small metadata file (duration, sample rate, and a unique id) so the rest of the pipeline can track it.</p><!-- /wp:paragraph -->
<!-- wp:heading {"level":3} --><h3 class="wp-block-heading">2. Sync</h3><!-- /wp:heading --><!-- wp:paragraph --><p>Nightjar has three independent ways to move recordings off the device, so one of them always fits your situation:</p><!-- /wp:paragraph --><!-- wp:list --><ul class="wp-block-list"><!-- wp:list-item --><li><strong>Bluetooth Low Energy</strong> handles control and status from the phone app: start or stop a recording, check the battery, and provision WiFi. It is low-power and always available.</li><!-- /wp:list-item --><!-- wp:list-item --><li><strong>WiFi to the app</strong> is the fast lane for transferring the actual audio. When your phone and the device are on the same network, recordings copy across quickly.</li><!-- /wp:list-item --><!-- wp:list-item --><li><strong>Independent upload on charge</strong> is the one that sets Nightjar apart. When the device is plugged in, it joins your WiFi on its own and uploads new recordings straight to your storage, with no phone involved. Leave it on the charger overnight and everything is waiting for you in the morning.</li><!-- /wp:list-item --></ul><!-- /wp:list -->
<!-- wp:heading {"level":3} --><h3 class="wp-block-heading">3. Transcribe</h3><!-- /wp:heading --><!-- wp:paragraph --><p>Once a recording reaches your server, it is transcribed into accurate, timestamped text. The transcription engine is your choice: a fully local model for maximum privacy, or a commercial speech-to-text API for the highest accuracy. Nothing is hard-wired to a single vendor.</p><!-- /wp:paragraph -->
<!-- wp:heading {"level":3} --><h3 class="wp-block-heading">4. Summarise</h3><!-- /wp:heading --><!-- wp:paragraph --><p>The transcript is then passed to a language model, which writes a structured summary: a short overview, the key points, and any action items. Again, the model is yours to pick, from a local model running on your own machine to a frontier commercial API. See <a href="/bring-your-own-ai/">Bring your own AI</a> for the full list.</p><!-- /wp:paragraph -->
<!-- wp:heading {"level":3} --><h3 class="wp-block-heading">5. Export</h3><!-- /wp:heading --><!-- wp:paragraph --><p>Everything is available through a completely open REST API. Pull the original audio, the plain-text transcript, subtitle files (SRT or VTT), a Markdown summary, or the full record as JSON. Because the API is documented and open, you can wire Nightjar into whatever you already use.</p><!-- /wp:paragraph -->
<!-- wp:separator --><hr class="wp-block-separator has-alpha-channel-opacity"/><!-- /wp:separator -->
<!-- wp:heading --><h2 class="wp-block-heading">How the pieces fit together</h2><!-- /wp:heading --><!-- wp:paragraph --><p>Four parts, all under your control, connected by an open API and a shared data model.</p><!-- /wp:paragraph -->
<!-- wp:html -->
<figure style="margin:0 0 8px;overflow-x:auto">
<svg viewBox="0 0 980 380" width="100%" role="img" aria-label="Nightjar architecture diagram" xmlns="http://www.w3.org/2000/svg" style="font-family:ui-sans-serif,system-ui,sans-serif;max-width:980px">
<defs><marker id="a2" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto"><path d="M0,0 L7,3 L0,6 Z" fill="#a1a1aa"/></marker></defs>
<rect x="20" y="150" width="160" height="90" rx="12" fill="#fafafa" stroke="#e4e4e7"/>
<text x="100" y="185" text-anchor="middle" font-size="15" font-weight="700" fill="#18181b">Nightjar device</text>
<text x="100" y="207" text-anchor="middle" font-size="12" fill="#52525b">records to microSD</text>
<rect x="360" y="110" width="260" height="170" rx="12" fill="#f5f5f4" stroke="#e7e5e4"/>
<text x="490" y="138" text-anchor="middle" font-size="15" font-weight="700" fill="#18181b">Your server</text>
<rect x="384" y="152" width="98" height="46" rx="8" fill="#fff7ed" stroke="#fdba74"/><text x="433" y="180" text-anchor="middle" font-size="12" fill="#9a3412">Transcribe</text>
<rect x="498" y="152" width="98" height="46" rx="8" fill="#fff7ed" stroke="#fdba74"/><text x="547" y="180" text-anchor="middle" font-size="12" fill="#9a3412">Summarise</text>
<rect x="384" y="212" width="212" height="46" rx="8" fill="#ecfeff" stroke="#67e8f9"/><text x="490" y="240" text-anchor="middle" font-size="12" fill="#155e75">Open REST API + exports</text>
<rect x="760" y="30" width="200" height="80" rx="12" fill="#fff7ed" stroke="#fdba74"/>
<text x="860" y="62" text-anchor="middle" font-size="14" font-weight="700" fill="#9a3412">AI provider</text>
<text x="860" y="83" text-anchor="middle" font-size="12" fill="#7c2d12">local or commercial</text>
<rect x="760" y="150" width="200" height="80" rx="12" fill="#fafafa" stroke="#e4e4e7"/>
<text x="860" y="182" text-anchor="middle" font-size="14" font-weight="700" fill="#18181b">Your storage</text>
<text x="860" y="203" text-anchor="middle" font-size="12" fill="#52525b">S3 / WebDAV / NAS</text>
<rect x="760" y="270" width="200" height="80" rx="12" fill="#fafafa" stroke="#e4e4e7"/>
<text x="860" y="302" text-anchor="middle" font-size="14" font-weight="700" fill="#18181b">Phone app</text>
<text x="860" y="323" text-anchor="middle" font-size="12" fill="#52525b">Android and iOS</text>
<line x1="182" y1="195" x2="356" y2="195" stroke="#a1a1aa" stroke-width="2" marker-end="url(#a2)"/>
<text x="265" y="186" text-anchor="middle" font-size="11" fill="#71717a">sync</text>
<line x1="620" y1="150" x2="758" y2="82" stroke="#a1a1aa" stroke-width="2" marker-end="url(#a2)"/>
<text x="690" y="108" text-anchor="middle" font-size="11" fill="#71717a">uses</text>
<line x1="620" y1="195" x2="758" y2="190" stroke="#a1a1aa" stroke-width="2" marker-end="url(#a2)"/>
<line x1="620" y1="240" x2="758" y2="305" stroke="#a1a1aa" stroke-width="2" marker-end="url(#a2)"/>
</svg>
</figure>
<!-- /wp:html -->
<!-- wp:list --><ul class="wp-block-list"><!-- wp:list-item --><li><strong>The device</strong> captures audio and syncs it three ways.</li><!-- /wp:list-item --><!-- wp:list-item --><li><strong>Your server</strong> ingests recordings, runs transcription and summaries, and serves the open API.</li><!-- /wp:list-item --><!-- wp:list-item --><li><strong>Your AI provider</strong> does the language work, chosen by you and swappable any time.</li><!-- /wp:list-item --><!-- wp:list-item --><li><strong>Your storage and app</strong> keep and present everything. Nothing lives on someone else's cloud unless you choose it.</li><!-- /wp:list-item --></ul><!-- /wp:list -->
<!-- wp:heading --><h2 class="wp-block-heading">Ready to go deeper?</h2><!-- /wp:heading --><!-- wp:paragraph --><p>The <a href="/guides/">guides</a> walk through connecting an AI provider, self-hosting the server, and building the device yourself.</p><!-- /wp:paragraph --><!-- wp:buttons --><div class="wp-block-buttons"><!-- wp:button --><div class="wp-block-button"><a class="wp-block-button__link wp-element-button" href="/guides/">Read the guides</a></div><!-- /wp:button --><!-- wp:button {"className":"is-style-outline"} --><div class="wp-block-button is-style-outline"><a class="wp-block-button__link wp-element-button" href="/hosted-plans/">Or let us host it</a></div><!-- /wp:button --></div><!-- /wp:buttons -->