The Release Ops Command Center
What you'll learn
~35 min- Build a Node.js static site generator producing a multi-page command center
- Understand the SSG pattern: data + templates = deployable HTML
- Integrate outputs from Lessons 1-5 into a unified dashboard
- Deploy the command center to Netlify, Vercel, or GitHub Pages
What you’re building
You’ve built five tools across this module. Asset engine. Campaign generator. YouTube episode builder. Analytics dashboard. Royalty reconciler. They all work. They all produce useful output. But right now, the output lives in five different folders, and every week you’re opening files in three different places to figure out what to do next.
You’re going to build one command center that pulls everything together. A static website — generated from your data files — that gives you a single place to see this week’s priorities, your campaign status, your revenue numbers, and your platform analytics. Not a live app with servers and databases. Just HTML files generated from your data, deployed for free, accessible from your phone or laptop anywhere.
This isn’t a fan-facing website. It’s your private operations dashboard. Think of it like a cockpit: all the instruments in one place so you can make decisions without switching between five different tools. You can password-protect it or just keep the URL private. Nobody needs to see this except you (and maybe your manager, if you have one).
How the pieces connect
Here’s what you built in each lesson and what data flows into the command center:
| Lesson | Tool | Output the command center uses |
|---|---|---|
| L1 | Release Asset Engine | Asset file paths (generated artwork) |
| L2 | Campaign Generator | campaign.json (captions, calendar, EPK status) |
| L3 | Episode Builder | Episode metadata (next YouTube publish date) |
| L4 | Control Room | analytics.csv (Spotify/Shopify data) |
| L5 | Royalty Reconciler | royalties.csv (revenue data, discrepancy flags) |
The command center reads from a release-data/ directory. You drop your data files there. One command generates the whole site.
Data files + templates = a deployable website. That’s it. Astro (this very training site), Hugo, Jekyll, Eleventy — they all work this way. You’re building a tiny version of the same pattern. No server runs your site. No database stores your data. A build script reads files and writes HTML. You deploy the HTML. Done.
The prompt
Start your AI CLI tool and paste this prompt:
Build a Node.js static site generator that produces a multi-page command centerfor an independent music artist. The tool reads data files from a release-data/directory and generates a deployable static site.
PROJECT STRUCTURE:command-center/ package.json src/ build.js (main build script, entry point) data-loader.js (reads and validates all data files) templates/ layout.hbs (shared HTML layout with nav and footer) index.hbs (This Week's Actions page) campaign.hbs (Campaign Status page) revenue.hbs (Revenue Dashboard page) analytics.hbs (Platform Analytics page) static/ style.css (dark theme stylesheet) release-data/ (input data directory -- sample data included) campaign.json analytics.csv royalties.csv release-info.json (basic release metadata) dist/ (generated output -- the deployable site)
REQUIREMENTS:
1. BUILD SCRIPT (src/build.js) - Usage: node src/build.js - Read all data files from release-data/ - Compile Handlebars templates - Generate HTML pages into dist/ - Copy static/ assets into dist/ - Print build summary: pages generated, data files loaded, any warnings
2. DATA LOADER (src/data-loader.js) - Load release-info.json: { artist, currentRelease, releaseDate, nextActions } - Load campaign.json: { posts (array of { platform, date, caption, status }), epkUrl, hashtags } - Parse analytics.csv: columns for date, platform, metric, value (streams, listeners, followers, merch_orders, merch_revenue) - Parse royalties.csv: columns for track, platform, streams, revenue, period, discrepancy_flag (boolean), discrepancy_note - If a file is missing, log a warning and use empty defaults (the site should still build with partial data)
3. PAGES:
a. index.html — "THIS WEEK'S ACTIONS" - Top 5 action items generated from the data: * Next scheduled social post from campaign.json (with date and platform) * Any royalty discrepancies that need follow-up * Revenue milestone alerts (e.g., "JADED crossed $500 total revenue") * Upcoming release date countdown * Analytics highlight (e.g., "Spotify listeners up 12% this week") - Each action item: icon indicator, description, priority level (urgent/normal/info) - Current release info card at the top
b. campaign.html — "CAMPAIGN STATUS" - Posting calendar: table with date, platform, caption preview, status (scheduled/posted/skipped) - Caption queue: next 5 unposted captions with full text - EPK link if available - Campaign completion percentage (posted / total posts)
c. revenue.html — "REVENUE DASHBOARD" - Total revenue summary card (all platforms combined) - Revenue breakdown by platform (table: platform, streams, revenue, avg per-stream rate) - Per-track revenue table: track name, total streams, total revenue, best platform - Discrepancy flags section: highlighted rows for any track where discrepancy_flag is true, showing the discrepancy_note - All currency values formatted with $ and 2 decimal places
d. analytics.html — "PLATFORM ANALYTICS" - Spotify section: total streams, total listeners, follower count - Merch section: total orders, total revenue, best-selling item - Week-over-week comparison if enough data points exist - Geographic summary if territory data is available
4. DESIGN - Dark theme: background #09090b, cards #141414, borders #262626, text #e5e5e5 - Accent color: #f97316 (orange) for highlights and active nav - Shared navigation bar across all pages with links to each section - Navigation shows current page as active (orange underline) - Responsive: single column on mobile, 2-column grid on desktop - Font: system sans-serif stack (-apple-system, BlinkMacSystemFont, Segoe UI, sans-serif) - Site title: "COMMAND CENTER" with artist name below - Footer: "Built with AI CLI tools | Data stays local"
5. SAMPLE DATA - Include realistic sample data in release-data/: - release-info.json: artist "moodmixformat", current release "JADED", release date "2026-03-14" - campaign.json: 14 posts across Instagram, TikTok, YouTube over 2 weeks, mix of "posted" and "scheduled" statuses - analytics.csv: 30 days of Spotify streams (trending up), Shopify orders, listener counts by city - royalties.csv: 6 tracks across 4 platforms, Q4 2025 data, with 2 rows flagged as discrepancies
6. DEPLOYMENT - Include a netlify.toml in the project root: [build] publish = "dist" command = "node src/build.js" - Include a vercel.json with similar config - Add a "deploy:github-pages" npm script that builds and copies dist/ to docs/ (for GitHub Pages)
DEPENDENCIES: handlebars, csv-parser, chalk (for build output coloring)What you get
After your AI CLI tool finishes, you’ll have the project:
command-center/ package.json netlify.toml vercel.json src/ build.js data-loader.js templates/ layout.hbs index.hbs campaign.hbs revenue.hbs analytics.hbs static/ style.css release-data/ release-info.json campaign.json analytics.csv royalties.csvSet it up and build
cd command-centernpm installnode src/build.jsYou should see output like:
Loading data files... ✓ release-info.json (1 release) ✓ campaign.json (14 posts) ✓ analytics.csv (127 rows) ✓ royalties.csv (24 rows, 2 discrepancies)
Building pages... ✓ dist/index.html — This Week's Actions ✓ dist/campaign.html — Campaign Status ✓ dist/revenue.html — Revenue Dashboard ✓ dist/analytics.html — Platform Analytics ✓ dist/style.css
Build complete: 4 pages generatedOpen dist/index.html in your browser. Click through all four pages. Check:
- Does the navigation work between pages?
- Does “This Week’s Actions” show relevant priorities from the sample data?
- Does the revenue page show discrepancy flags?
- Is the dark theme applied consistently?
While tweaking templates, you can add a watch mode: "If I ask you to 'add a watch mode', add a file watcher that rebuilds when any template or data file changes. Use fs.watch or chokidar." This makes it easy to iterate on the design without rerunning the build manually.
A worked example: building for a new single
Here’s a real scenario. You’re releasing “JADED” on March 14. Your data:
- release-info.json — You fill in the track name, release date, and your top priorities for the week
- campaign.json — You already generated this with the Campaign Generator (Lesson 2). Copy it into
release-data/ - analytics.csv — You exported this from your Control Room (Lesson 4) or directly from Spotify for Artists
- royalties.csv — You generated this with the Royalty Reconciler (Lesson 5)
Drop all four files into release-data/, run the build, and open the site. Your “This Week’s Actions” page might show:
- URGENT: Post Instagram teaser caption (scheduled for tomorrow, 6pm ET)
- URGENT: Follow up on MOOD’s Apple Music royalty discrepancy (-18% streams)
- NORMAL: Release day is in 4 days — EPK is ready, check all platform links
- INFO: Spotify listeners up 8% this week (52,400 → 56,590)
- INFO: KICK IT W/U crossed $1,000 total revenue this quarter
That’s your week in one glance. No digging through five different folders.
Deploying your command center
The generated site is just HTML, CSS, and nothing else. No server needed. Three free options:
Netlify
# Install Netlify CLI (one time)npm install -g netlify-cli
# Deploycd command-centernetlify deploy --prod --dir=distVercel
# Install Vercel CLI (one time)npm install -g vercel
# Deploycd command-centervercel --prodGitHub Pages
# Build and copy to docs/npm run deploy:github-pages
# Commit and pushgit add docs/git commit -m "Update command center"git pushThen enable GitHub Pages in your repo settings, pointing to the docs/ folder.
🔍Why a static site instead of a 'real' app
You might be wondering: why not build a React app with a database? Or use a service like Notion or Airtable?
A static site wins for this use case because:
- No server costs: HTML files served from a CDN cost nothing. Netlify, Vercel, and GitHub Pages are all free for this.
- No maintenance: There’s no database to back up, no server to keep running, no dependencies to update continuously. The site is just files.
- Fast: Static HTML loads instantly. No JavaScript frameworks, no API calls, no loading spinners.
- Private: Your data is baked into the HTML at build time. Nobody can query your database because there is no database. The built site contains only the data you chose to include.
- Portable: You can open the HTML files directly from your filesystem without deploying anywhere. It works offline.
The tradeoff: you have to rebuild when data changes. For a weekly check-in dashboard, that’s running one command before you look at it. Perfectly fine.
Netlify, Vercel, and GitHub Pages all have free tiers that are more than enough for a private dashboard. You’re not going to hit any limits with a 4-page static site. Pick whichever one feels simplest — Netlify’s drag-and-drop deployment is the easiest if you’ve never deployed anything before.
If something is off
| Problem | Follow-up prompt |
|---|---|
| Navigation links are broken between pages | The nav links use absolute paths (/campaign.html) but the site is deployed to a subdirectory. Change all nav links to relative paths (campaign.html, revenue.html, etc.) so they work whether the site is at the root or in a subdirectory. |
| Missing data file crashes the build | The build crashes when analytics.csv is missing. Make the data loader resilient: if a file doesn't exist, log a warning and use an empty default. The site should still build with partial data -- just show "No data available" in sections that need the missing file. |
| The CSS isn’t applied to generated pages | The pages are unstyled. Make sure build.js copies static/style.css to dist/style.css, and the layout template links to it with a relative path: <link rel="stylesheet" href="style.css">. Check that the copy step happens after the dist directory is created. |
| Handlebars template has raw curly braces | The template is rendering raw Handlebars syntax like {{revenue}} instead of actual values. Make sure build.js compiles each template with Handlebars.compile() and passes the data context when calling the compiled function. Check that the template files use .hbs extension and are read as strings. |
Customize it
Add automatic rebuild on data change
Add a "watch" npm script that uses chokidar to watch the release-data/ directoryand templates/ directory. When any file changes, automatically rebuild the site.Print a timestamp and which file triggered the rebuild. This way I can update aCSV, save it, and the site refreshes automatically.Add an email digest
Add a --digest flag to build.js that generates a plain-text email summary indist/digest.txt. Include: the top 5 action items from the index page, totalrevenue this period, any discrepancy flags, and the next 3 scheduled posts.Format it as a clean email I could send to myself or my manager every Monday.Keep it under 500 words.Add social media preview images
Add Open Graph meta tags to each page so they have proper previews when shared.Set og:title to the page name, og:description to a summary, and og:image to agenerated preview image. For the preview image, create a simple 1200x630 PNGwith the page title and a key metric on a dark background with the orange accent.Use the sharp npm package for image generation.Add historical release comparison
Add support for multiple releases. Instead of one release-data/ directory,support release-data/jaded/, release-data/kick-it-wu/, etc. Add a releases.htmlpage that compares metrics across releases: which release had the most first-weekstreams, best revenue, highest merch conversion. Show a comparison table andhighlight your best-performing release.When Things Go Wrong
Use the Symptom → Evidence → Request pattern: describe what you see, paste the error, then ask for a fix.
The story so far
Over six lessons, you’ve built the operations backbone:
- Release Asset Engine (Lesson 1) — one cover image in, six platform-sized assets out
- Campaign Generator (Lesson 2) — one metadata file in, captions, hashtags, calendar, and an EPK out
- Episode Builder (Lesson 3) — one notes file in, all YouTube publishing metadata out
- Control Room (Lesson 4) — CSV exports in, geographic and business intelligence out
- Royalty Reconciler (Lesson 5) — distributor CSVs in, discrepancy flags and revenue report out
- Command Center (Lesson 6) — all of the above in, one weekly action-plan dashboard out
These tools chain together. The campaign generator’s output feeds the command center’s campaign page. The reconciler’s flags appear on the revenue dashboard. The control room’s analytics populate the analytics page. The command center is the hub that ties every tool into a single view.
Next up: building your signature visualizer content — the tape deck aesthetic that makes your brand recognizable across every platform.
Try it yourself
- Open your AI CLI tool in an empty folder.
- Paste the main prompt.
- Run
npm installand thennode src/build.js. - Open
dist/index.htmland click through all four pages. - Replace the sample data with real output from your Lessons 1-5 tools.
- Deploy to Netlify, Vercel, or GitHub Pages.
Key takeaways
- Static site generators are data + templates — no server, no database, no complexity. Read files, render templates, write HTML. That’s the entire pattern.
- Free deployment is real — Netlify, Vercel, and GitHub Pages all host static sites for free. Your command center costs nothing to run.
- Integration is the capstone skill — building individual tools is valuable, but connecting them into a unified workflow is where the real power is. The command center doesn’t do anything new; it orchestrates what you already built.
- Private dashboards beat scattered files — one URL with all your release data is better than five folders you have to remember to check.
- Rebuild, don’t maintain — when data changes, rebuild the site. There’s no state to manage, no cache to invalidate, no database to migrate. Just run the build and deploy.
Your command center works locally but you want to deploy it. You choose Netlify. What does Netlify actually serve to visitors?
What’s next
The operations side is locked in. Next lesson: you build your signature audio visualizer — the tape deck aesthetic that turns every track into content for Reels, Shorts, and TikTok.