This guide takes you from nothing to an app running inside RentalTide in about 15 minutes. You'll fork the example, see it live in the sandbox, then register and publish it.
1. Fork the example
The fastest start is the Hello RentalTide example — a complete embedded app that reads context, calls the API, and drives host UI.
Standalone (outside the monorepo), install the SDK from npm instead:
The whole app is in src/App.tsx. The important part is the connection:
2. Preview it in the sandbox
Open the partner portal → App Sandbox. Enter your dev URL (http://localhost:5173), press Connect, and your app loads inside a simulated RentalTide with mock data and a live App Bridge log.
In the sandbox you can:
- switch the embed location (booking page, dashboard, POS cart, …),
- toggle light/dark to confirm your app follows the host theme,
- flip granted scopes to see how your app behaves with and without access,
- edit the mock context (account, location, current resource),
- watch every protocol message between host and app.
See Using the sandbox for details.
3. Read context and call the API
Every app.api.* call is checked against the scopes the merchant granted. A call your app wasn't granted comes back as a 403-style response — handle it gracefully.
4. Register your app
In the partner portal → App Developer → New app, set:
- Name, description, logo, category
- Embed locations — where your app renders
- Scopes — the data access you need (reference)
- Embed URL — where you deploy your app (this is what RentalTide loads in the iframe)
- Redirect URIs and (optionally) a webhook URL + secret
You'll get a client ID and a client secret (shown once — store it securely).
5. Submit and publish
Submit the app for review from the developer dashboard. Once approved it appears in the App Store for every RentalTide business to install.
Checklist
- [ ] App connects with
createApp()and renders context - [ ] Handles the "not connected" state (running outside a host)
- [ ] Follows the host theme (light + dark)
- [ ] Degrades gracefully when a scope isn't granted
- [ ] Auto-resizes (call
app.ready()after first render) - [ ] Tested at each declared embed location in the sandbox

