You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Index page for every widget roadmap in splashboard. Individual fetcher / renderer candidates live in the sub-issues below; this issue holds cross-cutting context (composition model, prioritization rubric, ReadStore recipes, ecosystem reference).
No separate issue per fetcher / renderer. A PR that ships one ticks the box on the relevant sub-issue and references that issue. Things that do get their own issue are cross-cutting features (splashboard fetch CLI #39, splashboard cache CLI #40, theme system #17). ReadStore fetcher shipped via #43.
A widget is Fetcher × Renderer × Layout slot. Fetchers produce Payload; renderers consume it. Most fetchers have a natural renderer pairing, but the two are swappable — same clock fetcher + text renderer = digital clock; + analog_clock renderer = analog face. Same github_contributions fetcher + heatmap renderer = 草; habit-tracker ReadStore + same heatmap renderer = habit grid.
Shapes are the only coupling between fetchers and renderers. Each Body variant corresponds to one Shape: Lines, Entries, Ratio, NumberSeries, PointSeries, Bars, Image, Calendar, Heatmap. See AGENTS.md for the full contract and the checklist to add a new shape.
Layering per item
Fetcher kind — Fetcher (cache-backed, async) vs RealtimeFetcher (sync, per-frame). "Right now" values (clock, system_cpu, clock_countdown, system_uptime) are realtime; everything else is cached.
Safety class — Safe (renders in untrusted local config), Network (gated if URL is config-provided). Fixed-host authenticated fetchers stay Safe — see project_trust_model.md.
Built-in vs ReadStore — ReadStore (shipped feat: $HOME/.splashboard/ home-dir layout + ReadStore fetcher #43) renders any file the user writes at $HOME/.splashboard/store/<id>.<ext>. It's the escape hatch, not the default: prefer a dedicated built-in whenever the widget warrants curated UX (parser, per-user auth, protocol handling, rate-limit strategy, stateful update). ReadStore fits when the data is ad-hoc and the user is willing to produce the file themselves.
Ecosystem reference
Before building a renderer from scratch, check awesome-ratatui. Many primitive gaps already have community crates that we can wrap with a thin Renderer impl — a few lines mapping Payload → widget input.
Two animation paradigms, with distinct upstream libraries:
Post-process effects — render the widget normally, then apply a shader-like pass (fade, color shift, glitch, slide, dissolve, sweep). tachyonfx (50+ effects) is the clear winner.
Reveal animations — the widget's final form emerges from a particle-like animation (matrix rain decrypting into text, beams, fireworks). TTE is the algorithmic reference; not expressible via tachyonfx's buffer-post-process paradigm. tui-rain covers matrix/rain.
Config conventions for the shipped read_store fetcher; the user produces the file and read_store renders it. Listed here for discoverability, not for implementation tracking — they don't need a sub-issue because no code ships for each one.
habit_tracker — daily 0/1 grid → heatmap
goal_progress — single ratio
journal_prompt — random line
gratitude_list
word_of_day
reading_queue_random
bookmark_random
portfolio_summary
spending_this_month
invoice_due
most_recent_file — MRU list
command_history_top
Composition helpers (layout-level, not fetchers)
Multi-widget layouts that compose existing pieces. Tracked here rather than any fetcher sub-issue.
combined_status_row — multiple badges in one row
daily_digest — weather + calendar + notifications
random_widget_of_day — N configured, pick 1
rotating_message — different text per cd
Prioritization rubric
For when/if we pick something up — not a commitment.
Renderer primitives first — a single renderer (heatmap, badge, timeline) unlocks many dependent fetchers. Highest leverage per unit effort. Lives in meta: renderer roadmap #61.
Daily-driver coverage — does a fresh install fill a satisfying home splash? Gaps: weather_*, calendar_*, full system_* rollout.
Per-dir killer feature — does cd into project show meaningfully more than without splashboard? Gaps: forge parity across gitlab_* / bitbucket_* / etc., ci_*.
Plugin protocol (core: Plugin protocol (subprocess-based I/O spec) #5) — closed. Splashboard is a curated splash renderer, not a dashboard framework. Subprocess plugins can't be bounded in blast radius. Custom widgets land as built-in PRs or use ReadStore.
Index page for every widget roadmap in splashboard. Individual fetcher / renderer candidates live in the sub-issues below; this issue holds cross-cutting context (composition model, prioritization rubric, ReadStore recipes, ecosystem reference).
No separate issue per fetcher / renderer. A PR that ships one ticks the box on the relevant sub-issue and references that issue. Things that do get their own issue are cross-cutting features (
splashboard fetchCLI #39,splashboard cacheCLI #40, theme system #17). ReadStore fetcher shipped via #43.Sub-issues
Renderers
meta: renderer roadmap— primitives (charts, gauges, QR, etc.) + animation families (animated_postfxvia tachyonfx,animated_revealTTE-style)Fetchers
meta: fetcher roadmap - Local / System—clock_*,system_*,disk_*,net_*,docker_*,k8s_*,code_*,project_*meta: fetcher roadmap - VCS / Forge—git_*,github_*,gitlab_*,bitbucket_*,gitea_*,sourcehut_*,azure_devops_*,gerrit_*meta: fetcher roadmap - Coding & Build—ci_*,deploy_*,leetcode_*,stackoverflow_*,oss_*, package downloads, trendingmeta: fetcher roadmap - Cloud / Infra / Ops—aws_*,gcp_*,terraform_*,cloudflare_*,tailscale_*, uptime monitors,pagerduty_*,cloudwatch_*/datadog_*/sentry_*meta: fetcher roadmap - Communication & PM—slack_*,discord_*,email_*,matrix_*,jira_*,linear_*,asana_*,todoist_*,notion_*meta: fetcher roadmap - Social & Media— RSS / news,mastodon_*,bluesky_*,youtube_*,twitch_*,spotify_*,plex_*, reading / watching, novelty image / text feedsmeta: fetcher roadmap - Life & Ambient—weather_*,calendar_*,holiday_*,travel_*,anki_*,health_*,strava_*, finance, monetization, analytics, home / IoT, gaming, public-API feedsComposition model
A widget is
Fetcher × Renderer × Layout slot. Fetchers producePayload; renderers consume it. Most fetchers have a natural renderer pairing, but the two are swappable — same clock fetcher +textrenderer = digital clock; +analog_clockrenderer = analog face. Samegithub_contributionsfetcher +heatmaprenderer = 草; habit-tracker ReadStore + sameheatmaprenderer = habit grid.Shapes are the only coupling between fetchers and renderers. Each
Bodyvariant corresponds to oneShape:Lines,Entries,Ratio,NumberSeries,PointSeries,Bars,Image,Calendar,Heatmap. SeeAGENTS.mdfor the full contract and the checklist to add a new shape.Layering per item
Fetcher(cache-backed, async) vsRealtimeFetcher(sync, per-frame). "Right now" values (clock,system_cpu,clock_countdown,system_uptime) are realtime; everything else is cached.Safe(renders in untrusted local config),Network(gated if URL is config-provided). Fixed-host authenticated fetchers staySafe— seeproject_trust_model.md.$HOME/.splashboard/store/<id>.<ext>. It's the escape hatch, not the default: prefer a dedicated built-in whenever the widget warrants curated UX (parser, per-user auth, protocol handling, rate-limit strategy, stateful update). ReadStore fits when the data is ad-hoc and the user is willing to produce the file themselves.Ecosystem reference
Before building a renderer from scratch, check awesome-ratatui. Many primitive gaps already have community crates that we can wrap with a thin
Rendererimpl — a few lines mappingPayload→ widget input.Two animation paradigms, with distinct upstream libraries:
ansi-to-tuicovers ANSI passthrough.Full primitive-gap list lives in #61.
ReadStore recipes (not dedicated fetchers)
Config conventions for the shipped
read_storefetcher; the user produces the file andread_storerenders it. Listed here for discoverability, not for implementation tracking — they don't need a sub-issue because no code ships for each one.habit_tracker— daily 0/1 grid → heatmapgoal_progress— single ratiojournal_prompt— random linegratitude_listword_of_dayreading_queue_randombookmark_randomportfolio_summaryspending_this_monthinvoice_duemost_recent_file— MRU listcommand_history_topComposition helpers (layout-level, not fetchers)
Multi-widget layouts that compose existing pieces. Tracked here rather than any fetcher sub-issue.
combined_status_row— multiple badges in one rowdaily_digest— weather + calendar + notificationsrandom_widget_of_day— N configured, pick 1rotating_message— different text per cdPrioritization rubric
For when/if we pick something up — not a commitment.
heatmap,badge,timeline) unlocks many dependent fetchers. Highest leverage per unit effort. Lives in meta: renderer roadmap #61.weather_*,calendar_*, fullsystem_*rollout.cdinto project show meaningfully more than without splashboard? Gaps: forge parity acrossgitlab_*/bitbucket_*/ etc.,ci_*.Rejected designs (don't reintroduce)
command = "..."fetcher, in any config scope. Local-vs-global rule carve-outs are not worth the footgun potential.