Your First App
Step-by-step walkthrough of building and deploying a full Bkper platform app from scratch — scaffold from template, run locally with HMR and automatic webhook tunnels, react to transaction events, and go live with a single deploy command.
This tutorial walks you through building and deploying a Bkper app from scratch. You’ll use the Bkper Platform — managed hosting, pre-configured OAuth, and automatic dev tunnels — so you can focus entirely on business logic.
By the end, you’ll have a working app live at https://my-app.bkper.app that displays account balances and reacts to transaction events.
Prerequisites
Make sure you’ve completed Development Setup — the CLI installed and authenticated.
Walkthrough
-
Create from the template
Terminal window bkper app init my-appcd my-appThis scaffolds a new project from the official template. The structure you get:
my-app/├── bkper.yaml ← Your entire infrastructure config├── env.d.ts ← Auto-generated type definitions├── .dev.vars.example ← Template for local secrets└── packages/├── shared/ ← Shared types and utilities├── web/│ ├── client/ ← Frontend UI (Lit + Vite)│ └── server/ ← Backend API (Hono on Workers)└── events/ ← Event handlers (webhooks) -
Look at
bkper.yamlOpen
bkper.yaml— this single file is your entire infrastructure configuration:id: my-appname: My Appdescription: A Bkper app that does something useful# Context menu entry in BkpermenuUrl: https://my-app.bkper.app?bookId=${book.id}menuUrlDev: http://localhost:8787?bookId=${book.id}# Event subscriptionswebhookUrl: https://my-app.bkper.app/eventsevents:- TRANSACTION_CHECKED# Deployment configdeployment:web:main: packages/web/server/src/index.tsclient: packages/web/clientevents:main: packages/events/src/index.tsservices:- KVsecrets:- BKPER_API_KEYThis declares hosting, OAuth integration, event subscriptions, KV storage, and secrets — no cloud console required.
See App Configuration for the full
bkper.yamlreference. -
Start developing
Terminal window bkper app devA single command starts everything:
- Vite dev server — hot module replacement for your UI
- Miniflare — simulates the Cloudflare Workers runtime locally
- Cloudflare tunnel — exposes your events handler at a public URL so Bkper can send webhooks to your laptop
You’ll see output like:
[web] Local: http://localhost:8787[events] Tunnel: https://a1b2c3.trycloudflare.com/events -
See the running app
Open http://localhost:8787.
You’re greeted with a book picker — no login screen, no redirect, no auth setup. The platform handled OAuth automatically. Select a book to see account balances.
The client code that makes this work is about 30 lines in
packages/web/client/src/components/my-app.ts:private auth = new BkperAuth({onLoginSuccess: () => this.loadData(),onLoginRequired: () => this.auth.login(),});private async loadData() {this.bkper = new Bkper({oauthTokenProvider: async () => this.auth.getAccessToken(),});this.user = await this.bkper.getUser();this.books = await this.bkper.getBooks();}That’s all the auth code you write. The platform provides the token endpoint, consent screen, and refresh handling.
-
Trigger an event
Go to your Bkper book and check (reconcile) any transaction.
Back in your terminal, you’ll see the event handler fire. The template handler in
packages/events/src/handlers/transaction-checked.tscreates a 20% draft transaction:export async function handleTransactionChecked(book: Book,event: bkper.Event): Promise<EventResult> {const operation = event.data?.object as bkper.TransactionOperation;const tx = operation.transaction;// Prevent loops — skip transactions created by this appif (event.agent?.id === 'my-app') return { result: false };const newAmount = Number(tx.amount) * 0.2;const draft = new Transaction(book).setDate(tx.date).setAmount(newAmount).setDescription(`20% of ${tx.description}`).setCreditAccount(tx.creditAccount).setDebitAccount(tx.debitAccount);await draft.create();return { result: `Created draft: 20% of ${tx.description}` };}The event arrived via the Cloudflare tunnel the CLI started — no manual ngrok setup, no URL configuration.
-
Make a change
Edit the handler to use 10% instead of 20%:
const newAmount = Number(tx.amount) * 0.1; // changed from 0.2Save the file. The Workers runtime reloads automatically. Check another transaction — you’ll see the new 10% amount.
-
Deploy to production
Terminal window bkper app deployThe CLI builds all three packages, syncs your app metadata to Bkper, and deploys to the platform:
✓ Built web client✓ Built web server✓ Built events handler✓ Deployed to https://my-app.bkper.appYour app is now live. Bkper will route production webhook events to
https://my-app.bkper.app/events.
What just happened
You built and deployed a full Bkper app. Here’s what you wrote versus what the platform handled:
| You wrote | Platform handled |
|---|---|
| ~30 lines: book picker + account list UI | OAuth client registration and consent screen |
| ~40 lines: event handler (business logic) | Token endpoint and refresh |
bkper.yaml: infrastructure as config | Global edge hosting (my-app.bkper.app) |
| Webhook routing and delivery | |
| Dev tunnel (webhooks on localhost) | |
| KV storage provisioning | |
| SSL certificates | |
env.d.ts type generation |
The platform handles the infrastructure. You handle the logic.
Next steps
- App Architecture — Understand the three-package pattern in depth
- Development Experience — Full reference for
bkper app dev - Building & Deploying — Deployment workflow, preview environments, secrets
- Event Handlers — All event types and how to handle them
- App Configuration — Full
bkper.yamlreference