create-snagset 0.0.4 → 0.1.1

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
@@ -20,8 +20,10 @@ bun create snagset my-review # then: bun install && bun start
20
20
  </details>
21
21
 
22
22
  Bring a Postgres URL — a free Neon or Supabase branch, or a local install — and
23
- put it in `.env` as `DATABASE_URL`. Open `http://localhost:8080` and follow the
24
- claim URL in the logs.
23
+ put it in `.env` as `DATABASE_URL`. Open `http://localhost:8080` and create the
24
+ first owner — an instance nobody has claimed shows a setup screen rather than a
25
+ sign-in form, and **the first person to fill it in becomes the owner**, so do
26
+ that before you share the address.
25
27
 
26
28
  **No Docker, on purpose.** No Dockerfile, no compose file, nothing to build:
27
29
  Snagset is a Node process and a Postgres URL.
package/dist/index.js CHANGED
@@ -26,6 +26,9 @@ process.stdout.write(`\n ✓ ${name}\n\n` +
26
26
  ` cd ${target}\n` +
27
27
  ` pnpm install && pnpm start\n\n` +
28
28
  ` (npm, yarn and bun work the same way.)\n\n` +
29
- ` Then open http://localhost:8080 and follow the claim URL in the logs.\n\n` +
29
+ ` Then open http://localhost:8080 and create the first owner.\n` +
30
+ ` An instance nobody has claimed shows a setup screen rather than a\n` +
31
+ ` sign-in form, and the FIRST person to fill it in becomes the owner —\n` +
32
+ ` so do that before you share the address.\n\n` +
30
33
  ` A signing key was generated into .env. Back it up — without it every\n` +
31
34
  ` session and stored credential is unrecoverable.\n\n`);
package/dist/scaffold.js CHANGED
@@ -101,6 +101,12 @@ export function scaffold(target, cwd = process.cwd()) {
101
101
  * would otherwise discover on the far side that they had no key to set.
102
102
  */
103
103
  const env = readFileSync(join(dir, ".env.example"), "utf8").replace("# SNAGSET_SECRET_KEY=", `SNAGSET_SECRET_KEY=${randomBytes(32).toString("base64url")}`);
104
+ // Nothing to quote here yet — the placeholder URL has no `&`. The QUOTED
105
+ // form is in the example itself, because a real connection string usually
106
+ // does: `?sslmode=require&channel_binding=require` ends a shell command at
107
+ // the `&` and runs the rest in the background, so `. .env` breaks on exactly
108
+ // the URL a Neon or Supabase branch hands you. Reported from a deploy trial,
109
+ // 2026-09-01.
104
110
  writeFileSync(join(dir, ".env"), env);
105
111
  return dir;
106
112
  }
@@ -26,7 +26,9 @@ bun install && bun start
26
26
  ```
27
27
  </details>
28
28
 
29
- Open http://localhost:8080 and follow the claim URL printed in the logs.
29
+ Open http://localhost:8080 and create the first owner. An instance nobody has
30
+ claimed shows a setup screen rather than a sign-in form, and **the first person
31
+ to fill it in becomes the owner** — so do that before you share the address.
30
32
 
31
33
  **No Docker anywhere in this project, deliberately.** One less thing to
32
34
  install, and one less thing between you and a database you can also reach from
@@ -55,8 +57,11 @@ ignored, which is the hardest failure here to spot from the outside.
55
57
  `.env`. Only `DATABASE_URL` is required.
56
58
 
57
59
  ```bash
58
- pnpm env # every variable this build accepts, with its default
59
- pnpm env MAIL # just the ones matching MAIL
60
+ pnpm run env # every variable this build accepts, with its default
61
+ pnpm run env MAIL # just the ones matching MAIL
62
+
63
+ # `run` is not optional here: `pnpm env` is pnpm's OWN command (it manages
64
+ # Node versions) and shadows the script. npm and yarn need no `run`.
60
65
  ```
61
66
 
62
67
  Screenshots need an S3-compatible bucket (R2, Spaces, MinIO, AWS).
@@ -82,10 +87,17 @@ the widget on one port.
82
87
  ## Upgrading
83
88
 
84
89
  ```bash
85
- pnpm update @snagset/server
90
+ pnpm update @snagset/server --latest
86
91
  ```
87
92
 
88
- Migrations run on boot. There is no build step to redo.
93
+ Then `pnpm start` again, or redeploy. Migrations run on boot; there is no
94
+ build step to redo.
95
+
96
+ `--latest` matters: this project pins `@snagset/server` to an exact version on
97
+ purpose (a fresh clone installs the version you last ran), and a plain
98
+ `pnpm update` respects the pin — it does nothing. Back up the database before
99
+ a version that carries migrations; the release notes name any that cannot
100
+ roll back.
89
101
 
90
102
  ## Back up your signing key
91
103
 
@@ -1,7 +1,9 @@
1
1
  # ── Required ───────────────────────────────────────────────────────────
2
2
  # Any Postgres 14+ — a free Neon or Supabase branch, or a local install.
3
3
  # Use the POOLED connection string where your provider offers one.
4
- DATABASE_URL=postgres://snagset:snagset@localhost:5432/snagset
4
+ # QUOTE IT. A managed provider appends `?sslmode=require&channel_binding=require`,
5
+ # and an unquoted `&` ends the line as far as `. .env` is concerned.
6
+ DATABASE_URL="postgres://snagset:snagset@localhost:5432/snagset"
5
7
 
6
8
  # ── Strongly recommended ───────────────────────────────────────────────
7
9
  # 32 random bytes, base64url. Generated to .snagset/secret.key on first boot
@@ -11,7 +13,7 @@ DATABASE_URL=postgres://snagset:snagset@localhost:5432/snagset
11
13
  # node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
12
14
  # SNAGSET_SECRET_KEY=
13
15
 
14
- # The public origin. Review links and the claim URL are built from it.
16
+ # The public origin. Review links are built from it.
15
17
  # SNAGSET_BASE_URL=http://localhost:8080
16
18
 
17
19
  # ── Claim it without a browser (optional) ──────────────────────────────
@@ -22,7 +24,24 @@ DATABASE_URL=postgres://snagset:snagset@localhost:5432/snagset
22
24
  # SNAGSET_BOOTSTRAP_PROJECT_NAME=First site
23
25
  # SNAGSET_BOOTSTRAP_PROJECT_ORIGINS=https://staging.example.com,http://localhost:3000
24
26
 
27
+ # ── Screenshots (optional) ─────────────────────────────────────────────
28
+ # Any S3-compatible bucket — DigitalOcean Spaces, Cloudflare R2, MinIO, S3.
29
+ # Without one the widget runs in annotation mode and SAYS so, rather than
30
+ # failing quietly at the moment somebody files their first snag.
31
+ # SNAGSET_STORAGE_S3_ENDPOINT=https://ams3.digitaloceanspaces.com
32
+ # SNAGSET_STORAGE_S3_BUCKET=my-bucket
33
+ # SNAGSET_STORAGE_S3_REGION=auto
34
+ # SNAGSET_STORAGE_S3_ACCESS_KEY_ID=
35
+ # SNAGSET_STORAGE_S3_SECRET_ACCESS_KEY=
36
+
37
+ # ── Email notifications (optional) ─────────────────────────────────────
38
+ # The URL SCHEME picks the transport: resend://, smtp://, smtps://.
39
+ # Unset means no mail, which is a supported way to run — nothing queues up
40
+ # waiting for a transport that never arrives.
41
+ # SNAGSET_MAIL_URL=resend://re_your_api_key
42
+ # SNAGSET_MAIL_FROM=snagset@example.com
43
+
25
44
  # ── Everything else ────────────────────────────────────────────────────
26
- # `npm run env` prints every variable this build accepts, with its default.
27
- # Screenshots need an S3-compatible bucket; notifications need a mailer.
28
- # Both are optional and the product is honest about running without them.
45
+ # `npm run env` prints every variable this build accepts, with its default —
46
+ # 70-odd of them, which is why only the ones most people want are written out
47
+ # above.
@@ -1,5 +1,9 @@
1
1
  {
2
2
  "$schema": "https://openapi.vercel.sh/vercel.json",
3
+
4
+ "//": "EVERY PATH REACHES THE ONE HANDLER. Without this, Vercel's filesystem router serves only /api/index and 404s /, /snag.js and even the cron's own /api/jobs/run — before the handler runs, with x-vercel-error: NOT_FOUND. Found on a real deploy 2026-09-01, not by any test we own: a serverless entry that is never reached looks identical to one that works until somebody opens the site.",
5
+ "rewrites": [{ "source": "/(.*)", "destination": "/api/index" }],
6
+
3
7
  "crons": [
4
8
  { "path": "/api/jobs/run", "schedule": "* * * * *" }
5
9
  ]
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "create-snagset",
3
- "version": "0.0.4",
3
+ "version": "0.1.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Scaffold your own Snagset instance. One command, Postgres included, one variable to fill in.",
7
7
  "license": "AGPL-3.0-only",
8
8
  "bin": {
9
- "create-snagset": "./dist/index.js"
9
+ "create-snagset": "dist/index.js"
10
10
  },
11
11
  "scripts": {
12
12
  "typecheck": "tsc -p tsconfig.json --noEmit",