Tinylib
DiscoverDocsSign in
Sign in
Tinylib
AboutDiscoverDocsMake an appPricingTermsPrivacyDeveloper TermsContact

Start

  • Quickstart
  • How Tinylib works
    • Where your app runs
    • What you write
    • What Tinylib runs
    • What this rules out

Guides

  • Data
  • Rooms and rules
  • Games
  • Friends
  • Places and links
  • Reminders and notifications
  • Publishing
  • Errors and offline
  • Platforms

Client API

  • tinylib
  • tinylib.data
  • tinylib.rooms
  • tinylib.invitations
  • tinylib.friends
  • tinylib.places
  • tinylib.reminders
  • Types
  • tinylib-sdk/kits

Rules API

  • Kinds
  • ctx

Reference

  • tinylib.json
  • Command line
  • Limits

Plain text

  • llms.txt
  • llms-full.txt

How Tinylib works

A Tinylib app is a web page. People open it at its link, like tinylib.app/tic-tac-toe, in a browser or in Tinylib's Android app, and your page reaches everything Tinylib runs for it through a tinylib object. You write the page, plus rules if people share live state.

The user's device Tinylib's servers Tinylib's app sandbox Your client Tinylib's sheets tinylib Local data Local reminders System notifications Room Your rules State Data Reminders actions / updates writes notify sync sync triggers push Your code Tinylib
The user's device System notifications Tinylib's app sandbox Your client Tinylib's sheets tinylib Local data Local reminders Tinylib's servers Data Reminders Room State Your rules actions / updates triggers sync sync writes push notify Your code Tinylib

Where your app runs

Anyone can use your app, with or without a Tinylib account. tinylib.user gives your app their name and id either way, and tinylib.user.guest says whether they have an account. An account is what lets Tinylib reach a user while your app is closed and connect them with other people: notifications, friends, and invitations need one, and it brings the user's apps and data to every device they sign in on. A user without one is a guest, whose apps, data, and rooms stay on the device they use until they sign in.

What Tinylib can do around your app, like notifications and opening offline, differs by device, and Platforms lists it.

What you write

The client

Write the client as an ordinary web page, index.html with its scripts and styles, plain or with any framework. publish bundles each script with the npm packages it imports. Before your scripts run, Tinylib puts the tinylib object on the page with the user and their data already loaded, so reading them is synchronous and works offline:

app.js
const todos = tinylib.data.values('todo/') document.querySelector('h1').textContent = `${tinylib.user.name}, ${todos.length} to do`

The rules

Anything people share live, like one game or one shared list, is a room on Tinylib's servers, with its state, its members, and the rules that run it. The rules are server code you write in rules.js.

Each export of rules.js with a create function is a kind of room, like game below. create returns a new room's state. When a member acts, an action handler changes the state or refuses with a sentence your client can show. After each change, view decides what each member sees. Here canInvite lets in a second player and no one after:

rules.js
export const game = { create(options, ctx) { return { board: Array(9).fill(''), players: { x: ctx.user.id, o: null }, turn: 'x', winner: null } }, canInvite(state) { return state.players.o === null }, join(state, via, ctx) { state.players.o = ctx.user.id }, actions: { move(state, square, ctx) { if (state.players[state.turn] !== ctx.user.id) ctx.refuse("It's not your turn.") if (!Number.isInteger(square) || state.board[square] !== '') ctx.refuse('Pick an empty square.') state.board[square] = state.turn // ...on a win or a draw, set state.winner and call ctx.end(); otherwise pass the turn }, }, view(state, member) { const you = member.id === state.players.x ? 'x' : member.id === state.players.o ? 'o' : null return { board: state.board, turn: state.turn, winner: state.winner, you } }, }

The client creates a room, draws each view, and invites the other player:

app.js
try { const { id } = await tinylib.rooms.create('game') tinylib.rooms.follow(id, ({ view, error }) => { if (error) toast(error.message) else if (view) drawBoard(view) }) await tinylib.rooms.invite(id) } catch (error) { toast(error.message) }

follow also passes the open room, and a tap on a square calls room.act('move', square), which runs move in the rules.

What Tinylib runs

  • Tinylib syncs the user's data across their devices. Only your rules can write the keys listed in rulesKeys in tinylib.json, so a device can't fake them.
  • Tinylib keeps each room's state, runs your rules on each action, join, leave, and timer in turn, and sends each member their view. A room needs a connection unless its kind is marked offline.
  • A user's friends are the same in every app. An app that uses friends can list the ones who have it, read what they save for friends, and offer to send them the app.
  • Your rules can notify a room's members, and your client can schedule reminders for the user. Tinylib delivers both, and the user can turn either off for your app.
  • Each screen can have an address after your app's link, like tinylib.app/tic-tac-toe/game/abc, which a shared link or a notification opens.
  • npx tinylib-sdk publish uploads your files and rules as a new version and makes it current for everyone at once, after Tinylib's review if your app is listed. Clients open in a room reload onto it, any other client uses it at its next open, and open rooms keep their state under the new rules.

Tinylib's sheets

For anything that involves other people or the user's settings, Tinylib draws a sheet over your app. Your client opens one with a call but can't see inside it, fake it, or press it for the user:

Your client callsTinylib showsYour client learns
tinylib.rooms.invite(id)
Tinylib shows
The invite sheet, with the user's friends and the room's link
Your client learns
That the sheet closed
tinylib.friends.sendApp()
Tinylib shows
The send sheet, with the user's friends
Your client learns
That the sheet closed
tinylib.places.share(address)
Tinylib shows
The device's share sheet with a link to that place, or Tinylib's own where the device has none
Your client learns
That the sheet closed
tinylib.user.manageSettings()
Tinylib shows
The settings sheet, with your app's switches
Your client learns
The switches' values
tinylib.block(id) or tinylib.report(id)
Tinylib shows
The block sheet or the report sheet
Your client learns
Whether the user went through with it

What this rules out

  • Your client loads files only from its own origin and talks only to Tinylib. Scripts, fonts, and images from a CDN don't load, and calls to another site's API fail, so everything it uses ships in the folder you publish.
  • The rules have no fetch, and their handlers are synchronous. They run only when something happens in a room. To act later, a room sets a timer.
  • Tinylib runs no code of yours outside rooms: no endpoints, webhooks, or scheduled jobs.
  • Tinylib stores JSON values: the user's data, up to 1 MB, and each room's state and room data. It has nowhere to keep photos or other files people add.
  • You get no view of any user's data or any room's state. The developer page shows your rules' errors.
  • Your app never sees a user's email address or contacts. Their id differs in every app, so you can't match them across apps or to another service.
  • The Developer Terms don't let your app ask for payment.

The Developer Terms also require your app to suit people 16 and over. An app that shows people to each other must let them block and report each other through Tinylib.

PreviousQuickstartNextData

On this page

  • Where your app runs
  • What you write
  • The client
  • The rules
  • What Tinylib runs
  • Tinylib's sheets
  • What this rules out