create-indiepub 0.0.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/index.js +538 -0
- package/package.json +34 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
#!/usr/bin/env node
|
|
3
|
+
|
|
4
|
+
// src/index.ts
|
|
5
|
+
import * as p from "@clack/prompts";
|
|
6
|
+
|
|
7
|
+
// src/scaffold.ts
|
|
8
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
9
|
+
import { dirname, join } from "path";
|
|
10
|
+
import { downloadTemplate } from "giget";
|
|
11
|
+
async function write(base, relPath, content) {
|
|
12
|
+
const full = join(base, relPath);
|
|
13
|
+
await mkdir(dirname(full), { recursive: true });
|
|
14
|
+
await writeFile(full, content, "utf-8");
|
|
15
|
+
}
|
|
16
|
+
function slugify(str) {
|
|
17
|
+
return str.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
18
|
+
}
|
|
19
|
+
var codeberg = (input) => {
|
|
20
|
+
const parts = input.split("/");
|
|
21
|
+
const owner = parts[0];
|
|
22
|
+
const repo = parts[1];
|
|
23
|
+
const subdir = parts.slice(2).join("/");
|
|
24
|
+
return {
|
|
25
|
+
name: input,
|
|
26
|
+
tar: `https://codeberg.org/${owner}/${repo}/archive/main.tar.gz`,
|
|
27
|
+
subdir: subdir ? `${repo}/${subdir}` : repo
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
function genPackageJson(cfg) {
|
|
31
|
+
const name = slugify(cfg.dir.replace(/^\.\//, "")) || "my-indiepub-site";
|
|
32
|
+
const baseDeps = {
|
|
33
|
+
"@astrojs/cloudflare": "^12.0.0",
|
|
34
|
+
"@iconify-json/lucide": "^1.2.0",
|
|
35
|
+
"@indiepub/admin": "^0.1.0",
|
|
36
|
+
"@indiepub/astro": "^0.1.0",
|
|
37
|
+
"astro": "^5.0.0",
|
|
38
|
+
"astro-icon": "^1.1.5",
|
|
39
|
+
"drizzle-orm": "^0.38.0",
|
|
40
|
+
"nanoid": "^5.0.0"
|
|
41
|
+
};
|
|
42
|
+
const baseDevDeps = {
|
|
43
|
+
"@astrojs/check": "^0.9.0",
|
|
44
|
+
"@cloudflare/workers-types": "^4.0.0",
|
|
45
|
+
"@indiepub/types": "^0.1.0",
|
|
46
|
+
"typescript": "^5.0.0",
|
|
47
|
+
"wrangler": "^4.0.0"
|
|
48
|
+
};
|
|
49
|
+
let deps;
|
|
50
|
+
let devDeps;
|
|
51
|
+
if (cfg.template === "minimal") {
|
|
52
|
+
deps = {
|
|
53
|
+
"@astrojs/cloudflare": "^12.0.0",
|
|
54
|
+
"@indiepub/admin": "^0.1.0",
|
|
55
|
+
"@indiepub/astro": "^0.1.0",
|
|
56
|
+
"astro": "^5.0.0"
|
|
57
|
+
};
|
|
58
|
+
devDeps = {
|
|
59
|
+
"@cloudflare/workers-types": "^4.0.0",
|
|
60
|
+
"typescript": "^5.0.0",
|
|
61
|
+
"wrangler": "^4.0.0"
|
|
62
|
+
};
|
|
63
|
+
} else if (cfg.template === "byline") {
|
|
64
|
+
deps = {
|
|
65
|
+
...baseDeps,
|
|
66
|
+
"@indiepub/db": "^0.1.0",
|
|
67
|
+
"@tiptap/core": "^3.20.0",
|
|
68
|
+
"@tiptap/extension-image": "^3.20.0",
|
|
69
|
+
"@tiptap/extension-link": "^3.20.0",
|
|
70
|
+
"@tiptap/extension-placeholder": "^3.20.0",
|
|
71
|
+
"@tiptap/starter-kit": "^3.20.0",
|
|
72
|
+
"tiptap-markdown": "^0.9.0"
|
|
73
|
+
};
|
|
74
|
+
devDeps = { ...baseDevDeps };
|
|
75
|
+
} else if (cfg.template === "timeline") {
|
|
76
|
+
deps = {
|
|
77
|
+
...baseDeps,
|
|
78
|
+
"@iconify-json/simple-icons": "^1.0.0"
|
|
79
|
+
};
|
|
80
|
+
devDeps = { ...baseDevDeps };
|
|
81
|
+
} else {
|
|
82
|
+
deps = { ...baseDeps };
|
|
83
|
+
if (cfg.subscriptions) {
|
|
84
|
+
deps["@indiepub/email"] = "^0.1.0";
|
|
85
|
+
}
|
|
86
|
+
devDeps = { ...baseDevDeps };
|
|
87
|
+
}
|
|
88
|
+
return JSON.stringify(
|
|
89
|
+
{
|
|
90
|
+
name,
|
|
91
|
+
version: "0.0.1",
|
|
92
|
+
type: "module",
|
|
93
|
+
scripts: {
|
|
94
|
+
dev: "astro dev",
|
|
95
|
+
build: "astro build",
|
|
96
|
+
preview: "astro preview",
|
|
97
|
+
"db:migrate": "wrangler d1 migrations apply DB --local",
|
|
98
|
+
typecheck: "astro check"
|
|
99
|
+
},
|
|
100
|
+
dependencies: deps,
|
|
101
|
+
devDependencies: devDeps
|
|
102
|
+
},
|
|
103
|
+
null,
|
|
104
|
+
2
|
|
105
|
+
) + "\n";
|
|
106
|
+
}
|
|
107
|
+
function genAstroConfig(cfg) {
|
|
108
|
+
const siteUrl = cfg.authorUrl || "https://example.com";
|
|
109
|
+
const syndicationLines = [];
|
|
110
|
+
if (cfg.bluesky && cfg.blueskyHandle) {
|
|
111
|
+
syndicationLines.push(` bluesky: { handle: '${cfg.blueskyHandle}' },`);
|
|
112
|
+
}
|
|
113
|
+
if (cfg.mastodon && cfg.mastodonInstance && cfg.mastodonHandle) {
|
|
114
|
+
syndicationLines.push(
|
|
115
|
+
` mastodon: { instance: '${cfg.mastodonInstance}', handle: '${cfg.mastodonHandle}' },`
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
const syndicationBlock = syndicationLines.length > 0 ? ` syndication: {
|
|
119
|
+
${syndicationLines.join("\n")}
|
|
120
|
+
},
|
|
121
|
+
` : "";
|
|
122
|
+
const subscriptionsBlock = cfg.subscriptions ? ` subscriptions: { enabled: true },
|
|
123
|
+
` : "";
|
|
124
|
+
return `import { defineConfig } from 'astro/config';
|
|
125
|
+
import cloudflare from '@astrojs/cloudflare';
|
|
126
|
+
import icon from 'astro-icon';
|
|
127
|
+
import { indiepub } from '@indiepub/astro';
|
|
128
|
+
import { indiepubAdmin } from '@indiepub/admin';
|
|
129
|
+
|
|
130
|
+
export default defineConfig({
|
|
131
|
+
site: '${siteUrl}',
|
|
132
|
+
output: 'server',
|
|
133
|
+
adapter: cloudflare({
|
|
134
|
+
platformProxy: { enabled: true },
|
|
135
|
+
imageService: 'cloudflare',
|
|
136
|
+
}),
|
|
137
|
+
vite: {
|
|
138
|
+
environments: {
|
|
139
|
+
ssr: {
|
|
140
|
+
external: ['node:fs/promises', 'node:path', 'node:url', 'node:crypto'],
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
integrations: [
|
|
145
|
+
icon(),
|
|
146
|
+
indiepub({
|
|
147
|
+
title: ${JSON.stringify(cfg.title || "My IndieWeb Site")},
|
|
148
|
+
author: {
|
|
149
|
+
name: ${JSON.stringify(cfg.authorName || "Site Author")},
|
|
150
|
+
url: '${siteUrl}',
|
|
151
|
+
},
|
|
152
|
+
${syndicationBlock}${subscriptionsBlock} }),
|
|
153
|
+
indiepubAdmin(),
|
|
154
|
+
],
|
|
155
|
+
});
|
|
156
|
+
`;
|
|
157
|
+
}
|
|
158
|
+
function genTsconfig() {
|
|
159
|
+
return JSON.stringify(
|
|
160
|
+
{
|
|
161
|
+
compilerOptions: {
|
|
162
|
+
target: "ES2022",
|
|
163
|
+
module: "ES2022",
|
|
164
|
+
moduleResolution: "bundler",
|
|
165
|
+
resolveJsonModule: true,
|
|
166
|
+
esModuleInterop: true,
|
|
167
|
+
strict: true,
|
|
168
|
+
exactOptionalPropertyTypes: true,
|
|
169
|
+
noUnusedLocals: true,
|
|
170
|
+
noUnusedParameters: true,
|
|
171
|
+
noFallthroughCasesInSwitch: true,
|
|
172
|
+
skipLibCheck: true,
|
|
173
|
+
jsx: "preserve",
|
|
174
|
+
jsxImportSource: "react",
|
|
175
|
+
allowImportingTsExtensions: true
|
|
176
|
+
},
|
|
177
|
+
include: ["src", "astro.config.mjs", ".astro/types.d.ts"]
|
|
178
|
+
},
|
|
179
|
+
null,
|
|
180
|
+
2
|
|
181
|
+
) + "\n";
|
|
182
|
+
}
|
|
183
|
+
function genWranglerToml(cfg) {
|
|
184
|
+
const name = slugify(cfg.dir.replace(/^\.\//, "")) || "my-indiepub-site";
|
|
185
|
+
return `name = "${name}"
|
|
186
|
+
compatibility_date = "2025-01-01"
|
|
187
|
+
compatibility_flags = ["nodejs_compat"]
|
|
188
|
+
pages_build_output_dir = "./dist"
|
|
189
|
+
|
|
190
|
+
[[d1_databases]]
|
|
191
|
+
binding = "DB"
|
|
192
|
+
database_name = "${name}-db"
|
|
193
|
+
database_id = "YOUR_D1_DATABASE_ID_HERE"
|
|
194
|
+
|
|
195
|
+
[[r2_buckets]]
|
|
196
|
+
binding = "BUCKET"
|
|
197
|
+
bucket_name = "${name}-bucket"
|
|
198
|
+
|
|
199
|
+
[[kv_namespaces]]
|
|
200
|
+
binding = "SESSION"
|
|
201
|
+
id = "YOUR_KV_NAMESPACE_ID_HERE"
|
|
202
|
+
`;
|
|
203
|
+
}
|
|
204
|
+
function genNpmrc() {
|
|
205
|
+
return [
|
|
206
|
+
"@indiepub:registry=https://registry.indiepub.dev",
|
|
207
|
+
"//registry.indiepub.dev/:_authToken=${INDIEPUB_NPM_TOKEN}",
|
|
208
|
+
""
|
|
209
|
+
].join("\n");
|
|
210
|
+
}
|
|
211
|
+
function genDevVarsExample(cfg) {
|
|
212
|
+
const lines = [
|
|
213
|
+
"# Required: license token for @indiepub/* npm registry access",
|
|
214
|
+
"INDIEPUB_NPM_TOKEN=your-license-token-here",
|
|
215
|
+
"",
|
|
216
|
+
"# Required: secret token for Micropub / admin authentication",
|
|
217
|
+
"INDIEPUB_TOKEN=choose-a-secure-random-token",
|
|
218
|
+
""
|
|
219
|
+
];
|
|
220
|
+
if (cfg.bluesky) {
|
|
221
|
+
lines.push("# Bluesky syndication");
|
|
222
|
+
lines.push("BSKY_APP_PASSWORD=your-bluesky-app-password");
|
|
223
|
+
lines.push("");
|
|
224
|
+
}
|
|
225
|
+
if (cfg.mastodon) {
|
|
226
|
+
lines.push("# Mastodon syndication + ActivityPub federation");
|
|
227
|
+
lines.push("MASTODON_ACCESS_TOKEN=your-mastodon-access-token");
|
|
228
|
+
lines.push(
|
|
229
|
+
"# Generate RSA key pair: openssl genrsa 2048 | tee private.pem | openssl rsa -pubout -out public.pem"
|
|
230
|
+
);
|
|
231
|
+
lines.push(
|
|
232
|
+
'ACTIVITYPUB_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\\n...\\n-----END PRIVATE KEY-----"'
|
|
233
|
+
);
|
|
234
|
+
lines.push(
|
|
235
|
+
'ACTIVITYPUB_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\\n...\\n-----END PUBLIC KEY-----"'
|
|
236
|
+
);
|
|
237
|
+
lines.push("");
|
|
238
|
+
}
|
|
239
|
+
if (cfg.subscriptions) {
|
|
240
|
+
lines.push("# Email subscriptions (Resend)");
|
|
241
|
+
lines.push("RESEND_API_KEY=re_...");
|
|
242
|
+
lines.push("RESEND_FROM_EMAIL=Your Name <newsletter@yourdomain.com>");
|
|
243
|
+
lines.push(`SITE_TITLE=${cfg.title || "My Site"}`);
|
|
244
|
+
lines.push("");
|
|
245
|
+
}
|
|
246
|
+
return lines.join("\n");
|
|
247
|
+
}
|
|
248
|
+
function genDevVars(licenseToken) {
|
|
249
|
+
return [
|
|
250
|
+
"# Local dev secrets \u2014 DO NOT COMMIT (this file is gitignored)",
|
|
251
|
+
`INDIEPUB_NPM_TOKEN=${licenseToken}`,
|
|
252
|
+
"INDIEPUB_TOKEN=change-me-before-deploying",
|
|
253
|
+
""
|
|
254
|
+
].join("\n");
|
|
255
|
+
}
|
|
256
|
+
function genGitignore() {
|
|
257
|
+
return [
|
|
258
|
+
"node_modules/",
|
|
259
|
+
"dist/",
|
|
260
|
+
".astro/",
|
|
261
|
+
".cloudflare/",
|
|
262
|
+
".wrangler/",
|
|
263
|
+
".dev.vars",
|
|
264
|
+
".dev.vars.local",
|
|
265
|
+
".npmrc",
|
|
266
|
+
"*.local",
|
|
267
|
+
""
|
|
268
|
+
].join("\n");
|
|
269
|
+
}
|
|
270
|
+
function genGitHubWorkflow(cfg) {
|
|
271
|
+
const name = slugify(cfg.dir.replace(/^\.\//, "")) || "my-indiepub-site";
|
|
272
|
+
return `name: Deploy to Cloudflare Pages
|
|
273
|
+
|
|
274
|
+
on:
|
|
275
|
+
push:
|
|
276
|
+
branches: [main]
|
|
277
|
+
workflow_dispatch:
|
|
278
|
+
|
|
279
|
+
# Required repository secrets:
|
|
280
|
+
# CLOUDFLARE_API_TOKEN \u2014 Cloudflare API token with Pages:Edit permission
|
|
281
|
+
# CLOUDFLARE_ACCOUNT_ID \u2014 your Cloudflare account ID
|
|
282
|
+
# INDIEPUB_TOKEN \u2014 your IndiePub admin token (same as .dev.vars)
|
|
283
|
+
# NPM_TOKEN \u2014 your IndiePub license token for @indiepub/* packages
|
|
284
|
+
|
|
285
|
+
jobs:
|
|
286
|
+
deploy:
|
|
287
|
+
runs-on: ubuntu-latest
|
|
288
|
+
permissions:
|
|
289
|
+
contents: read
|
|
290
|
+
deployments: write
|
|
291
|
+
steps:
|
|
292
|
+
- uses: actions/checkout@v4
|
|
293
|
+
|
|
294
|
+
- uses: pnpm/action-setup@v4
|
|
295
|
+
with:
|
|
296
|
+
version: 10
|
|
297
|
+
|
|
298
|
+
- uses: actions/setup-node@v4
|
|
299
|
+
with:
|
|
300
|
+
node-version: 22
|
|
301
|
+
cache: pnpm
|
|
302
|
+
|
|
303
|
+
- name: Configure private registry
|
|
304
|
+
run: |
|
|
305
|
+
echo "@indiepub:registry=https://registry.indiepub.dev" >> .npmrc
|
|
306
|
+
echo "//registry.indiepub.dev/:_authToken=\${{ secrets.NPM_TOKEN }}" >> .npmrc
|
|
307
|
+
|
|
308
|
+
- name: Install dependencies
|
|
309
|
+
run: pnpm install --frozen-lockfile
|
|
310
|
+
|
|
311
|
+
- name: Build
|
|
312
|
+
run: pnpm build
|
|
313
|
+
|
|
314
|
+
- name: Deploy
|
|
315
|
+
uses: cloudflare/wrangler-action@v3
|
|
316
|
+
with:
|
|
317
|
+
apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
318
|
+
accountId: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
319
|
+
command: pages deploy dist --project-name=${name}
|
|
320
|
+
`;
|
|
321
|
+
}
|
|
322
|
+
async function scaffold(cfg) {
|
|
323
|
+
const base = cfg.dir;
|
|
324
|
+
if (cfg.template !== "minimal") {
|
|
325
|
+
await downloadTemplate(`codeberg:indiepub/themes/${cfg.template}`, {
|
|
326
|
+
dir: base,
|
|
327
|
+
force: true,
|
|
328
|
+
providers: { codeberg }
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
const files = [
|
|
332
|
+
write(base, "package.json", genPackageJson(cfg)),
|
|
333
|
+
write(base, "astro.config.mjs", genAstroConfig(cfg)),
|
|
334
|
+
write(base, "tsconfig.json", genTsconfig()),
|
|
335
|
+
write(base, "wrangler.toml", genWranglerToml(cfg)),
|
|
336
|
+
write(base, ".npmrc", genNpmrc()),
|
|
337
|
+
write(base, ".gitignore", genGitignore()),
|
|
338
|
+
write(base, ".dev.vars.example", genDevVarsExample(cfg)),
|
|
339
|
+
write(base, ".dev.vars", genDevVars(cfg.licenseToken))
|
|
340
|
+
];
|
|
341
|
+
if (cfg.template === "minimal") {
|
|
342
|
+
files.push(write(base, "src/env.d.ts", `/// <reference types="astro/client" />
|
|
343
|
+
`));
|
|
344
|
+
}
|
|
345
|
+
if (cfg.githubActions) {
|
|
346
|
+
files.push(write(base, ".github/workflows/deploy.yml", genGitHubWorkflow(cfg)));
|
|
347
|
+
}
|
|
348
|
+
await Promise.all(files);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// src/index.ts
|
|
352
|
+
async function main() {
|
|
353
|
+
console.log();
|
|
354
|
+
p.intro(" create-indiepub ");
|
|
355
|
+
const answers = await p.group(
|
|
356
|
+
{
|
|
357
|
+
dir: () => p.text({
|
|
358
|
+
message: "Where should we create your project?",
|
|
359
|
+
placeholder: "./my-site",
|
|
360
|
+
validate: (v) => {
|
|
361
|
+
if (!v || v.trim() === "") return "Please enter a directory path";
|
|
362
|
+
if (/\s/.test(v)) return "Path cannot contain spaces";
|
|
363
|
+
}
|
|
364
|
+
}),
|
|
365
|
+
template: () => p.select({
|
|
366
|
+
message: "Which template?",
|
|
367
|
+
options: [
|
|
368
|
+
{
|
|
369
|
+
value: "default",
|
|
370
|
+
label: "Default",
|
|
371
|
+
hint: "dev-focused IndieWeb site; all post types, public-facing pages + admin"
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
value: "byline",
|
|
375
|
+
label: "Byline",
|
|
376
|
+
hint: "writer-focused blog; TipTap editor, /write dashboard, redirects UI"
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
value: "timeline",
|
|
380
|
+
label: "Timeline",
|
|
381
|
+
hint: "feed-based social media profile; unified timeline, left sidebar, interaction counts"
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
value: "minimal",
|
|
385
|
+
label: "Minimal",
|
|
386
|
+
hint: "bare config only; bring your own pages"
|
|
387
|
+
}
|
|
388
|
+
]
|
|
389
|
+
}),
|
|
390
|
+
title: () => p.text({
|
|
391
|
+
message: "Site title",
|
|
392
|
+
placeholder: "My IndieWeb Site",
|
|
393
|
+
defaultValue: "My IndieWeb Site"
|
|
394
|
+
}),
|
|
395
|
+
authorName: () => p.text({
|
|
396
|
+
message: "Your name (shown as author)",
|
|
397
|
+
placeholder: "Jane Doe"
|
|
398
|
+
}),
|
|
399
|
+
authorUrl: () => p.text({
|
|
400
|
+
message: "Your site URL",
|
|
401
|
+
placeholder: "https://example.com",
|
|
402
|
+
defaultValue: "https://example.com"
|
|
403
|
+
}),
|
|
404
|
+
licenseToken: () => p.password({
|
|
405
|
+
message: "License token (from indiepub.dev/account)",
|
|
406
|
+
validate: (v) => {
|
|
407
|
+
if (!v || v.trim() === "") return "A license token is required to install @indiepub/* packages";
|
|
408
|
+
}
|
|
409
|
+
}),
|
|
410
|
+
bluesky: () => p.confirm({ message: "Enable Bluesky syndication?", initialValue: false }),
|
|
411
|
+
blueskyHandle: ({ results }) => {
|
|
412
|
+
if (!results.bluesky) return void 0;
|
|
413
|
+
return p.text({
|
|
414
|
+
message: "Your Bluesky handle",
|
|
415
|
+
placeholder: "you.bsky.social"
|
|
416
|
+
});
|
|
417
|
+
},
|
|
418
|
+
mastodon: () => p.confirm({
|
|
419
|
+
message: "Enable Mastodon syndication + ActivityPub federation?",
|
|
420
|
+
initialValue: false
|
|
421
|
+
}),
|
|
422
|
+
mastodonInstance: ({ results }) => {
|
|
423
|
+
if (!results.mastodon) return void 0;
|
|
424
|
+
return p.text({
|
|
425
|
+
message: "Mastodon instance domain",
|
|
426
|
+
placeholder: "mastodon.social"
|
|
427
|
+
});
|
|
428
|
+
},
|
|
429
|
+
mastodonHandle: ({ results }) => {
|
|
430
|
+
if (!results.mastodon) return void 0;
|
|
431
|
+
return p.text({
|
|
432
|
+
message: "Your Mastodon handle (without @)",
|
|
433
|
+
placeholder: "yourhandle"
|
|
434
|
+
});
|
|
435
|
+
},
|
|
436
|
+
subscriptions: () => p.confirm({ message: "Enable email subscriptions / newsletter?", initialValue: false }),
|
|
437
|
+
githubActions: () => p.confirm({ message: "Generate GitHub Actions deploy workflow?", initialValue: true })
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
onCancel: () => {
|
|
441
|
+
p.cancel("Setup cancelled.");
|
|
442
|
+
process.exit(0);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
);
|
|
446
|
+
const template = answers.template;
|
|
447
|
+
const cfg = {
|
|
448
|
+
dir: answers.dir,
|
|
449
|
+
template,
|
|
450
|
+
title: answers.title,
|
|
451
|
+
authorName: answers.authorName,
|
|
452
|
+
authorUrl: answers.authorUrl,
|
|
453
|
+
licenseToken: answers.licenseToken,
|
|
454
|
+
bluesky: answers.bluesky,
|
|
455
|
+
blueskyHandle: answers.blueskyHandle,
|
|
456
|
+
mastodon: answers.mastodon,
|
|
457
|
+
mastodonInstance: answers.mastodonInstance,
|
|
458
|
+
mastodonHandle: answers.mastodonHandle,
|
|
459
|
+
subscriptions: answers.subscriptions,
|
|
460
|
+
githubActions: answers.githubActions
|
|
461
|
+
};
|
|
462
|
+
const spinner2 = p.spinner();
|
|
463
|
+
spinner2.start(
|
|
464
|
+
cfg.template === "minimal" ? "Scaffolding project files\u2026" : `Cloning ${cfg.template} theme and scaffolding project\u2026`
|
|
465
|
+
);
|
|
466
|
+
try {
|
|
467
|
+
await scaffold(cfg);
|
|
468
|
+
spinner2.stop("Project files created!");
|
|
469
|
+
} catch (err) {
|
|
470
|
+
spinner2.error("Failed to scaffold project");
|
|
471
|
+
p.log.error(String(err));
|
|
472
|
+
process.exit(1);
|
|
473
|
+
}
|
|
474
|
+
const nextStepsDefault = [
|
|
475
|
+
`cd ${cfg.dir}`,
|
|
476
|
+
`cp .dev.vars.example .dev.vars # add your secrets`,
|
|
477
|
+
``,
|
|
478
|
+
`# Create your D1 database:`,
|
|
479
|
+
`npx wrangler d1 create <your-db-name>`,
|
|
480
|
+
`# Copy the database_id into wrangler.toml`,
|
|
481
|
+
``,
|
|
482
|
+
`pnpm install`,
|
|
483
|
+
`pnpm db:migrate`,
|
|
484
|
+
`pnpm dev`,
|
|
485
|
+
``,
|
|
486
|
+
`# Then visit /admin/onboarding to finish setup`
|
|
487
|
+
];
|
|
488
|
+
const nextStepsByline = [
|
|
489
|
+
`cd ${cfg.dir}`,
|
|
490
|
+
`cp .dev.vars.example .dev.vars # add your secrets`,
|
|
491
|
+
``,
|
|
492
|
+
`# Create your D1 database:`,
|
|
493
|
+
`npx wrangler d1 create <your-db-name>`,
|
|
494
|
+
`# Copy the database_id into wrangler.toml`,
|
|
495
|
+
``,
|
|
496
|
+
`pnpm install`,
|
|
497
|
+
`pnpm db:migrate`,
|
|
498
|
+
`pnpm dev`,
|
|
499
|
+
``,
|
|
500
|
+
`# Visit /admin/onboarding to finish setup`,
|
|
501
|
+
`# Visit /write to start writing`
|
|
502
|
+
];
|
|
503
|
+
const nextStepsTimeline = [
|
|
504
|
+
`cd ${cfg.dir}`,
|
|
505
|
+
`cp .dev.vars.example .dev.vars # add your secrets`,
|
|
506
|
+
``,
|
|
507
|
+
`# Create your D1 database:`,
|
|
508
|
+
`npx wrangler d1 create <your-db-name>`,
|
|
509
|
+
`# Copy the database_id into wrangler.toml`,
|
|
510
|
+
``,
|
|
511
|
+
`pnpm install`,
|
|
512
|
+
`pnpm db:migrate`,
|
|
513
|
+
`pnpm dev`,
|
|
514
|
+
``,
|
|
515
|
+
`# Then visit /admin/onboarding to finish setup`
|
|
516
|
+
];
|
|
517
|
+
const nextStepsMinimal = [
|
|
518
|
+
`cd ${cfg.dir}`,
|
|
519
|
+
`cp .dev.vars.example .dev.vars # add your secrets`,
|
|
520
|
+
``,
|
|
521
|
+
`# Create your D1 database:`,
|
|
522
|
+
`npx wrangler d1 create <your-db-name>`,
|
|
523
|
+
`# Copy the database_id into wrangler.toml`,
|
|
524
|
+
``,
|
|
525
|
+
`# Add your pages to src/ before running pnpm dev`,
|
|
526
|
+
``,
|
|
527
|
+
`pnpm install`,
|
|
528
|
+
`pnpm db:migrate`,
|
|
529
|
+
`pnpm dev`
|
|
530
|
+
];
|
|
531
|
+
const nextSteps = template === "byline" ? nextStepsByline : template === "timeline" ? nextStepsTimeline : template === "minimal" ? nextStepsMinimal : nextStepsDefault;
|
|
532
|
+
p.note(nextSteps.join("\n"), "Next steps");
|
|
533
|
+
p.outro("Happy publishing! https://indiepub.dev");
|
|
534
|
+
}
|
|
535
|
+
main().catch((err) => {
|
|
536
|
+
console.error(err);
|
|
537
|
+
process.exit(1);
|
|
538
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-indiepub",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-indiepub": "./dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@clack/prompts": "^1.0.1",
|
|
16
|
+
"giget": "^3.1.2"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^22.0.0",
|
|
20
|
+
"tsup": "^8.0.0",
|
|
21
|
+
"typescript": "^5.0.0"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsup",
|
|
25
|
+
"typecheck": "tsc --noEmit"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"create",
|
|
29
|
+
"indiepub",
|
|
30
|
+
"indieweb",
|
|
31
|
+
"astro"
|
|
32
|
+
],
|
|
33
|
+
"packageManager": "pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017"
|
|
34
|
+
}
|