create-vexcms 0.0.3 → 0.0.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.
Files changed (3) hide show
  1. package/README.md +161 -0
  2. package/dist/index.js +39 -7
  3. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,161 @@
1
+ # create-vexcms
2
+
3
+ Scaffolding CLI for [VEX CMS](https://github.com/ianyimi/vex) projects. Creates a complete Next.js application with Convex backend, Better Auth authentication, and an admin panel — ready to run.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ pnpm create vexcms@latest
9
+ ```
10
+
11
+ Or with a project name:
12
+
13
+ ```bash
14
+ pnpm create vexcms@latest my-project
15
+ ```
16
+
17
+ Supports relative paths:
18
+
19
+ ```bash
20
+ pnpm create vexcms@latest apps/website
21
+ ```
22
+
23
+ ## Flags
24
+
25
+ | Flag | Description |
26
+ |------|-------------|
27
+ | `--bare` | Skip the marketing site template. Scaffolds an empty VEX CMS project with no collections. |
28
+ | `--orgs` | Enable multi-tenant organizations (adds Better Auth organizations plugin). |
29
+
30
+ ```bash
31
+ # Empty project with no pre-built collections
32
+ pnpm create vexcms@latest my-app --bare
33
+
34
+ # Project with organizations support
35
+ pnpm create vexcms@latest my-app --orgs
36
+ ```
37
+
38
+ ## Interactive Prompts
39
+
40
+ The CLI walks you through:
41
+
42
+ 1. **Project name** — validates npm package name rules, supports `.` for current directory
43
+ 2. **Framework** — Next.js (recommended) or TanStack Start (coming soon)
44
+ 3. **Email/password auth** — enable or disable (default: yes)
45
+ 4. **OAuth providers** — multi-select from 30+ Better Auth providers (Google, GitHub, Discord, etc.)
46
+ 5. **Organizations** — enable multi-tenant support (default: no, skipped if `--orgs` passed)
47
+ 6. **Git repository** — initialize git (default: yes)
48
+ 7. **Install dependencies** — run package install (default: no)
49
+
50
+ ## Templates
51
+
52
+ ### Marketing Site (default)
53
+
54
+ Pre-built collections for a marketing website:
55
+
56
+ - **Pages** — with title, slug, richtext content, draft/publish versioning, and live preview
57
+ - **Headers** — name, logo upload, sticky option
58
+ - **Footers** — name, richtext content, copyright text
59
+ - **Themes** — name, colors, font family
60
+ - **Site Settings** — site name, description, favicon upload
61
+
62
+ Also includes:
63
+
64
+ - Landing page with sign-in/sign-up flow
65
+ - First-user auto-admin promotion
66
+ - Admin panel onboarding tour (driver.js)
67
+ - Preview routes at `/preview/[slug]` with live preview support
68
+ - Public page routes at `/[slug]` (published pages only)
69
+ - Draft-aware queries using `vexQuery`
70
+
71
+ ### Bare (`--bare`)
72
+
73
+ Empty VEX CMS project with:
74
+
75
+ - Authentication setup (Better Auth + Convex adapter)
76
+ - Admin panel wired at `/admin`
77
+ - Empty `collections: []` in `vex.config.ts`
78
+ - No onboarding tour
79
+
80
+ ## Getting Started
81
+
82
+ After scaffolding your project:
83
+
84
+ ### 1. Install dependencies
85
+
86
+ ```bash
87
+ cd my-project
88
+ pnpm install
89
+ ```
90
+
91
+ ### 2. Generate a Better Auth secret
92
+
93
+ ```bash
94
+ pnpm secret:create
95
+ ```
96
+
97
+ This generates a random 32-character string and copies it to your clipboard.
98
+
99
+ ### 3. Configure environment variables
100
+
101
+ The CLI creates a `.env.local` file with `NEXT_PUBLIC_SITE_URL` set to your chosen port. Add the auth secret:
102
+
103
+ ```env
104
+ # .env.local (auto-generated)
105
+ NEXT_PUBLIC_SITE_URL=http://localhost:3010
106
+
107
+ # Add manually:
108
+ BETTER_AUTH_SECRET=your-generated-secret-here
109
+ ```
110
+
111
+ ### 4. Start VEX dev server
112
+
113
+ ```bash
114
+ pnpm vex:dev
115
+ ```
116
+
117
+ This starts the VEX CLI watcher (generates schema, types, and queries) and the Convex dev server. On first run, it will prompt you to create or select a Convex project.
118
+
119
+ ### 5. Add environment variables to Convex
120
+
121
+ In the [Convex Dashboard](https://dashboard.convex.dev), navigate to your project's **Settings > Environment Variables** and add:
122
+
123
+ - `BETTER_AUTH_SECRET` — the same secret from step 2
124
+ - `SITE_URL` — `http://localhost:3010` (or your chosen port)
125
+
126
+ ### 6. Start the Next.js dev server
127
+
128
+ In a separate terminal:
129
+
130
+ ```bash
131
+ pnpm dev
132
+ ```
133
+
134
+ ### 7. Create your admin account
135
+
136
+ Open `http://localhost:3010` in your browser. Click **"Create Admin Account"** to sign up. The first user is automatically promoted to admin and redirected to the admin panel.
137
+
138
+ ### Available Scripts
139
+
140
+ | Script | Description |
141
+ |--------|-------------|
142
+ | `pnpm dev` | Start Next.js development server |
143
+ | `pnpm vex:dev` | Start VEX CLI watcher + Convex dev server |
144
+ | `pnpm vex:generate` | One-shot schema/type/query generation |
145
+ | `pnpm vex:update` | Update all `@vexcms/*` packages to latest |
146
+ | `pnpm secret:create` | Generate a random 32-character secret and copy to clipboard |
147
+ | `pnpm build` | Production build |
148
+
149
+ ## Versioning
150
+
151
+ `create-vexcms` is versioned alongside all `@vexcms/*` packages. Running `pnpm create vexcms@latest` always scaffolds with the latest package versions. You can also pin a specific version:
152
+
153
+ ```bash
154
+ pnpm create vexcms@0.0.3
155
+ ```
156
+
157
+ The scaffolded project's `@vexcms/*` dependencies match the version of `create-vexcms` used.
158
+
159
+ ## License
160
+
161
+ MIT
package/dist/index.js CHANGED
@@ -157,6 +157,26 @@ var VexFrameworkInstaller = class {
157
157
  }
158
158
  await fs3.writeJson(pkgPath, pkg, { spaces: 2 });
159
159
  }
160
+ /**
161
+ * Configure the dev server port.
162
+ * Updates package.json dev script and creates .env.local with NEXT_PUBLIC_SITE_URL.
163
+ */
164
+ async configurePort(port) {
165
+ const pkgPath = path.join(this.targetPath, "package.json");
166
+ const pkg = await fs3.readJson(pkgPath);
167
+ if (pkg.scripts?.dev) {
168
+ if (pkg.scripts.dev.includes("--port")) {
169
+ pkg.scripts.dev = pkg.scripts.dev.replace(/--port[= ]\d+/, `--port=${port}`);
170
+ } else {
171
+ pkg.scripts.dev = `${pkg.scripts.dev} --port=${port}`;
172
+ }
173
+ }
174
+ await fs3.writeJson(pkgPath, pkg, { spaces: 2 });
175
+ const envLocalPath = path.join(this.targetPath, ".env.local");
176
+ const envContent = `NEXT_PUBLIC_SITE_URL=http://localhost:${port}
177
+ `;
178
+ await fs3.writeFile(envLocalPath, envContent);
179
+ }
160
180
  /**
161
181
  * Detect the package manager used to invoke the CLI
162
182
  */
@@ -330,6 +350,7 @@ var VexFrameworkInstaller = class {
330
350
  const nameSpinner = ora("Configuring project...").start();
331
351
  try {
332
352
  await this.updatePackageName(options.projectName);
353
+ await this.configurePort(options.port);
333
354
  nameSpinner.succeed("Project configured");
334
355
  } catch (error) {
335
356
  nameSpinner.fail("Failed to configure project");
@@ -2308,7 +2329,7 @@ async function main() {
2308
2329
  inputArg = args[0];
2309
2330
  } else {
2310
2331
  inputArg = await input({
2311
- message: "What is your project named?",
2332
+ message: "(1/8) What is your project named?",
2312
2333
  default: "my-vexcms-app",
2313
2334
  validate: (value) => {
2314
2335
  const name = value.includes("/") ? path2.basename(value) : value;
@@ -2336,7 +2357,7 @@ async function main() {
2336
2357
  let framework;
2337
2358
  while (true) {
2338
2359
  framework = await select({
2339
- message: "Select a framework:",
2360
+ message: "(2/8) Select a framework:",
2340
2361
  choices: [
2341
2362
  { name: "Next.js (Recommended)", value: "nextjs" },
2342
2363
  { name: "TanStack Start (Coming Soon)", value: "tanstack" }
@@ -2348,8 +2369,18 @@ async function main() {
2348
2369
  }
2349
2370
  break;
2350
2371
  }
2372
+ const portInput = await input({
2373
+ message: "(3/8) Dev server port:",
2374
+ default: "3010",
2375
+ validate: (value) => {
2376
+ const num = parseInt(value, 10);
2377
+ if (isNaN(num) || num < 1 || num > 65535) return "Must be a valid port number (1-65535)";
2378
+ return true;
2379
+ }
2380
+ });
2381
+ const port = parseInt(portInput, 10);
2351
2382
  const emailPasswordAuth = await confirm({
2352
- message: "Enable email/password authentication?",
2383
+ message: "(4/8) Enable email/password authentication?",
2353
2384
  default: true
2354
2385
  });
2355
2386
  const popularProviders = getPopularProviders();
@@ -2366,25 +2397,26 @@ async function main() {
2366
2397
  }))
2367
2398
  ];
2368
2399
  const oauthProviders = await checkbox({
2369
- message: "Select OAuth providers (space to toggle, enter to confirm):",
2400
+ message: "(5/8) Select OAuth providers (space to toggle, enter to confirm):",
2370
2401
  choices: allProviderChoices
2371
2402
  });
2372
2403
  const orgs = opts.orgs ?? await confirm({
2373
- message: "Enable multi-tenant (organizations)?",
2404
+ message: "(6/8) Enable multi-tenant (organizations)?",
2374
2405
  default: false
2375
2406
  });
2376
2407
  const initGit = await confirm({
2377
- message: "Initialize a Git repository?",
2408
+ message: "(7/8) Initialize a Git repository?",
2378
2409
  default: true
2379
2410
  });
2380
2411
  const installDependencies = await confirm({
2381
- message: "Install dependencies?",
2412
+ message: "(8/8) Install dependencies?",
2382
2413
  default: false
2383
2414
  });
2384
2415
  const options = {
2385
2416
  projectName,
2386
2417
  projectDir: targetDir,
2387
2418
  framework,
2419
+ port,
2388
2420
  bare,
2389
2421
  orgs,
2390
2422
  emailPasswordAuth,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-vexcms",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "create-vexcms": "./dist/index.js"