Show HN: Build your own apps on Mu

asim1 pts0 comments

Build your own apps on Mu | Mu

Mu

Home<br>Agent<br>Chat<br>News<br>Blog<br>Mail<br>Social<br>Video<br>Search<br>Apps<br>Wallet

Login

Build your own apps on Mu

apps · dev<br>Updated 48 minutes ago · Mu · {this.textContent='Copied!';setTimeout(()=>{this.textContent='Share'},2000)})}" title="Share this post">Share<br>Mu is a set of everyday services you own — news, mail, markets, weather, and the rest — with an agent that drives them. But not everything belongs in the core. You shouldn&rsquo;t have to fork Mu to get a bookmarks tool, a reading list, or whatever small thing fits your day. That&rsquo;s what apps are for.

A Mu app is just an HTML page with a little JavaScript. What makes it more than a static page is the SDK — a global mu object that gives the page real backend building blocks, without you standing up a backend.

Who&rsquo;s using it

mu.user() tells you who is signed in, so an app can greet them and keep their data separate from everyone else&rsquo;s:

const u = await mu.user(); // { account: 'alice', admin: false }

Storage that knows who you are

mu.db is a small database, not just a key-value bucket. Each record has an owner (you) and a public flag, so one app can hold your private data and a shared public set at the same time:

await mu.db.create('notes', { title: 'Idea', body: '...' }); // private to me<br>await mu.db.create('notes', { title: 'Public tip' }, { public: true }); // shared

await mu.db.list('notes'); // my notes<br>await mu.db.list('notes', { scope: 'public' }); // everyone's public notes<br>await mu.db.list('tasks', { where: { done: false, priority: { gte: 2 } } });

The owner is set on the server from your session — never from the page — so an app can&rsquo;t read or write someone else&rsquo;s private data even if it tries.

Reach the web, server-side

mu.web.fetch makes an HTTP request from the server, so your app gets past CORS and can keep API keys off the client. It&rsquo;s SSRF-guarded — public hosts only:

const res = await mu.web.fetch('https://api.example.com/data');<br>const data = JSON.parse(res.body);

The agent, in your app

mu.ai(prompt) for a one-shot answer, mu.agent(prompt) for the full tool-using agent — plus typed wrappers for every service (mu.weather, mu.markets, mu.news, and more):

const tldr = await mu.ai('Summarise this', { context: text });<br>const answer = await mu.agent('What changed in the markets today and why?');

A real example: bookmarks

Here&rsquo;s the whole backend of an app that saves links — privately or shared — and fetches each page&rsquo;s title for you. Three primitives, working together:

async function add(url, isPublic) {<br>const res = await mu.web.fetch(url); // read the page<br>const title = (/]*>([\s\S]*?)/i.exec(res.body) || [])[1] || url;<br>await mu.db.create('bookmarks', { url, title }, { public: isPublic }); // save it<br>const mine = await mu.db.list('bookmarks', { scope: 'mine' });<br>const shared = await mu.db.list('bookmarks', { scope: 'public' });

No server to deploy, no database to provision, no CORS proxy to run. The Bookmarks and Notes apps ship built-in — open them, or fork them from the editor to make your own.

How to build one

Describe it at /apps/new and Mu builds a working app.

Ask the agent — &ldquo;build me a reading list&rdquo; — it makes the app and gives you a URL.

Write it yourself — paste HTML at /apps/new, or hand-edit any app at /apps/{slug}/edit.

Pin the ones you use to the top of your home screen. Keep them private, or make them public for anyone on your instance.

It runs on your Mu — your instance, your data, your account. Same idea as the rest of Mu: instead of renting a service from a platform that keeps your data, you own the whole stack, and apps are how you extend it.

Full SDK reference: /docs/apps .

Comments<br>Login to add a comment<br>No comments yet. Be the first to comment!<br>← Back to posts

API · Docs · MCP · Status

await apps public rsquo const agent

Related Articles