create-meith 0.26.1 → 0.27.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.
package/dist/bin.mjs CHANGED
@@ -23,7 +23,7 @@ var MATERIALIZED_AT_ROOT = [
23
23
  "tsconfig.json",
24
24
  "next-env.d.ts"
25
25
  ];
26
- var VERCEL_BUILD_COMMAND = `community migrate && forum-web build ${AT_ROOT_FLAG}`;
26
+ var VERCEL_BUILD_COMMAND = `meith migrate && forum-web build ${AT_ROOT_FLAG}`;
27
27
  var TICK_PATH = "/api/system/tick";
28
28
  var TICK_SCHEDULE = "0 3 * * *";
29
29
  var RESEND_SENDER_MAILBOX = "noreply";
@@ -85,7 +85,7 @@ var ENV_DATABASE_URL_PROSE = `# Your Postgres connection string.
85
85
  # database rather than the cause. Your own Postgres, with a fixed number of
86
86
  # processes in front of it, does not need one.`;
87
87
  var ENV_DIRECT_DATABASE_URL_PROSE = `# The other half of that pair: the DIRECT (non-pooler) string, used only by
88
- # \`community migrate\` and \`community backup\`. Migrations hold a session-level
88
+ # \`meith migrate\` and \`meith backup\`. Migrations hold a session-level
89
89
  # advisory lock so that two deploys landing together queue instead of both
90
90
  # applying the same migration, and a transaction-mode pooler cannot hold that
91
91
  # lock: it takes the connection back the moment the lock statement ends, which
@@ -213,7 +213,7 @@ DATABASE_URL=
213
213
  ${ENV_DIRECT_DATABASE_URL_PROSE}
214
214
  #
215
215
  # On Vercel this is not optional, and it is no longer yours to copy. DATABASE_URL
216
- # here is the pooler string, the build runs \`community migrate\` against it, and
216
+ # here is the pooler string, the build runs \`meith migrate\` against it, and
217
217
  # /install takes the second of those two session locks on first run. Left blank,
218
218
  # the board reads Neon's own direct string \u2014 \`DATABASE_URL_UNPOOLED\` first, then
219
219
  # \`POSTGRES_URL_NON_POOLING\` \u2014 and refuses to boot if neither is there, naming
@@ -250,7 +250,7 @@ CRON_SECRET=
250
250
  #
251
251
  # BLOB_READ_WRITE_TOKEN is the other way in, and you make it yourself on the
252
252
  # store. Set it when something has to reach the store from OUTSIDE a Vercel
253
- # deployment \u2014 \`community backup\` run on your own machine is the case that
253
+ # deployment \u2014 \`meith backup\` run on your own machine is the case that
254
254
  # matters \u2014 because there is no OIDC identity there to borrow. Set both and the
255
255
  # board prefers the store id, unless the token names a different store, in which
256
256
  # case the token wins: naming another store is a deliberate act.
@@ -401,7 +401,7 @@ function scaffold(options) {
401
401
  dev: `forum-web dev${atRootFlag}`,
402
402
  build: `forum-web build${atRootFlag}`,
403
403
  start: `forum-web start${atRootFlag}`,
404
- community: "community"
404
+ meith: "meith"
405
405
  },
406
406
  dependencies: {
407
407
  "@meith/web": version,
@@ -489,7 +489,7 @@ export default defineForumConfig({
489
489
  * ]
490
490
  *
491
491
  * and the matching entry in board.plugins.json, which is what
492
- * \`community plugin:add\`/\`plugin:remove\` read inside the monorepo \u2014 kept
492
+ * \`meith plugin:add\`/\`plugin:remove\` read inside the monorepo \u2014 kept
493
493
  * here too so the two files agree about what is installed.
494
494
  */
495
495
  import type { InstalledPlugin } from '@meith/web/config'
@@ -552,8 +552,8 @@ updates:
552
552
  # "Custom boards").
553
553
  #
554
554
  # Two stages, not three: unlike the official image, this does not prune down
555
- # to Next's own standalone output. The migrate role below runs \`community
556
- # migrate\`, and \`community\` materializes @meith/cli's sources and runs them
555
+ # to Next's own standalone output. The migrate role below runs \`meith
556
+ # migrate\`, and \`meith\` materializes @meith/cli's sources and runs them
557
557
  # with tsx at the moment it runs (see the meith repository's
558
558
  # docs/contributing/development.md, "Consuming the board from a workspace") \u2014 it needs
559
559
  # the full, un-pruned node_modules tree this board installed, not what Next
@@ -628,8 +628,8 @@ ENTRYPOINT ["./docker-entrypoint.sh"]
628
628
  # of minutes rather than a cold toolchain build.
629
629
  #
630
630
  # Two stages, not three: unlike the official image, this does not prune down
631
- # to Next's own standalone output. The migrate role below runs \`community
632
- # migrate\`, and \`community\` materializes @meith/cli's sources and runs them
631
+ # to Next's own standalone output. The migrate role below runs \`meith
632
+ # migrate\`, and \`meith\` materializes @meith/cli's sources and runs them
633
633
  # with tsx at the moment it runs (see the meith repository's
634
634
  # docs/contributing/development.md, "Consuming the board from a workspace") \u2014 it needs
635
635
  # the full, un-pruned node_modules tree this board installed, not what Next
@@ -699,22 +699,22 @@ ENTRYPOINT ["./docker-entrypoint.sh"]
699
699
  set -e
700
700
 
701
701
  # An explicit command wins over the role, the same as the official image \u2014
702
- # \`docker run <image> node_modules/.bin/community --help\` should still run
702
+ # \`docker run <image> node_modules/.bin/meith --help\` should still run
703
703
  # the CLI rather than silently starting the web server.
704
704
  if [ "$#" -gt 0 ]; then
705
705
  exec "$@"
706
706
  fi
707
707
 
708
- case "\${COMMUNITY_ROLE:-web}" in
708
+ case "\${MEITH_ROLE:-web}" in
709
709
  migrate)
710
710
  # Runs to completion and exits; compose's one-shot service waits on it.
711
- exec node_modules/.bin/community migrate
711
+ exec node_modules/.bin/meith migrate
712
712
  ;;
713
713
  web)
714
714
  exec node_modules/.bin/forum-web start
715
715
  ;;
716
716
  *)
717
- echo "Unknown COMMUNITY_ROLE: \${COMMUNITY_ROLE}. Expected 'web' or 'migrate'." >&2
717
+ echo "Unknown MEITH_ROLE: \${MEITH_ROLE}. Expected 'web' or 'migrate'." >&2
718
718
  exit 1
719
719
  ;;
720
720
  esac
@@ -728,7 +728,7 @@ esac
728
728
  # a health probe taken while it runs has no opinion.
729
729
  set -e
730
730
 
731
- if [ "\${COMMUNITY_ROLE:-web}" = "migrate" ]; then
731
+ if [ "\${MEITH_ROLE:-web}" = "migrate" ]; then
732
732
  exit 0
733
733
  fi
734
734
 
@@ -865,7 +865,7 @@ services:
865
865
  build: .
866
866
  image: ${name}
867
867
  environment:
868
- COMMUNITY_ROLE: migrate
868
+ MEITH_ROLE: migrate
869
869
  DATABASE_URL: postgres://community:$SERVICE_PASSWORD_POSTGRES@postgres:5432/community
870
870
  AUTH_SECRET: $SERVICE_BASE64_64_AUTH
871
871
  TICK_SECRET: $SERVICE_BASE64_64_TICK
@@ -997,7 +997,7 @@ services:
997
997
  # runs the old code.
998
998
  pull_policy: always
999
999
  environment:
1000
- COMMUNITY_ROLE: migrate
1000
+ MEITH_ROLE: migrate
1001
1001
  DATABASE_URL: postgres://community:$SERVICE_PASSWORD_POSTGRES@postgres:5432/community
1002
1002
  AUTH_SECRET: $SERVICE_BASE64_64_AUTH
1003
1003
  TICK_SECRET: $SERVICE_BASE64_64_TICK
@@ -1196,7 +1196,7 @@ Two things nothing configures for you, on either path:
1196
1196
  loop calling \`/api/system/tick\` once a minute, since \`@meith/web\`'s own
1197
1197
  worker package is not something a board outside the meith monorepo can
1198
1198
  depend on yet. Deploy some other way and something still has to call that
1199
- route (or run \`community task:run\`) every minute, or nothing catches up
1199
+ route (or run \`meith task:run\`) every minute, or nothing catches up
1200
1200
  and nothing errors.
1201
1201
 
1202
1202
  ## Local
@@ -1214,8 +1214,8 @@ Posting needs Postgres. Copy \`.env.example\` to \`.env.local\`, set
1214
1214
  \`DATABASE_URL\` and the two secrets in it, then:
1215
1215
 
1216
1216
  \`\`\`sh
1217
- npm run community -- migrate
1218
- echo "<password>" | npm run community -- user:create --username <name> --email <address> --group administrators
1217
+ npm run meith -- migrate
1218
+ echo "<password>" | npm run meith -- user:create --username <name> --email <address> --group administrators
1219
1219
  \`\`\`
1220
1220
 
1221
1221
  ## Configuring
@@ -1226,9 +1226,51 @@ echo "<password>" | npm run community -- user:create --username <name> --email <
1226
1226
  - **\`/admin\`** \u2014 settings, forums, groups, members, themes, maintenance. An
1227
1227
  administrator re-enters their password to get in, and again for anything
1228
1228
  destructive.
1229
- - **\`npm run community -- --help\`** \u2014 the operator CLI. Everything the panel does
1229
+ - **\`npm run meith -- --help\`** \u2014 the operator CLI. Everything the panel does
1230
1230
  and a few things it cannot, without a browser.
1231
1231
 
1232
+ ## Installing plugins and themes
1233
+
1234
+ Nothing installs into a running container \u2014 a plugin or theme has to be
1235
+ built into the image, the same as any other dependency:
1236
+
1237
+ 1. **In this repository**, install it:
1238
+
1239
+ \`\`\`sh
1240
+ npm install --save-exact @meith/plugin-dues
1241
+ \`\`\`
1242
+
1243
+ (a theme is the same command with its own package, e.g.
1244
+ \`@meith/theme-midnight\`).
1245
+
1246
+ 2. **Register it.** A **theme** goes in \`meith.config.ts\`, in the \`themes\`
1247
+ map, following the shape of the \`default\` entry already there. A
1248
+ **plugin** goes in \`meith.plugins.ts\`: import its \`plugin\` and
1249
+ \`messages\` exports and add \`{ key, enabled: true, plugin, messages }\`
1250
+ to \`INSTALLED_PLUGINS\` \u2014 or run
1251
+
1252
+ \`\`\`sh
1253
+ npm run meith -- plugin:add @meith/plugin-dues
1254
+ \`\`\`
1255
+
1256
+ which edits \`board.plugins.json\` and regenerates \`meith.plugins.ts\`
1257
+ for you.
1258
+
1259
+ 3. **Commit and push**, then **Redeploy** from Coolify \u2014 pushing alone does
1260
+ not rebuild. Quick start builds the new image on that redeploy; advanced/prebuilt
1261
+ waits for \`.github/workflows/build.yml\` to finish first, and Redeploy is
1262
+ what actually pulls the result.
1263
+
1264
+ 4. **Once it is up, run its migrations one time:**
1265
+
1266
+ \`\`\`sh
1267
+ docker compose run --rm web meith upgrade
1268
+ \`\`\`
1269
+
1270
+ See [docs/customization/plugins.md](${repositoryUrl}/blob/main/docs/customization/plugins.md)
1271
+ and [docs/customization/themes.md](${repositoryUrl}/blob/main/docs/customization/themes.md)
1272
+ for the full reference.
1273
+
1232
1274
  ## Upgrading
1233
1275
 
1234
1276
  \`\`\`sh
@@ -1269,7 +1311,7 @@ project's own \`.npmrc\` sets \`save-exact=true\` for the same reason, so an
1269
1311
  \`npm install\` of anything else here \u2014 a plugin, say \u2014 stays pinned too; the
1270
1312
  build workflow also refuses to build from anything but an exact version, as
1271
1313
  a second line of defense. Once the rebuilt image is deployed, run
1272
- \`npm run community -- upgrade\` against it for the plugin migrations \u2014 see
1314
+ \`npm run meith -- upgrade\` against it for the plugin migrations \u2014 see
1273
1315
  [the operator CLI](${repositoryUrl}/blob/main/docs/guides/operations/operating.md#the-operator-cli)
1274
1316
  for running it against this deployment.
1275
1317
 
@@ -1512,9 +1554,9 @@ A board must stay movable, and the Blob store is the one part of this shape that
1512
1554
  is not portable: Neon and Upstash hand out ordinary Postgres and Redis strings
1513
1555
  that any host accepts, but a Vercel Blob store is reachable only through Vercel's
1514
1556
  own API and there is no bucket to sync out of it. **The uploads are the thing you
1515
- have to carry out deliberately, and \`community backup\` is how.**
1557
+ have to carry out deliberately, and \`meith backup\` is how.**
1516
1558
 
1517
- Under \`FILESTORE_DRIVER=blob\`, \`community backup\` includes the uploads **by
1559
+ Under \`FILESTORE_DRIVER=blob\`, \`meith backup\` includes the uploads **by
1518
1560
  default** \u2014 it walks the Blob store, pulls every object, and puts them in the
1519
1561
  bundle beside the database dump. This is the opposite of the \`s3\` default, which
1520
1562
  skips them, because a bucket has its own backup story you can drive yourself and
@@ -1525,7 +1567,7 @@ DATABASE_URL=\u2026 # Neon's pooled string
1525
1567
  DIRECT_DATABASE_URL=\u2026 # Neon's DATABASE_URL_UNPOOLED
1526
1568
  FILESTORE_DRIVER=blob
1527
1569
  BLOB_READ_WRITE_TOKEN=\u2026 # create one on the store; see below
1528
- npm run community -- backup
1570
+ npm run meith -- backup
1529
1571
  \`\`\`
1530
1572
 
1531
1573
  Run that from a checkout of this repository, with those four values in the
@@ -1546,10 +1588,10 @@ so the same bundle moves the board either onward or away:
1546
1588
 
1547
1589
  \`\`\`sh
1548
1590
  # onto a self-hosted board with a bucket
1549
- FILESTORE_DRIVER=s3 S3_BUCKET=\u2026 RESTORE_DATABASE_URL=\u2026 npm run community -- restore bundle.tar.gz
1591
+ FILESTORE_DRIVER=s3 S3_BUCKET=\u2026 RESTORE_DATABASE_URL=\u2026 npm run meith -- restore bundle.tar.gz
1550
1592
 
1551
1593
  # onto a board that keeps uploads on its own disk
1552
- RESTORE_DATABASE_URL=\u2026 npm run community -- restore bundle.tar.gz --uploads-dir ./uploads
1594
+ RESTORE_DATABASE_URL=\u2026 npm run meith -- restore bundle.tar.gz --uploads-dir ./uploads
1553
1595
  \`\`\`
1554
1596
 
1555
1597
  Take one before you need it. A Blob store deleted with the Vercel project takes
@@ -1893,7 +1935,7 @@ and add the matching entry to \`board.plugins.json\`:
1893
1935
  { "plugins": [{ "key": "${name}", "package": "${name}", "enabled": true }] }
1894
1936
 
1895
1937
  Rebuild the board (\`npm run build\`) and, because this plugin ships a
1896
- migration, run \`npx community migrate\`. The plugin then appears under
1938
+ migration, run \`npx meith migrate\`. The plugin then appears under
1897
1939
  **Admin \u2192 Plugins**.
1898
1940
 
1899
1941
  ## Publish and list it
@@ -2152,7 +2194,7 @@ async function run(argv, version) {
2152
2194
  ...kind === null ? [
2153
2195
  "Then set DATABASE_URL, AUTH_SECRET and TICK_SECRET and deploy.",
2154
2196
  "Something must run the tick every minute \u2014 the worker process, or",
2155
- "`community task:run`. Without it nothing catches up, and nothing errors."
2197
+ "`meith task:run`. Without it nothing catches up, and nothing errors."
2156
2198
  ] : [
2157
2199
  `Then follow README.md \u2014 it walks through running the ${kind} inside a`,
2158
2200
  "scaffolded board and submitting it to the meith.dev marketplace."
@@ -2162,7 +2204,7 @@ async function run(argv, version) {
2162
2204
  }
2163
2205
 
2164
2206
  // src/bin.ts
2165
- var result = await run(process.argv.slice(2), "0.26.1");
2207
+ var result = await run(process.argv.slice(2), "0.27.0");
2166
2208
  for (const line of result.lines) {
2167
2209
  if (result.code === 0) console.log(line);
2168
2210
  else console.error(line);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-meith",
3
- "version": "0.26.1",
3
+ "version": "0.27.0",
4
4
  "description": "Scaffold a Meith board, plugin or theme — npx create-meith <name> writes a deployable board workspace; --plugin and --theme write extension workspaces built on the published kits.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/bin.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { run } from './cli'
3
3
 
4
- const result = await run(process.argv.slice(2), '0.26.1')
4
+ const result = await run(process.argv.slice(2), '0.27.0')
5
5
  for (const line of result.lines) {
6
6
  if (result.code === 0) console.log(line)
7
7
  else console.error(line)
package/src/cli.ts CHANGED
@@ -145,7 +145,7 @@ export async function run(argv: readonly string[], version: string): Promise<Cli
145
145
  ? [
146
146
  'Then set DATABASE_URL, AUTH_SECRET and TICK_SECRET and deploy.',
147
147
  'Something must run the tick every minute — the worker process, or',
148
- '`community task:run`. Without it nothing catches up, and nothing errors.',
148
+ '`meith task:run`. Without it nothing catches up, and nothing errors.',
149
149
  ]
150
150
  : [
151
151
  `Then follow README.md — it walks through running the ${kind} inside a`,
@@ -206,7 +206,7 @@ and add the matching entry to \`board.plugins.json\`:
206
206
  { "plugins": [{ "key": "${name}", "package": "${name}", "enabled": true }] }
207
207
 
208
208
  Rebuild the board (\`npm run build\`) and, because this plugin ships a
209
- migration, run \`npx community migrate\`. The plugin then appears under
209
+ migration, run \`npx meith migrate\`. The plugin then appears under
210
210
  **Admin → Plugins**.
211
211
 
212
212
  ## Publish and list it
package/src/scaffold.ts CHANGED
@@ -29,7 +29,7 @@ export const MATERIALIZED_AT_ROOT = [
29
29
  'next-env.d.ts',
30
30
  ]
31
31
 
32
- export const VERCEL_BUILD_COMMAND = `community migrate && forum-web build ${AT_ROOT_FLAG}`
32
+ export const VERCEL_BUILD_COMMAND = `meith migrate && forum-web build ${AT_ROOT_FLAG}`
33
33
 
34
34
  export const TICK_PATH = '/api/system/tick'
35
35
 
@@ -103,7 +103,7 @@ const ENV_DATABASE_URL_PROSE = `# Your Postgres connection string.
103
103
  # processes in front of it, does not need one.`
104
104
 
105
105
  const ENV_DIRECT_DATABASE_URL_PROSE = `# The other half of that pair: the DIRECT (non-pooler) string, used only by
106
- # \`community migrate\` and \`community backup\`. Migrations hold a session-level
106
+ # \`meith migrate\` and \`meith backup\`. Migrations hold a session-level
107
107
  # advisory lock so that two deploys landing together queue instead of both
108
108
  # applying the same migration, and a transaction-mode pooler cannot hold that
109
109
  # lock: it takes the connection back the moment the lock statement ends, which
@@ -238,7 +238,7 @@ DATABASE_URL=
238
238
  ${ENV_DIRECT_DATABASE_URL_PROSE}
239
239
  #
240
240
  # On Vercel this is not optional, and it is no longer yours to copy. DATABASE_URL
241
- # here is the pooler string, the build runs \`community migrate\` against it, and
241
+ # here is the pooler string, the build runs \`meith migrate\` against it, and
242
242
  # /install takes the second of those two session locks on first run. Left blank,
243
243
  # the board reads Neon's own direct string — \`DATABASE_URL_UNPOOLED\` first, then
244
244
  # \`POSTGRES_URL_NON_POOLING\` — and refuses to boot if neither is there, naming
@@ -275,7 +275,7 @@ CRON_SECRET=
275
275
  #
276
276
  # BLOB_READ_WRITE_TOKEN is the other way in, and you make it yourself on the
277
277
  # store. Set it when something has to reach the store from OUTSIDE a Vercel
278
- # deployment — \`community backup\` run on your own machine is the case that
278
+ # deployment — \`meith backup\` run on your own machine is the case that
279
279
  # matters — because there is no OIDC identity there to borrow. Set both and the
280
280
  # board prefers the store id, unless the token names a different store, in which
281
281
  # case the token wins: naming another store is a deliberate act.
@@ -435,7 +435,7 @@ export function scaffold(options: ScaffoldOptions): ReadonlyMap<string, string>
435
435
  dev: `forum-web dev${atRootFlag}`,
436
436
  build: `forum-web build${atRootFlag}`,
437
437
  start: `forum-web start${atRootFlag}`,
438
- community: 'community',
438
+ meith: 'meith',
439
439
  },
440
440
  dependencies: {
441
441
  '@meith/web': version,
@@ -525,7 +525,7 @@ export default defineForumConfig({
525
525
  * ]
526
526
  *
527
527
  * and the matching entry in board.plugins.json, which is what
528
- * \`community plugin:add\`/\`plugin:remove\` read inside the monorepo — kept
528
+ * \`meith plugin:add\`/\`plugin:remove\` read inside the monorepo — kept
529
529
  * here too so the two files agree about what is installed.
530
530
  */
531
531
  import type { InstalledPlugin } from '@meith/web/config'
@@ -592,8 +592,8 @@ updates:
592
592
  # "Custom boards").
593
593
  #
594
594
  # Two stages, not three: unlike the official image, this does not prune down
595
- # to Next's own standalone output. The migrate role below runs \`community
596
- # migrate\`, and \`community\` materializes @meith/cli's sources and runs them
595
+ # to Next's own standalone output. The migrate role below runs \`meith
596
+ # migrate\`, and \`meith\` materializes @meith/cli's sources and runs them
597
597
  # with tsx at the moment it runs (see the meith repository's
598
598
  # docs/contributing/development.md, "Consuming the board from a workspace") — it needs
599
599
  # the full, un-pruned node_modules tree this board installed, not what Next
@@ -669,8 +669,8 @@ ENTRYPOINT ["./docker-entrypoint.sh"]
669
669
  # of minutes rather than a cold toolchain build.
670
670
  #
671
671
  # Two stages, not three: unlike the official image, this does not prune down
672
- # to Next's own standalone output. The migrate role below runs \`community
673
- # migrate\`, and \`community\` materializes @meith/cli's sources and runs them
672
+ # to Next's own standalone output. The migrate role below runs \`meith
673
+ # migrate\`, and \`meith\` materializes @meith/cli's sources and runs them
674
674
  # with tsx at the moment it runs (see the meith repository's
675
675
  # docs/contributing/development.md, "Consuming the board from a workspace") — it needs
676
676
  # the full, un-pruned node_modules tree this board installed, not what Next
@@ -741,22 +741,22 @@ ENTRYPOINT ["./docker-entrypoint.sh"]
741
741
  set -e
742
742
 
743
743
  # An explicit command wins over the role, the same as the official image —
744
- # \`docker run <image> node_modules/.bin/community --help\` should still run
744
+ # \`docker run <image> node_modules/.bin/meith --help\` should still run
745
745
  # the CLI rather than silently starting the web server.
746
746
  if [ "$#" -gt 0 ]; then
747
747
  exec "$@"
748
748
  fi
749
749
 
750
- case "\${COMMUNITY_ROLE:-web}" in
750
+ case "\${MEITH_ROLE:-web}" in
751
751
  migrate)
752
752
  # Runs to completion and exits; compose's one-shot service waits on it.
753
- exec node_modules/.bin/community migrate
753
+ exec node_modules/.bin/meith migrate
754
754
  ;;
755
755
  web)
756
756
  exec node_modules/.bin/forum-web start
757
757
  ;;
758
758
  *)
759
- echo "Unknown COMMUNITY_ROLE: \${COMMUNITY_ROLE}. Expected 'web' or 'migrate'." >&2
759
+ echo "Unknown MEITH_ROLE: \${MEITH_ROLE}. Expected 'web' or 'migrate'." >&2
760
760
  exit 1
761
761
  ;;
762
762
  esac
@@ -771,7 +771,7 @@ esac
771
771
  # a health probe taken while it runs has no opinion.
772
772
  set -e
773
773
 
774
- if [ "\${COMMUNITY_ROLE:-web}" = "migrate" ]; then
774
+ if [ "\${MEITH_ROLE:-web}" = "migrate" ]; then
775
775
  exit 0
776
776
  fi
777
777
 
@@ -911,7 +911,7 @@ services:
911
911
  build: .
912
912
  image: ${name}
913
913
  environment:
914
- COMMUNITY_ROLE: migrate
914
+ MEITH_ROLE: migrate
915
915
  DATABASE_URL: postgres://community:$SERVICE_PASSWORD_POSTGRES@postgres:5432/community
916
916
  AUTH_SECRET: $SERVICE_BASE64_64_AUTH
917
917
  TICK_SECRET: $SERVICE_BASE64_64_TICK
@@ -1044,7 +1044,7 @@ services:
1044
1044
  # runs the old code.
1045
1045
  pull_policy: always
1046
1046
  environment:
1047
- COMMUNITY_ROLE: migrate
1047
+ MEITH_ROLE: migrate
1048
1048
  DATABASE_URL: postgres://community:$SERVICE_PASSWORD_POSTGRES@postgres:5432/community
1049
1049
  AUTH_SECRET: $SERVICE_BASE64_64_AUTH
1050
1050
  TICK_SECRET: $SERVICE_BASE64_64_TICK
@@ -1244,7 +1244,7 @@ Two things nothing configures for you, on either path:
1244
1244
  loop calling \`/api/system/tick\` once a minute, since \`@meith/web\`'s own
1245
1245
  worker package is not something a board outside the meith monorepo can
1246
1246
  depend on yet. Deploy some other way and something still has to call that
1247
- route (or run \`community task:run\`) every minute, or nothing catches up
1247
+ route (or run \`meith task:run\`) every minute, or nothing catches up
1248
1248
  and nothing errors.
1249
1249
 
1250
1250
  ## Local
@@ -1262,8 +1262,8 @@ Posting needs Postgres. Copy \`.env.example\` to \`.env.local\`, set
1262
1262
  \`DATABASE_URL\` and the two secrets in it, then:
1263
1263
 
1264
1264
  \`\`\`sh
1265
- npm run community -- migrate
1266
- echo "<password>" | npm run community -- user:create --username <name> --email <address> --group administrators
1265
+ npm run meith -- migrate
1266
+ echo "<password>" | npm run meith -- user:create --username <name> --email <address> --group administrators
1267
1267
  \`\`\`
1268
1268
 
1269
1269
  ## Configuring
@@ -1274,9 +1274,51 @@ echo "<password>" | npm run community -- user:create --username <name> --email <
1274
1274
  - **\`/admin\`** — settings, forums, groups, members, themes, maintenance. An
1275
1275
  administrator re-enters their password to get in, and again for anything
1276
1276
  destructive.
1277
- - **\`npm run community -- --help\`** — the operator CLI. Everything the panel does
1277
+ - **\`npm run meith -- --help\`** — the operator CLI. Everything the panel does
1278
1278
  and a few things it cannot, without a browser.
1279
1279
 
1280
+ ## Installing plugins and themes
1281
+
1282
+ Nothing installs into a running container — a plugin or theme has to be
1283
+ built into the image, the same as any other dependency:
1284
+
1285
+ 1. **In this repository**, install it:
1286
+
1287
+ \`\`\`sh
1288
+ npm install --save-exact @meith/plugin-dues
1289
+ \`\`\`
1290
+
1291
+ (a theme is the same command with its own package, e.g.
1292
+ \`@meith/theme-midnight\`).
1293
+
1294
+ 2. **Register it.** A **theme** goes in \`meith.config.ts\`, in the \`themes\`
1295
+ map, following the shape of the \`default\` entry already there. A
1296
+ **plugin** goes in \`meith.plugins.ts\`: import its \`plugin\` and
1297
+ \`messages\` exports and add \`{ key, enabled: true, plugin, messages }\`
1298
+ to \`INSTALLED_PLUGINS\` — or run
1299
+
1300
+ \`\`\`sh
1301
+ npm run meith -- plugin:add @meith/plugin-dues
1302
+ \`\`\`
1303
+
1304
+ which edits \`board.plugins.json\` and regenerates \`meith.plugins.ts\`
1305
+ for you.
1306
+
1307
+ 3. **Commit and push**, then **Redeploy** from Coolify — pushing alone does
1308
+ not rebuild. Quick start builds the new image on that redeploy; advanced/prebuilt
1309
+ waits for \`.github/workflows/build.yml\` to finish first, and Redeploy is
1310
+ what actually pulls the result.
1311
+
1312
+ 4. **Once it is up, run its migrations one time:**
1313
+
1314
+ \`\`\`sh
1315
+ docker compose run --rm web meith upgrade
1316
+ \`\`\`
1317
+
1318
+ See [docs/customization/plugins.md](${repositoryUrl}/blob/main/docs/customization/plugins.md)
1319
+ and [docs/customization/themes.md](${repositoryUrl}/blob/main/docs/customization/themes.md)
1320
+ for the full reference.
1321
+
1280
1322
  ## Upgrading
1281
1323
 
1282
1324
  \`\`\`sh
@@ -1317,7 +1359,7 @@ project's own \`.npmrc\` sets \`save-exact=true\` for the same reason, so an
1317
1359
  \`npm install\` of anything else here — a plugin, say — stays pinned too; the
1318
1360
  build workflow also refuses to build from anything but an exact version, as
1319
1361
  a second line of defense. Once the rebuilt image is deployed, run
1320
- \`npm run community -- upgrade\` against it for the plugin migrations — see
1362
+ \`npm run meith -- upgrade\` against it for the plugin migrations — see
1321
1363
  [the operator CLI](${repositoryUrl}/blob/main/docs/guides/operations/operating.md#the-operator-cli)
1322
1364
  for running it against this deployment.
1323
1365
 
@@ -1577,9 +1619,9 @@ A board must stay movable, and the Blob store is the one part of this shape that
1577
1619
  is not portable: Neon and Upstash hand out ordinary Postgres and Redis strings
1578
1620
  that any host accepts, but a Vercel Blob store is reachable only through Vercel's
1579
1621
  own API and there is no bucket to sync out of it. **The uploads are the thing you
1580
- have to carry out deliberately, and \`community backup\` is how.**
1622
+ have to carry out deliberately, and \`meith backup\` is how.**
1581
1623
 
1582
- Under \`FILESTORE_DRIVER=blob\`, \`community backup\` includes the uploads **by
1624
+ Under \`FILESTORE_DRIVER=blob\`, \`meith backup\` includes the uploads **by
1583
1625
  default** — it walks the Blob store, pulls every object, and puts them in the
1584
1626
  bundle beside the database dump. This is the opposite of the \`s3\` default, which
1585
1627
  skips them, because a bucket has its own backup story you can drive yourself and
@@ -1590,7 +1632,7 @@ DATABASE_URL=… # Neon's pooled string
1590
1632
  DIRECT_DATABASE_URL=… # Neon's DATABASE_URL_UNPOOLED
1591
1633
  FILESTORE_DRIVER=blob
1592
1634
  BLOB_READ_WRITE_TOKEN=… # create one on the store; see below
1593
- npm run community -- backup
1635
+ npm run meith -- backup
1594
1636
  \`\`\`
1595
1637
 
1596
1638
  Run that from a checkout of this repository, with those four values in the
@@ -1611,10 +1653,10 @@ so the same bundle moves the board either onward or away:
1611
1653
 
1612
1654
  \`\`\`sh
1613
1655
  # onto a self-hosted board with a bucket
1614
- FILESTORE_DRIVER=s3 S3_BUCKET=… RESTORE_DATABASE_URL=… npm run community -- restore bundle.tar.gz
1656
+ FILESTORE_DRIVER=s3 S3_BUCKET=… RESTORE_DATABASE_URL=… npm run meith -- restore bundle.tar.gz
1615
1657
 
1616
1658
  # onto a board that keeps uploads on its own disk
1617
- RESTORE_DATABASE_URL=… npm run community -- restore bundle.tar.gz --uploads-dir ./uploads
1659
+ RESTORE_DATABASE_URL=… npm run meith -- restore bundle.tar.gz --uploads-dir ./uploads
1618
1660
  \`\`\`
1619
1661
 
1620
1662
  Take one before you need it. A Blob store deleted with the Vercel project takes