How I Built
The Command Center
in a Weekend
A Portfolio Executive's walkthrough of building a double-click portfolio cockpit plus a Shabbat-aware morning brief that lands in your inbox before you wake up. No server, no SaaS, no recurring cost.
Yuri Kruman
Portfolio operator across 8 properties · Jun 2026
properties tracked in one view
/month to run
file you double-click to open
setup, including Gmail App Password
The 30-Second Version
The Command Center is a single offline HTML file plus a Node morning-engine. The HTML is your portfolio cockpit (six tabs, click-to-edit, localStorage persistence). The engine runs each morning via Windows Task Scheduler, refreshes RSS feeds and the KB digest, rewrites data.js and emails you a five-minute brief. It is Shabbat-aware: Friday-evening through Saturday it refreshes data silently and suppresses the email.
The Problem
Portfolio operators waking up to 14 dashboards, three Notion pages and a wall of RSS noise.
The Stack
Static HTML + vanilla JS + localStorage + Node + Nodemailer + Windows Task Scheduler.
What It Doesn't Need
No server, no database, no SaaS subscription, no auth, no JavaScript framework.
Build Time
One weekend for v1. A second weekend for the morning engine and scheduler.
If you are a portfolio operator who has ever opened five browser tabs at 7 am to figure out what changed overnight, this is for you. The point is not that you should clone this. The point is that your cockpit should be one click away, work with the WiFi off and remember your edits without a backend.
Why a Single HTML File, and Why a Morning Email
I run a portfolio of eight properties (DueDrill, AI HR Pilot, BookToCourse.AI, the Beast Score / Leverage Brief stack, Ohr Vishua, the 92 Percent Fund, the PE-fund-website business and the consulting practice). Plus the Fortune-500 fractional CHRO work. Plus the book. Plus the podcast. By Q2 2026 I had:
14
dashboards across Stripe, Vercel, Supabase, Notion, beehiiv, ConvertKit, Beehiiv, GitHub, Plausible, Hubspot, Linear, Lattice, Google Analytics
~40 min
to do my "where am I" check each morning before any actual work
$0
that I was willing to add to monthly burn for ANOTHER SaaS dashboard
1
non-negotiable: it had to respect Shabbat without any thinking on my part
The instinct was to spin up a Next.js dashboard on Vercel. I started doing exactly that and stopped after four hours. The problem with the framework-and-server approach is that for an audience of one (me), the cost-of-running is 100% friction and 0% value. I do not need auth. I do not need realtime. I do not need a database. I need a thing I can double-click on a Sunday and trust.
- 1An audience of one is a different product than an audience of a thousand. Stop building like you have users.
- 2The browser is a perfectly good runtime. A static HTML file with localStorage will outlive most of my SaaS subscriptions.
- 3The morning brief is the whole product. The dashboard is for forensics. The email is the daily ritual.
Static HTML for the cockpit. Node for the morning brief. Nothing in between.
A server is a thing you babysit. A static HTML file is a thing you ignore. The morning engine is a script that runs and dies. If anything breaks, the dashboard still opens. If the dashboard breaks, the email still arrives. Two independent failure domains beat one always-on service every time.
The Stack (and Why Each Piece)
Click each layer for the reasoning.
Cockpit
Single static HTML file
No build step, no framework, no transpiler. One index.html with inline Tailwind via CDN and vanilla JS. The file is the artifact. You email it to yourself, you back it up to Dropbox, you carry it on a USB stick.
Persistence
localStorage + JSON export
Edits live in localStorage. Top-right buttons export your overlay to JSON for backup and re-import on a new machine. No cloud sync. No race conditions. Your data never leaves your browser unless you choose.
Morning Engine
Node.js + Nodemailer
Pure ESM Node scripts. Nodemailer sends through Gmail using an App Password (not your real password). No framework, no orchestrator, no queue. scripts/daily-brief.mjs is the entrypoint. Read it top to bottom, understand it in 10 minutes.
Market Intel
4 RSS feeds, parsed in Node
AI+HR, AI Wage Gap, VC funding, HR Tech. Fetched at 07:00, parsed with a tiny XML reader, top 3 from each feed make the brief. Anything older than 24h is filtered out. No webhooks, no third-party aggregator.
Scheduling
Windows Task Scheduler
No cron service, no Vercel job, no AWS Lambda. install-scheduler.ps1 registers a Sun-Fri 07:00 task. On Linux or Mac the same script becomes a single cron line. The OS already has a scheduler. Use it.
Shabbat Logic
Day-of-week + sundown check
Scheduler skips Saturday. Friday evening / Saturday the script still runs at 07:00 but the brief composer emits no email; data still refreshes silently so Sunday morning is fresh. One-line check, infinite halakhic upside.
The Six-Phase Build Sequence
Each phase is 2-8 hours. Sequence them in order; don't try to parallelize until Phase 4.
The Portfolio Schema
One Node module: scripts/data.mjs. It is the single source of truth for portfolio defaults: companies, deals, OKRs, recurring tasks, build status. The dashboard and the email both read from this file. Edit once, both surfaces update.
export const portfolio = { companies: [ { id: 'duedrill', name: 'DueDrill', stage: 'live', mrr: 0, health: 7, owner: 'YK' }, { id: 'aihrpilot', name: 'AI HR Pilot', stage: 'pilot', mrr: 0, health: 8, owner: 'YK' }, // ...6 more ], deals: [ { co: 'Finesse', stage: 'verbal', arr: 114000, due: '2026-06-09' }, ], okrs: [ { id: 'q2-mrr', label: 'Q2 MRR', target: 5000, current: 0 }, ], tasks: [ { id: 'edgar', label: '92% Fund EDGAR', done: false, daysOpen: 5 }, ] };
"I run a portfolio of [N] properties / projects. Help me design a JavaScript module that's the single source of truth for: (a) per-company state (stage, MRR, health 0-10, owner), (b) open deals (counterparty, stage, value, due date), (c) quarterly OKRs (label, target, current), (d) recurring tasks (label, done bool, daysOpen). Output as a default-export const so the same file can be imported by Node scripts AND read as a script tag in a static HTML page."
What I'd Do Differently Today
Resist the Next.js variant entirely
An earlier richer-but-server-dependent version still lives in app/, components/, lib/. It works, requires npm run dev, and is the version I never open. The static index.html is the real product. Delete the framework variant on day one.
Write the brief in plaintext FIRST, HTML second
I built the HTML email first, then bolted on plaintext for fallback. Half my reads are on my phone in mail.app's plaintext-favored preview. Build the plaintext brief first; the HTML is a render of it, not the reverse.
Move the data module to a shared package, not a sibling file
As the portfolio added a 9th and 10th property, I wanted the same schema in the CEO Command Center and the Newsletter OS. Today I'd publish @yk/portfolio-schema as a private npm package on day one.
Add a one-line CHANGELOG to every refresh
After 30 days you want to know what changed. The refresh now logs to refresh.log. I should have added that on commit #1, not commit #84.
Adapt This for YOUR Cockpit
The architecture (schema → static dashboard → morning refresh → brief composer → OS scheduler → localStorage overlay) is the template for any audience-of-one operating dashboard. Five adaptations off the same skeleton:
| Cockpit For | Schema | Morning Brief Sections | Persona |
|---|---|---|---|
| Solo GP | Funds, LPs, deals, OKRs | Pipeline, port co alerts, IC prep | Solo investor |
| Fundraising lead | Donors, gifts, meetings, OKRs | Today's outreach, stale relationships | Nonprofit ED |
| Sales operator | Accounts, opps, AE quotas | Today's calls, slip risks | Sales leader |
| Founder | Products, exps, hiring, runway | Burn, exp delta, hires due | Multi-product founder |
| Portfolio executive | 8 properties + consulting | Top 3 actions + market + KB | Yuri Kruman |
Starter Prompts for Claude / Cursor
If you want to start today, these are the four prompts that took me from zero to running.
"Write scripts/data.mjs as the single source of truth for a portfolio cockpit. Export a default const with: companies (id, name, stage, mrr, health 0-10, owner), deals (counterparty, stage, value, due), okrs (label, target, current), tasks (label, done, daysOpen). Make it importable from Node AND readable as a script tag in static HTML. Pre-populate with [YOUR LIST] entries as starter rows."
"Build index.html as a single self-contained file with inline Tailwind via CDN and vanilla JS. Six tabs: Portfolio, Pipeline, OKRs, Tasks, Feeds, Builds. Read window.__DATA__ from data.js. Overlay localStorage edits keyed by entity id. Every cell click-to-edit. Top-right toolbar: export-JSON, import-JSON, reset (with confirm). No React, no Vue, no build step."
"Write scripts/daily-brief.mjs (ESM Node) that: (1) fetches [N] RSS feeds in parallel, (2) reads my KB daily digest from disk, (3) rewrites data.js as window.__DATA__ = {...}, (4) composes an HTML+plaintext email with sections [Top 3 Actions | Pipeline This Week | Per-Company | Market Headlines | KB Digest | Stale Warnings], (5) sends via Gmail App Password using Nodemailer, (6) suppresses the email between Friday 17:00 and Saturday end-of-day. Use top-level await, no orchestrator framework."
"Write setup/install-scheduler.ps1 that registers a Windows Task Scheduler task to run node scripts/daily-brief.mjs Sun-Fri at 07:00 local. Include a matching uninstall-scheduler.ps1. The task should run hidden (no popup), with the project directory as the working directory, even when the user is not logged in (require stored credentials)."
What the Command Center Is Not
It is not a CRM. It is not an analytics platform. It is not a team product — there is no concept of users, sharing or permissions. It does not sync between machines automatically; if you want your edits on a second laptop, you export and import. It does not replace Stripe, Vercel, Supabase or Plausible dashboards for forensic investigation.
What it is: a single-operator cockpit that gives you the one view you need at 7 am and the one email that tells you what to do. The narrowness is the point. Cockpits that try to become CRMs become Notion. Cockpits that stay cockpits stay opened daily.
The question is not
"do I need a dashboard?"
The question is:
"What three numbers, if I knew them by 7 am every day, would change what I work on by 9 am?"
Write down those three. The next 16 hours are the cockpit. The 16 after that are the morning brief. Then it runs forever, for $0/month, on your own machine.
This walkthrough is part of the Portfolio Leverage Co. Build Bench series. For the weekly operating brief, subscribe above. For the cohort where we build these tools together, apply here.