Tinylib
DiscoverDocsSign in
Sign in
Tinylib
AboutDiscoverDocsMake an appPricingTermsPrivacyDeveloper TermsContact

Start

  • Quickstart
  • How Tinylib works

Guides

  • Data
  • Rooms and rules
  • Games
  • Friends
    • How friends work
    • Share a value with friends
    • Show a leaderboard of friends
    • Read one friend's values
    • Send your app to friends
    • Show other users' names
    • Let users block and report
  • 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

Friends

tinylib.friends lists the user's friends who use your app and reads what they save for friends. It also opens Tinylib's send sheet, where the user picks friends to send your app to.

How friends work

Friendships are mutual, and people make them in Tinylib, outside your app. Your app can't add or remove a friend.

Add "friends" to uses in tinylib.json:

tinylib.json
{ "uses": ["friends"] }

The first time a user opens your app, Tinylib's onboarding tells them your app can share data with their friends. There's no separate permission to ask for.

For a guest, a user without a Tinylib account, every friends call rejects with refused. A call made as the user taps, such as friends.sendApp() behind a Send to a friend button, first opens Tinylib's offer of an account, so such a button can stay for a guest; a list or leaderboard of friends can't be filled for one, so check tinylib.user.guest before reading it. In npx tinylib-sdk dev, the simulated users are all friends with each other.

Share a value with friends

To let the user's friends read a value, save it with audience: 'friends':

JavaScript
tinylib.data.set('best', 41, { audience: 'friends' })

A later save without audience keeps it shared, and audience: 'me' makes it private again. Keep a score friends should trust in a key only the rules write, which the rules share the same way.

Show a leaderboard of friends

tinylib.friends.list() resolves with the user's friends who use your app, sorted by name, each as { id, name }. tinylib.friends.data.get(key) resolves with a Map from each friend's id to { value, changedAt }, for each friend who shared a value under key. Neither includes the user, so add their own row from tinylib.data:

app.js
try { const [friends, wins] = await Promise.all([tinylib.friends.list(), tinylib.friends.data.get('wins')]) const board = [ { name: tinylib.user.name, wins: tinylib.data.get('wins') ?? 0 }, ...friends.map((friend) => ({ name: friend.name, wins: wins.get(friend.id)?.value ?? 0 })), ] board.sort((a, b) => b.wins - a.wins) drawBoard(board) } catch (error) { if (error.code !== 'offline') throw error document.querySelector('#board-offline').hidden = false }

Every friends call rejects with offline without a connection. Nothing tells your client when a friend's value changes, so read it again each time you show it. changedAt is on the same clock as tinylib.now(), so you can leave out old scores.

Read one friend's values

tinylib.friends.data.of(id) has the read methods of tinylib.data for what one friend shared. Each returns a promise, and each value comes as { value, changedAt }:

JavaScript
const days = await tinylib.friends.data.of(friend.id).entries('day/') // [['day/2026-10-20', { value: 280, changedAt: 1792540800000 }], …]

For anyone who isn't the user's friend in your app, it's empty.

Send your app to friends

tinylib.friends.sendApp() opens Tinylib's send sheet. It resolves when the sheet closes, and your app never learns who the user picked. An empty leaderboard is a good place to offer it:

app.js
document.querySelector('#invite-friends').addEventListener('click', async () => { try { await tinylib.friends.sendApp() } catch (error) { toast(error.message) } })

Show other users' names

Tinylib has no call that turns a user id into a name. Take each name from the list its id came from:

An id fromIs named by
tinylib.friends.list(), tinylib.friends.data
Is named by
tinylib.friends.list()
ctx.members in the rules
Is named by
ctx.members
A room's data
Is named by
The room's members in tinylib.rooms.list()

These lists have current names, and leave out blocked users and users whose data in your app was deleted. When an id is missing from its list, drop its row rather than show it without a name.

Let users block and report

If your app shows people to each other, the Developer Terms require it to let them block and report each other through Tinylib. tinylib.block(id) and tinylib.report(id) open Tinylib's own sheets. Each resolves true if the user went through with it and false if they backed out, and rejects with offline without a connection:

app.js
try { if (await tinylib.block(friend.id)) await showLeaderboard() // the friends list now leaves them out } catch (error) { toast(error.message) }

Blocking someone ends the friendship, and the user who blocked leaves every room they share with that person.

PreviousGamesNextPlaces and links

On this page

  • How friends work
  • Share a value with friends
  • Show a leaderboard of friends
  • Read one friend's values
  • Send your app to friends
  • Show other users' names
  • Let users block and report