Hush (device)
Open-hardware speaker with NFC reader and offline-first audio cache. Firmware fetches playlists from your dashboard and plays locally. Optional cloud sync for multi-device households.
firmware · NFC · audio OpenHush is a TypeScript monorepo: a Next.js dashboard, an SDK for authoring Whispers, and firmware that talks to both. Web standards. Boring tech. Cloneable in a minute.
Every layer speaks the same language and shares the same types. No hidden services, no proprietary protocols.
Open-hardware speaker with NFC reader and offline-first audio cache. Firmware fetches playlists from your dashboard and plays locally. Optional cloud sync for multi-device households.
firmware · NFC · audio NFC tags bound to playlists in your library. Pre-printed sets ship with art and audio; blank cards let you bind anything to anything. Tap → play. Remove → stop.
NFC · playlists · binding Next.js app for authoring Whispers, uploading audio, managing devices, and seeing what's been played. Self-host on your LAN, a Pi, or a VPS — your call.
Next.js · Drizzle · self-hosted No accounts to create, no API keys to wait for. Everything runs locally first; sync to the cloud only if you want to.
Pull the monorepo. The website, dashboard, and firmware all live together.
git clone https://github.com/OpenHush/website.git
cd openhush Everything is pnpm-based. One command, the whole stack.
pnpm install The dashboard is where you author Whispers, manage devices, and bind cards.
pnpm --filter dashboard dev
# Open http://localhost:3000 Point your Hush at your dashboard URL. Local dev works over your home network — no public tunnel required.
// hush.config.ts
export default {
dashboard: "http://192.168.1.42:3000",
cache: "./.audio-cache",
ledColor: "warm",
} satisfies HushConfig; Upload audio, drop tracks into a playlist, scan a blank NFC card, and you're done. Tap on Hush — it plays.
// scripts/seed-whisper.ts
import { createWhisper } from "@openhush/sdk";
await createWhisper({
title: "Bedtime stories",
tracks: [
{ src: "./audio/01-the-moon.mp3", title: "The moon" },
{ src: "./audio/02-the-fox.mp3", title: "The fox" },
],
cardUid: "04:A2:B7:33:5E",
}); Boring, well-supported, well-documented technology. On purpose.
The SDK is a thin TypeScript wrapper over the dashboard API. Build importers, scripts, or full integrations.
import { OpenHush } from "@openhush/sdk";
const hush = new OpenHush({
baseUrl: process.env.DASHBOARD_URL!,
token: process.env.OPENHUSH_TOKEN!,
});
const whisper = await hush.whispers.create({
title: "Forest sounds",
description: "Ambient loop for quiet time.",
tracks: ["./audio/birds.mp3", "./audio/leaves.mp3"],
});
await hush.cards.bind({
cardUid: "04:A2:B7:33:5E",
whisperId: whisper.id,
}); import { onPlayback } from "@openhush/sdk/events";
onPlayback(async (event) => {
// Log, analyze, or react however you like.
console.log(`[${event.deviceId}] ${event.whisper.title}`);
if (event.track.title === "The moon") {
await dim_lights_in_kids_room();
}
}); Bugs, ideas, hardware mods, audio packs, translations — all welcome. Open an issue, send a PR, or just say hi.
Code of conduct, contribution guide, and roadmap live in the repo. Licensed under MIT.