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 +4 -2
- package/dist/index.js +4 -1
- package/dist/scaffold.js +6 -0
- package/dist/template/README.md +17 -5
- package/dist/template/_env.example +24 -5
- package/dist/template/vercel.json +4 -0
- package/package.json +2 -2
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
|
|
24
|
-
|
|
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
|
|
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
|
}
|
package/dist/template/README.md
CHANGED
|
@@ -26,7 +26,9 @@ bun install && bun start
|
|
|
26
26
|
```
|
|
27
27
|
</details>
|
|
28
28
|
|
|
29
|
-
Open http://localhost:8080 and
|
|
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
|
|
59
|
-
pnpm env 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
|
|
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
|
-
|
|
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
|
|
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
|
-
#
|
|
28
|
-
#
|
|
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.
|
|
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": "
|
|
9
|
+
"create-snagset": "dist/index.js"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|