bkper 4.25.0 → 4.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +1 -1
  2. package/lib/agent/extensions/handoff.d.ts.map +1 -1
  3. package/lib/agent/extensions/handoff.js +2 -0
  4. package/lib/agent/extensions/handoff.js.map +1 -1
  5. package/lib/agent/startup-maintenance.d.ts +1 -0
  6. package/lib/agent/startup-maintenance.d.ts.map +1 -1
  7. package/lib/agent/startup-maintenance.js +7 -1
  8. package/lib/agent/startup-maintenance.js.map +1 -1
  9. package/lib/agent/system-prompt.js +1 -1
  10. package/lib/commands/apps/git/clone.js +1 -1
  11. package/lib/commands/apps/git/clone.js.map +1 -1
  12. package/lib/commands/apps/init.d.ts +3 -1
  13. package/lib/commands/apps/init.d.ts.map +1 -1
  14. package/lib/commands/apps/init.js +105 -58
  15. package/lib/commands/apps/init.js.map +1 -1
  16. package/lib/commands/apps/register.js +2 -2
  17. package/lib/commands/apps/register.js.map +1 -1
  18. package/lib/dev/miniflare.js +1 -1
  19. package/lib/dev/miniflare.js.map +1 -1
  20. package/lib/dev/preflight.js +1 -1
  21. package/lib/dev/preflight.js.map +1 -1
  22. package/lib/dev/shared.js +1 -1
  23. package/lib/dev/shared.js.map +1 -1
  24. package/lib/docs/apps/app-listing.md +86 -0
  25. package/lib/docs/apps/architecture.md +188 -0
  26. package/lib/docs/apps/configuration.md +171 -0
  27. package/lib/docs/apps/context-menu.md +69 -0
  28. package/lib/docs/apps/deploying.md +181 -0
  29. package/lib/docs/apps/development.md +122 -0
  30. package/lib/docs/apps/event-handlers.md +248 -0
  31. package/lib/docs/apps/first-app.md +76 -0
  32. package/lib/docs/apps/overview.md +100 -0
  33. package/lib/docs/apps/self-hosted.md +63 -0
  34. package/lib/docs/apps/shared-app-source.md +85 -0
  35. package/lib/docs/cli/app-management.md +16 -4
  36. package/lib/docs/index.md +11 -1
  37. package/lib/docs/sdk/bkper-js.md +5 -0
  38. package/lib/upgrade/index.d.ts +1 -1
  39. package/lib/upgrade/index.d.ts.map +1 -1
  40. package/lib/upgrade/index.js +1 -1
  41. package/lib/upgrade/index.js.map +1 -1
  42. package/lib/upgrade/installation.d.ts +4 -0
  43. package/lib/upgrade/installation.d.ts.map +1 -1
  44. package/lib/upgrade/installation.js +23 -0
  45. package/lib/upgrade/installation.js.map +1 -1
  46. package/package.json +3 -3
  47. package/lib/docs/apps/app-building.md +0 -1429
@@ -65,7 +65,7 @@ export function preflightDependencies(projectRoot, options = {}) {
65
65
  if (!isDeclaredDependency(projectRoot, 'miniflare')) {
66
66
  return {
67
67
  ok: false,
68
- message: 'Missing Miniflare. Install it in the app root devDependencies (e.g. bun add -d miniflare or npm install -D miniflare).',
68
+ message: "Missing Miniflare. Add it to the app root devDependencies using the project's package manager.",
69
69
  };
70
70
  }
71
71
  if (!isDependencyResolvable(projectRoot, 'miniflare')) {
@@ -1 +1 @@
1
- {"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/dev/preflight.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/dev/preflight.ts"],"names":[],"mappings":"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"}
package/lib/dev/shared.js CHANGED
@@ -59,7 +59,7 @@ export function buildSharedIfPresent(projectRoot) {
59
59
  built: false,
60
60
  success: false,
61
61
  diagnostics: [
62
- 'TypeScript not found. Run bun install at the app root (required for shared package build).',
62
+ "TypeScript not found. Install dependencies at the app root using the project's package manager (required for shared package build).",
63
63
  ],
64
64
  };
65
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/dev/shared.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/dev/shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ # App Listing
2
+
3
+ All Bkper apps are listed on the Automations Portal at _[app.bkper.com](https://app.bkper.com/) > Automations > Apps_. Each app has its own page with logo, description, and details:
4
+
5
+ ![App listing on the Automations Portal](https://bkper.com/docs/_astro/bkper-app-listing.BgcbAsjE.png)
6
+
7
+ App listings are populated from the fields you declare in [`bkper.yaml`](https://bkper.com/docs/build/apps/configuration.md). Sync metadata changes with `bkper app sync`. Deploying code is a separate step.
8
+
9
+ ## Listing fields
10
+
11
+ Make sure your `bkper.yaml` has the following fields populated for a complete listing:
12
+
13
+ ```yaml
14
+ id: your-app-id
15
+ name: Your App Name
16
+ description: A clear description of what your app does
17
+
18
+ logoUrl: https://your-app.bkper.app/images/logo.svg
19
+ logoUrlDark: https://your-app.bkper.app/images/logo-dark.svg
20
+
21
+ ownerName: Your Name or Organization
22
+ ownerWebsite: https://yourwebsite.com
23
+
24
+ website: https://your-app.bkper.app
25
+ ```
26
+
27
+ See [App Configuration](https://bkper.com/docs/build/apps/configuration.md) for the full `bkper.yaml` reference.
28
+
29
+ ## Default visibility
30
+
31
+ By default, installation is limited to the users you've declared in `bkper.yaml`:
32
+
33
+ ```yaml
34
+ # Specific Bkper usernames
35
+ users: alice bob
36
+
37
+ # Your entire domain
38
+ users: *@yourcompany.com
39
+ ```
40
+
41
+ Use Bkper usernames for individual access, not email addresses.
42
+
43
+ Your team can install and use the app, but it doesn't appear in the public Bkper app directory for other users.
44
+
45
+ ## Publishing to all users
46
+
47
+ To make your app available to all Bkper users, contact us at [support@bkper.com](mailto:support@bkper.com?subject=Publish+Bkper+App). We'll review your app and, once approved, publish it.
48
+
49
+ ### What the review involves
50
+
51
+ - **Functionality check** — The app works correctly and handles errors gracefully
52
+ - **Security review** — Event handlers are idempotent and include loop prevention
53
+ - **Listing quality** — The app has a clear name, description, logo, and user-facing documentation
54
+
55
+ ### README matters
56
+
57
+ Your app's `README.md` is displayed to end users on the app listing page. Write it for the people who will install and use your app — not for developers.
58
+
59
+ **README should explain:**
60
+
61
+ - What the app does from a user's perspective
62
+ - How to use it (step-by-step for non-technical users)
63
+ - What features are available
64
+ - API access details when the app intentionally exposes `/api/*` routes for users or integrators
65
+
66
+ **API access details should stay concise:**
67
+
68
+ - App base URL for production and preview
69
+ - OpenAPI spec URL at `/openapi.json`
70
+ - One minimal authenticated example, such as a `curl` call with `Authorization: Bearer <token>`
71
+
72
+ **README should NOT contain:**
73
+
74
+ - Tech stack or architecture details
75
+ - Build commands or development setup
76
+ - Project structure or internal file paths
77
+ - Long API references, generated schemas, SDK internals, or route-by-route developer docs
78
+
79
+ Put developer documentation in `AGENTS.md` or internal docs instead. Keep `README.md` focused on the user experience and any integration entry points users need.
80
+
81
+ ### Where published apps appear
82
+
83
+ Once published, your app appears in:
84
+
85
+ - **[bkper.com/apps](https://bkper.com/apps)** — The public app directory
86
+ - **Automations Portal** — Inside every Bkper book, users can find and install your app
@@ -0,0 +1,188 @@
1
+ # App Architecture
2
+
3
+ Bkper platform apps use one Worker bundle per app and environment. The same Worker serves the browser client, app-defined `/api/*` routes, and Bkper event ingress at `/events`.
4
+
5
+ Treat `/api/*` as the reusable surface for app behavior. The bundled web client is one consumer; scripts, external clients, and agents can call the same routes with bearer authentication.
6
+
7
+ ## Structure
8
+
9
+ ```txt
10
+ my-app/
11
+ ├── client/
12
+ │ ├── index.html
13
+ │ ├── package.json
14
+ │ ├── vite.config.ts
15
+ │ └── src/
16
+ │ ├── api/
17
+ │ ├── app/
18
+ │ ├── auth/
19
+ │ ├── components/
20
+ │ └── services/
21
+ ├── server/
22
+ │ ├── package.json
23
+ │ └── src/
24
+ │ ├── api/
25
+ │ ├── events/
26
+ │ ├── services/
27
+ │ └── index.ts
28
+ ├── scripts/
29
+ ├── bkper.yaml
30
+ ├── env.d.ts
31
+ ├── package.json
32
+ ├── package-lock.json
33
+ └── tsconfig.json
34
+ ```
35
+
36
+ The root npm workspace orchestrates development, tests, builds, and deployment. The template keeps browser dependencies in `client/` and Worker dependencies in `server/`. Add a shared package only when both sides actually need one.
37
+
38
+ ## Client
39
+
40
+ The client uses:
41
+
42
+ - [Lit](https://lit.dev/) for components and rendering.
43
+ - [Web Awesome](https://webawesome.com/) for UI components.
44
+ - [`@bkper/web-design`](https://www.npmjs.com/package/@bkper/web-design) for Bkper design tokens.
45
+ - [Vite](https://vitejs.dev/) for development and production builds, configured in `client/vite.config.ts`.
46
+
47
+ Client code has two data paths:
48
+
49
+ - **Direct Bkper calls** use `bkper-js` for browser-specific behavior.
50
+ - **App API calls** use the generated typed client in `client/src/api/` with `auth.authenticatedFetch()`.
51
+
52
+ ### Client authentication
53
+
54
+ The client authenticates users with [`@bkper/web-auth`](https://www.npmjs.com/package/@bkper/web-auth). OAuth is preconfigured on the platform, so there are no client IDs, redirect URIs, or consent screens to configure.
55
+
56
+ ```ts
57
+ import { Bkper } from 'bkper-js';
58
+ import { BkperAuth } from '@bkper/web-auth';
59
+
60
+ const isLocalDev = ['localhost', '127.0.0.1'].includes(window.location.hostname);
61
+ const auth = new BkperAuth({
62
+ baseUrl: isLocalDev ? window.location.origin : undefined,
63
+ onLoginSuccess: () => initializeApp(),
64
+ onLoginRequired: () => showLoginButton(),
65
+ });
66
+ await auth.init();
67
+
68
+ const bkper = new Bkper({
69
+ oauthTokenProvider: async () => auth.getAccessToken(),
70
+ });
71
+ ```
72
+
73
+ `@bkper/web-auth` handles login, redirects, and token refresh. The template keeps this behavior behind `client/src/auth/auth-session.ts`.
74
+
75
+ See the [@bkper/web-auth API Reference](https://bkper.com/docs/api/bkper-web-auth.md) for the full SDK documentation.
76
+
77
+ ## Server Worker
78
+
79
+ The server runs on [Cloudflare Workers](https://developers.cloudflare.com/workers/) and uses [Hono](https://hono.dev/) with typed OpenAPI routes. It handles:
80
+
81
+ - app API routes under `/api/*`;
82
+ - Bkper event ingress under `/events`;
83
+ - platform services such as KV and secrets through `c.env`;
84
+ - static client assets through the `ASSETS` binding.
85
+
86
+ The Worker entry point composes those concerns while routes delegate business behavior to services:
87
+
88
+ ```ts
89
+ import { OpenAPIHono } from '@hono/zod-openapi';
90
+ import { registerApiRoutes } from './api/routes.js';
91
+ import { registerEventRoutes } from './events/routes.js';
92
+ import { appContextMiddleware, type AppEnv } from './app-context.js';
93
+
94
+ const app = new OpenAPIHono();
95
+
96
+ app.use('/api/*', appContextMiddleware());
97
+ app.use('/events', appContextMiddleware());
98
+ registerApiRoutes(app);
99
+ registerEventRoutes(app);
100
+
101
+ app.get('*', c => c.env.ASSETS.fetch(c.req.raw));
102
+
103
+ export default app;
104
+ ```
105
+
106
+ ## App API contract
107
+
108
+ The default template publishes versioned routes under `/api/v1/*` and exposes their OpenAPI contract at `/openapi.json`.
109
+
110
+ | Concern | Location |
111
+ | ---------------------------- | ------------------------------------- |
112
+ | OpenAPI metadata | `server/src/api/openapi.ts` |
113
+ | Request and response schemas | `server/src/api/schemas.ts` |
114
+ | Thin route handlers | `server/src/api/routes.ts` |
115
+ | Business behavior | `server/src/services/` |
116
+ | Generated client types | `client/src/api/generated/types.d.ts` |
117
+ | Typed client wrapper | `client/src/api/app-api.ts` |
118
+ | Contract snapshot | `server/test/openapi.snapshot.json` |
119
+
120
+ When changing the API:
121
+
122
+ 1. Update schemas, services, routes, and focused unit tests.
123
+ 2. Run `npm run api` to regenerate client types.
124
+ 3. Review the OpenAPI snapshot when the public contract changes.
125
+ 4. Run `npm run check` before release.
126
+
127
+ Keep existing `/api/v1/*` contracts backward compatible. Additive fields and routes can remain in `v1`; breaking changes belong in a new namespace such as `/api/v2/*`.
128
+
129
+ ### URLs
130
+
131
+ ```txt
132
+ Production API: https://{appId}.bkper.app/api/*
133
+ Preview API: https://{appId}-preview.bkper.app/api/*
134
+ Local API: http://localhost:8787/api/*
135
+
136
+ Production spec: https://{appId}.bkper.app/openapi.json
137
+ Preview spec: https://{appId}-preview.bkper.app/openapi.json
138
+ Local spec: http://localhost:8787/openapi.json
139
+ ```
140
+
141
+ Example script call:
142
+
143
+ ```bash
144
+ TOKEN="$(bkper auth token)"
145
+
146
+ curl \
147
+ -H "Authorization: Bearer ${TOKEN}" \
148
+ "https://my-app.bkper.app/api/v1/books"
149
+ ```
150
+
151
+ Replace `my-app` with the app id from `bkper.yaml`.
152
+
153
+ ### Server API authentication
154
+
155
+ Deployed `/api/*` routes require a Bkper OAuth bearer token. The template client uses `authenticatedFetch()` so token attachment and refresh stay inside `@bkper/web-auth`:
156
+
157
+ ```ts
158
+ const response = await auth.authenticatedFetch('/api/v1/books');
159
+ ```
160
+
161
+ Dispatch validates the incoming bearer token and strips the `Authorization` header before the Worker runs. Server code should not read or forward the token.
162
+
163
+ When a route calls Bkper, create the SDK without a token provider:
164
+
165
+ ```ts
166
+ import { Bkper } from 'bkper-js';
167
+
168
+ const bkper = new Bkper();
169
+ const books = await bkper.getBooks();
170
+ ```
171
+
172
+ Platform outbound authentication injects the validated user's OAuth token on Bkper API requests.
173
+
174
+ ## Event handlers
175
+
176
+ Platform event deliveries reach `/events` on the same Worker. Event adapters live in `server/src/events/`, while reusable business behavior belongs in `server/src/services/`.
177
+
178
+ Event code uses server-side `new Bkper()` and must not read `bkper-oauth-token`, `bkper-agent-id`, or `Authorization` headers. Dispatch and platform outbound authentication handle the event token and app agent identity.
179
+
180
+ See [Event Handlers](https://bkper.com/docs/build/apps/event-handlers.md) for routing, responses, loop prevention, and event types. Self-hosted handlers process event authentication directly because the platform outbound layer is not involved.
181
+
182
+ ## App shapes
183
+
184
+ The platform supports different shapes:
185
+
186
+ - **Full app** — Client UI, `/api/*` backend behavior, and `/events` automation in one Worker. This is the default template.
187
+ - **Event-only app** — Keep `server/` and omit `deployment.client`.
188
+ - **UI-only app** — Keep a minimal Worker for static assets when behavior is truly browser-only. Add `/api/*` when scripts, integrations, or agents should reuse that behavior.
@@ -0,0 +1,171 @@
1
+ # App Configuration
2
+
3
+ The `bkper.yaml` file is the single configuration file for your Bkper app. It defines the app's identity, access control, menu integration, event handling, and deployment settings.
4
+
5
+ It lives in the root of your project. Use `bkper app sync` to push metadata changes to Bkper, and use `bkper app deploy` to upload built code to the platform.
6
+
7
+ ## Minimal example
8
+
9
+ ```yaml
10
+ id: my-app
11
+ name: My App
12
+ description: A Bkper app that does something useful
13
+ developers: myuser
14
+ ```
15
+
16
+ ## Starter example
17
+
18
+ From the [app template](https://github.com/bkper/bkper-app-template):
19
+
20
+ ```yaml
21
+ id: my-app
22
+ name: My App
23
+ description: A Bkper app that does something useful
24
+
25
+ logoUrl: https://my-app.bkper.app/images/logo-light.svg
26
+ logoUrlDark: https://my-app.bkper.app/images/logo-dark.svg
27
+
28
+ website: https://my-app.bkper.app
29
+ ownerName: Bkper
30
+ ownerLogoUrl: https://avatars.githubusercontent.com/u/11943086?v=4
31
+ ownerWebsite: https://bkper.com
32
+
33
+ developers: someuser *@yoursite.com
34
+ users: someuser *@yoursite.com
35
+
36
+ menuUrl: https://my-app.bkper.app?bookId=${book.id}
37
+ menuUrlDev: https://my-app-preview.bkper.app?bookId=${book.id}
38
+ menuOpenMode: SIDEBAR
39
+
40
+ webhookUrl: https://my-app.bkper.app/events
41
+ webhookUrlDev: https://my-app-preview.bkper.app/events
42
+ apiVersion: v5
43
+ events:
44
+ - TRANSACTION_CHECKED
45
+
46
+ deployment:
47
+ server: server/src/index.ts
48
+ client: client
49
+ services:
50
+ - KV
51
+ secrets: []
52
+ compatibility_date: '2026-01-28'
53
+ ```
54
+
55
+ ### App identity
56
+
57
+ | Field | Description |
58
+ | ------------- | --------------------------------------------------------------------------------------------------------- |
59
+ | `id` | Permanent app identifier. Lowercase letters, numbers, and hyphens only. Cannot be changed after creation. |
60
+ | `name` | Display name shown in the Bkper UI. |
61
+ | `description` | Brief description of what the app does. |
62
+
63
+ ### Branding
64
+
65
+ | Field | Description |
66
+ | ------------- | ------------------------------------------ |
67
+ | `logoUrl` | App logo for light mode (SVG recommended). |
68
+ | `logoUrlDark` | App logo for dark mode. |
69
+ | `website` | App website or documentation URL. |
70
+
71
+ ### Ownership
72
+
73
+ | Field | Description |
74
+ | -------------- | ------------------------------------------------------------ |
75
+ | `ownerName` | Developer or company name. |
76
+ | `ownerLogoUrl` | Owner's logo/avatar URL. |
77
+ | `ownerWebsite` | Owner's website. |
78
+ | `repoUrl` | Source code repository URL. |
79
+ | `repoPrivate` | Whether the repository is private. |
80
+ | `deprecated` | Hides from app listings; existing installs continue working. |
81
+
82
+ ### Access control
83
+
84
+ | Field | Description |
85
+ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
86
+ | `developers` | Who can update the app and deploy new versions. Accepts comma- or space-separated Bkper usernames and domain wildcards such as `*@yoursite.com`. |
87
+ | `users` | Who can install and use the app. Uses the same format as `developers`; leave empty for public apps. |
88
+
89
+ ### Menu integration
90
+
91
+ | Field | Description |
92
+ | -------------- | --------------------------------------------------------------------------- |
93
+ | `menuUrl` | Production menu URL. Supports [variable substitution](#menu-url-variables). |
94
+ | `menuUrlDev` | Development menu URL, typically a preview or local app URL. |
95
+ | `menuText` | Custom menu text (defaults to app name). |
96
+ | `menuOpenMode` | How the app menu opens: `SIDEBAR` (default), `EXPANDED`, or `NEW_TAB`. |
97
+
98
+ See [Context Menu](https://bkper.com/docs/build/apps/context-menu.md) for details on building menu integrations.
99
+
100
+ ### Menu URL variables
101
+
102
+ The following variables can be used in `menuUrl` and `menuUrlDev`:
103
+
104
+ | Variable | Description |
105
+ | --------------------------- | ---------------------------------------- |
106
+ | `${book.id}` | Current book ID |
107
+ | `${book.properties.xxx}` | Book property value |
108
+ | `${account.id}` | Selected account ID |
109
+ | `${account.name}` | Selected account name |
110
+ | `${account.properties.xxx}` | Account property value |
111
+ | `${group.id}` | Selected group ID |
112
+ | `${group.name}` | Selected group name |
113
+ | `${group.properties.xxx}` | Group property value |
114
+ | `${transactions.ids}` | Comma-separated selected transaction IDs |
115
+ | `${transactions.query}` | Current search query |
116
+
117
+ ### Event handling
118
+
119
+ | Field | Description |
120
+ | --------------- | ----------------------------------------------------------------------------------- |
121
+ | `webhookUrl` | Production webhook URL for receiving events. |
122
+ | `webhookUrlDev` | Development webhook URL (auto-updated by `bkper app dev`). |
123
+ | `apiVersion` | API version for event payloads (currently `v5`). |
124
+ | `events` | List of [event types](https://bkper.com/docs/build/apps/event-handlers.md#event-types) to subscribe to. |
125
+
126
+ See [Event Handlers](https://bkper.com/docs/build/apps/event-handlers.md) for details on handling events.
127
+
128
+ ### File patterns
129
+
130
+ | Field | Description |
131
+ | -------------- | ---------------------------------------------------------------------------------------------------------------------- |
132
+ | `filePatterns` | List of glob patterns (e.g., `*.ofx`, `*.csv`). When a matching file is uploaded, a `FILE_CREATED` event is triggered. |
133
+
134
+ ### Properties schema
135
+
136
+ The `propertiesSchema` field defines autocomplete suggestions for custom properties in the Bkper UI, helping users discover the correct property keys and values for your app.
137
+
138
+ Suggested keys must follow the same custom property rules as user-entered keys, including the 30-character maximum after normalization.
139
+
140
+ ```yaml
141
+ propertiesSchema:
142
+ book:
143
+ keys:
144
+ - my_app_enabled
145
+ values:
146
+ - 'true'
147
+ - 'false'
148
+ group:
149
+ keys:
150
+ - my_app_category
151
+ account:
152
+ keys:
153
+ - my_app_sync_id
154
+ transaction:
155
+ keys:
156
+ - my_app_reference
157
+ ```
158
+
159
+ ### Deployment
160
+
161
+ For apps deployed to the [Bkper Platform](https://bkper.com/docs/build/apps/overview.md):
162
+
163
+ | Field | Description |
164
+ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
165
+ | `deployment.server` | TypeScript entry point for the single server Worker. It serves `/api/*`, `/events`, and static assets. |
166
+ | `deployment.client` | Optional Vite/static client root. Built assets are deployed with the same Worker. |
167
+ | `deployment.services` | Platform services to provision. Currently: `KV` (key-value storage). |
168
+ | `deployment.secrets` | Secret names used by the app. Managed via `bkper app secrets`. |
169
+ | `deployment.compatibility_date` | [Cloudflare Workers compatibility date](https://developers.cloudflare.com/workers/configuration/compatibility-dates/). |
170
+
171
+ See [Building & Deploying](https://bkper.com/docs/build/apps/deploying.md) for the full deployment workflow.
@@ -0,0 +1,69 @@
1
+ # Context Menu
2
+
3
+ Apps can add context menu items on the Transactions page **More** menu in your Books. This lets you open dynamically built URLs with reference to the current Book's context — the active query, selected account, date range, and more.
4
+
5
+ ## How it works
6
+
7
+ Once you install an App with a menu configuration, a new menu item appears in your Book:
8
+
9
+ ![Custom menu item in the More menu](https://bkper.com/docs/_astro/bkper-report-menu.eu_pyhWe.png)
10
+
11
+ When clicked, a popup opens carrying the particular context of that book at that moment:
12
+
13
+ ![App menu popup with book context](https://bkper.com/docs/_astro/bkper-app-menu-popup.BQ95Y-ki.png)
14
+
15
+ ## Configuration
16
+
17
+ Configure the menu URL in your [`bkper.yaml`](https://bkper.com/docs/build/apps/configuration.md):
18
+
19
+ ```yaml
20
+ menuUrl: https://my-app.bkper.app?bookId=${book.id}&query=${transactions.query}
21
+ ```
22
+
23
+ When the user clicks the menu item, the URL expressions `${xxxx}` are replaced with contextual information from the Book:
24
+
25
+ ```
26
+ https://my-app.bkper.app?bookId=abc123&query=account:Sales
27
+ ```
28
+
29
+ Where `abc123` is the current Book id and `account:Sales` is the current query being executed.
30
+
31
+ ### Development URL
32
+
33
+ Use `menuUrlDev` to keep developer testing separate from production. The app template points it to the preview deployment:
34
+
35
+ ```yaml
36
+ menuUrl: https://my-app.bkper.app?bookId=${book.id}&query=${transactions.query}
37
+ menuUrlDev: https://my-app-preview.bkper.app?bookId=${book.id}&query=${transactions.query}
38
+ ```
39
+
40
+ During local development, you can instead point it to the local Worker URL at `http://localhost:8787`. The development URL is used when an app developer clicks the menu item.
41
+
42
+ ### Menu open mode
43
+
44
+ Control how the menu opens with `menuOpenMode`:
45
+
46
+ ```yaml
47
+ menuOpenMode: SIDEBAR
48
+ ```
49
+
50
+ | Mode | Behavior |
51
+ | ---------- | --------------------------------------------------------------------- |
52
+ | `SIDEBAR` | Opens in a narrow side panel (default). |
53
+ | `EXPANDED` | Opens in a wider panel with more room for complex UIs. |
54
+ | `NEW_TAB` | Opens the menu URL in a new browser tab instead of an embedded panel. |
55
+
56
+ ### Available expressions
57
+
58
+ The menu URL supports these dynamic expressions:
59
+
60
+ | Expression | Description |
61
+ | ----------------------- | ------------------------- |
62
+ | `${book.id}` | The current Book ID |
63
+ | `${transactions.query}` | The current query string |
64
+ | `${account.id}` | The selected account ID |
65
+ | `${account.name}` | The selected account name |
66
+ | `${group.id}` | The selected group ID |
67
+ | `${group.name}` | The selected group name |
68
+
69
+ For the full list of accepted expressions, see the [Menu URL variables](https://bkper.com/docs/build/apps/configuration.md#menu-url-variables) reference.