Underwrite a music catalog using only what the public can see.
Catalog Underwriter is an interactive public-data workbench for reconstructing a musical catalog and testing what a selected interest may be worth. It separates observed consumption, modeled consumption, economic assumptions, estimated cash flow, and valuation throughout the product.
The repository includes a complete stored demonstration underwrite for Kendrick Lamar and live MusicBrainz artist resolution. A user can inspect evidence coverage, override cash flow, edit rights and capital assumptions, compare bear/base/bull cases, use a two-dimensional DCF sensitivity matrix, review concentration, and run deterministic “Break the Deal” diagnostics.
Music catalogs trade like financial assets, but royalty statements and contracts are usually private. This project explores what disciplined underwriting can still do with public evidence—without claiming actual artist income, inventing ownership, or letting an LLM decide the valuation.
Public evidence → explicit assumptions → deterministic cash flow → DCF → user judgment
- MusicBrainz resolves ambiguous artist identities and returns public catalog structure.
- An optional server-side Last.fm adapter adds track-demand evidence, looked up by MusicBrainz ID.
- An optional server-side YouTube adapter adds cumulative views for conservatively matched official uploads.
- Last.fm listeners and YouTube views are annualized with a disclosed calibration and multiplied by default per-1,000-stream rates to pre-fill a modeled cash flow, labeled as modeled and fully editable.
- A stored snapshot of Kendrick Lamar's public evidence (
data/kendrick-lamar-snapshot.json) runs through the same model as a live lookup, so the homepage demonstration is reliable without live APIs and always matches the current model. - Pure TypeScript functions calculate cash flow, DCF, scenarios, sensitivity, concentration, and risk diagnostics.
- Missing data stays visible as unknown; live catalogs without Last.fm or YouTube evidence require a user-entered cash-flow base.
- DCF and transaction-derived market-multiple values are shown separately and reconciled without mechanical averaging.
The application uses Vinext, React 19, TypeScript, Tailwind CSS, restyled shadcn primitives, and Recharts. Provider adapters are separated from application types and the financial engine. See docs/architecture.md.
- MusicBrainz: artist identity, release groups, dates, types, and genres.
- Last.fm: optional relative demand and concentration evidence only.
- YouTube Data API: optional cumulative official-video evidence only.
- Repository-managed comparable transactions: each record links to an original announcement and, when different, a reported-price source.
The engine projects ten explicit annual periods and a Gordon-growth terminal value. Default discount and growth rates are anchored to catalog-market practice (Citrin Cooperman's 8.5% discount rate; about 17× annual cash flow in the base case). Master and publishing interests are weighted separately before fees. Terminal growth must be below the effective discount rate. See docs/methodology.md and the in-product /methodology page.
- Public data cannot verify royalty income, rights ownership, recoupment, or private contract terms.
- MusicBrainz coverage varies and its live lightweight route does not perform recording-level normalization.
- Last.fm is a demand signal, not a royalty or total-market stream count. The modeled annual stream range rests on a 29-artist calibration; individual artists can miss by up to 5×, and Last.fm under-represents mainstream pop, hip-hop, and Latin audiences.
- Default payout rates are public-reporting averages, not any catalog's contract terms.
- The demo's value is a modeled estimate from public evidence captured on the snapshot date, not a factual claim about artist earnings. Refresh the snapshot to update it.
- Request throttling is process-local until production hosting adds durable edge infrastructure.
Requirements: Node.js 22.13 or newer.
npm install
cp .env.example .env.local
npm run devOpen http://localhost:3000. The stored demo works without API credentials.
LASTFM_API_KEY is optional. When present, the server retrieves Last.fm top-track signals for live artist underwrites, which also drive the modeled audio cash flow. YOUTUBE_API_KEY is also optional and enables likely-official cumulative video evidence. Without either key a live underwrite has no modeled cash flow. Secrets remain server-side and .env.local is ignored by Git.
npm test
npm run typecheck
npm run lint
npm run buildThe automated fixtures cover DCF present value, terminal guardrails, rights weighting, scenario order, discount-rate sensitivity, and concentration.
The production target is catalog.ankitkapoor.me. The repository is compatible with the OpenAI Sites / Cloudflare Worker build path. Deployment and custom-domain configuration are intentionally deferred to the hosting milestone.
- Rights-term runoff and copyright-life override
- Bid mode, target IRR, and maximum purchase price
- Shareable valuation snapshots
- Richer public-performance coverage
- Generated investment memo constrained to deterministic outputs
- Portfolio integration at
ankitkapoor.me/work/catalog-underwriter
Catalog Underwriter is an educational analytical tool based on publicly available information and user-defined assumptions. Estimates do not represent verified royalty statements, ownership interests, market offers, investment advice, or legal advice.