Skip to content
Peqaboo
Open Peqaboo
Explore Peqaboo

Open Peqaboo
Choose your language

EnglishUnited States

Quickstart

Ship your first BooApp in 5 minutes

One HTML file. One deploy. One submission. We'll walk through it end-to-end.

1

Write a single HTML file

Save the file below as index.html. It calls peqaboo.requireLogin() and peqaboo.pet.list(), then renders the result.

Notice there is no <script src=...> for an SDK and no import. The peqaboo global is auto-injected by the runtime — your code talks to it directly.

index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
  <title>My First BooApp</title>
  <style>
    :root { color-scheme: light dark; }
    body {
      margin: 0;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
      background: #fafafa;
      color: #111;
      padding: 24px 20px;
    }
    @media (prefers-color-scheme: dark) {
      body { background: #0a0a0a; color: #f5f5f5; }
    }
    h1 { font-size: 22px; margin: 0 0 4px; }
    .sub { color: #888; font-size: 14px; margin-bottom: 24px; }
    .pet {
      display: flex; gap: 12px; align-items: center;
      padding: 14px; border-radius: 14px;
      background: #fff;
      box-shadow: 0 1px 3px rgba(0,0,0,.06);
      margin-bottom: 10px;
    }
    @media (prefers-color-scheme: dark) {
      .pet { background: #161616; box-shadow: none; }
    }
    .pet img { width: 48px; height: 48px; border-radius: 50%; object-fit: cover; background: #eee; }
    .pet .name { font-weight: 600; }
    .pet .meta { color: #888; font-size: 12px; }
    .empty { text-align: center; color: #888; padding: 40px 16px; }
    button {
      width: 100%; padding: 14px 18px; border: 0; border-radius: 12px;
      background: #7c3aed; color: white; font-weight: 600; font-size: 15px;
      margin-top: 16px; cursor: pointer;
    }
  </style>
</head>
<body>
  <h1 id="greeting">Loading…</h1>
  <p class="sub" id="status">Connecting to Peqaboo…</p>
  <div id="list"></div>
  <button id="refresh" hidden>Refresh</button>

<script>
  // peqaboo is auto-injected as a global. No import, no install.
  async function main() {
    await peqaboo.ready();

    const greeting = document.getElementById('greeting');
    const status   = document.getElementById('status');
    const list     = document.getElementById('list');
    const refresh  = document.getElementById('refresh');

    if (!peqaboo.isInApp) {
      greeting.textContent = 'Open me in Peqaboo';
      status.textContent = 'This BooApp uses Peqaboo APIs. Open inside the Peqaboo app.';
      return;
    }

    const loggedIn = await peqaboo.requireLogin();
    if (!loggedIn) {
      status.textContent = 'Finish signing in, then reopen this BooApp.';
      return;
    }
    const user = await peqaboo.getUserInfo();
    greeting.textContent = 'Hi ' + (user.userName || 'friend');
    status.textContent = 'Here are your pets:';

    async function render() {
      const pets = await peqaboo.pet.list();
      if (!pets.length) {
        list.innerHTML = '<div class="empty">No pets yet. Add one in Peqaboo first.</div>';
        return;
      }
      list.innerHTML = pets.map(p => `
        <div class="pet">
          <img src="${p.petProfileImgUrl || ''}" alt="" />
          <div>
            <div class="name">${p.petName}</div>
            <div class="meta">${p.petType || ''} · ${p.petBreedTranslated || p.petBreed || ''}</div>
          </div>
        </div>
      `).join('');
    }

    await render();
    refresh.hidden = false;
    refresh.onclick = render;

    // React to lifecycle events too:
    peqaboo.on('appResume', render);
  }

  main().catch(err => {
    document.getElementById('status').textContent = 'Error: ' + err.message;
  });
</script>
</body>
</html>
Want TypeScript autocomplete?

Install the types-only package and add a triple-slash reference. The runtime is still a global — this only adds editor autocomplete.

terminal
npm i -D @decennium/booapp-sdk
app.ts
/// <reference types="@decennium/booapp-sdk" />

// Optional — only if you use TypeScript and want autocomplete.
// The actual peqaboo runtime is still injected as a global at runtime.
// No `import` line is ever needed.

await peqaboo.ready();
const loggedIn = await peqaboo.requireLogin();
if (!loggedIn) throw new Error('Finish signing in, then reopen this BooApp.');
const user = await peqaboo.getUserInfo();
const pets = await peqaboo.pet.list();
2

Deploy to any HTTPS host

BooApps must be served over HTTPS. We don't care which host — pick whatever you already use.

Grab the resulting URL — something like https://my-pet-app.vercel.app. You'll paste it in the next step.

3

Submit your URL

Open the BooApp dashboard and create a new app. Fill in the basics:

  • App ID (kebab-case, unique — e.g. my-pet-card)
  • Display name and short description
  • Icon URL (any HTTPS image, hosted by you)
  • Entry URL (the deployment from step 2)
  • Permissions you call (e.g. auth.requireLogin, pet.list)
  • Category (event, tool, game, commerce, utility…)
Open BooApp dashboard
4

Wait for review

A reviewer will load your URL inside a sandbox, walk through the flows, and check that every permission you call is declared. Approvals usually land within a few business days.

Once approved, your BooApp is discoverable in the Peqaboo app launcher and at peqaboo.app/apps/<your-app-id>. Any change to entryUrl creates a fresh submission for re-review.