Skip to main content
Marooned Software

Software you run yourself, and can read all the way down.

We make self-hosted products and the open-source TypeScript they are built on. Every layer we wrote is published, MIT licensed, and on GitHub.

Runs on your box
  • deadair
  • rhapsode
  • curator
Built on
  • ContractKit
  • ServerKit
  • InjectKit
Underneath
  • TypeScript
  • Node.js
  • PostgreSQL
  • Docker

Products

Three things you can install today

Each runs on your own hardware from a Docker image. rhapsode started as deadair’s speech layer, and became its own server when nothing else did the job.

deadair

An AI radio station you run yourself.

It picks the records, writes what the presenter says between them, speaks it in that presenter’s voice, and streams the result. One running order, and everybody hears the same thing at the same moment.

  • Plays your music: Spotify, YouTube Music, Apple Music, or your own Navidrome, Jellyfin or Plex
  • Any language model, or none: the station’s own phrasings are a floor that cannot fail
  • A console, an Android app and a Stream Deck plugin

rhapsode

One contract, many TTS models.

A speech server you run yourself. Install the engines you want, and every client talks to one HTTP API that says honestly what each engine can do. Ollama, but for speech.

  • Each engine in its own process, so a crash takes down a worker and not the server
  • Voice cloning, cues and dials, reported per engine and per loaded build
  • An OpenAI-compatible speech route and an MCP server over the same core

curator

Your own art on a Samsung Frame TV.

Finds the Frames on your network, pairs with them, and manages what they show over the TV’s local art-mode protocol. No phone app and no cloud account in between.

  • Upload a JPEG or PNG, pick its matte, and show it at once
  • Browse each TV’s library by category, change mattes, and remove uploads
  • One Docker image beside a Postgres, with an Unraid template

Toolkits

What the products are built on

Pulled out of the products as soon as a second one needed them, and published so anyone can build on them too.

  • ContractKit

    Define an API once, in a file you can read aloud.

    Generate the parts you would otherwise keep in sync by hand: Zod schemas, a Koa or Fastify router, SDK clients in TypeScript, Python, Kotlin, Swift and C#, an OpenAPI document, Markdown docs and a Bruno collection.

    pnpm add -D @contractkit/cliUsed by deadair, rhapsode

  • ServerKit

    The parts of a Node.js server you should not write twice.

    A modular set of TypeScript packages: configuration from files and secret stores, authentication with passkeys, one-time codes and sessions, permissions, caching, jobs and an event bus, on Koa or Fastify with Kysely underneath.

    pnpm add @maroonedsoftware/appconfigUsed by deadair, rhapsode, curator

  • InjectKit

    A lightweight, type-safe dependency injection container.

    Singleton, transient and scoped lifetimes, disposal, and a container that validates its registrations before anything resolves. Runs in Node and the browser.

    pnpm add injectkitUsed by deadair, rhapsode, curator

pets.ck
contract Pet: {
id: readonly uuid
name: string
status: enum(available, pending, sold) = available
}

operation /pets/{id}: {
params: { id: uuid }
get: { # fetch a pet
sdk: getPet
response: {
200: { application/json: Pet }
404:
}
}
}

A ContractKit file. The router, the validation, the clients in five languages and the OpenAPI document are all generated from it, and regenerated when it changes.

How it is made

A few rules every project keeps

The contract comes first
An API is written down before it is written, and the server, the clients and the docs are generated from that one file. rhapsode’s protocol outranks its own code.
Say what it can do, honestly
rhapsode reports what each engine performs for the build that is loaded. A presenter on deadair states a fact only when it has the sentence of source that supports it.
Have a floor
deadair cannot be made silent by a model that is slow or wrong: its own phrasings are always there underneath. In rhapsode a failure is reported, never delivered as a short, silent file.
Yours to run
Self-hosted, on your own hardware, with your music and your data. A Docker image is the install, and every deadair plugin says what it will talk to before it does.

Workshop

Smaller things, made to scratch an itch