Build AI apps without a backend
Write a web app, call any model through our SDK, and upload it as a zip. Users sign in with RunApps and pay for their own AI usage — no servers or API keys for you to manage.
Free to publish · Users pay for their own usage
Before you upload
An app gets its slug the moment you create it — no zip needed. Develop on your own machine against that slug; the published app runs on the very same identity.
- 1
Create the app as a draft
Dashboard → Creator → Publish. Name and describe it, leave the bundle empty, save. A draft is private to you and never reviewed.
- 2
Point your dev server at it
Pass the slug as the SDK's project option. Sign-in from http://localhost works, calls go through the real gateway on your own balance, and files land in the app's real namespace.
- 3
Upload when it's ready
Build, zip, upload to the same app. Slug, files and prompts are already in place, so the code that ran locally is the code that ships.
// The slug from your draft app — the same one the published
// app will have, so nothing changes at upload time.
const client = new RunApps.Client({
authProvider: "runapps",
project: "my-tool",
});
const resp = await client.chat.create({
model: "Claude Sonnet 4.6",
messages: [{ role: "user", content: "Hello!" }],
// While developing, send a prompt inline; ship it as
// .runapps/prompts/outline.md and use { id: "outline" } later.
prompt: import.meta.env.DEV
? { template: "You write outlines in five acts." }
: { id: "outline" },
});Publish in three steps
- 1
Call AI with the SDK
Add one script tag or npm i @runjobsai/sdk. Users sign in with RunApps, so there is no API key in your code.
- 2
Upload a zip
Upload your built static files. The app goes live on its own runapps.dev link.
- 3
List it
Share the link, or submit the app for review to be listed in the library.
<script src="https://cdn.jsdelivr.net/npm/@runjobsai/sdk/dist/sdk.umd.js"></script>
<script>
const client = new RunApps.Client({ authProvider: "runapps" });
const resp = await client.chat.create({
model: "Claude Sonnet 4.6",
messages: [{ role: "user", content: "Hello!" }],
});
console.log(resp.choices[0].message.content);
</script>Keep your prompts private
Anything in your frontend code can be read in the browser. Ship prompts as files inside your zip and list them in bundle.json: RunApps never serves that file or anything it names, and your app calls a prompt by id.
- 1
Write the prompt file
Write one Markdown file per prompt anywhere in your project, e.g. prompts/outline.md, and map an id to it in bundle.json at the zip root. Mark values your app fills in at call time as {{genre}}.
- 2
Call it by name
Pass the prompt's name and values as the prompt option of chat.create, as in the code. The server adds the prompt as the system message; only the name goes over the network.
- 3
Zip it with your build
Copy bundle.json and the prompt files into your build output and zip it. The publish page lists the prompts it found. (A file under .runapps/prompts/<id>.md works with no config entry.)
While developing locally
Your own dev server has no uploaded bundle yet, so send the text along as prompt.template. The server accepts that only from the app's creator, and import.meta.env.DEV keeps it out of the production build.
The model is told to keep the prompt confidential, and any reply that repeats it word for word is withheld. A determined user may still get a model to paraphrase it, so never put keys or passwords in a prompt.
{
"prompts": {
"outline": "prompts/outline.md",
"rewrite": "prompts/rewrite.md"
}
}You are the outline writer for this studio.
Every story has five acts, with a twist in act four.
Genre: {{genre}}async function privatePrompt(id, vars) {
const prompt = { id, vars };
// Your dev server only: send the text along. Vite drops
// this branch (and the file) from production builds.
if (import.meta.env.DEV) {
prompt.template = (await import(
`../prompts/${id}.md?raw`)).default;
}
return prompt;
}
const resp = await client.chat.create({
model: "Claude Sonnet 4.6",
prompt: await privatePrompt("outline", { genre: "mystery" }),
messages: [{ role: "user", content: idea }],
});npm run build
cp -r bundle.json prompts dist/
cd dist && zip -r ../app.zip .Ready to build?
Publish your first app, or create an API key and start calling models.
Publish an appFree to publish · Users pay for their own usage