KaidayDocs
Start here
  • Overview
  • Why solo wins now
  • Getting started
  • Concepts
  • What Kai can do
Setup guides
  • Add a domain
  • Set up email
  • Connect data & tools
Platform
  • Workspaces
  • Automations
  • Control & governance
MiniApps
  • What MiniApps are
  • Templates
  • MiniApp SDK
  • Use cases by persona
Use cases
  • Common workflows

MiniApps

MiniApp SDK

The small, stable contract every MiniApp imports. You don't write this yourself, Kai does. But knowing what's available helps you describe what your app can do.

You will not see this code by default
This page is for the curious. Kai writes the code. The whole point of MiniApps is that you describe behavior in plain language. If you're not asking "what can my app actually do?", skip to Use cases.

The manifest

Every MiniApp has a kaiday.app.yaml at the root. It declares the entry point, the secrets the app needs, and which scopes it's allowed to use.

kaiday.app.yaml
name: client-portal entry: app:application sdk: 1 secrets: - STRIPE_SECRET_KEY scopes: - db.read - db.write - storage.read - storage.write - email.send - kai.invoke

The runtime refuses to mount apps that request scopes you haven't approved, and refuses to mount apps targeting an SDK version newer than what it ships.

The SDK surface

kaiday.db

Per-app namespaced Mongo. Read and write your own collections; you cannot read another app's data unless an admin grants a cross-app view.

python
from kaiday import db # Each app gets its own namespace db.bookings.insert_one({"client_id": user.id, "package": "premium"}) recent = db.bookings.find({"client_id": user.id}).limit(10)

kaiday.current_user

The authenticated caller. Either a team member (your Kaiday user) or a client (a person you've invited into a portal).

python
from kaiday import current_user if current_user.is_client: show_client_view(current_user) else: show_admin_view()

kaiday.secrets

Per-company secrets, scoped to the app's manifest declarations. The raw secret never appears in your code.

python
from kaiday import secrets stripe_client = stripe.Client(api_key=secrets.STRIPE_SECRET_KEY)

kaiday.storage

Object storage backed by MinIO. Use it for user uploads, generated PDFs, gallery images. Files can be private (signed URL access) or public (CDN URL).

python
from kaiday import storage key = storage.put("uploads/intake-{user_id}.pdf", file_bytes) url = storage.signed_url(key, ttl=3600)

kaiday.email

Send mail from your verified domain. Subject to the same SPF/DKIM that Email uses.

python
from kaiday import email email.send( to="client@example.com", subject="Your wedding shot list", template="shot-list-confirmation", vars={"name": user.name}, )

kaiday.kai

Call Kai from inside your app. Kai acts on the calling user's behalf and produces drafts the app can render or send.

python
from kaiday import kai quote = kai.draft( intent="generate a quote", package="premium", client_id=user.id, ) return render("quote.html", quote=quote)

How an app runs

Inbound request
https://app.menoru.com/dyn/...
↓
Reverse proxy
routes by workspace slug
↓
Workspace runtime container
one per workspace, long-lived
↓
MiniApp mount
/dyn/<workspace-slug>/<app-slug>
SDK contracts exposed inside the runtime
kaiday.dbkaiday.current_userkaiday.secretskaiday.storagekaiday.emailkaiday.kai
Every workspace gets one long-lived runtime. Apps mount under /dyn/<workspace>/<app>; the SDK is what's available inside.

The runtime architecture, in plain language:

  • Every workspace gets one long-lived runtime container.
  • The supervisor pulls every MiniApp repo this workspace owns.
  • Each app is mounted under /dyn/<workspace-slug>/<app-slug>.
  • A reverse proxy routes inbound requests to the right workspace's runtime.
  • Inside the runtime, the SDK provides the contracts above.

What the SDK does not expose

The contract is deliberately small. There is no kaiday.calendar, no kaiday.crm. Those domains are accessible via db views, not dedicated module surfaces. Keeping the SDK minimal lets us evolve the platform without breaking your apps.

TemplatesUse cases by persona