/ ideas.org
ideas.org
  1  #+title: KB-Dashboard — Ideas & Initial Scope
  2  #+author: Xavier Brinon
  3  #+date: [2026-04-24 Fri]
  4  #+startup: indent
  5  #+options: toc:3 num:t ^:{}
  6  
  7  * Concept
  8  
  9  A personal web dashboard listing all the projects I'm working on — their current
 10  status, stats, progress, delivery speed, lines of code, and so on. Intended as
 11  the default page when I open a new tab in Firefox or Chrome.
 12  
 13  *Offline-first*: builds and runs locally, displays via =file://= URL or a tiny
 14  localhost server. Later, a filtered public variant deploys online at
 15  =dashboard.brinon.eu= as the beginning of a personal online presence.
 16  
 17  * Use case
 18  
 19  - *Private new-tab page*: every new browser tab opens to the dashboard, giving
 20    me an at-a-glance view of what I'm working on and where each project stands.
 21  - *Public portfolio snapshot* (later): a filtered, allowlisted version serves at
 22    a =brinon.eu=-related URL alongside eventual blog / CV pages.
 23  - Personal-scale only. Not multi-user, not a SaaS, not shared.
 24  
 25  * Data sources
 26  
 27  Minimum first-cut:
 28  
 29  - *Subdirectories of the parent folder* (=../= from this repo's parent) — each
 30    folder that looks like a project gets surfaced.
 31  - *Git history* of each project (commits, diff stats, LOC, velocity derived from
 32    commit frequency).
 33  - *=rad= issue state* per project (open / solved / closed counts; maybe
 34    breakdown by label).
 35  - *Time tracker* (tool TBD — candidates include =timewarrior=, Toggl, a CSV I
 36    maintain, or something else).
 37  
 38  Potentially extensible:
 39  
 40  - GitHub / GitLab remote metadata (stars, issues, PRs) for projects with
 41    remotes.
 42  - CI / CD status.
 43  - Linear / Jira if I end up using either.
 44  - Published artifacts (HTML / PDF / images) grouped by project.
 45  
 46  * Features
 47  
 48  ** MVP — read-only
 49  
 50  - Discover projects in =../= (something marks a folder as "a project" — =.git=
 51    presence? A manifest file? An allowlist config?).
 52  - Compute stats per project (LOC, commit velocity, last-commit date, open issue
 53    count).
 54  - Render a dashboard grid / list with each project card showing its key numbers.
 55  - Refresh mechanism (cron, timer, or manual "regenerate" button).
 56  
 57  ** Polish
 58  
 59  - Typography and visual hierarchy — the dashboard has to be pleasant to look at
 60    dozens of times a day.
 61  - Project status categories / colour coding (active / idle / done / stuck).
 62  - Responsive layout (desktop primary; tablet / phone as secondary).
 63  - Dark mode default — it's a new-tab page, bright is unfriendly.
 64  
 65  ** Write-back (later, optional)
 66  
 67  - Per-project annotation: free-form notes, "why is this stuck?", next-action
 68    prose.
 69  - Annotations live in markdown files the dashboard can round-trip:
 70    auto-refreshed data cells (dates, LOC, counts) regenerate each run;
 71    user-authored text cells (my notes) are preserved verbatim across
 72    regenerations.
 73  - Requires clean separation between generated and user-authored content.
 74  
 75  ** Public variant
 76  
 77  - A filtered build that only exposes projects explicitly marked public.
 78  - *Default-private*: projects must opt in (allowlist), not opt out (blocklist).
 79  - Per-project opt-in mechanism (candidate: a =.dashboard.public.yaml= marker
 80    file in each project, or a central allowlist config).
 81  - Redaction of sensitive columns even within public projects (e.g., LOC OK;
 82    client name / hourly rate not).
 83  
 84  * Deployment & hosting
 85  
 86  ** Domain
 87  
 88  - Primary: =brinon.eu= (candidate).
 89  - *Subdomain architecture*: each subdomain is a separate app / repo / deploy.
 90    Subpaths are workflows within an app.
 91  - Dashboard at =dashboard.brinon.eu=; apex =brinon.eu= reserved for a future
 92    minimal landing page. Rationale: keeps apex decoupled from dashboard identity,
 93    so either can evolve without the other breaking.
 94  
 95  ** Infrastructure
 96  
 97  - Self-hosted VPS already running *Dokploy* (open-source Heroku-alternative;
 98    Docker + Traefik + automatic Let's Encrypt + built-in CI/CD).
 99  - Dokploy handles SSL, routing, cert rotation, auto-deploy on git push.
100  
101  ** Deployment pattern
102  
103  - *Generator runs locally* — on my dev machine where =../= project folders
104    actually exist.
105  - Generator outputs two builds: =dist/private/= (full) and =dist/public/=
106    (filtered).
107  - =dist/public/= is committed and pushed to the repo that Dokploy watches.
108  - Dokploy builds a tiny nginx-serves-dist container and deploys.
109  - *The VPS never sees private data* — it's a dumb CDN for pre-built static HTML.
110  
111  ** Refresh cadence
112  
113  - Local machine runs a scheduled regen (cron / launchd / systemd-user-timer) —
114    say every 30 minutes or on git-commit hook — then pushes committed
115    =dist/public/= changes.
116  - Manual "refresh now" option for on-demand regen.
117  
118  * Architecture notes
119  
120  ** Local-first build
121  
122  All data access happens on my dev machine. The VPS is a static file server. This
123  decouples "where data lives" from "where it's served" and keeps private data out
124  of any network-exposed environment.
125  
126  ** Single-source-of-truth generator
127  
128  One Node / Bun / Python / Go binary (stack TBD) reads all data sources, produces
129  an intermediate model, and renders to static HTML with a flag gating
130  public-vs-private scope.
131  
132  ** No server-side state
133  
134  Static HTML only. No database, no runtime data fetching, no API calls from the
135  browser. Simplifies security, caching, and failure modes. All "freshness" comes
136  from the next regen.
137  
138  * Privacy & safety
139  
140  Publishing something tied to my name (near a future CV / resume) raises stakes
141  meaningfully:
142  
143  - *Data leakage risk*: any private repo or client project accidentally surfaced
144    is a confidentiality breach.
145  - *Correctness risk*: wrong numbers on a resume-adjacent page misrepresent me
146    professionally.
147  - *Reputation coupling*: whatever the dashboard says about velocity / progress
148    becomes part of my online brand.
149  
150  Mitigations:
151  
152  - *Default-private*: projects must explicitly opt in to the =--public= build.
153  - *Diff-visible publish*: the committed =dist/public/= directory is readable — a
154    pre-publish audit can grep it for project names, file paths, client
155    identifiers, or any string that shouldn't be there.
156  - *Staging environment* (later): a staging Dokploy app at
157    =dashboard-staging.brinon.eu= that I can preview before promoting to
158    production.
159  
160  * Open questions
161  
162  - *Stack choice*: Bun + TypeScript? Python? Go? Plain HTML with a build-time
163    generator? Each has tradeoffs — TS gives shared types between generator and
164    (future) client JS; Python has the richest stats ecosystem; Go produces tiny
165    static binaries; plain HTML is simplest but least expressive.
166  - *Project discovery marker*: how does the generator decide a folder in =../= is
167    a project to show? =.git= presence? An explicit manifest file? An allowlist
168    config? The answer affects day-one UX.
169  - *Time-tracker integration*: which tracker, and does the dashboard read its
170    data live or from a periodic export? This is the least-defined data source.
171  - *Visual identity*: the dashboard as first public artifact under my name sets
172    tone for whatever follows. Minimalist / data-dense / colourful? Worth settling
173    before the polish phase.
174  - *Update strategy for public deploy*: auto-deploy every commit, or explicit
175    "publish" button? Staging environment as gate before production?
176  - *"What is a project" boundary*: is a project one folder, or can a folder
177    contain multiple projects (e.g., monorepos)? Does the dashboard treat
178    sub-folders as children, or flatten?
179  
180  * Suggested sequence
181  
182  1. Decide stack.
183  2. Scaffold project with minimal build pipeline (generator reads =../=, outputs
184     a placeholder HTML).
185  3. First real data source: git stats for one project.
186  4. Expand to all projects; add =rad= issue counts.
187  5. Read-only MVP — usable as a new-tab page locally.
188  6. Visual polish.
189  7. Additional data sources (time tracker, remote metadata).
190  8. Optional: write-back feature for annotations.
191  9. Privacy filter implementation + =--public= build target.
192  10. First deploy to =dashboard.brinon.eu= via Dokploy.