@karaoke-cms/create 0.9.3 → 0.9.6
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 +46 -40
- package/karaoke-create-vault/.obsidian/workspace.json +5 -19
- package/package.json +1 -1
- package/src/index.js +31 -20
- package/src/templates.js +10 -14
- package/karaoke-create-vault/karaoke-cms/config/collections.yaml +0 -10
- package/karaoke-create-vault/karaoke-cms/config/index.md +0 -14
- package/karaoke-create-vault/karaoke-cms/config/menus.yaml +0 -58
- package/karaoke-create-vault/karaoke-cms/manual/configuration.md +0 -77
- package/karaoke-create-vault/karaoke-cms/manual/content.md +0 -38
- package/karaoke-create-vault/karaoke-cms/manual/deployment.md +0 -46
- package/karaoke-create-vault/karaoke-cms/manual/index.md +0 -41
- package/karaoke-create-vault/karaoke-cms/manual/privacy.md +0 -37
- package/karaoke-create-vault/karaoke-cms/templates/blog-header.md +0 -9
- package/karaoke-create-vault/karaoke-cms/templates/docs-header.md +0 -9
- package/karaoke-create-vault/karaoke-cms/templates/index-by-foldernote.md +0 -8
- package/karaoke-create-vault/karaoke-cms/templates/index.md +0 -15
package/README.md
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# @karaoke-cms/create
|
|
2
2
|
|
|
3
|
-
Scaffolding tool for karaoke-cms. Creates a complete new project from scratch with a single command.
|
|
3
|
+
Scaffolding tool for karaoke-cms. Creates a complete new project from scratch with a single command, then optionally deploys a live preview to Cloudflare Pages.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
`packages/create/` in the monorepo. Published to npm as `@karaoke-cms/create` and invoked via npm's `create` shorthand:
|
|
5
|
+
## Usage
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
8
|
npm create @karaoke-cms@latest
|
|
@@ -12,37 +10,26 @@ npm create @karaoke-cms@latest
|
|
|
12
10
|
npm create @karaoke-cms@latest my-site
|
|
13
11
|
```
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
## What it does
|
|
13
|
+
The wizard asks for your project name, site title, URL, and description, then generates everything and installs dependencies.
|
|
18
14
|
|
|
19
|
-
|
|
15
|
+
At the end you're offered a one-step deploy to Cloudflare Pages (defaults to **yes** — your site can be live before you open your code editor).
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
1. Project directory name
|
|
23
|
-
2. Site title
|
|
24
|
-
3. Site URL (for sitemap and OG tags)
|
|
25
|
-
4. Description
|
|
26
|
-
5. Theme (`default`, `minimal`, or `blog`)
|
|
27
|
-
6. Enable Pagefind search? (y/n)
|
|
28
|
-
7. Enable Giscus comments? (y/n) — if yes, prompts for repo, repoId, category, categoryId
|
|
17
|
+
## What gets created
|
|
29
18
|
|
|
30
|
-
**Generated files:**
|
|
31
19
|
```
|
|
32
20
|
my-site/
|
|
33
|
-
package.json
|
|
34
|
-
astro.config.mjs
|
|
35
|
-
karaoke.config.ts
|
|
21
|
+
package.json # @karaoke-cms/* deps pinned to current version
|
|
22
|
+
astro.config.mjs # karaoke() integration, site URL
|
|
23
|
+
karaoke.config.ts # title, description, theme, blog module
|
|
36
24
|
src/
|
|
37
|
-
content.config.ts
|
|
38
|
-
env.d.ts
|
|
25
|
+
content.config.ts # makeCollections() wired to vault/
|
|
26
|
+
env.d.ts # TypeScript types for virtual:karaoke-cms/config
|
|
39
27
|
tsconfig.json
|
|
40
28
|
.gitignore
|
|
41
|
-
.env.default
|
|
42
|
-
public/
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
blog/
|
|
29
|
+
.env.default # KARAOKE_VAULT=./vault/
|
|
30
|
+
public/_redirects # Cloudflare Pages 404 config
|
|
31
|
+
vault/ # Obsidian vault with sample blog posts
|
|
32
|
+
blog/ # 30 demo posts (publish: true)
|
|
46
33
|
docs/
|
|
47
34
|
karaoke-cms/
|
|
48
35
|
config/
|
|
@@ -50,27 +37,46 @@ my-site/
|
|
|
50
37
|
menus.yaml
|
|
51
38
|
```
|
|
52
39
|
|
|
53
|
-
|
|
40
|
+
A git repository is initialised with an initial commit. Opening `vault/` in Obsidian lets you write content immediately.
|
|
54
41
|
|
|
55
|
-
##
|
|
42
|
+
## Generated karaoke.config.ts
|
|
56
43
|
|
|
57
|
-
```
|
|
58
|
-
|
|
44
|
+
```ts
|
|
45
|
+
import { defineConfig } from '@karaoke-cms/astro';
|
|
46
|
+
import { blog } from '@karaoke-cms/module-blog';
|
|
47
|
+
import { themeDefault } from '@karaoke-cms/theme-default';
|
|
48
|
+
import { loadEnv } from '@karaoke-cms/astro/env';
|
|
49
|
+
|
|
50
|
+
const env = loadEnv(new URL('.', import.meta.url));
|
|
59
51
|
|
|
52
|
+
export default defineConfig({
|
|
53
|
+
vault: env.KARAOKE_VAULT,
|
|
54
|
+
title: 'My Site',
|
|
55
|
+
description: 'What this site is about.',
|
|
56
|
+
modules: [blog({ mount: '/blog' })],
|
|
57
|
+
theme: themeDefault(),
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Local dev
|
|
62
|
+
|
|
63
|
+
```bash
|
|
60
64
|
cd my-site
|
|
61
|
-
npm install
|
|
62
65
|
npm run dev # → http://localhost:4321
|
|
63
66
|
```
|
|
64
67
|
|
|
65
|
-
|
|
68
|
+
## Deploy
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
```bash
|
|
71
|
+
npm run deploy # publishes to Cloudflare Pages
|
|
72
|
+
```
|
|
68
73
|
|
|
69
|
-
|
|
74
|
+
Requires a Cloudflare account and the `wrangler` CLI. The wizard handles the first deploy interactively.
|
|
70
75
|
|
|
71
|
-
|
|
76
|
+
## What's new in 0.9.5
|
|
72
77
|
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
78
|
+
- **Deploy defaults to yes** — the Cloudflare Pages deploy prompt now defaults to YES, so new sites are live by the end of the wizard
|
|
79
|
+
- **Three success screens** — distinct output for deploy success, declined, and failed (failed surfaces the error and next steps)
|
|
80
|
+
- **isTTY color guard** — ANSI color codes are disabled in CI and piped output
|
|
81
|
+
- **30 demo blog posts** included in the scaffolded vault so the site is populated on first visit
|
|
82
|
+
- **Generated `karaoke.config.ts`** uses `themeDefault()` + `blog()` module API (replaces the old string-based theme config)
|
|
@@ -20,23 +20,8 @@
|
|
|
20
20
|
"icon": "lucide-file",
|
|
21
21
|
"title": "getting-started"
|
|
22
22
|
}
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"id": "52e565c48d7a7c39",
|
|
26
|
-
"type": "leaf",
|
|
27
|
-
"state": {
|
|
28
|
-
"type": "markdown",
|
|
29
|
-
"state": {
|
|
30
|
-
"file": "karaoke-cms/manual/deployment.md",
|
|
31
|
-
"mode": "source",
|
|
32
|
-
"source": false
|
|
33
|
-
},
|
|
34
|
-
"icon": "lucide-file",
|
|
35
|
-
"title": "deployment"
|
|
36
|
-
}
|
|
37
23
|
}
|
|
38
|
-
]
|
|
39
|
-
"currentTab": 1
|
|
24
|
+
]
|
|
40
25
|
}
|
|
41
26
|
],
|
|
42
27
|
"direction": "vertical"
|
|
@@ -183,10 +168,10 @@
|
|
|
183
168
|
"state": {
|
|
184
169
|
"type": "file-properties",
|
|
185
170
|
"state": {
|
|
186
|
-
"file": "
|
|
171
|
+
"file": "docs/getting-started.md"
|
|
187
172
|
},
|
|
188
173
|
"icon": "lucide-info",
|
|
189
|
-
"title": "File properties for
|
|
174
|
+
"title": "File properties for getting-started"
|
|
190
175
|
}
|
|
191
176
|
}
|
|
192
177
|
],
|
|
@@ -208,8 +193,9 @@
|
|
|
208
193
|
"templater-obsidian:Templater": false
|
|
209
194
|
}
|
|
210
195
|
},
|
|
211
|
-
"active": "
|
|
196
|
+
"active": "d663da17c7b12a45",
|
|
212
197
|
"lastOpenFiles": [
|
|
198
|
+
"karaoke-cms/manual/deployment.md",
|
|
213
199
|
"karaoke-cms/manual/configuration.md",
|
|
214
200
|
"karaoke-cms/templates/index.md",
|
|
215
201
|
"karaoke-cms/config/index.md",
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -17,12 +17,13 @@ import {
|
|
|
17
17
|
} from './templates.js';
|
|
18
18
|
|
|
19
19
|
// ── ANSI helpers ─────────────────────────────────────────────────────────────
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
20
|
+
const NO_COLOR = !process.stdout.isTTY;
|
|
21
|
+
const R = NO_COLOR ? '' : '\x1b[0m';
|
|
22
|
+
const BOLD = NO_COLOR ? '' : '\x1b[1m';
|
|
23
|
+
const GREEN = NO_COLOR ? '' : '\x1b[32m';
|
|
24
|
+
const CYAN = NO_COLOR ? '' : '\x1b[36m';
|
|
25
|
+
const GRAY = NO_COLOR ? '' : '\x1b[90m';
|
|
26
|
+
const RED = NO_COLOR ? '' : '\x1b[31m';
|
|
26
27
|
|
|
27
28
|
// Use create package's own version as the @karaoke-cms/astro dep range
|
|
28
29
|
// (packages ship in lockstep)
|
|
@@ -174,34 +175,40 @@ async function main() {
|
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
// ── npm install ──────────────────────────────────────────────────────────────
|
|
177
|
-
console.log(`\n Installing dependencies
|
|
178
|
+
console.log(`\n Installing dependencies... ${GRAY}(this may take a minute)${R}\n`);
|
|
178
179
|
const installResult = spawnSync('npm', ['install'], { cwd: targetDir, stdio: 'inherit' });
|
|
179
180
|
if (installResult.status !== 0) {
|
|
180
181
|
console.log(` ${GRAY}(install failed — run npm install manually)${R}`);
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
// ── Deploy prompt ────────────────────────────────────────────────────────────
|
|
184
|
-
const deployNow = await askYesNo('Publish a live preview to Cloudflare Pages now?',
|
|
185
|
-
|
|
186
|
-
rl.close();
|
|
185
|
+
const deployNow = await askYesNo('Publish a live preview to Cloudflare Pages now?', true);
|
|
187
186
|
|
|
188
187
|
let liveUrl = null;
|
|
188
|
+
let deployFailed = false;
|
|
189
189
|
if (deployNow) {
|
|
190
190
|
const projectName = `${slugify(dir)}-preview`;
|
|
191
191
|
liveUrl = await deployToCloudflare(targetDir, projectName);
|
|
192
|
+
if (!liveUrl) deployFailed = true;
|
|
192
193
|
}
|
|
193
194
|
|
|
195
|
+
rl.close();
|
|
196
|
+
|
|
194
197
|
// ── Success screen ───────────────────────────────────────────────────────────
|
|
195
|
-
|
|
198
|
+
const failNote = deployFailed ? ` ${GRAY}(deploy failed — see above)${R}` : '';
|
|
199
|
+
console.log(`\n${GREEN}✓${R} Done! Created ${BOLD}${dir}/${R}${failNote}\n`);
|
|
196
200
|
if (liveUrl) {
|
|
197
|
-
console.log(` ${BOLD}🎤 Live:${R}
|
|
198
|
-
console.log(` ${BOLD}💻
|
|
201
|
+
console.log(` ${BOLD}🎤 Live URL:${R} ${GREEN}${liveUrl}${R}`);
|
|
202
|
+
console.log(` ${BOLD}💻 Local dev:${R} ${CYAN}cd ${dir} && npm run dev${R}`);
|
|
199
203
|
console.log(` ${BOLD}🔄 Redeploy:${R} ${CYAN}npm run deploy${R}\n`);
|
|
204
|
+
} else if (deployFailed) {
|
|
205
|
+
console.log(` The project is ready. Fix the error above, then:`);
|
|
206
|
+
console.log(` ${CYAN}cd ${dir}${R}`);
|
|
207
|
+
console.log(` ${CYAN}npm run deploy${R} ${GRAY}→ retry publishing to Cloudflare Pages${R}\n`);
|
|
200
208
|
} else {
|
|
201
|
-
console.log(` Next steps:\n`);
|
|
202
209
|
console.log(` ${CYAN}cd ${dir}${R}`);
|
|
203
|
-
console.log(` ${CYAN}npm run dev${R} ${GRAY}→
|
|
204
|
-
console.log(` ${CYAN}npm run deploy${R} ${GRAY}→ publish to Cloudflare Pages${R}\n`);
|
|
210
|
+
console.log(` ${CYAN}npm run dev${R} ${GRAY}→ start local dev server${R}`);
|
|
211
|
+
console.log(` ${CYAN}npm run deploy${R} ${GRAY}→ publish to Cloudflare Pages when ready${R}\n`);
|
|
205
212
|
}
|
|
206
213
|
console.log(` ${GRAY}Open ${BOLD}${dir}/vault/${R}${GRAY} in Obsidian to write content.${R}\n`);
|
|
207
214
|
}
|
|
@@ -230,7 +237,7 @@ export async function deployToCloudflare(targetDir, projectName) {
|
|
|
230
237
|
}
|
|
231
238
|
|
|
232
239
|
// 2. Build
|
|
233
|
-
console.log(` ${CYAN}Building
|
|
240
|
+
console.log(` ${CYAN}Building... ${GRAY}(15–30 seconds)${R}`);
|
|
234
241
|
const build = spawnSync('npm', ['run', 'build'],
|
|
235
242
|
{ cwd: targetDir, stdio: 'inherit' });
|
|
236
243
|
if (build.status !== 0) {
|
|
@@ -261,9 +268,13 @@ export async function deployToCloudflare(targetDir, projectName) {
|
|
|
261
268
|
const liveUrl = `https://${projectName}.pages.dev`;
|
|
262
269
|
|
|
263
270
|
// 6. Write real URL back to astro.config.mjs (replaces placeholder set during scaffold)
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
271
|
+
try {
|
|
272
|
+
const configPath = join(targetDir, 'astro.config.mjs');
|
|
273
|
+
const configSrc = readFileSync(configPath, 'utf8');
|
|
274
|
+
writeFileSync(configPath, configSrc.replace('https://your-site.pages.dev', liveUrl));
|
|
275
|
+
} catch {
|
|
276
|
+
console.log(` ${GRAY}Could not update site URL — edit astro.config.mjs manually.${R}`);
|
|
277
|
+
}
|
|
267
278
|
|
|
268
279
|
return liveUrl;
|
|
269
280
|
}
|
package/src/templates.js
CHANGED
|
@@ -75,32 +75,28 @@ export default defineConfig({
|
|
|
75
75
|
* title: string,
|
|
76
76
|
* description: string,
|
|
77
77
|
* theme: string,
|
|
78
|
-
* search: boolean,
|
|
79
78
|
* comments: { repo: string, repoId: string, category: string, categoryId: string } | null,
|
|
80
79
|
* }} opts
|
|
81
80
|
*/
|
|
82
|
-
export function karaokeConfig({ title, description, theme,
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
if (comments) modules.comments = { enabled: true, ...comments };
|
|
86
|
-
|
|
87
|
-
const modulesStr = Object.keys(modules).length > 0
|
|
88
|
-
? `\n modules: ${JSON.stringify(modules, null, 2).replace(/\n/g, '\n ')},`
|
|
81
|
+
export function karaokeConfig({ title, description, theme, comments }) {
|
|
82
|
+
const commentsStr = comments
|
|
83
|
+
? `\n comments: ${JSON.stringify({ enabled: true, ...comments }, null, 2).replace(/\n/g, '\n ')},`
|
|
89
84
|
: '';
|
|
90
85
|
|
|
91
|
-
return `import
|
|
86
|
+
return `import { defineConfig } from '@karaoke-cms/astro';
|
|
87
|
+
import { blog } from '@karaoke-cms/module-blog';
|
|
88
|
+
import { themeDefault } from '@karaoke-cms/theme-default';
|
|
92
89
|
import { loadEnv } from '@karaoke-cms/astro/env';
|
|
93
90
|
|
|
94
91
|
const env = loadEnv(new URL('.', import.meta.url));
|
|
95
92
|
|
|
96
|
-
|
|
93
|
+
export default defineConfig({
|
|
97
94
|
vault: env.KARAOKE_VAULT,
|
|
98
95
|
title: ${JSON.stringify(title)},
|
|
99
96
|
description: ${JSON.stringify(description)},
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export default config;
|
|
97
|
+
modules: [blog({ mount: '/blog' })],
|
|
98
|
+
theme: themeDefault(),${commentsStr}
|
|
99
|
+
});
|
|
104
100
|
`;
|
|
105
101
|
}
|
|
106
102
|
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Config"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Config
|
|
6
|
-
|
|
7
|
-
Configuration files for your karaoke-cms vault.
|
|
8
|
-
|
|
9
|
-
| File | Purpose |
|
|
10
|
-
|------|---------|
|
|
11
|
-
| `collections.yaml` | Which collections are visible in dev vs production |
|
|
12
|
-
| `menus.yaml` | Site navigation: header menu, footer columns, and their entries |
|
|
13
|
-
|
|
14
|
-
Edit these files to change what appears on your site and in the navigation. Changes take effect on the next dev server restart or build.
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# menus.yaml — define named menus for your site.
|
|
2
|
-
#
|
|
3
|
-
# Each menu has an orientation (horizontal or vertical) and a list of entries.
|
|
4
|
-
# Entries are sorted by weight (ascending). Submenus are defined by nesting entries.
|
|
5
|
-
#
|
|
6
|
-
# when: collection:name — hide entry when the collection is disabled or has no
|
|
7
|
-
# published posts. Omit `when` to always show.
|
|
8
|
-
#
|
|
9
|
-
# If this file is absent, karaoke-cms generates a default main menu (Blog/Docs/Tags)
|
|
10
|
-
# and a default footer menu (RSS) from your active collections.
|
|
11
|
-
|
|
12
|
-
menus:
|
|
13
|
-
main:
|
|
14
|
-
orientation: horizontal
|
|
15
|
-
entries:
|
|
16
|
-
- text: Blog
|
|
17
|
-
href: /blog
|
|
18
|
-
weight: 10
|
|
19
|
-
when: collection:blog
|
|
20
|
-
- text: Docs
|
|
21
|
-
href: /docs
|
|
22
|
-
weight: 20
|
|
23
|
-
when: collection:docs
|
|
24
|
-
- text: Tags
|
|
25
|
-
href: /tags
|
|
26
|
-
weight: 30
|
|
27
|
-
- text: karaoke-cms
|
|
28
|
-
href: /karaoke-cms
|
|
29
|
-
weight: 40
|
|
30
|
-
when: collection:karaoke-cms
|
|
31
|
-
|
|
32
|
-
footer-2:
|
|
33
|
-
orientation: vertical
|
|
34
|
-
entries:
|
|
35
|
-
- text: karaoke-cms
|
|
36
|
-
href: /karaoke-cms/manual/index
|
|
37
|
-
weight: 10
|
|
38
|
-
when: collection:karaoke-cms
|
|
39
|
-
entries:
|
|
40
|
-
- text: Manual
|
|
41
|
-
href: /karaoke-cms/manual/index
|
|
42
|
-
weight: 10
|
|
43
|
-
when: collection:karaoke-cms
|
|
44
|
-
- text: Config
|
|
45
|
-
href: /karaoke-cms/config/index
|
|
46
|
-
weight: 20
|
|
47
|
-
when: collection:karaoke-cms
|
|
48
|
-
- text: Templates
|
|
49
|
-
href: /karaoke-cms/templates/index
|
|
50
|
-
weight: 30
|
|
51
|
-
when: collection:karaoke-cms
|
|
52
|
-
|
|
53
|
-
footer:
|
|
54
|
-
orientation: vertical
|
|
55
|
-
entries:
|
|
56
|
-
- text: RSS
|
|
57
|
-
href: /rss.xml
|
|
58
|
-
weight: 10
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Configuration"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Configuration
|
|
6
|
-
|
|
7
|
-
> **Handbook — dev only.**
|
|
8
|
-
|
|
9
|
-
## karaoke.config.ts
|
|
10
|
-
|
|
11
|
-
The main config file at your project root. TypeScript — fully typed.
|
|
12
|
-
|
|
13
|
-
```ts
|
|
14
|
-
import type { KaraokeConfig } from '@karaoke-cms/astro';
|
|
15
|
-
|
|
16
|
-
const config: KaraokeConfig = {
|
|
17
|
-
title: "My Site",
|
|
18
|
-
description: "What this site is about.",
|
|
19
|
-
theme: "default", // "default" | "minimal"
|
|
20
|
-
modules: {
|
|
21
|
-
search: {
|
|
22
|
-
enabled: true, // Pagefind full-text search
|
|
23
|
-
},
|
|
24
|
-
comments: {
|
|
25
|
-
enabled: true, // Giscus (GitHub Discussions)
|
|
26
|
-
repo: "owner/repo",
|
|
27
|
-
repoId: "R_...",
|
|
28
|
-
category: "General",
|
|
29
|
-
categoryId: "DIC_...",
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export default config;
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Get Giscus values from [giscus.app](https://giscus.app) after enabling Discussions on your repo.
|
|
38
|
-
|
|
39
|
-
## collections.yaml
|
|
40
|
-
|
|
41
|
-
`content/karaoke-cms/config/collections.yaml` controls which collections are visible in dev vs prod:
|
|
42
|
-
|
|
43
|
-
```yaml
|
|
44
|
-
collections:
|
|
45
|
-
blog:
|
|
46
|
-
modes: [dev, prod] # visible in both dev and production
|
|
47
|
-
label: Blog
|
|
48
|
-
docs:
|
|
49
|
-
modes: [dev, prod]
|
|
50
|
-
label: Docs
|
|
51
|
-
karaoke-cms:
|
|
52
|
-
modes: [dev] # dev-only — never ships
|
|
53
|
-
label: Handbook
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
To add a custom collection (e.g., `content/notes/`):
|
|
57
|
-
|
|
58
|
-
```yaml
|
|
59
|
-
collections:
|
|
60
|
-
notes:
|
|
61
|
-
modes: [dev, prod]
|
|
62
|
-
label: Notes
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Layout regions
|
|
66
|
-
|
|
67
|
-
Place UI components in the sidebar or header via `karaoke.config.ts`:
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
layout: {
|
|
71
|
-
regions: {
|
|
72
|
-
right: { components: ['recent-posts'] },
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Available components: `header`, `main-menu`, `search`, `recent-posts`, `footer`.
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Writing Content"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Writing Content
|
|
6
|
-
|
|
7
|
-
> **Handbook — dev only.**
|
|
8
|
-
|
|
9
|
-
## Frontmatter fields
|
|
10
|
-
|
|
11
|
-
```yaml
|
|
12
|
-
---
|
|
13
|
-
title: "My Post" # required — build fails without it
|
|
14
|
-
publish: true # required to appear on site (default: false)
|
|
15
|
-
date: 2026-01-15 # optional — YYYY-MM-DD, used for sorting
|
|
16
|
-
author: "Name" # optional — string or array ["Alice", "Bob"]
|
|
17
|
-
description: "..." # optional — used in OG meta tags and RSS
|
|
18
|
-
tags: [writing, tutorial] # optional — enables tag pages at /tags/[tag]
|
|
19
|
-
---
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Privacy model
|
|
23
|
-
|
|
24
|
-
Every file is **private by default**. `publish: false` (or a missing `publish` field) means the file stays in your vault and never enters the build — not in HTML, not in RSS, not in the sitemap, not in the Pagefind search index.
|
|
25
|
-
|
|
26
|
-
Only `publish: true` files appear on your site.
|
|
27
|
-
|
|
28
|
-
## Wikilinks
|
|
29
|
-
|
|
30
|
-
Use `[[slug]]` syntax to link between notes. karaoke-cms resolves wikilinks automatically:
|
|
31
|
-
|
|
32
|
-
- `[[blog/hello-world]]` → `/blog/hello-world/`
|
|
33
|
-
- `[[docs/getting-started]]` → `/docs/getting-started/`
|
|
34
|
-
- `[[docs/getting-started|Getting Started]]` → link text "Getting Started"
|
|
35
|
-
|
|
36
|
-
## AI enrichment (optional)
|
|
37
|
-
|
|
38
|
-
Run `npx @karaoke-cms/enrich` to auto-generate `tags`, `description`, and `reading_time` for published notes using OpenAI or Anthropic. Skips already-enriched notes via a local cache.
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Deployment"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Deployment
|
|
6
|
-
|
|
7
|
-
> **Handbook — dev only.**
|
|
8
|
-
|
|
9
|
-
## Cloudflare Pages (recommended)
|
|
10
|
-
|
|
11
|
-
1. Push your project to a GitHub repo
|
|
12
|
-
2. Go to [Cloudflare Pages](https://pages.cloudflare.com) → Create a project → Connect to your repo
|
|
13
|
-
3. Build settings:
|
|
14
|
-
- **Build command:** `npm run build`
|
|
15
|
-
- **Build output directory:** `dist`
|
|
16
|
-
- **Node.js version:** 22
|
|
17
|
-
4. Deploy
|
|
18
|
-
|
|
19
|
-
On every push to `main`, Cloudflare Pages rebuilds and redeploys automatically.
|
|
20
|
-
|
|
21
|
-
## GitHub Actions (privacy gate)
|
|
22
|
-
|
|
23
|
-
The included `deploy.yml` workflow runs `assert-privacy` on every build to verify that no private content leaks into `dist/`. If a private note accidentally gets into the build, the deploy fails before it reaches production.
|
|
24
|
-
|
|
25
|
-
## Custom domain
|
|
26
|
-
|
|
27
|
-
In Cloudflare Pages → your project → Custom domains → Add a domain. Update `site:` in `astro.config.mjs` to match:
|
|
28
|
-
|
|
29
|
-
```js
|
|
30
|
-
export default defineConfig({
|
|
31
|
-
site: 'https://your-domain.com',
|
|
32
|
-
// ...
|
|
33
|
-
});
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Environment variables
|
|
37
|
-
|
|
38
|
-
If you use `@karaoke-cms/enrich` in CI:
|
|
39
|
-
|
|
40
|
-
| Variable | Purpose |
|
|
41
|
-
|----------|---------|
|
|
42
|
-
| `OPENAI_API_KEY` | Required if `ENRICH_PROVIDER=openai` (default) |
|
|
43
|
-
| `ANTHROPIC_API_KEY` | Required if `ENRICH_PROVIDER=anthropic` |
|
|
44
|
-
| `ENRICH_ENABLED` | Set to `true` to enable AI enrichment in CI |
|
|
45
|
-
| `CLOUDFLARE_API_TOKEN` | For Cloudflare Pages deploy via GitHub Actions |
|
|
46
|
-
| `CLOUDFLARE_ACCOUNT_ID` | For Cloudflare Pages deploy via GitHub Actions |
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Handbook"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# karaoke-cms Handbook
|
|
6
|
-
|
|
7
|
-
> **Handbook — dev only.** This section is visible at `/karaoke-cms` in dev mode and never ships to production.
|
|
8
|
-
|
|
9
|
-
karaoke-cms is an Astro framework for publishing Obsidian vaults as static sites. Private-by-default: only files with `publish: true` in frontmatter appear on your site.
|
|
10
|
-
|
|
11
|
-
## How it works
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
Obsidian vault (this directory)
|
|
15
|
-
↓ write notes with publish: true
|
|
16
|
-
↓ push to main
|
|
17
|
-
↓ GitHub Actions: astro build + assert-privacy
|
|
18
|
-
↓ Cloudflare Pages
|
|
19
|
-
↓ live site
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Your vault is also your deploy pipeline config, your documentation, and your content collection — all in one place.
|
|
23
|
-
|
|
24
|
-
## Handbook sections
|
|
25
|
-
|
|
26
|
-
- [[content]] — Writing content and frontmatter
|
|
27
|
-
- [[configuration]] — karaoke.config.ts reference
|
|
28
|
-
- [[deployment]] — Deploying to Cloudflare Pages
|
|
29
|
-
- [[privacy]] — How publish:true works
|
|
30
|
-
|
|
31
|
-
## Collections
|
|
32
|
-
|
|
33
|
-
This vault has three content collections:
|
|
34
|
-
|
|
35
|
-
| Collection | Mode | Purpose |
|
|
36
|
-
|------------|------|---------|
|
|
37
|
-
| `blog/` | dev + prod | Published blog posts |
|
|
38
|
-
| `docs/` | dev + prod | Published documentation |
|
|
39
|
-
| `karaoke-cms/` | dev only | This handbook — never ships |
|
|
40
|
-
|
|
41
|
-
Edit `content/karaoke-cms/config/collections.yaml` to add your own collections or change their visibility.
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Privacy"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Privacy Model
|
|
6
|
-
|
|
7
|
-
> **Handbook — dev only.**
|
|
8
|
-
|
|
9
|
-
## The rule
|
|
10
|
-
|
|
11
|
-
**Every file is private by default.** Only files with `publish: true` in frontmatter appear on your site.
|
|
12
|
-
|
|
13
|
-
A file without `publish: true` never enters the build — not in HTML, RSS, sitemap, or the Pagefind search index.
|
|
14
|
-
|
|
15
|
-
## How it's enforced
|
|
16
|
-
|
|
17
|
-
Two independent layers:
|
|
18
|
-
|
|
19
|
-
1. **Astro content filter** — `getCollection('blog', ({ data }) => data.publish === true)` filters at the query level. Pages only receive published entries.
|
|
20
|
-
|
|
21
|
-
2. **assert-privacy** — a post-build check that scans `dist/` for known private note titles and content. If any private content leaks, the build fails before deploy.
|
|
22
|
-
|
|
23
|
-
The collection mode system adds a third layer: `karaoke-cms/` is excluded from `makeCollections()` in production entirely. Even if a handbook page had `publish: true`, it would never enter the prod build graph.
|
|
24
|
-
|
|
25
|
-
## What "private" means
|
|
26
|
-
|
|
27
|
-
| Field | Builds? | Searchable? | In RSS? | In sitemap? |
|
|
28
|
-
|-------|---------|-------------|---------|-------------|
|
|
29
|
-
| `publish: true` | Yes | Yes | Yes | Yes |
|
|
30
|
-
| `publish: false` | No | No | No | No |
|
|
31
|
-
| missing | No | No | No | No |
|
|
32
|
-
|
|
33
|
-
## Audit your site
|
|
34
|
-
|
|
35
|
-
After every build, `assert-privacy.js` outputs a summary of what shipped. Check it in your CI logs.
|
|
36
|
-
|
|
37
|
-
For a manual check: `node node_modules/@karaoke-cms/assert-privacy/dist/index.js dist`
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "" # required — build fails without it
|
|
3
|
-
publish: false # required to appear on site (default: false)
|
|
4
|
-
date: 2026-01-15 # optional — YYYY-MM-DD, used for sorting
|
|
5
|
-
author: "" # optional — string or array ["Alice", "Bob"]
|
|
6
|
-
description: "" # optional — used in OG meta tags and RSS
|
|
7
|
-
tags: [general] # optional — enables tag pages at /tags/[tag]
|
|
8
|
-
notetype: blog
|
|
9
|
-
---
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "" # required — build fails without it
|
|
3
|
-
publish: false # required to appear on site (default: false)
|
|
4
|
-
date: 2026-01-15 # optional — YYYY-MM-DD, used for sorting
|
|
5
|
-
author: "" # optional — string or array ["Alice", "Bob"]
|
|
6
|
-
description: "" # optional — used in OG meta tags and RSS
|
|
7
|
-
tags: [general] # optional — enables tag pages at /tags/[tag]
|
|
8
|
-
notetype: blog
|
|
9
|
-
---
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "" # required — build fails without it
|
|
3
|
-
publish: false # required to appear on site (default: false)
|
|
4
|
-
date: 2026-01-15 # optional — YYYY-MM-DD, used for sorting
|
|
5
|
-
author: "" # optional — string or array ["Alice", "Bob"]
|
|
6
|
-
description: "..." # optional — used in OG meta tags and RSS
|
|
7
|
-
tags: [general] # optional — enables tag pages at /tags/[tag]
|
|
8
|
-
---
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Templates"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Templates
|
|
6
|
-
|
|
7
|
-
Obsidian templates for common note types. Use with the [Templater](https://github.com/SilentVoid13/Templater) plugin.
|
|
8
|
-
|
|
9
|
-
| Template | Use for |
|
|
10
|
-
|----------|---------|
|
|
11
|
-
| `blog-header.md` | New blog posts — sets `title`, `date`, `publish: false` |
|
|
12
|
-
| `docs-header.md` | New documentation pages |
|
|
13
|
-
| `index-by-foldernote.md` | Folder index notes (requires the folder-notes Obsidian plugin) |
|
|
14
|
-
|
|
15
|
-
In Templater settings, set the template folder to `karaoke-cms/templates`.
|