create-grist-widget 0.2.3 → 0.2.5

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.
package/README.md CHANGED
@@ -14,4 +14,72 @@ The template ships embedded in this package — nothing is fetched from GitHub a
14
14
  scaffold time. See [Getting started](https://grist-widgets.com/guide/getting-started)
15
15
  for the full walkthrough (dev loop, deploying, embedding in Grist).
16
16
 
17
+ ## Using Claude Code?
18
+
19
+ The scaffolded project ships a working GitHub Pages deploy pipeline
20
+ ([release + dev channels](https://grist-widgets.com/guide/getting-started)), which
21
+ needs a couple of one-time repo settings that only a human can click through. The
22
+ simplest way to get from zero to a deployed widget:
23
+
24
+ 1. Create a new, empty GitHub repo for the widget.
25
+ 2. Install the [Claude GitHub App](https://github.com/apps/claude) on that repo.
26
+ 3. Start a Claude Code session connected to it and ask it to scaffold and push:
27
+
28
+ ```bash
29
+ npm create grist-widget my-widget
30
+ cd my-widget
31
+ ```
32
+
33
+ The scaffold already commits itself on `main` (the branch the deploy
34
+ workflow releases from) with a `dev` branch ready alongside it — no
35
+ separate `git init`/`git commit` needed. Just add the remote and push:
36
+
37
+ ```bash
38
+ git remote add origin https://github.com/<owner>/<repo>.git
39
+ git push -u origin main
40
+ git push origin dev # optional, for the live-preview channel
41
+ ```
42
+
43
+ 4. That push triggers the deploy workflow's first run. Once it completes
44
+ (it creates a `gh-pages` branch), there's **one one-time setting**:
45
+ Settings → Pages → Source → **Deploy from a branch** → branch `gh-pages`,
46
+ folder `/ (root)`. This can only be set once `gh-pages` exists, which is
47
+ why it's a step *after* the first push, not before.
48
+
49
+ Once that's saved, your widget is live at two URLs:
50
+
51
+ - `https://<owner>.github.io/<repo>/latest/` — mutable, always points at
52
+ whatever version was last released.
53
+ - `https://<owner>.github.io/<repo>/v<version>/` — immutable, e.g. `/v0.0.1/`;
54
+ this exact version, forever, even after later releases move `/latest/`.
55
+
56
+ Paste whichever one fits into Grist's custom widget URL field — `/latest/`
57
+ if you want the widget to update automatically as you release new
58
+ versions, or a pinned `/v<version>/` if you don't.
59
+
60
+ > If the very first workflow run fails with a permissions error pushing
61
+ > to `gh-pages`, your repo's default Actions token permissions are
62
+ > read-only — Settings → Actions → General → Workflow permissions →
63
+ > **Read and write permissions** fixes it. Most repos don't need this;
64
+ > it depends on account/org defaults.
65
+
66
+ 5. **Ongoing workflow: always develop on `dev`, release by merging to `main`.**
67
+ The `dev` branch already exists from step 3. From here on:
68
+
69
+ - Commit and push to `dev` for every change. Each push auto-deploys a live
70
+ preview at `https://<owner>.github.io/<repo>/dev/` that self-reloads
71
+ inside an open Grist document a few seconds later.
72
+ - Ready to publish? **Bump `package.json`'s `version`** as part of your
73
+ `dev` changes, then open a PR from `dev` into `main` and merge it —
74
+ merging is what actually publishes (`/v<version>/` + `/latest/`).
75
+
76
+ > ⚠️ **Merging without a version bump publishes nothing.** The release
77
+ > build skips whenever the version already has a published `v<version>/`
78
+ > directory, which is always true if you forgot to bump it. The PR merges
79
+ > cleanly and CI runs "successfully," but `/latest/` doesn't change. Bump
80
+ > the version *before* merging.
81
+
82
+ Keep committing to the same `dev` branch afterward — it's the permanent
83
+ working/preview branch, not a one-off branch to delete per change.
84
+
17
85
  MIT licensed.
@@ -2,6 +2,7 @@
2
2
  import { existsSync, mkdirSync, readdirSync, cpSync, readFileSync, writeFileSync, renameSync } from "node:fs"
3
3
  import path from "node:path"
4
4
  import { fileURLToPath } from "node:url"
5
+ import { execFileSync } from "node:child_process"
5
6
 
6
7
  const TEMPLATE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "template")
7
8
 
@@ -49,7 +50,41 @@ for (const [file, subs] of edits) {
49
50
  writeFileSync(p, content)
50
51
  }
51
52
 
53
+ // Initialize git on `main` with the scaffold as its first commit, and a
54
+ // `dev` branch ready to push for live-preview later. Doing this here (not
55
+ // leaving it to whoever/whatever runs next) is what actually prevents the
56
+ // scaffold from ending up on some other branch — the deploy workflow only
57
+ // ever releases from `main`, so committing anywhere else silently never
58
+ // deploys. Degrades gracefully: if there's no git identity configured yet,
59
+ // `main` still exists locally, just without a commit.
60
+ function git(args) {
61
+ execFileSync("git", args, { cwd: target, stdio: "ignore" })
62
+ }
63
+ let committed = false
64
+ try {
65
+ git(["init", "-q", "-b", "main"])
66
+ git(["add", "-A"])
67
+ git(["commit", "-q", "-m", "scaffold: initial widget"])
68
+ git(["branch", "dev"])
69
+ committed = true
70
+ } catch {
71
+ // No git identity configured (or git unavailable) — leave it to the
72
+ // printed next steps below.
73
+ }
74
+
52
75
  console.log(`Created ${rawName}/\n`)
53
76
  console.log(` cd ${rawName}`)
54
77
  console.log(" pnpm install # or npm/yarn")
55
78
  console.log(" pnpm dev")
79
+ if (committed) {
80
+ console.log("\nGit is initialized on main (first commit done) with a dev branch ready.")
81
+ console.log("To push to GitHub:")
82
+ console.log(" git remote add origin https://github.com/<owner>/<repo>.git")
83
+ console.log(" git push -u origin main")
84
+ console.log(" git push origin dev # optional, for the live-preview channel")
85
+ } else {
86
+ console.log("\nCould not create the initial git commit automatically (no git identity")
87
+ console.log('configured?) — run `git config user.name`/`user.email`, then:')
88
+ console.log(" git init -b main && git add -A && git commit -m 'scaffold: initial widget'")
89
+ console.log(" git branch dev")
90
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-grist-widget",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Scaffold a new Grist custom widget from the grist-widget-sdk Vite template",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -33,16 +33,30 @@ ignored (the root workspace governs).
33
33
  ## Deployment
34
34
 
35
35
  A bundled GitHub Actions workflow (`.github/workflows/deploy.yml` +
36
- `scripts/deploy.mjs`) publishes this widget to **your own** GitHub Pages,
37
- with the same two-channel model the SDK's own widgets use:
38
-
39
- - **Push `main`** (after bumping `package.json`'s `version`) → immutable
40
- `/v<version>/` + mutable `/latest/`. Re-pushing without a version bump is a
41
- no-op — a version is only ever built once.
42
- - **Push a `dev` branch** → mutable `/dev/`, which self-reloads inside an
43
- open Grist document a few seconds after every new push — paste the `/dev/`
44
- URL into a Grist doc once, then just keep pushing while you iterate.
45
- - **Delete the `dev` branch** → `/dev/` is retired automatically.
36
+ `scripts/deploy.mjs`) publishes this widget to **your own** GitHub Pages.
37
+
38
+ ### The workflow: always develop on `dev`, release by merging to `main`
39
+
40
+ 1. Commit and push to the `dev` branch (created for you at scaffold time).
41
+ Every push auto-deploys a live preview at `/dev/` that self-reloads
42
+ inside an open Grist document a few seconds later — paste that URL into
43
+ a Grist doc once, then just keep pushing while you iterate.
44
+ 2. Ready to publish a release? **Bump `package.json`'s `version`** as part
45
+ of your `dev` branch changes, then open a PR from `dev` into `main`.
46
+ 3. **Merge the PR.** This is the step that actually publishes — merging to
47
+ `main` builds immutable `/v<version>/` and updates mutable `/latest/`.
48
+
49
+ > ⚠️ **Merging without bumping the version publishes nothing.** The release
50
+ > build is idempotent — it skips whenever `package.json`'s version already
51
+ > has a matching `v<version>/` directory published, which is always true if
52
+ > you forgot to bump it (it'll match whatever's already live). The PR merges
53
+ > cleanly and CI runs "successfully," but `/latest/` silently stays exactly
54
+ > as it was. Bump the version *before* merging, not after.
55
+
56
+ After merging, keep committing to the same `dev` branch for your next round
57
+ of changes — it's the permanent working/preview branch for this widget, not
58
+ a one-off feature branch to delete and recreate. Deleting it retires `/dev/`
59
+ automatically.
46
60
 
47
61
  **One-time setup** (the workflow can't do this part for you):
48
62