Get Heard

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.x releases 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

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:

  1. Google Cloud Console โ†’ create a project โ†’ APIs & Services โ†’ Library โ†’ enable Gmail API.
  2. Credentials โ†’ Create Credentials โ†’ OAuth client ID โ†’ Web application.
  3. Add the redirect URI shown in Settings โ†’ Connections - copy it from there, it carries the port you are actually on.
  4. 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.