No description
  • JavaScript 77.1%
  • CSS 13.1%
  • HTML 9.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-22 10:48:38 +02:00
assets/bergamot Der Composer formatiert als Markdown und bindet Emoji sowie PeerTube ein, Namen zeigen Custom-Emoji, und Skripte, Einbettungen und der Schriftname sind enger gefasst. 2026-10-16 12:51:07 +02:00
css Lange Thread-Titel kuerzen den Dialog-Kopf nicht mehr aus dem sichtbaren Bereich, Schliessen-Button bleibt auf mobilen Geraeten sichtbar. 2026-10-22 10:10:57 +02:00
fonts Der Composer formatiert als Markdown und bindet Emoji sowie PeerTube ein, Namen zeigen Custom-Emoji, und Skripte, Einbettungen und der Schriftname sind enger gefasst. 2026-10-16 12:51:07 +02:00
i18n Folgeanfragen lassen sich annehmen oder ablehnen, Blocks und Stummschaltungen in den Einstellungen aufheben, gelesene Beiträge haben eine Trennlinie, und der Live-Modus speichert Beiträge nicht mehr lokal. 2026-10-19 21:28:13 +02:00
icons Favicon und PWA-Icons aus dem silbernen Fediverse-Logo 2026-09-22 12:14:55 +02:00
js Die Android-Zuruecktaste schliesst offene Dialoge auch unter Firefox Mobile: History-Guard-Eintrag waehrend ein Modal-Dialog offen ist, popstate schliesst den obersten Dialog statt wegzunavigieren; Guard wird beim normalen Schliessen wieder abgebaut. 2026-10-22 10:48:38 +02:00
test Folgeanfragen lassen sich annehmen oder ablehnen, Blocks und Stummschaltungen in den Einstellungen aufheben, gelesene Beiträge haben eine Trennlinie, und der Live-Modus speichert Beiträge nicht mehr lokal. 2026-10-19 21:28:13 +02:00
.gitignore feat: config-gesteuerte Föderiert-Spalte (federated, SW v41) 2026-09-10 12:15:12 +02:00
config.json Mistral-Theme und Forgejo-Deploy entfernt, Dark-Mode-Hintergrund auf Anthrazit 2026-10-16 09:03:37 +02:00
index.html Folgeanfragen lassen sich annehmen oder ablehnen, Blocks und Stummschaltungen in den Einstellungen aufheben, gelesene Beiträge haben eine Trennlinie, und der Live-Modus speichert Beiträge nicht mehr lokal. 2026-10-19 21:28:13 +02:00
LICENSE Orbitron und Oxanium statt Astro und Sephora, Zeichen-Flip 2026-10-01 12:03:52 +02:00
manifest.webmanifest Mistral-Theme und Forgejo-Deploy entfernt, Dark-Mode-Hintergrund auf Anthrazit 2026-10-16 09:03:37 +02:00
README.md Der Composer formatiert als Markdown und bindet Emoji sowie PeerTube ein, Namen zeigen Custom-Emoji, und Skripte, Einbettungen und der Schriftname sind enger gefasst. 2026-10-16 12:51:07 +02:00
sw.js Auf dem Desktop nimmt ein geöffneter Post maximal 70% der Bildschirmbreite ein; mobil bleibt die volle Breite. 2026-10-19 11:15:51 +02:00

Nightboard '83

ATTENTION: This project is created by making heavy use of LLM systems, if you don't want to use software created in this way this particular app may not be for you

Nightboard '83 is a static web client for Mastodon-compatible servers, written especially with GoToSocial in mind. It is a set of HTML, CSS, and JavaScript files with no build step and no backend of its own. The interface ships with German and English UI strings (default German), in an design trying to emulate the look of old FASA Pen-and-Paper rulebooks, and can be installed as a Progressive Web App.

Offline is the core idea: After an initial sync you can view your timelines, compose replies, react and create posts to push them back to the net the next time you have internet access.

The client talks to the instance you configure (or type in at login) using OAuth 2.0 with PKCE. After you authorize, the instance redirects back to Nightboard. A paste-the-code fallback remains for stubborn servers.

Homepage: https://nightboard83.de · Main Instance: https://nightboard83.de/app/

Features

  • Four independently scrollable columns: Home, Local, Federated (public timeline), and Notifications
  • Safe mode and a local circle (German: Kreis, English: Screened). The profile button adds or removes an account at any time. While safe mode is on, only that column and Notifications stay visible and update. Mentions and new posts from outside the circle are held back.
  • Offline cache (last timelines and media) via PouchDB / IndexedDB
  • Outbox: compose or reply while offline, send automatically when the connection returns
  • Drafts stored locally; a drafts icon appears in the header when any exist
  • Installable as PWA
  • Threads with replies, boosts, favourites, and a reply composer
  • Local in-browser post translation via Bergamot WASM engine (24 language pairs, privacy-friendly)
  • Doomscrolling detector: Tracks scroll velocity, session duration, post-consumption rate, and time of day to estimate a "humanity" score. Escalating edge-glow warnings fire when humanity drops. Configurable via config.json (cyberpsych)

Requirements

  • A web server that can serve static files (any origin is fine)
  • A Mastodon-compatible instance with OAuth and the client API (GoToSocial is the primary target)
  • A current browser (Chromium, Firefox, Safari). file:// will not work: the app loads config.json, registers a service worker, and uses IndexedDB

For PWA install and a reliable service worker, serve the files over HTTPS (or http://localhost).

Installation

Copy the project directory onto the server as-is. There is nothing to compile.

Quick local preview

From the project root:

python3 -m http.server 8000

Open http://127.0.0.1:8000/.

Production

Point any static host (nginx, Caddy, Apache, Git forge pages, object storage with a website mode) at the directory where the files reside. Example with Caddy:

nightboard83.de {
        root * /var/www/Nightboard83.de
        file_server
}

The app checks for a new service worker on startup, when the tab becomes visible, and about every ten minutes. HTML, CSS, and JavaScript are fetched network-first (cache only if offline). If a new version is found, a SYS.UPDATE overlay runs a short install sequence, then the PWA reloads. If a compose or reply draft is open, the overlay pauses and dismisses so you can finish writing; the update resumes once the buffer is empty.

Configuration

Edit config.json in the program directory. The file is fetched at startup (cache: no-store) and is not baked into the service worker precache, so changing it does not require a rebuild.

{
  "instance": "fediverse2.blackneon.net",
  "poll_minutes": 2,
  "lang_switch": true,
  "federated": true,
  "local": true,
  "theme": "default",
  "cyberpsych": true
}
Key Type Default Description
instance string (empty) Hostname or URL used to prefill the instance field on the login screen. https:// is added if you omit the scheme. Trailing slashes are stripped. Aliases: url, host.
poll_minutes number 2 How often to look for new posts while you are logged in and no detail window is open. Allowed range: 0.25–1440 minutes (15 seconds to 24 hours). Aliases: pollMinutes, polling_minutes, poll.
lang_switch boolean true Show the **DE
federated boolean true Show the Federated (public timeline) column and its dock icon. Set to false to remove the column entirely — it is not loaded, polled, or streamed. Aliases: federatedTimeline, federated_timeline, showFederated.
local boolean true Show the Local column and its dock icon. Set to false to remove the column entirely — it is not loaded, polled, or streamed. Aliases: localTimeline, local_timeline, showLocal.
theme string default Color theme. Only default (Grid Protocol) is available. Unknown values fall back to default. Alias: skin.
cyberpsych boolean true Enable the Cyberpsychosis Danger doomscrolling detector. When true, a humanity HUD appears below the top bar after login; it decays with fast/continuous scrolling and recovers during pauses, escalating through five levels (STABLE → ELEVATED → UNSTABLE → CRITICAL → CYBERPSYCHOSIS) with edge-glow warnings and dialogs. Set to false to disable entirely.

The login form can still point at a different instance. The last successful instance is stored in localStorage (nightboard83.instance) and wins over config.json on later visits. Changing the instance on login registers a new OAuth app on that server.

Polling is paused while a thread, profile, compose, media, drafts, outbox, or settings dialog is open, and while the tab is hidden.

Safe mode and backup

On someone else's profile, Screen / In den Kreis only changes membership in a circle stored on this device. It does not call the instance. Your own profile has no such button. Safe mode does not hide the button. Turn safe mode on in Settings when you want the circle to become the timeline: Home, Local, and Federated are hidden and are not loaded, polled, or streamed. Notifications are still fetched. Mentions and new posts from accounts outside the circle are held on this device (up to 200). Follows, follow requests, boosts, favourites, polls, and edits stay visible. Turning safe mode off asks whether to show the held mentions. The circle you built beforehand is still there.

Settings can also write an encrypted .nb83 file and read one back. The passphrase is typed at export and import. It is not stored and not included in the file. A lost passphrase makes that backup unreadable. Share uses the system share sheet when the browser can share files; Download always saves the file. Merge keeps the newer circle entry, the newer safe-mode stamp, and the newer read cursor, and leaves this device's language alone. Replace with this file overwrites safe mode, language, read cursors, and the circle. The file is tied to the account that exported it. It does not contain the login token, drafts, the outbox, media, or the timeline cache. Nothing is synced through a server.

Local data

All of this lives in the browser, not on your instance:

  • Session: localStorage keys prefixed nightboard83.
  • Circle, safe mode, and the device-local held-mention stack: nightboard83.screened (separate per instance and account). The held stack is not part of the .nb83 file.
  • Timeline cache, media blobs, outbox, drafts: IndexedDB databases nightboard83-cache, nightboard83-media, nightboard83-outbox, nightboard83-drafts (PouchDB)

Clearing site data logs you out and deletes drafts and queued posts.

Local post translation (Bergamot)

Posts can be translated entirely in the browser with the Bergamot WASM engine. Post text never leaves the device.

  • Engine: assets/bergamot/ (lazy-loaded). Models are downloaded on demand from the Bergamot registry and cached in the Cache API. They are released under CC-BY-SA-4.0 — see assets/bergamot/NOTICE.txt
  • 24 language pairs (en↔de, es, fr, it, pt, ru, cs, bg, uk, zh, ja); pivot via English when no direct pair exists
  • A "Translate" control appears only when source ≠ UI language and a registry path exists
  • Falls back gracefully if WebAssembly or Workers are unavailable

License

  • Application code: GNU Affero GPL v3 or later — see LICENSE
  • Syne, IBM Plex Sans, and Oxanium: SIL Open Font License 1.1 — see fonts/OFL.txt. These are the families the interface loads.
  • NB Mark (fonts/NBMark-latin.woff2): a modified latin subset of Orbitron, renamed so it does not use the Reserved Font Name "Orbitron". SIL Open Font License 1.1 — see fonts/OFL.txt
  • PouchDB 8.0.1 (js/pouchdb.min.js): Apache License 2.0 — see js/pouchdb.Apache-2.0.txt
  • Bergamot translator engine (assets/bergamot/): Mozilla Public License 2.0 — see assets/bergamot/LICENSE and assets/bergamot/NOTICE.txt
  • Bergamot translation models (downloaded on demand, not bundled): Creative Commons Attribution-ShareAlike 4.0 — see assets/bergamot/NOTICE.txt