| name | tinycloud-app-dev |
| description | Build apps with TinyCloud as the backend. Use when the user wants to build a TinyCloud app, store data in TinyCloud, add TinyCloud auth, use OpenKey for authentication, or work with @tinycloud/* or @openkey/* packages. |
TinyCloud App Development
TinyCloud is a decentralized data platform where users own their data in "spaces." Apps read/write to a user's space via services. Auth is handled by OpenKey (OAuth 2.1 with passkeys). No custom backend needed — TinyCloud IS the backend.
Terminology: ALWAYS use "space" — never "namespace" or "orbit."
Platform Availability
| Service | Browser (@tinycloud/web-sdk) | Node.js (@tinycloud/node-sdk) |
|---|
| KVService | Yes | Yes |
| SQLService | No | Yes |
| DataVaultService | Yes | No |
| Delegations | Yes | Yes |
Install
npm install @tinycloud/web-sdk @openkey/sdk
npm install @tinycloud/node-sdk
Do NOT install ethers — it is not needed for TinyCloud auth.
Auth Setup
Browser (OpenKey)
import { OpenKey, OpenKeyEIP1193Provider } from '@openkey/sdk';
import { TinyCloudWeb } from '@tinycloud/web-sdk';
const openkey = new OpenKey({
host: 'https://openkey.so',
appName: 'My App',
});
const authResult = await openkey.connect();
const provider = new OpenKeyEIP1193Provider(openkey, authResult);
const tc = new TinyCloudWeb({
providers: { web3: { driver: provider } },
tinycloudHosts: ['https://node.tinycloud.xyz'],
spacePrefix: 'myapp',
autoCreateSpace: true,
});
await tc.signIn();
Key points:
OpenKeyEIP1193Provider is exported from @openkey/sdk — do not implement it inline.
- Constructor is
new OpenKeyEIP1193Provider(openkey, authResult) — two args, not separate fields.
signStrategy must be { type: 'wallet-popup' } (object), never a plain string.
Node.js (Private Key)
import { TinyCloudNode } from '@tinycloud/node-sdk';
const tc = new TinyCloudNode({
privateKey: process.env.PRIVATE_KEY,
host: 'https://node.tinycloud.xyz',
prefix: 'myapp',
autoCreateSpace: true,
});
await tc.signIn();
KV Storage (Primary Pattern)
KV is the most common service. Available on both platforms.
await tc.kv.put('settings', { theme: 'dark', lang: 'en' });
const result = await tc.kv.get<{ theme: string }>('settings');
if (result.ok) {
console.log(result.data.data);
}
const list = await tc.kv.list({ prefix: 'users/' });
await tc.kv.delete('old-key');
const appKV = tc.kv.withPrefix('/myapp');
await appKV.put('config', { version: 2 });
Choosing the Right Architecture
| Scenario | Pattern | Start with |
|---|
| Simple app (notes, settings, secrets) | Direct (browser → TinyCloud) | This skill's patterns below |
| Full-stack app with backend logic | Backend-mediated (three-actor) | Clone tinyboilerplate |
| Third-party API integration | Backend-mediated | Clone tinyboilerplate |
For full-stack apps, see references/backend-patterns.md for the three-actor architecture (user → backend → TinyCloud via delegations).
Choosing the Right Service
| Use case | Service | Details |
|---|
| JSON, files, key-value data | KV | references/kv-service.md |
| Relational data, queries, joins | SQL (Node.js only) | references/sql-service.md |
| Sensitive/encrypted data | Vault (browser only) | references/vault-service.md |
| Multi-user access | Delegations | references/delegations-and-sharing.md |
Critical Patterns
Result Type
All service methods return a Result<T>. ALWAYS check .ok before accessing .data.
type Result<T, E = ServiceError> =
| { ok: true; data: T }
| { ok: false; error: E };
const result = await tc.kv.get('key');
if (result.ok) {
console.log(result.data.data);
} else {
console.error(result.error.code, result.error.message);
}
Never access .data without checking .ok first. This applies to KV, SQL, Vault, and Delegations.
Auto-Space Creation
new TinyCloudWeb({ autoCreateSpace: true, spacePrefix: 'myapp' });
new TinyCloudNode({ autoCreateSpace: true, prefix: 'myapp' });
The space is created on first signIn if it doesn't exist. spacePrefix/prefix scopes the space name to your app.
Prefix Isolation
const myApp = tc.kv.withPrefix('/app.mycompany.com');
await myApp.put('config', { version: 2 });
Use prefixes to isolate app data within a shared space. Recommended for all production apps.
Delegations (Multi-User Access)
const delegation = await tc.createDelegation({
delegateDID: recipientPrimaryDID,
actions: ['tinycloud.kv/*'],
expiryMs: 1000 * 60 * 60 * 24,
});
expiryMs is milliseconds from now (number), NOT a Date object.
- Always use the recipient's primary DID (
did:pkh:eip155:...), not their session key DID.
- Child delegation expiry must be <= parent expiry.
SQL Service (Node.js Only)
await tc.sql.execute(`CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
done BOOLEAN DEFAULT 0
)`);
await tc.sql.execute(`INSERT INTO tasks (title) VALUES (?)`, ['Buy milk']);
const result = await tc.sql.query(
`SELECT id, title, done FROM tasks WHERE done = ?`, [0]
);
if (result.ok) {
for (const row of result.data.rows) {
console.log(row[1]);
}
}
SQL QueryResponse rows are T[][] — arrays of arrays. Use positional indexing (row[0], row[1]), not property access (row.title).
Data Vault (Browser Only)
await tc.vault.unlock(signer);
await tc.vault.put('secrets/api-key', { key: 'sk_live_...' });
const secret = await tc.vault.get('secrets/api-key');
if (secret.ok) console.log(secret.data.value);
What NOT to Do
- No
tc.sql in browser — SQLService is @tinycloud/node-sdk only.
- No
tc.vault in Node.js — DataVaultService is @tinycloud/web-sdk only.
- No
.data without .ok check — all service methods return Result types.
- No session key DID for delegations — use
tc.did after signIn (primary DID).
- No "namespace" or "orbit" — the correct term is "space."
- No string
signStrategy — use { type: 'wallet-popup' } (object).
- No
ethers for auth — TinyCloud auth uses EIP-1193 provider directly.
- No
row.title from SQL — rows are arrays, use row[0], row[1], etc.
- No
expiry: Date for delegations — use expiryMs: number (milliseconds from now).
- No inline
OpenKeyEIP1193Provider — import it from @openkey/sdk.
Reference Docs
Deep dives on each service are in the references/ directory alongside this skill:
references/sdk-quickstart.md — Package map, minimal browser + Node.js examples
references/kv-service.md — Full IKVService interface, option types, prefix patterns
references/sql-service.md — Full ISQLService interface, row mapping, auto-DDL (Node.js only)
references/vault-service.md — Full IDataVaultService interface, unlock flow, sharing (browser only)
references/auth-patterns.md — OpenKey SDK, TinyCloudWeb/Node configs, DID formats, sign strategies
references/delegations-and-sharing.md — UCAN delegations, SpaceService, ability strings table
references/backend-patterns.md — Three-actor architecture, tinyboilerplate, delegation store/cache
references/common-pitfalls.md — Platform gaps, Result pattern, terminology, known gotchas
Full-Stack Boilerplate
For apps that need a backend, clone tinyboilerplate:
git clone https://github.com/TinyCloudLabs/tinyboilerplate.git myapp
cd myapp && bun install && bun run build && bun run generate-key
bun run dev
Provides: OpenKey auth, delegation management, KV + SQL + DuckDB storage, React frontend, Express backend.
Public Resources