@mediamonks/canopy-cli 0.7.12 → 0.7.13

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 (119) hide show
  1. package/dist/{db-8Etjmzxh.mjs → db-DKnJQPm5.mjs} +2 -2
  2. package/dist/{deploy-B1WrPq5W.mjs → deploy-CnxJ4TE6.mjs} +2 -2
  3. package/dist/dev-BqLvttKc.mjs +2 -0
  4. package/dist/{dev-BnUYGQQm.mjs → dev-CyJT6EfQ.mjs} +4 -4
  5. package/dist/docs/ci.md +50 -0
  6. package/dist/docs/cli-create.md +46 -0
  7. package/dist/docs/cli-db.md +86 -0
  8. package/dist/docs/cli-delete.md +44 -0
  9. package/dist/docs/cli-deploy.md +58 -0
  10. package/dist/docs/cli-dev.md +82 -0
  11. package/dist/docs/cli-docs.md +47 -0
  12. package/dist/docs/cli-download.md +42 -0
  13. package/dist/docs/cli-egress.md +37 -0
  14. package/dist/docs/cli-feedback.md +75 -0
  15. package/dist/docs/cli-index.md +61 -0
  16. package/dist/docs/cli-init.md +46 -0
  17. package/dist/docs/cli-login.md +43 -0
  18. package/dist/docs/cli-logout.md +32 -0
  19. package/dist/docs/cli-logs.md +57 -0
  20. package/dist/docs/cli-open.md +41 -0
  21. package/dist/docs/cli-projects.md +43 -0
  22. package/dist/docs/cli-promote.md +44 -0
  23. package/dist/docs/cli-rollback.md +45 -0
  24. package/dist/docs/cli-skill.md +39 -0
  25. package/dist/docs/cli-staging.md +54 -0
  26. package/dist/docs/cli-token.md +47 -0
  27. package/dist/docs/cli-upgrade.md +43 -0
  28. package/dist/docs/cli-usage.md +43 -0
  29. package/dist/docs/cli-whoami.md +46 -0
  30. package/dist/docs/cli.md +86 -0
  31. package/dist/docs/data.md +85 -0
  32. package/dist/docs/deploy.md +81 -0
  33. package/dist/docs/dev.md +72 -0
  34. package/dist/docs/developers-agents-and-ai.md +95 -0
  35. package/dist/docs/developers-architecture.md +106 -0
  36. package/dist/docs/getting-started.md +108 -0
  37. package/dist/docs/index.json +336 -0
  38. package/dist/docs/infrastructure.md +406 -0
  39. package/dist/docs/migrations.md +183 -0
  40. package/dist/docs/overview-faq.md +105 -0
  41. package/dist/docs/overview-how-it-works.md +82 -0
  42. package/dist/docs/overview-use-cases.md +76 -0
  43. package/dist/docs/overview-what-is-canopy.md +75 -0
  44. package/dist/docs/platform-ai-usage.md +65 -0
  45. package/dist/docs/platform-client-access.md +54 -0
  46. package/dist/docs/platform-deploys-and-rollbacks.md +93 -0
  47. package/dist/docs/platform-egress.md +75 -0
  48. package/dist/docs/platform-feedback.md +114 -0
  49. package/dist/docs/platform-google.md +213 -0
  50. package/dist/docs/platform-members-and-access.md +71 -0
  51. package/dist/docs/platform-project-data.md +76 -0
  52. package/dist/docs/platform-schedules.md +90 -0
  53. package/dist/docs/platform-sites-and-profiles.md +61 -0
  54. package/dist/docs/porting-nextjs.md +233 -0
  55. package/dist/docs/sdk-ai.md +103 -0
  56. package/dist/docs/sdk-auth.md +57 -0
  57. package/dist/docs/sdk-database.md +126 -0
  58. package/dist/docs/sdk-files.md +82 -0
  59. package/dist/docs/sdk-services.md +58 -0
  60. package/dist/docs/sdk.md +126 -0
  61. package/dist/docs/staging.md +106 -0
  62. package/dist/docs/static-serving.md +323 -0
  63. package/dist/docs/troubleshooting.md +102 -0
  64. package/dist/{docs-DxB7NhZs.mjs → docs-BBMVxVta.mjs} +2 -2
  65. package/dist/{egress-CN_axsAN.mjs → egress-BFSwa8Uu.mjs} +1 -1
  66. package/dist/{feedback-B-GXUBPs.mjs → feedback-BMX_d4KZ.mjs} +2 -2
  67. package/dist/index.mjs +25 -24
  68. package/dist/{local-BGRd_FMZ.mjs → local-BQxsp-ZQ.mjs} +2 -2
  69. package/dist/{login-D7dI8D9N.mjs → login-BDTO3nVw.mjs} +1 -1
  70. package/dist/{logs-DNiZquki.mjs → logs-C53y2eAS.mjs} +1 -1
  71. package/dist/{migrations-C-5x6SYf.mjs → migrations-C6EcKD6a.mjs} +1 -1
  72. package/dist/{open-DRPp4QJg.mjs → open-C5x3tX6I.mjs} +1 -1
  73. package/dist/{package-CDLufecy.mjs → package-vJXq4RNN.mjs} +1 -1
  74. package/dist/{projects-C6JQjVqg.mjs → projects-MMbv7MmK.mjs} +1 -1
  75. package/dist/schedule-Cq9K0rnE.mjs +106 -0
  76. package/dist/skill/canopy/SKILL.md +160 -0
  77. package/dist/{skill-BOWfqwr2.mjs → skill-Zq9aIPKf.mjs} +2 -2
  78. package/dist/{staging-Bw1D_J8M.mjs → staging-D8G4amjO.mjs} +1 -1
  79. package/dist/templates/spa/.github/workflows/canopy-deploy.yml +34 -0
  80. package/dist/templates/spa/AGENTS.md +47 -0
  81. package/dist/templates/spa/README.md +14 -0
  82. package/dist/templates/spa/_gitignore +4 -0
  83. package/dist/templates/spa/canopy.json +5 -0
  84. package/dist/templates/spa/index.html +12 -0
  85. package/dist/templates/spa/package.json +21 -0
  86. package/dist/templates/spa/src/app.tsx +25 -0
  87. package/dist/templates/spa/src/canopy.ts +5 -0
  88. package/dist/templates/spa/src/main.tsx +10 -0
  89. package/dist/templates/spa/src/style.css +29 -0
  90. package/dist/templates/spa/tsconfig.json +16 -0
  91. package/dist/templates/spa/vite.config.ts +7 -0
  92. package/dist/templates/static/AGENTS.md +45 -0
  93. package/dist/templates/static/README.md +9 -0
  94. package/dist/templates/static/_gitignore +2 -0
  95. package/dist/templates/static/canopy.json +4 -0
  96. package/dist/templates/static/index.html +21 -0
  97. package/dist/templates/static/main.js +9 -0
  98. package/dist/templates/static/style.css +29 -0
  99. package/dist/templates/worker/.dev.vars.example +9 -0
  100. package/dist/templates/worker/.github/workflows/canopy-deploy.yml +34 -0
  101. package/dist/templates/worker/AGENTS.md +63 -0
  102. package/dist/templates/worker/README.md +17 -0
  103. package/dist/templates/worker/_gitignore +5 -0
  104. package/dist/templates/worker/canopy.json +6 -0
  105. package/dist/templates/worker/index.html +12 -0
  106. package/dist/templates/worker/package.json +22 -0
  107. package/dist/templates/worker/src/app.tsx +25 -0
  108. package/dist/templates/worker/src/canopy.ts +5 -0
  109. package/dist/templates/worker/src/main.tsx +10 -0
  110. package/dist/templates/worker/src/style.css +29 -0
  111. package/dist/templates/worker/tsconfig.json +16 -0
  112. package/dist/templates/worker/vite.config.ts +7 -0
  113. package/dist/templates/worker/worker/index.ts +52 -0
  114. package/dist/{token-D7zrIF8G.mjs → token-BUxgRJVA.mjs} +1 -1
  115. package/dist/{ui-2mrJcjYC.mjs → ui-B1Px5y7q.mjs} +17 -0
  116. package/dist/{upgrade-fhfrid_O.mjs → upgrade-ES8u8_Pn.mjs} +2 -2
  117. package/dist/{usage-CX1Izj_l.mjs → usage-DjNngyvy.mjs} +1 -1
  118. package/package.json +1 -1
  119. package/dist/dev-CySBxW7I.mjs +0 -2
@@ -0,0 +1,114 @@
1
+ ---
2
+ title: Feedback & bug reports
3
+ description: A built-in feedback widget on every project, a ticket-lite inbox behind it, and a CLI that lets agents work the backlog.
4
+ ---
5
+
6
+ Every Canopy project gets an in-app feedback channel without writing a line of
7
+ code: signed-in Monks see a small floating button on the live app, pick **Bug**
8
+ or **Feedback**, type what happened, and send. The report lands in the
9
+ project's **Feedback tab** on the dashboard, with everything an investigator
10
+ needs captured automatically — page URL, the deploy version that served it,
11
+ viewport, and recent console errors.
12
+
13
+ It is deliberately **not** a ticketing product: an item has a status, an
14
+ append-only comment trail, and nothing else. No assignees, priorities, or
15
+ boards.
16
+
17
+ ## The widget
18
+
19
+ - Appears only for **signed-in Monks**. Client-password visitors never see it —
20
+ the platform doesn't even send them the script.
21
+ - On by default for every project. Turn it off per project in
22
+ **Settings → Feedback widget**; the change applies on the next page load.
23
+ - Submissions are always identified (your company sign-in), so there's no
24
+ anonymous spam and no reporter field to fill in.
25
+ - The widget also shows your own previous reports for that project with their
26
+ current status.
27
+ - A page can reshape the chooser with meta tags — this docs site does exactly
28
+ that: `<meta name="canopy-feedback-kinds" content="docs,feedback">` swaps
29
+ "Bug" for "Docs issue", and `canopy-feedback-prompt` replaces the textarea
30
+ placeholder. Kinds are limited to `bug`, `feedback`, `docs`.
31
+
32
+ ## Screenshots
33
+
34
+ A screenshot is often the whole report, so you can attach up to six to any
35
+ report:
36
+
37
+ - **In the widget:** click **Attach screenshot**, or paste one straight from
38
+ the clipboard into the message box, or drop an image on the panel. Thumbnails
39
+ show what will be sent, and each one can be removed before you hit Send.
40
+ - **On the dashboard:** the same three ways, from the report itself — so you can
41
+ add a picture to a report after filing it, or to a comment as you write it
42
+ ("here's what it looks like after the fix"). Click any thumbnail for the full
43
+ image, then use the arrow keys to page through the rest.
44
+ - **From the CLI:** `canopy feedback report "…" --attach ./shot.png`, or
45
+ `canopy feedback attach <id> ./after-fix.png` for a report that already
46
+ exists. `canopy feedback show <id> --download <dir>` saves a report's
47
+ screenshots so an agent can look at them.
48
+
49
+ PNG, JPEG, WebP and GIF, up to 5 MB each. Large screenshots are scaled down in
50
+ your browser before they're sent, so a full-screen retina capture goes up small
51
+ without you doing anything. Screenshots are visible to the same people as the
52
+ report itself, and are deleted with it.
53
+
54
+ ## The inbox
55
+
56
+ Project members triage reports on the **Feedback tab**:
57
+
58
+ - Statuses: `investigate → investigated → accepted → in_progress → resolved`,
59
+ plus `declined`.
60
+ - Everything arrives as **investigate** — nobody has looked at it yet. An agent
61
+ can pick those up, work out what is actually going on, and write the findings
62
+ on the report as **investigated**.
63
+ - **`accepted` means a person said "build this."** It is the one status an
64
+ agent should never reach for on its own.
65
+ - The order is a suggestion, not a track. Accept something straight away, skip
66
+ the investigation, or decline it at any point.
67
+ - Every status change and comment is recorded on the item's trail.
68
+ - Reporters follow their submissions on the **Reports page** (dashboard
69
+ header) and can comment on or withdraw their own items; only project
70
+ members change statuses.
71
+
72
+ ## Working the backlog with an agent
73
+
74
+ Because the CLI exposes the inbox, "look into the new reports" and "work
75
+ through the accepted feedback" are both prompts, not processes:
76
+
77
+ ```bash
78
+ canopy feedback list --status investigate # what nobody has looked at yet
79
+ canopy feedback show <id> # body + captured context + trail
80
+ canopy feedback status <id> investigated \
81
+ --comment "root cause: the upload grant expires too early"
82
+ canopy feedback list --status accepted # what a person asked for
83
+ canopy feedback status <id> resolved --comment "fixed in v42"
84
+ ```
85
+
86
+ `investigated` always carries the findings — the note is required, because a
87
+ report that claims someone looked into it and shows nothing is worse than an
88
+ untouched one. Then it waits: **accepting is the person's call**, so an agent
89
+ sets `accepted` only when the person it is working with says to build the
90
+ thing.
91
+
92
+ `show` includes the deploy version that served the page when the bug was
93
+ reported — reproduce against that, not whatever is live now. A report worth
94
+ pushing back on gets `status <id> declined` with a comment saying why.
95
+
96
+ ## Reporting problems with Canopy itself
97
+
98
+ When a `canopy` command fails while you (or your agent) are building a
99
+ project, file it against the **platform inbox** — not your own project:
100
+
101
+ ```bash
102
+ canopy feedback report "deploy failed after upload" \
103
+ --command "canopy deploy --staging" --error "upload_grant_expired …"
104
+ ```
105
+
106
+ With no `--project`, the report goes to the platform team automatically, with
107
+ your CLI version, site, and the project you were working on attached. Before
108
+ filing: rule out user error first (`canopy docs troubleshooting`,
109
+ `vp env doctor` for toolchain issues), and skim `canopy feedback mine` to
110
+ avoid filing the same issue twice.
111
+
112
+ ## CLI reference
113
+
114
+ See [canopy feedback](https://docs.canopy.website/cli/feedback) for every subcommand and flag.
@@ -0,0 +1,213 @@
1
+ ---
2
+ title: Google
3
+ description: Let your project work with Google data — Sheets, Docs, Calendar, Drive, Gmail — without handling any OAuth yourself.
4
+ ---
5
+
6
+ Your project can work with Google data in two different ways, and the
7
+ difference matters: as **the project's own account**, or as **each visitor's
8
+ own account**.
9
+
10
+ Either way there is no OAuth setup to do. No Cloud project, no consent screen,
11
+ no client ID or secret, no redirect URLs, no tokens to store or refresh. Canopy
12
+ holds all of that.
13
+
14
+ ## The project's own account
15
+
16
+ The owner connects one Google account on the project's **Services** tab and
17
+ picks what it may do. Everything the project sends to Google then happens as
18
+ that account — including scheduled jobs that run when nobody is signed in. A
19
+ shared team account is usually a better choice than a personal one.
20
+
21
+ This account is **only usable from your backend code**:
22
+
23
+ ```ts
24
+ // in your worker
25
+ const doc = await canopy.google.project().fetch("https://docs.googleapis.com/v1/documents/<id>");
26
+ ```
27
+
28
+ Pages cannot use it at all. That is deliberate: it is one person's real
29
+ account, and anything a page can call, any visitor can call from their browser
30
+ console. When your pages need something from it, put a route in your backend
31
+ that returns just that — you decide what to expose.
32
+
33
+ > **Note:** Only the project owner can connect or disconnect this account.
34
+
35
+ ## Each visitor's own account
36
+
37
+ Visitors can connect their own Google account to your project, and your pages
38
+ can then work with _their_ data — their calendar, their documents. They consent
39
+ themselves, and it only ever acts as them.
40
+
41
+ First, on the **Services** tab, tick what your app is allowed to ask visitors
42
+ for. Your app can never request more than that.
43
+
44
+ Then, from your pages:
45
+
46
+ ```ts
47
+ const google = canopy.google.user();
48
+
49
+ // On load: has this visitor connected, and what came back from a connect?
50
+ const result = google.consumeConnectResult(); // toast this, if not null
51
+ const status = await google.status();
52
+
53
+ if (!status.connected) {
54
+ // A full-page trip to Google, then straight back to this page.
55
+ google.connect(["calendar"]);
56
+ }
57
+
58
+ const events = await google.fetch(
59
+ "https://www.googleapis.com/calendar/v3/calendars/primary/events",
60
+ );
61
+ ```
62
+
63
+ `connect()` leaves the page, so put the button somewhere without unsaved work.
64
+ When the visitor comes back, `status()` is the reliable answer to "are they
65
+ connected" — `consumeConnectResult()` just tells you how the trip that _just_
66
+ happened went, so you can show a message.
67
+
68
+ Google asks the visitor for exactly the permissions you passed. Nothing your
69
+ project holds elsewhere carries over into what they see.
70
+
71
+ Your backend can use a visitor's connection too, while handling that visitor's
72
+ request — same `canopy.google.user()`, same account. It cannot in a scheduled
73
+ job, because then nobody is signed in.
74
+
75
+ > **Note:** Visitors need a Monks account to connect. People visiting with a project password cannot connect
76
+ > their own Google account.
77
+
78
+ ## What a connection can reach
79
+
80
+ Permissions are grouped by product — Sheets, Docs, Slides, Calendar, Drive,
81
+ Gmail, Directory, Tasks, Forms, Meet — and most come in a reading and a
82
+ read-and-write form. Pick the narrowest that does the job: a page that shows a
83
+ spreadsheet wants **read spreadsheets**, not read and write.
84
+
85
+ A few are narrower than they first look, and are usually the right answer —
86
+ the full list is below:
87
+
88
+ | Instead of | Consider |
89
+ | ------------------------ | ------------------------------------------------------------------------------------------ |
90
+ | Read and write events | **Availability only** — find free slots without seeing what any meeting is |
91
+ | Read and write events | **Its own calendar** — a separate calendar your project owns, never touching the account's |
92
+ | Files this project makes | **Its own config folder** — a hidden folder nothing else can see |
93
+
94
+ A call to anything that wasn't ticked is refused before it reaches Google, and
95
+ so is a write using a reading-only permission.
96
+
97
+ Drive is deliberately limited to files your project created or that someone
98
+ explicitly opened with it — connecting Drive does not expose a whole Drive.
99
+
100
+ ### Wider permissions
101
+
102
+ A few permissions read broadly across an account — a whole mailbox, meeting
103
+ recordings. Those are switched off until a Canopy admin unlocks them for your
104
+ project, and the picker shows them greyed out with the reason. Ask if you need
105
+ one. Others are listed as _under consideration_: they exist, we haven't opened
106
+ them yet.
107
+
108
+ ## Every permission
109
+
110
+ Grouped the way the picker groups them. Pick the narrowest row that does
111
+ the job — most products offer a reading-only version, and a write using a
112
+ reading-only permission is refused before it reaches Google.
113
+
114
+ **Sheets**
115
+
116
+ | Permission | What it allows |
117
+ | --------------------------- | ----------------------------------------------------------- |
118
+ | Read spreadsheets | Read spreadsheets the account can open. Cannot change them. |
119
+ | Read and write spreadsheets | Read and change spreadsheets the account can open. |
120
+
121
+ **Docs**
122
+
123
+ | Permission | What it allows |
124
+ | ------------------------ | -------------------------------------------------------- |
125
+ | Read documents | Read documents the account can open. Cannot change them. |
126
+ | Read and write documents | Read and change documents the account can open. |
127
+
128
+ **Slides**
129
+
130
+ | Permission | What it allows |
131
+ | ---------------------------- | ------------------------------------------------------------ |
132
+ | Read presentations | Read presentations the account can open. Cannot change them. |
133
+ | Read and write presentations | Build and change presentations the account can open. |
134
+
135
+ **Calendar**
136
+
137
+ | Permission | What it allows |
138
+ | -------------------------------------------- | ----------------------------------------------------------------------------------- |
139
+ | Availability only | See when the account is free or busy, never what the meetings are. |
140
+ | Read events | Read events on the account's calendars. Cannot change them. |
141
+ | Read and write events | Read and manage events on the account's calendars. |
142
+ | Its own calendar | A separate calendar this project creates and owns. Never touches the account's own. |
143
+ | Manage all calendars _(under consideration)_ | Full control of every calendar, including creating and deleting them. |
144
+
145
+ **Drive**
146
+
147
+ | Permission | What it allows |
148
+ | --------------------------------------------- | ----------------------------------------------------------------------------- |
149
+ | Files this project makes | Create files, and reopen the ones this project made or someone picked for it. |
150
+ | Its own config folder | A hidden folder only this project can see. Invisible in the account's Drive. |
151
+ | Recordings and transcripts **(wider access)** | Read the recordings and transcripts Meet saved to Drive. |
152
+ | Read the whole Drive _(under consideration)_ | Read and download every file the account can see. |
153
+ | Read all file names _(under consideration)_ | Names and metadata of every file the account can see, without contents. |
154
+ | Full Drive access _(under consideration)_ | Read, change and delete every file the account can see. |
155
+
156
+ **Gmail**
157
+
158
+ | Permission | What it allows |
159
+ | ---------------------------------------------- | ---------------------------------------------------------------- |
160
+ | Send mail | Send mail as the account. Cannot read the mailbox. |
161
+ | Read mail **(wider access)** | Read the account's mail. Cannot send, change or delete anything. |
162
+ | Read and organise mail _(under consideration)_ | Read, label and archive mail. Cannot permanently delete. |
163
+
164
+ **Directory**
165
+
166
+ | Permission | What it allows |
167
+ | ------------------------------------------------- | -------------------------------------------------------------------- |
168
+ | Look people up | Search the organisation's directory for colleagues. |
169
+ | Read personal contacts | Read the account's own contacts. |
170
+ | Read org users and groups _(under consideration)_ | Admin view of every user and group. Only works for Workspace admins. |
171
+
172
+ **Tasks**
173
+
174
+ | Permission | What it allows |
175
+ | -------------------- | ---------------------------------- |
176
+ | Read tasks | Read the account's task lists. |
177
+ | Read and write tasks | Create, change and complete tasks. |
178
+
179
+ **Forms**
180
+
181
+ | Permission | What it allows |
182
+ | ------------------- | -------------------------------------------------------- |
183
+ | Read form structure | Read a form's questions and settings, not its responses. |
184
+ | Build forms | Create and change forms. |
185
+ | Read responses | Read what people submitted. Often personal information. |
186
+
187
+ **Meet**
188
+
189
+ | Permission | What it allows |
190
+ | --------------------------- | ---------------------------------------------------------- |
191
+ | Meetings this project makes | Create meeting links and read details of the ones it made. |
192
+
193
+ ## When a connection stops working
194
+
195
+ Google grants end on their own sometimes: someone changes their password,
196
+ removes Canopy from their account permissions, or the connection sits unused
197
+ for six months. Calls then fail asking for a reconnect. For the project's
198
+ account, the owner reconnects on the Services tab; for a visitor's, show the
199
+ connect button again. Nothing else needs changing.
200
+
201
+ Disconnecting also tells Google the grant is over, so access stops immediately
202
+ rather than lingering. Visitors can drop their own connection with
203
+ `canopy.google.user().disconnect()`.
204
+
205
+ ## Local development
206
+
207
+ `canopy dev` uses the real connections, so Google works the same on your
208
+ machine as in production — including with `--local`. There is nothing to set up
209
+ locally, and no localhost URLs to register.
210
+
211
+ Because it is real, calls in development touch real data. Sending mail really
212
+ sends it. If that matters, connect a test account on your project's staging
213
+ channel and develop against that.
@@ -0,0 +1,71 @@
1
+ ---
2
+ title: Members & access
3
+ description: Everything on Canopy sits behind Monks sign-in. Collaborators manage a project; other Monks can view the live app — unless you tighten it.
4
+ ---
5
+
6
+ Nothing on Canopy is reachable by the anonymous internet. Every project URL
7
+ and the dashboard itself sit behind Monks OneLogin — visitors sign in with
8
+ their company account before they see anything. On top of that wall, each
9
+ project has its own roster that decides who can _manage_ it and, optionally,
10
+ who can _view_ it.
11
+
12
+ ## The default: any Monk can look, members can manage
13
+
14
+ Out of the box:
15
+
16
+ - **Any signed-in Monk** can open a project's live URL and see the app. The
17
+ project also appears in the company-wide list on the dashboard.
18
+ - **Only the project's members** (and platform admins) can open its
19
+ management pages — deploy history, data browser, usage, and settings.
20
+
21
+ That default fits most internal work: colleagues can try what you built, but
22
+ nobody outside the team can touch its data or settings.
23
+
24
+ ## Roles
25
+
26
+ - **Owner** — the person who created the project. Owners govern it: they
27
+ invite and remove collaborators, change access settings, and can delete
28
+ the project.
29
+ - **Collaborator** — invited teammates. They can do day-to-day work — deploy,
30
+ roll back, browse and edit data, manage schedules and secrets — but not
31
+ delete the project or manage its roster.
32
+ - **Platform admin** — can manage any project from the dashboard. Admins keep
33
+ governance access, but they do not silently bypass a collaborators-only
34
+ live app (see below).
35
+
36
+ ## Inviting collaborators
37
+
38
+ Open the project's **Settings** tab and use the **Collaborators** card. A
39
+ searchable people picker finds anyone who has signed in to Canopy; adding
40
+ them takes effect immediately. Owners (and admins) can also remove people
41
+ from the same card.
42
+
43
+ ## Collaborators-only mode
44
+
45
+ Sometimes "any Monk can look" is too open — payroll prototypes, sensitive
46
+ client work, unfinished things you'd rather not demo by accident. Flip on
47
+ **Settings → Who at Monks can open it → Restrict to collaborators** and the
48
+ live app is limited to the project's roster:
49
+
50
+ - Other Monks who open the URL get a clear "limited to its collaborators"
51
+ page instead of the app.
52
+ - The project still appears in the company list — it isn't hidden, just
53
+ closed.
54
+ - Platform admins can still manage the project in the dashboard, but they
55
+ must add themselves as collaborators if they need to open the live app.
56
+ - [Client password access](https://docs.canopy.website/platform/client-access), if you've enabled
57
+ it, is unaffected — the two controls are independent.
58
+
59
+ Turning it off again is the same toggle.
60
+
61
+ > **Note:** Collaborators-only gates the **live app**. Management access (settings, data, deploys) is always
62
+ > members-only, regardless of this toggle.
63
+
64
+ ## Platform admins and the Users page
65
+
66
+ Platform admins get an extra **Users** page in the dashboard listing everyone
67
+ on Canopy — name, email, and when they first signed in — with a one-click way
68
+ to grant or remove admin. Accounts are created automatically on first
69
+ OneLogin sign-in; there is nothing to provision.
70
+
71
+ - [Client access](https://docs.canopy.website/platform/client-access) — Share work-in-progress with clients who don't have a Monks account.
@@ -0,0 +1,76 @@
1
+ ---
2
+ title: Project data
3
+ description: Every project gets its own private database and file storage — browse it in the dashboard, snapshot it before risky changes, and pull it locally.
4
+ ---
5
+
6
+ Every Canopy project comes with its own private database and file storage,
7
+ created automatically the moment the project exists. There are no connection
8
+ strings to configure and no servers to run — your app reads and writes through
9
+ the Canopy SDK, and no other project can ever see your data.
10
+
11
+ ## The Data tab and the data explorer
12
+
13
+ Open a project in the dashboard and the **Data** tab shows what your app has
14
+ stored — every collection and table at a glance — plus the door into the
15
+ **data explorer**, a full-page workspace for actually digging in:
16
+
17
+ - **Schema sidebar** — collections and tables, each expandable to its
18
+ columns (types, primary keys) and indexes.
19
+ - **Browse** — click any table or collection to page through it with real
20
+ totals, sort by any column, and stack filters (equals, contains,
21
+ comparisons, null checks) without writing SQL. Click a row for the full
22
+ record, JSON pretty-printed. Export the current page as CSV or JSON.
23
+ - **SQL console** — a real editor with syntax highlighting and autocomplete
24
+ fed by your schema. Run with <kbd>⌘⏎</kbd>, see row counts and timing,
25
+ recall earlier queries from history, and hit **Explain** to see the query
26
+ plan.
27
+
28
+ The console is **read-only by default** — the platform rejects anything but
29
+ reads until you flip the writes toggle, so exploring production data is safe
30
+ by design. The explorer is fixed to the channel (live or staging) you opened
31
+ it from; to look at the other one, go back to the Data tab and switch there.
32
+
33
+ The **Files** tab next to it lists the project's blob storage — the uploads
34
+ and files your app has saved.
35
+
36
+ ## Snapshots and restores
37
+
38
+ The Data tab's **Data safety** card is your undo button for data:
39
+
40
+ - **Snapshot** stores a full dump of the database on the platform. Take one
41
+ before a risky change — a big import, a cleanup script, letting an agent
42
+ loose on production data.
43
+ - **Restore** replaces the project's current data with a snapshot. This is
44
+ destructive by design (that's the point), so the dashboard asks you to
45
+ confirm.
46
+ - **Export** downloads a dump to your machine.
47
+
48
+ Snapshots live server-side and stay available until you delete the project,
49
+ so you can restore from days ago, not just from your last session.
50
+
51
+ > **Warning:** Restoring replaces **all** current data with the snapshot's contents. Take a fresh snapshot first
52
+ > if there's anything recent you might want back.
53
+
54
+ ## The same tools from the terminal
55
+
56
+ Everything above is also available to you (and your coding agent) via the CLI:
57
+
58
+ ```bash
59
+ canopy db pull # download a fresh SQL dump
60
+ canopy db snapshot # store a dump server-side
61
+ canopy db snapshots # list stored snapshots
62
+ canopy db restore # replace project data with a snapshot
63
+ ```
64
+
65
+ `canopy db pull` is also how you develop against realistic data: pull a dump,
66
+ then run `canopy dev --local --pull` for a throwaway sandbox seeded with it.
67
+
68
+ ## Portable by default, SQL when you need it
69
+
70
+ The SDK's document API (`canopy.db.collection(...)`) behaves the same
71
+ everywhere Canopy runs. Raw SQL via `canopy.db.sql()` passes straight through
72
+ to the underlying database — SQLite on the Cloudflare sites, Postgres on the
73
+ GCP pilot — so anything that database supports works. Your code can ask
74
+ `canopy.db.dialect()` which one it's talking to.
75
+
76
+ - [Working with project data](https://docs.canopy.website/guides/data) — Collection naming rules, dialects and raw SQL, dumps, and restore workflows in depth.
@@ -0,0 +1,90 @@
1
+ ---
2
+ title: Schedules
3
+ description: Run named cron jobs in your project's backend — configured in the dashboard, so you can change the cadence without redeploying.
4
+ ---
5
+
6
+ Schedules let a project do things on a clock: send a daily digest, refresh a
7
+ cache every hour, tick a counter every minute. You define **named jobs** in
8
+ the dashboard, and the platform wakes your project's backend at the right
9
+ times — your code only decides what each job does.
10
+
11
+ > **Note:** Schedules need a project with a custom backend. Per-project backends run on the **main** site and
12
+ > the **GCP pilot** site. On sites without backend support the Schedules section doesn't appear in
13
+ > Settings, and the API answers `not_supported_on_target`.
14
+
15
+ ## Defining a schedule
16
+
17
+ In the dashboard, open the project's **Settings → Schedules**. Each schedule
18
+ has:
19
+
20
+ - a **name** (like `daily-digest`) — this is what your code switches on;
21
+ - a **cron expression** — standard 5-field cron, always in **UTC**;
22
+ - an **enabled** toggle, so you can pause a job without deleting it.
23
+
24
+ A project can have up to **5 schedules**, and the shortest interval is one
25
+ minute. Each row also shows its last run and, if it failed, the error — so
26
+ you can see at a glance whether a job is healthy.
27
+
28
+ You can also trigger a schedule manually from the dashboard, which is the
29
+ quickest way to test a handler without waiting for the clock.
30
+
31
+ ## Handling schedules in your code
32
+
33
+ Your project's worker exports a `scheduled` handler next to its normal
34
+ `fetch` handler, and switches on the job's name:
35
+
36
+ ```ts
37
+ export default {
38
+ async fetch(request, env, ctx) {
39
+ return app.fetch(request, env, ctx);
40
+ },
41
+
42
+ async scheduled(event, env, ctx) {
43
+ switch (event.name) {
44
+ case "daily-digest":
45
+ await sendDigest(env);
46
+ break;
47
+ default:
48
+ console.warn("unknown schedule", event.name);
49
+ }
50
+ },
51
+ };
52
+ ```
53
+
54
+ `event.name` is the name you gave the schedule in the dashboard, `event.cron`
55
+ is the expression that fired, and `event.scheduledTime` is when it fired.
56
+ Inside the handler your code has the same environment as an HTTP request —
57
+ secrets, the project database, and blob storage all work the same way.
58
+
59
+ ## Data access without a signed-in user
60
+
61
+ A scheduled run has no browser session attached, but `canopy.db`, `canopy.blob`
62
+ and `canopy.ai` still work: the platform seals a **project-scoped worker
63
+ token** into your backend on every deploy, and calls through the platform
64
+ fall back to it whenever the request carries no user credential. You don't
65
+ configure or see this token — it's minted, rotated (every deploy replaces
66
+ it), and revoked with the project automatically, and it only ever reaches
67
+ your own project's data.
68
+
69
+ The one thing that behaves differently is identity: `canopy.auth.user()`
70
+ resolves with `kind: "worker"` and empty `id`/`email`/`name` — there is no
71
+ one signed in during a cron tick, and your code should treat that as "no
72
+ user", not as an error.
73
+
74
+ ## Why the name matters
75
+
76
+ Switch on `event.name`, not on the cron string. The dashboard is the source
77
+ of truth for _when_ a job runs, so you can change `daily-digest` from 6:00 to
78
+ 7:30 — or pause it — without touching code or redeploying. The name is the
79
+ stable contract between the dashboard and your handler.
80
+
81
+ ## Things to know
82
+
83
+ - **Cron runs as the project, not as a person.** Data access works (see
84
+ above), but there is no signed-in user — `auth.user()` answers with
85
+ `kind: "worker"` and no identity.
86
+ - **All times are UTC.** `0 6 * * *` is 6:00 UTC, not local time.
87
+ - **Failures are visible.** A run that throws records its error on the
88
+ schedule row in Settings, so silent breakage doesn't stay silent.
89
+
90
+ - [Infrastructure](https://docs.canopy.website/guides/infrastructure) — What runs where — assets, backends, databases — across the Canopy sites.
@@ -0,0 +1,61 @@
1
+ ---
2
+ title: Sites & profiles
3
+ description: Canopy runs as more than one installation. Most people only ever use main — here's what the others are and how the CLI keeps them straight.
4
+ ---
5
+
6
+ Canopy isn't a single installation: the same platform runs as a few separate
7
+ **sites**, each with its own domain, its own projects, and its own data.
8
+ Unless someone told you otherwise, **you're on `main` and can stop reading
9
+ here** — the rest of this page explains what the other sites are for and how
10
+ the CLI targets them.
11
+
12
+ ## The sites
13
+
14
+ | Site | Project URLs | What it's for |
15
+ | ----------- | --------------------- | ------------------------------------------------- |
16
+ | `main` | `*.canopy.website` | The real platform. Your projects live here. |
17
+ | `staging` | `*.thanarie.dev` | The platform team's testbed for platform changes. |
18
+ | `gcp-pilot` | `*.canopy.monks.zone` | A pilot running on Google Cloud. |
19
+
20
+ Sites are fully separate: a project on `main` doesn't exist on `staging`, and
21
+ signing in to one doesn't create anything on another. They can also differ in
22
+ what they support — the dashboard simply hides features a site can't honor,
23
+ and the API says `not_supported_on_target` if asked directly.
24
+
25
+ ## What a profile is
26
+
27
+ A **profile** is the CLI's name for a site. `canopy login` signs you in once
28
+ via OneLogin and stores a credential for every site in one go; the profile
29
+ just picks which one a command talks to.
30
+
31
+ Three things decide the effective profile, in order:
32
+
33
+ 1. `--profile <id>` on the command (or the `CANOPY_PROFILE` environment
34
+ variable) — one-off override.
35
+ 2. The `"profile"` pinned in the project's `canopy.json` — set when the
36
+ project was created, so a checkout always targets the site it belongs to.
37
+ 3. Your default active profile — `main` unless you chose otherwise at login.
38
+
39
+ Every command prints the site it's talking to in its header line, and
40
+ `canopy whoami` shows your email, active profile, and API host — so there's
41
+ never a mystery about where a deploy just went.
42
+
43
+ ```bash
44
+ canopy whoami # who am I, on which site?
45
+ canopy --profile gcp-pilot deploy # one command against the pilot
46
+ ```
47
+
48
+ ## When you'd actually care
49
+
50
+ - **Never, usually.** Day-to-day work on your own projects is all `main`,
51
+ and the `canopy.json` pin keeps it that way without any flags.
52
+ - **Trying backend features.** Custom backends and
53
+ [schedules](https://docs.canopy.website/platform/schedules) currently run on `gcp-pilot`, so
54
+ experiments with those happen there.
55
+ - **Helping test platform changes.** If the platform team asks you to check
56
+ something on `staging`, `--profile staging` points any command at it.
57
+
58
+ > **Note:** Deploying to a different site publishes a **separate copy** of the project there — it doesn't move
59
+ > or mirror the one on `main`. Each site keeps its own versions, data, and members.
60
+
61
+ - [CLI reference](https://docs.canopy.website/guides/cli) — Every canopy command, including login, whoami, and the --profile flag.