Start here
Seven steps. Each one runs right here against a real backend, so you can see what it does before you build anything.
1
perusta has two halves. The client runs in the browser and holds no secrets; the server holds your storage credentials. You need somewhere for the server half to live.
The fastest route is the Deploy button — it creates the storage for you and you paste nothing. Two things to know before you click: the Upstash step makes you choose a plan and none of them are free, and on a Pro account the finished deploy answers 401 until you attach a domain or turn off Deployment Protection. Both are covered in what the button does.
Or run it locally first if you would rather not deploy anything yet.
Locally:
git clone https://github.com/miikakuisma/perusta
cd perusta && pnpm install && pnpm build
pnpm --filter @perusta/example-drive-vanilla startThat runs entirely in memory with nothing provisioned, so it works on a fresh clone.
2
If your page is served from the same deployment, there is nothing to configure — that is the common case and the default.
<script src="https://unpkg.com/perusta"></script>
<script type="module">
// `perusta` is now a global. That is the whole setup.
</script>With a bundler, or to point somewhere else:
import { createClient } from 'perusta';
const cloud = createClient(); // same origin
const cloud = createClient({ origin: 'https://api.you.dev' }); // elsewhere3
Everything is scoped to a user, so this comes first. ensureUser signs somebody in anonymously if they have no session — no signup screen, no friction, and they get a real id straight away.
Run it. You will get a fresh identity.
Press Run.4
Two places to put things. kv is for small values you look up by name — a setting, a counter, a bit of state. fs is for files, with real folders.
Change the text and run it again. It persists, because it is going to actual storage.
Press Run.5
Nothing was configured between those two steps, and no key went anywhere near the browser. Reload this page and run it again — it is still there.
Press Run.6
Same shape. The gateway key stays on your server, and the reply streams back token by token.
Press Run.7
Some things do not belong in a browser: an API key, a charge, anything you cannot trust the client to do honestly. Define a function on the server and call it from the page — it receives the caller already signed in, with ctx.fs and ctx.kv already scoped to them.
// server
functions: {
async publish(ctx, { slug }) {
const draft = await ctx.fs.readText(`drafts/${slug}.md`);
await ctx.fs.write(`published/${slug}.md`, draft);
return { url: `/p/${slug}` };
},
}The two below are real functions on this site’s server. Run them.
Press Run.That is the whole API
You have seen every namespace. The rest is detail you can look up when you need it — the recipes are complete little apps you can paste into an HTML file, and the reference pages cover each method properly.