-
Notifications
You must be signed in to change notification settings - Fork 0
Data Contracts
github-actions[bot] edited this page May 5, 2026
·
50 revisions
runtime data lives under /data.
repo intent:
-
/datais not supposed to be versioned normally -
.gitignoreignores/data/**/* -
.rsyncignoreexcludes/data/**from deployment sync
so local/dev/prod data has to be managed separately.
expected top-level shape:
{
"accounts": [
{
"username": "string",
"name": "string",
"password": "bcrypt-hash or empty",
"isAdmin": true,
"mustResetPassword": false,
"discordUserId": "optional discord snowflake string",
"allowedPages": ["feed", "journal", "comments"],
"bookmarks": ["2026-01-01_12-00-00", "journal:12", "newsletter:2026-01-01"],
"theme": "default|custom|theme-id",
"glowIntensity": "none|low|medium|high",
"mobileFriendlyView": true,
"colors": {
"bg": "#RRGGBB",
"fg": "#RRGGBB",
"border": "#RRGGBB",
"subtle": "#RRGGBB",
"links": "#RRGGBB"
}
}
]
}notes:
- extra unknown keys can exist and are preserved by
account/admin/edit - bookmarks are the current source of truth for logged-in users
- bookmark ids currently use raw feed ids,
journal:{id}, andnewsletter:{id} -
theme: defaultuses the standard template and/style.css;theme: customenables savedcolors; any other valid value refers to a/themes/{theme-id}.jsonfile -
mustResetPasswordis used by the shared session bootstrap to force first-login password changes -
discordUserIdlinks a site account to a Discord member for bot DMs and notifications -
allowedPagescurrently includes functional grants likefeed,journal, andcomments
theme metadata lives as JSON files directly under /themes.
{
"name": "Theme Name",
"html": "template-file.html",
"css": "stylesheet-file.css"
}notes:
- the metadata filename is the saved theme id, for example
/themes/cool.jsonbecomescool -
nameis the label shown in/settings -
htmlandcssmust be relative paths in/themes/lib, for exampleaero/aero.htmlandaero/aero.css - theme asset paths cannot be absolute, contain
.., or use characters outside letters, numbers,.,_,-, and/ - desktop rendering uses both themed HTML and CSS
- mobile rendering keeps
template_mobile.htmland only swaps the CSS
- map of client IP -> unix timestamp array
- used for login throttling
feed post format:
@usernameYYYY-MM-DD HH:MM:SS- body text / BBCode
other file:
-
index.tomlis generated by/feed/index.php
per-post replies live in {postId}.json files shaped roughly like:
{
"replies": [
{
"id": "20260413153000_deadbeef",
"username": "toast",
"date": "2026-04-13 15:30:00",
"body": "reply body with BBCode"
}
]
}notes:
- reply ids are generated on write; older data may be normalized into
legacy_*ids at read time - reply bodies can contain image BBCode that points at
/data/images/*
published journal post:
YYYY-MM-DD- title
- description
- trusted HTML body
draft format:
USER:<username>- title
- description
- optional
FORMAT:html - draft body
without FORMAT:html, preview treats the body as BBCode.
with it, preview treats the body as raw HTML.
entry format:
- timestamp
- display name
- message body
plus:
-
ip_index.jsonfor one-post-per-IP ownership tracking
- uploaded images used across feed, journal, gallery, and newsletter content
- expected web path is
/data/images/<filename>
artist folders currently include:
frdg3cactile
album JSON shape:
{
"album_name": "string",
"album_caption": "string",
"album_type": "Album|EP|Single|Remix|...",
"album_art": "/data/images/example.jpg",
"album_art_directory": "/data/images/example.jpg",
"order": 6,
"songs": [
{ "name": "Track", "directory": "/data/audio/file.wav" }
]
}album_art_directory is preferred by current code.
- track files referenced by music metadata
- also used by shared playback features
- published newsletter bodies as
{id}.html - commonly date-shaped ids like
YYYY-MM-DD
- temporary markdown paste records as
{id}.json - ids are 16 lowercase hex characters
- records expire after 30 days and are cleaned up opportunistically on create/view
- unencrypted records store a
markdownstring - encrypted records store only AES-256-GCM ciphertext plus PBKDF2-SHA256 salt/nonce/tag metadata; the password is never stored
-
hard_breakscontrols whether single paragraph newlines render as<br>instead of spaces
- plain text maintenance flag
used key:
{
"discord_feed": "https://discord.com/api/webhooks/..."
}expected shape:
{
"bot": { "token": "...", "client_id": "...", "status": "online|offline" },
"stream": { "url": "http(s)://...", "name": "..." },
"channel": { "id": "...", "name": "..." },
"features": { "auto_play": true, "loop": true }
}- array of timestamped bot status entries
- internal bot dedupe state for sent feed mention/reply notifications
- stores which feed mentions and replies have already triggered DMs
- tracked inbound/outbound DM threads used by
/others/toast-discord-bot/messages - stores per-user profile snapshot data plus message history
- Discord export blob used by the archive viewer
shape is roughly:
{
"pages": {
"/": {
"count": 12,
"visitors": {
"<sha256>": 1730931224
}
}
},
"updated_at": "2026-03-02T00:00:00Z"
}- downloadable binaries, archives, presets, and similar files linked from the site