modern-cms 1.1.3 → 1.1.4
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 +23 -1
- package/bin/modern-cms.js +7 -1
- package/package.json +1 -1
- package/template/README.md +64 -9
- package/template/apps/api/package.json +2 -1
- package/template/apps/api/prisma/reset-admin.ts +11 -3
- package/template/gitignore +9 -0
- package/template/package.json +2 -1
- package/template/tsconfig.base.json +15 -0
package/README.md
CHANGED
|
@@ -25,11 +25,29 @@ A self-hosted, drag-and-drop website CMS: a Next.js (App Router) front end, an E
|
|
|
25
25
|
|
|
26
26
|
## Installation
|
|
27
27
|
|
|
28
|
+
**npx (no install — always runs the latest version):**
|
|
29
|
+
|
|
28
30
|
```bash
|
|
29
31
|
npx modern-cms
|
|
30
32
|
```
|
|
31
33
|
|
|
32
|
-
(
|
|
34
|
+
**npm (global install):**
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install -g modern-cms
|
|
38
|
+
modern-cms
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**yarn:**
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Yarn Classic (v1)
|
|
45
|
+
yarn global add modern-cms
|
|
46
|
+
modern-cms
|
|
47
|
+
|
|
48
|
+
# Yarn Berry (v2+)
|
|
49
|
+
yarn dlx modern-cms
|
|
50
|
+
```
|
|
33
51
|
|
|
34
52
|
### What the installer asks
|
|
35
53
|
|
|
@@ -66,6 +84,10 @@ npm run dev
|
|
|
66
84
|
|
|
67
85
|
Then open the web app at the URL you chose (default `http://localhost:3000`) and log in at `/admin` with the admin email/password from the wizard.
|
|
68
86
|
|
|
87
|
+
> **Prefer yarn for the scaffolded project too?** `yarn install` works fine, and `dev`/`db:migrate`/`db:seed` all run correctly (they use `tsx`, which doesn't type-check). The one caveat: yarn's dependency hoisting can occasionally produce a duplicate `@types/express`, which shows up as spurious TypeScript errors only if you run `npm run build` or `tsc` directly — running `npm install` once resolves it.
|
|
88
|
+
>
|
|
89
|
+
> **Logged in with the wrong password?** The admin user is only created the *first* time `db:seed` runs — editing `.env` afterward doesn't retroactively change it. Run `npm run db:reset-admin && npm run db:seed` to delete and recreate it from the current `.env` values.
|
|
90
|
+
|
|
69
91
|
## Project layout
|
|
70
92
|
|
|
71
93
|
The scaffolded project is an npm-workspaces monorepo:
|
package/bin/modern-cms.js
CHANGED
|
@@ -18,11 +18,17 @@ import {
|
|
|
18
18
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
19
19
|
const TEMPLATE_DIR = path.join(__dirname, "..", "template");
|
|
20
20
|
|
|
21
|
+
// npm's packlist strips any file literally named ".gitignore" out of the published
|
|
22
|
+
// tarball, so the template ships it as "gitignore" — restore the leading dot on scaffold.
|
|
23
|
+
function destName(name) {
|
|
24
|
+
return name === "gitignore" ? ".gitignore" : name;
|
|
25
|
+
}
|
|
26
|
+
|
|
21
27
|
function copyDir(src, dest) {
|
|
22
28
|
fs.mkdirSync(dest, { recursive: true });
|
|
23
29
|
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
24
30
|
const srcPath = path.join(src, entry.name);
|
|
25
|
-
const destPath = path.join(dest, entry.name);
|
|
31
|
+
const destPath = path.join(dest, destName(entry.name));
|
|
26
32
|
if (entry.isDirectory()) copyDir(srcPath, destPath);
|
|
27
33
|
else fs.copyFileSync(srcPath, destPath);
|
|
28
34
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modern-cms",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "Self-hosted, drag-and-drop website CMS (Next.js + Express + Prisma). Interactive installer scaffolds a full project with your choice of PostgreSQL/MySQL and AWS S3/Azure Blob/Cloudinary storage.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/template/README.md
CHANGED
|
@@ -12,14 +12,68 @@ Built as an npm-workspaces monorepo:
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Installation
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
There are two ways to get a working project: install the published `modern-cms` package (fastest — an interactive wizard scaffolds everything and writes your `.env` files), or clone this repository directly (for contributing to pg-cms itself). Most people want the first one.
|
|
18
|
+
|
|
19
|
+
### Option A — Install the `modern-cms` package (recommended)
|
|
20
|
+
|
|
21
|
+
Works with npx, npm, or yarn — pick whichever you already use.
|
|
22
|
+
|
|
23
|
+
**npx (no install — always runs the latest version):**
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx modern-cms
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**npm (global install, then run anytime with just `modern-cms`):**
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g modern-cms
|
|
33
|
+
modern-cms
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**yarn:**
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Yarn Classic (v1)
|
|
40
|
+
yarn global add modern-cms
|
|
41
|
+
modern-cms
|
|
42
|
+
|
|
43
|
+
# Yarn Berry (v2+) — no global install needed
|
|
44
|
+
yarn dlx modern-cms
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The wizard asks for your database (PostgreSQL or MySQL, with host/port/name/username/password), the web app port and API port, your file storage provider (AWS S3, Azure Blob Storage, or Cloudinary, with that provider's credentials), and an admin email/password — then scaffolds a full project and writes working `.env` files. It never runs `npm install`, touches your database, or starts anything by itself; it prints the exact next commands.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
cd <your-project-dir>
|
|
51
|
+
|
|
52
|
+
# npm (recommended — see the yarn note below):
|
|
53
|
+
npm install
|
|
54
|
+
npm run db:migrate # PostgreSQL
|
|
55
|
+
# MySQL installs use schema-push instead, since the bundled migration
|
|
56
|
+
# history is Postgres-specific SQL:
|
|
57
|
+
# npx prisma generate --schema apps/api/prisma/schema.prisma
|
|
58
|
+
# npx prisma db push --schema apps/api/prisma/schema.prisma
|
|
59
|
+
npm run db:seed
|
|
60
|
+
npm run dev
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
> **Using yarn to install the scaffolded project itself?** `yarn install` works fine, and `npm run dev` / `db:migrate` / `db:seed` all run correctly under a yarn-installed `node_modules` (they invoke `tsx`, which doesn't type-check). The one thing to watch for: yarn's dependency hoisting can occasionally produce a duplicate `@types/express` in the tree, which shows up as spurious TypeScript errors *only* if you run `npm run build` or `tsc` directly. If that happens, running `npm install` once (even alongside your yarn workflow) resolves it — that's yarn's hoisting, not a bug in the project.
|
|
64
|
+
|
|
65
|
+
See [`packages/modern-cms/README.md`](packages/modern-cms/README.md) for the full prompt-by-prompt reference and configuration details.
|
|
66
|
+
|
|
67
|
+
### Option B — Clone this repository
|
|
68
|
+
|
|
69
|
+
For working on pg-cms itself, not for building a site with it.
|
|
70
|
+
|
|
71
|
+
#### Prerequisites
|
|
18
72
|
|
|
19
73
|
- Node.js 18+
|
|
20
74
|
- Docker Desktop (for PostgreSQL + MinIO)
|
|
21
75
|
|
|
22
|
-
|
|
76
|
+
#### 1. Start the databases
|
|
23
77
|
|
|
24
78
|
```bash
|
|
25
79
|
npm run docker:up
|
|
@@ -37,7 +91,7 @@ A one-shot init container creates the `pgcms-media` bucket automatically.
|
|
|
37
91
|
|
|
38
92
|
> **Port conflicts:** if `docker compose up` fails with "port is already allocated", another container or service owns that port — run `docker ps` to find it, then either stop it or change the host-side port in `docker-compose.yml` **and** the matching URLs in `apps/api/.env`.
|
|
39
93
|
|
|
40
|
-
|
|
94
|
+
#### 2. Environment files
|
|
41
95
|
|
|
42
96
|
Two env files are used:
|
|
43
97
|
|
|
@@ -53,7 +107,7 @@ cp .env.example apps/api/.env # then trim to the API-relevant keys, or keep al
|
|
|
53
107
|
|
|
54
108
|
**Important:** the password inside `DATABASE_URL` in `apps/api/.env` must match `POSTGRES_PASSWORD` in the root `.env`. Postgres sets its password the *first* time its data volume is created — changing `.env` later does not change the database password.
|
|
55
109
|
|
|
56
|
-
|
|
110
|
+
#### 3. Install, migrate, seed
|
|
57
111
|
|
|
58
112
|
```bash
|
|
59
113
|
npm install
|
|
@@ -69,7 +123,7 @@ npx tsx prisma/seed-homepage.ts
|
|
|
69
123
|
npx tsx prisma/seed-our-charities.ts
|
|
70
124
|
```
|
|
71
125
|
|
|
72
|
-
|
|
126
|
+
#### 4. Run the dev servers
|
|
73
127
|
|
|
74
128
|
```bash
|
|
75
129
|
npm run dev # API (port 4000) + web (port 3000) together
|
|
@@ -78,7 +132,7 @@ npm run dev:api
|
|
|
78
132
|
npm run dev:web
|
|
79
133
|
```
|
|
80
134
|
|
|
81
|
-
|
|
135
|
+
#### 5. Log in
|
|
82
136
|
|
|
83
137
|
| URL | What |
|
|
84
138
|
|---|---|
|
|
@@ -161,6 +215,7 @@ Six scene presets usable in the Hero or the dedicated 3D Background component: *
|
|
|
161
215
|
| `npm run docker:up` / `npm run docker:down` | Start / stop Postgres + MinIO |
|
|
162
216
|
| `npm run db:migrate` | Apply Prisma migrations (`prisma migrate dev`) |
|
|
163
217
|
| `npm run db:seed` | Seed admin user, theme, sample page |
|
|
218
|
+
| `npm run db:reset-admin` | Delete the admin user matching `SEED_ADMIN_EMAIL` so the next `db:seed` recreates it (e.g. after changing the seed password) |
|
|
164
219
|
|
|
165
220
|
---
|
|
166
221
|
|
|
@@ -202,9 +257,9 @@ No builder-chrome changes needed — the palette, inspector, and drag-and-drop p
|
|
|
202
257
|
|
|
203
258
|
**`port is already allocated` from Docker** — another container owns the host port. `docker ps`, then stop it or change the port mapping in `docker-compose.yml` + the URLs in `apps/api/.env`.
|
|
204
259
|
|
|
205
|
-
**"Invalid email or password"** — credentials are case-sensitive; watch for browser autofill inserting a stale saved password. The current values live in `apps/api/.env`.
|
|
260
|
+
**"Invalid email or password"** — credentials are case-sensitive; watch for browser autofill inserting a stale saved password. The current values live in `apps/api/.env` (`SEED_ADMIN_EMAIL` / `SEED_ADMIN_PASSWORD`, used only the *first* time `db:seed` creates that user — editing `.env` afterward doesn't change an already-created password). If you scaffolded the project with `modern-cms` before v1.1.3 and your password contains `#`, it was silently truncated by `dotenv`'s comment parsing (fixed in 1.1.3 — update and rescaffold, or run `npm run db:reset-admin && npm run db:seed` to delete and recreate the existing admin user from the current `.env` values, without rescaffolding).
|
|
206
261
|
|
|
207
262
|
**Prisma `EPERM ... query_engine ... .dll.node` on Windows** — the running API dev server is holding the engine file. Stop it (`netstat -ano | findstr :4000`, then kill that PID), run the migration, restart.
|
|
208
263
|
|
|
209
264
|
**Dev server "running" but serving stale code** — an orphaned process may still own the port. Verify with `netstat -ano | findstr :3000` (or `:4000`) and kill the listed PID before restarting.
|
|
210
|
-
|
|
265
|
+
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"db:generate": "prisma generate",
|
|
12
12
|
"db:seed": "tsx prisma/seed.ts",
|
|
13
13
|
"db:seed:demo-charities": "tsx prisma/seed-our-charities.ts",
|
|
14
|
-
"db:seed:templates": "tsx prisma/seed-templates.ts"
|
|
14
|
+
"db:seed:templates": "tsx prisma/seed-templates.ts",
|
|
15
|
+
"db:reset-admin": "tsx prisma/reset-admin.ts"
|
|
15
16
|
},
|
|
16
17
|
"dependencies": {
|
|
17
18
|
"@aws-sdk/client-s3": "^3.665.0",
|
|
@@ -3,10 +3,18 @@ import { PrismaClient } from "@prisma/client";
|
|
|
3
3
|
|
|
4
4
|
const prisma = new PrismaClient();
|
|
5
5
|
|
|
6
|
+
// Matches whatever seed.ts actually used to create the user — a hardcoded fallback
|
|
7
|
+
// here would silently no-op for anyone who set a custom SEED_ADMIN_EMAIL (which the
|
|
8
|
+
// modern-cms installer always prompts for).
|
|
6
9
|
async function main() {
|
|
7
|
-
const email = "admin@example.com";
|
|
8
|
-
await prisma.user.deleteMany({ where: { email } });
|
|
9
|
-
|
|
10
|
+
const email = process.env.SEED_ADMIN_EMAIL ?? "admin@example.com";
|
|
11
|
+
const { count } = await prisma.user.deleteMany({ where: { email } });
|
|
12
|
+
if (count === 0) {
|
|
13
|
+
console.log(`No user found for ${email} — nothing to delete.`);
|
|
14
|
+
} else {
|
|
15
|
+
console.log(`Deleted existing admin user: ${email}`);
|
|
16
|
+
}
|
|
17
|
+
console.log('Run "npm run db:seed" (from the repo root) to recreate it with the current SEED_ADMIN_EMAIL/SEED_ADMIN_PASSWORD in .env.');
|
|
10
18
|
}
|
|
11
19
|
|
|
12
20
|
main()
|
package/template/package.json
CHANGED
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"docker:up": "docker compose up -d",
|
|
19
19
|
"docker:down": "docker compose down",
|
|
20
20
|
"db:migrate": "npm run db:migrate -w apps/api",
|
|
21
|
-
"db:seed": "npm run db:seed -w apps/api"
|
|
21
|
+
"db:seed": "npm run db:seed -w apps/api",
|
|
22
|
+
"db:reset-admin": "npm run db:reset-admin -w apps/api"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@types/react": "^19.2.17",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": ["ES2022"],
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "Bundler",
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"isolatedModules": true,
|
|
13
|
+
"declaration": false
|
|
14
|
+
}
|
|
15
|
+
}
|