Get Heard
โ ๏ธ Work in progress - early preview
This package is published to reserve the name while the app is still being built. It runs, and it does the things below, but it is pre-1.0 and unfinished: expect rough edges, breaking changes between versions, and setup steps that still assume you are comfortable with a terminal. There is no support contract, no stability promise, and no migration guarantee between
0.xreleases yet.If you are here early: welcome, and please keep a backup of your data folder.
Get your song heard. Get Heard finds the outlets, writes and sends the pitches, tracks what came back, and produces the artifacts a release needs - a press kit, a smart link, a link-in-bio page, a fan kit, and 9:16 shorts cut from the song itself.
It runs on your own machine, on your own data. The only things that leave it are the pitches you approve, the pages you choose to publish, and whatever you send to the AI provider you configured.
npx getheard
That is the whole install. It opens your browser, and a guide walks you through the first release.
๐ Full documentation: DOCS.md - getting started, AI setup, connecting a mailbox, a page-by-page feature guide, template variables, every environment variable, and troubleshooting.
What it does
- Finds outlets - blogs, radio stations, magazines, YouTube channels and playlist curators that accept free submissions, with their real contact address and submission rules read off the page.
- Vets curators before you pitch - a playlist trust audit that flags payola farms and botted audiences, because a bad placement is worse than none.
- Writes and sends the pitches - personalized per outlet, from your own mailbox, and never without your approval. Opens, clicks, replies and coverage all come back into one place.
- Builds the release's pages - a press kit, a smart link, a link-in-bio page and a fan kit, published to your own domain as static files that load fast on a phone.
- Cuts the shorts - 9:16 vertical video from your master and cover, hook-aligned, captioned, with the beat and the countdown baked in.
- Holds on to the fans who arrive early - before release day a visitor can leave an address and get exactly one email, in their own language, the day the song is out.
What you have to bring
| Node.js 24 or newer | Required, not preferred: the app is native ESM and runs its TypeScript through Node's own type stripping. node --version to check, nodejs.org to install. |
| AI credentials | One lane of four - a Claude subscription through Claude Code, an Anthropic API key, an OpenAI API key, or a ChatGPT subscription through the Codex CLI. โ These are read from the environment, not from Settings - put them in a .env file (see DOCS.md ยง2). Settings picks the provider and the models, and tells you which credentials it can see. |
| A mailbox | Optional until you send. Either your own mailbox over SMTP + IMAP (an address and an app password - the app derives the hosts and ports and verifies them), or Gmail through a Google OAuth client of your own. |
| A Netlify account | Optional until you publish. A free personal access token hosts the press kit, smart link, bio page, fan kit and the tracking beacon. |
| A domain | Optional. Point it at the published pages and every link moves onto it once it actually resolves. |
| Spotify API credentials | Optional. Free, and only playlist-curator discovery and the release-day watcher use them. |
| Your own social apps | Optional, per platform, and only if you want the app to post: Instagram, Facebook, TikTok and YouTube each want a developer app you register yourself. |
Nothing above blocks the app from booting. Every credential that is missing shows as a connection disabled with the reason, never as a button that dead-ends at a vendor.
Running it
npx getheard # start it, open a browser
npx getheard --port 4000 # a specific port
npx getheard --data ~/music # keep the database and renders somewhere else
npx getheard --no-open # do not open a browser
npx getheard --version
npx getheard --help
Your database, uploaded masters, rendered videos and fonts live in one folder outside the app, so upgrading never touches them:
| OS | Location |
|---|---|
| macOS | ~/Library/Application Support/GetHeard |
| Linux | ~/.local/share/getheard |
| Windows | %APPDATA%\GetHeard |
A .env file is read from the working directory and from beside that database, so an installed copy can be configured without exporting shell variables.
A note on the port. Get Heard remembers the port it started on and asks for the same one every time, because connecting Gmail means registering http://localhost:<port>/api/settings/gmail/callback with Google, and Google matches it exactly. If that port is taken, it moves and tells you - update the redirect URI in Settings โ Connections and in your Google console to match.
Connecting a mailbox
Pitches are sent from your own mailbox, so they come from you rather than from a tool. Two lanes, and Settings โ Connections says which one is live, with the address an editor will see:
Your own mail server (SMTP + IMAP). Type the address you send from and an app password. The app looks the provider up from the domain, fills in the hosts and ports, and verifies both halves against the real server before storing anything. Sending and reading are separate: SMTP alone sends pitches, and reply detection stays off until IMAP is connected too. For a Gmail address this means Google's own three steps - 2-Step Verification, an app password for Mail, and IMAP switched on - and the card links each one. โ A Google Workspace account cannot use app passwords at all; the card says so rather than leaving you retrying.
Gmail over OAuth. A Google Cloud project of your own, walked through in Settings โ Connections and in full in DOCS.md ยง3. The short version:
- Google Cloud Console โ create a project โ APIs & Services โ Library โ enable Gmail API.
- Credentials โ Create Credentials โ OAuth client ID โ Web application.
- Add the redirect URI shown in Settings โ Connections - copy it from there, it carries the port you are actually on.
- Paste the client ID and secret into Settings, then click Authorize Gmail.
Important: a new Google project starts in "Testing" mode, and you must add your own Gmail address under OAuth consent screen โ Test users, or authorizing fails with a 403
access_denied. It can stay in Testing mode forever - you are the only user.
Running from source
For working on Get Heard itself:
npm install
npm run dev # server watch + frontend bundle watch
Then open http://localhost:3000. Configuration can go in a .env file (.env.example lists every variable, commented out), but everything has a default and the app boots without any of it.
npm test # the whole suite
npm run test:one tests/docs.test.ts # one file, the tight loop
npm run test:ui # real-browser UI tests (needs Chrome)
npx tsc --noEmit -p tsconfig.json # backend typecheck
npx tsc --noEmit -p tsconfig.frontend.json # frontend typecheck
npm run lint # eslint --fix
npm run build && npm start # compiled build
Two editions
Everything above describes selfhost - one owner, one laptop, one SQLite file, your own API keys, no login. It is the default and it is what npx getheard gives you; if you never set APP_EDITION, it is the only edition you will ever meet.
There is a second one. saas (APP_EDITION=saas) is the same app built as a hosted, multi-tenant product: a login gate, many workspaces in one database, metered AI with a per-workspace budget, Stripe billing, and published pages served from the operator's own domain. The fork lives in exactly one named place - config.edition in src/config.ts - and the rule is that anything reading it leaves selfhost byte-identical.
To run it locally:
npm run dev:saas # its own folder (data/saas-dev/), its own port (3998)
npm run dev:saas -- --reset # start over from a clean signup - removes that folder, and only that folder
It will not start against your selfhost database, or anywhere that would put its uploads beside yours, on purpose. Sign-in has no password to guess: sign up, then copy the magic link out of the server log - with no RESEND_API_KEY the auth mail transport is deliberately the console.
npm run dev:crew is the internal back-office, a separate process on port 3997 against the same dev database, and npm run dev:landing is the signed-out front door.
Full detail - what each edition includes, what the saas run disarms, and every environment variable - is in DOCS.md ยง1b. Deploying the hosted edition for real is deploy/DEPLOY.md.
Tech
Node + Express + TypeScript, SQLite via better-sqlite3, a Lit frontend bundled with esbuild, ffmpeg for rendering, Handlebars for the published pages. AI through Anthropic, OpenAI, the Claude Agent SDK or the Codex SDK - whichever you configure.
Contributing
CONTRIBUTING.md is the front door: how the project works, which conventions are enforced by something that fails rather than by someone remembering, and the gotchas that cost somebody a day. The architecture document is CLAUDE.md - it is addressed to an AI agent, deliberately, and CONTRIBUTING explains why.
License
AGPL-3.0-only. Run it for your own music, at any scale, and nothing is asked of you - using it carries no obligation. If you modify it and let other people use your version over a network, you have to offer them the source of your version, and anything you distribute stays AGPL.