idcmd 0.0.7 → 0.0.9

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 (54) hide show
  1. package/README.md +16 -16
  2. package/package.json +4 -4
  3. package/src/build.ts +38 -36
  4. package/src/cli/commands/build.ts +3 -3
  5. package/src/cli/commands/client.ts +6 -8
  6. package/src/cli/commands/deploy.ts +7 -7
  7. package/src/cli/commands/dev.ts +3 -3
  8. package/src/cli/commands/init.ts +1 -1
  9. package/src/cli/commands/preview.ts +3 -3
  10. package/src/cli/runtime-assets.ts +2 -2
  11. package/src/content/paths.ts +1 -1
  12. package/src/project/paths.ts +18 -27
  13. package/src/render/layout-loader.ts +1 -1
  14. package/src/render/right-rail-loader.ts +1 -1
  15. package/src/search/index.ts +1 -1
  16. package/src/search/search-page-loader.ts +1 -1
  17. package/src/seo/server.ts +6 -6
  18. package/src/server/live-reload.ts +1 -1
  19. package/src/server/static.ts +3 -3
  20. package/src/server.ts +5 -5
  21. package/src/site/config.ts +1 -1
  22. package/templates/default/README.md +13 -13
  23. package/templates/default/{site/content → content}/index.md +1 -1
  24. package/templates/default/scripts/check-internal.ts +6 -6
  25. package/templates/default/scripts/check.ts +6 -6
  26. package/templates/default/src/runtime/live-reload.ts +18 -0
  27. package/templates/default/src/runtime/llm-menu.ts +162 -0
  28. package/templates/default/src/runtime/nav-prefetch.ts +30 -0
  29. package/templates/default/src/runtime/right-rail-scrollspy.ts +303 -0
  30. package/templates/default/{site/code → src}/server.ts +1 -1
  31. package/templates/default/vercel.json +1 -1
  32. package/public/anthropic-black.svg +0 -16
  33. package/public/openai-black.svg +0 -15
  34. package/templates/default/site/assets/anthropic-white.svg +0 -16
  35. package/templates/default/site/assets/favicon.svg +0 -13
  36. package/templates/default/site/assets/openai-white.svg +0 -15
  37. /package/{templates/default/site/code → src}/runtime/live-reload.ts +0 -0
  38. /package/{templates/default/site/code → src}/runtime/llm-menu.ts +0 -0
  39. /package/{templates/default/site/code → src}/runtime/nav-prefetch.ts +0 -0
  40. /package/{templates/default/site/code → src}/runtime/right-rail-scrollspy.ts +0 -0
  41. /package/{public → templates/default/assets}/anthropic-white.svg +0 -0
  42. /package/{public → templates/default/assets}/favicon.svg +0 -0
  43. /package/templates/default/{site/assets → assets}/icons/file.svg +0 -0
  44. /package/templates/default/{site/assets → assets}/icons/home.svg +0 -0
  45. /package/templates/default/{site/assets → assets}/icons/info.svg +0 -0
  46. /package/{public → templates/default/assets}/openai-white.svg +0 -0
  47. /package/templates/default/{site/content → content}/404.md +0 -0
  48. /package/templates/default/{site/content → content}/about.md +0 -0
  49. /package/templates/default/{site/site.jsonc → site.jsonc} +0 -0
  50. /package/templates/default/{site/code → src}/routes/api/hello.ts +0 -0
  51. /package/templates/default/{site/code → src}/ui/layout.tsx +0 -0
  52. /package/templates/default/{site/code → src}/ui/right-rail.tsx +0 -0
  53. /package/templates/default/{site/code → src}/ui/search-page.tsx +0 -0
  54. /package/templates/default/{site/styles → styles}/tailwind.css +0 -0
package/README.md CHANGED
@@ -9,29 +9,29 @@ bun install
9
9
  bun run dev
10
10
  ```
11
11
 
12
- Everything you edit lives in `site/`.
12
+ Everything you edit lives at the project root-level source folders (`content/`, `src/`, `styles/`, `assets/`, `site.jsonc`).
13
13
 
14
14
  ## CLI
15
15
 
16
16
  ```bash
17
17
  idcmd init [dir] # scaffold a new site
18
18
  idcmd dev # tailwind watch + SSR dev server
19
- idcmd build # static dist/
20
- idcmd preview # serve dist/ locally
19
+ idcmd build # static public/
20
+ idcmd preview # serve public/ locally
21
21
  idcmd deploy # build + validate Vercel static deploy config
22
- idcmd client ... # add/update local site/code implementations
22
+ idcmd client ... # add/update local src implementations
23
23
  ```
24
24
 
25
25
  ## Layout (V1)
26
26
 
27
- - `site/content/<slug>.md` -> `/<slug>/` (`index.md` -> `/`)
28
- - `site/code/ui/*` is local UI source code (you own and edit these files)
29
- - `site/code/runtime/*.ts` is local browser runtime code (compiled to `dist/_idcmd/*.js`)
30
- - `site/code/routes/**` file-based server routes (dev/server-host only)
31
- - `site/styles/tailwind.css` -> `dist/styles.css`
32
- - `site/assets/` static assets
33
- - `site/site.jsonc` site config
34
- - `dist/` generated output (gitignored)
27
+ - `content/<slug>.md` -> `/<slug>/` (`index.md` -> `/`)
28
+ - `src/ui/*` is local UI source code (you own and edit these files)
29
+ - `src/runtime/*.ts` is local browser runtime code (compiled to `public/_idcmd/*.js`)
30
+ - `src/routes/**` file-based server routes (dev/server-host only)
31
+ - `styles/tailwind.css` -> `public/styles.css`
32
+ - `assets/` static assets
33
+ - `site.jsonc` site config
34
+ - `public/` generated output (gitignored)
35
35
 
36
36
  ## Syncing Local Client Code
37
37
 
@@ -45,11 +45,11 @@ idcmd client update runtime --yes
45
45
  ```
46
46
 
47
47
  `add` creates missing files. `update` overwrites changed files and requires `--yes` unless `--dry-run` is used.
48
- Runtime files in `site/code/runtime/` are compiled automatically by `idcmd dev` and `idcmd build`.
48
+ Runtime files in `src/runtime/` are compiled automatically by `idcmd dev` and `idcmd build`.
49
49
 
50
50
  ## Example: Add A Page
51
51
 
52
- Create `site/content/hello.md`:
52
+ Create `content/hello.md`:
53
53
 
54
54
  ```md
55
55
  ---
@@ -68,7 +68,7 @@ It renders at `/hello/`.
68
68
 
69
69
  ## Custom Server Routes (V1)
70
70
 
71
- Add `site/code/routes/api/hello.ts`:
71
+ Add `src/routes/api/hello.ts`:
72
72
 
73
73
  ```ts
74
74
  export const GET = (): Response => Response.json({ ok: true });
@@ -94,7 +94,7 @@ It responds at `/api/hello`.
94
94
 
95
95
  ### Slug and path rules
96
96
 
97
- - Content lives at `site/content/<slug>.md`.
97
+ - Content lives at `content/<slug>.md`.
98
98
  - `slug="index"` is the home page.
99
99
  - Canonical HTML paths are `/` for index and `/<slug>/` otherwise.
100
100
  - Markdown download paths exist in two forms:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "idcmd",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/rustydotwtf/idcmd"
@@ -22,11 +22,11 @@
22
22
  },
23
23
  "scripts": {
24
24
  "dev": "concurrently -k -n css,server -c blue,green \"bun run dev:css\" \"bun run dev:server\"",
25
- "dev:css": "bunx @tailwindcss/cli -i content/styles.css -o public/styles.css --watch",
25
+ "dev:css": "bunx @tailwindcss/cli -i styles/tailwind.css -o public/styles.css --watch",
26
26
  "dev:server": "bun --hot src/server.ts",
27
- "build:css": "bunx @tailwindcss/cli -i content/styles.css -o dist/styles.css --minify",
27
+ "build:css": "bunx @tailwindcss/cli -i styles/tailwind.css -o public/styles.css --minify",
28
28
  "build": "bun run build:css && bun src/build.ts",
29
- "preview": "bunx serve dist",
29
+ "preview": "bunx serve public",
30
30
  "start": "bun src/server.ts",
31
31
  "check": "bun run scripts/check.ts",
32
32
  "test": "bun test",
package/src/build.ts CHANGED
@@ -20,7 +20,7 @@ const MIN_SEARCH_QUERY_LENGTH = 2;
20
20
 
21
21
  const project = await getProjectPaths();
22
22
 
23
- // Find all content files in `site/content/` (`site/content/<slug>.md`).
23
+ // Find all content files in `content/` (`content/<slug>.md`).
24
24
  const contentFiles: string[] = [];
25
25
 
26
26
  const buildStart = performance.now();
@@ -40,26 +40,26 @@ console.log(
40
40
  `Found ${navigation.length} groups with ${navigation.reduce((acc, g) => acc + g.items.length, 0)} total pages`
41
41
  );
42
42
 
43
- // Ensure dist directory exists
44
- await Bun.write(`${project.distDir}/.gitkeep`, "");
43
+ // Ensure output directory exists
44
+ await Bun.write(`${project.outputDir}/.gitkeep`, "");
45
45
 
46
- const shouldCopyPublicPath = (relativePath: string): boolean =>
47
- // Do not overwrite the minified `dist/styles.css` produced by `build:css`.
46
+ const shouldCopyAssetPath = (relativePath: string): boolean =>
47
+ // Do not overwrite the minified `public/styles.css` produced by `build:css`.
48
48
  relativePath !== "styles.css";
49
49
 
50
- const copyPublicFileToDist = async (relativePath: string): Promise<void> => {
51
- const file = Bun.file(`${project.publicDir}/${relativePath}`);
50
+ const copyAssetFileToOutput = async (relativePath: string): Promise<void> => {
51
+ const file = Bun.file(`${project.assetsDir}/${relativePath}`);
52
52
  if (!(await file.exists())) {
53
53
  return;
54
54
  }
55
- await Bun.write(`${project.distDir}/${relativePath}`, file);
55
+ await Bun.write(`${project.outputDir}/${relativePath}`, file);
56
56
  };
57
57
 
58
- const copyPublicToDist = async (): Promise<void> => {
59
- const publicFiles = new Bun.Glob("**/*").scan(project.publicDir);
60
- for await (const relativePath of publicFiles) {
61
- if (shouldCopyPublicPath(relativePath)) {
62
- await copyPublicFileToDist(relativePath);
58
+ const copyAssetsToOutput = async (): Promise<void> => {
59
+ const assetFiles = new Bun.Glob("**/*").scan(project.assetsDir);
60
+ for await (const relativePath of assetFiles) {
61
+ if (shouldCopyAssetPath(relativePath)) {
62
+ await copyAssetFileToOutput(relativePath);
63
63
  }
64
64
  }
65
65
  };
@@ -70,8 +70,8 @@ const writeMarkdownOutputs = async (
70
70
  ): Promise<void> => {
71
71
  const flatMarkdownPath =
72
72
  slug === "index"
73
- ? `${project.distDir}/index.md`
74
- : `${project.distDir}/${slug}.md`;
73
+ ? `${project.outputDir}/index.md`
74
+ : `${project.outputDir}/${slug}.md`;
75
75
 
76
76
  const expanded = await expandMarkdownForAgent(markdown, {
77
77
  currentPath: slug === "index" ? "/" : `/${slug}/`,
@@ -84,14 +84,14 @@ const writeMarkdownOutputs = async (
84
84
  console.log(` markdown -> ${flatMarkdownPath}`);
85
85
  };
86
86
 
87
- await copyPublicToDist();
87
+ await copyAssetsToOutput();
88
88
 
89
89
  const resolveCssSource = async (): Promise<string | null> => {
90
- if (await Bun.file(`${project.distDir}/styles.css`).exists()) {
91
- return `${project.distDir}/styles.css`;
90
+ if (await Bun.file(`${project.outputDir}/styles.css`).exists()) {
91
+ return `${project.outputDir}/styles.css`;
92
92
  }
93
- if (await Bun.file(`${project.publicDir}/styles.css`).exists()) {
94
- return `${project.publicDir}/styles.css`;
93
+ if (await Bun.file(`${project.assetsDir}/styles.css`).exists()) {
94
+ return `${project.assetsDir}/styles.css`;
95
95
  }
96
96
  return null;
97
97
  };
@@ -138,10 +138,10 @@ const renderStaticSearchPage = async (): Promise<string> => {
138
138
  };
139
139
 
140
140
  await Bun.write(
141
- `${project.distDir}/search/index.html`,
141
+ `${project.outputDir}/search/index.html`,
142
142
  await renderStaticSearchPage()
143
143
  );
144
- console.log(` generated ${project.distDir}/search/index.html`);
144
+ console.log(` generated ${project.outputDir}/search/index.html`);
145
145
 
146
146
  for (const file of contentFiles) {
147
147
  const filePath = `${project.contentDir}/${file}`;
@@ -160,11 +160,11 @@ for (const file of contentFiles) {
160
160
 
161
161
  let outPath: string;
162
162
  if (slug === "index") {
163
- outPath = `${project.distDir}/index.html`;
163
+ outPath = `${project.outputDir}/index.html`;
164
164
  } else if (slug === "404") {
165
- outPath = `${project.distDir}/404.html`;
165
+ outPath = `${project.outputDir}/404.html`;
166
166
  } else {
167
- outPath = `${project.distDir}/${slug}/index.html`;
167
+ outPath = `${project.outputDir}/${slug}/index.html`;
168
168
  }
169
169
 
170
170
  await Bun.write(outPath, html);
@@ -172,24 +172,26 @@ for (const file of contentFiles) {
172
172
  await writeMarkdownOutputs(slug, markdown);
173
173
 
174
174
  if (slug === "404") {
175
- const nested404Path = `${project.distDir}/404/index.html`;
175
+ const nested404Path = `${project.outputDir}/404/index.html`;
176
176
  await Bun.write(nested404Path, html);
177
177
  console.log(` ${filePath} -> ${nested404Path}`);
178
178
  }
179
179
  }
180
180
 
181
181
  const llmsTxt = await generateLlmsTxt();
182
- await Bun.write(`${project.distDir}/llms.txt`, llmsTxt);
183
- console.log(` generated ${project.distDir}/llms.txt`);
182
+ await Bun.write(`${project.outputDir}/llms.txt`, llmsTxt);
183
+ console.log(` generated ${project.outputDir}/llms.txt`);
184
184
 
185
185
  const searchIndex = await generateSearchIndexFromContent({ siteConfig });
186
186
  await Bun.write(
187
- `${project.distDir}/search-index.json`,
187
+ `${project.outputDir}/search-index.json`,
188
188
  JSON.stringify(searchIndex)
189
189
  );
190
- const searchIndexBytes = Bun.file(`${project.distDir}/search-index.json`).size;
190
+ const searchIndexBytes = Bun.file(
191
+ `${project.outputDir}/search-index.json`
192
+ ).size;
191
193
  console.log(
192
- ` generated dist/search-index.json (${(searchIndexBytes / (1024 * 1024)).toFixed(2)} MB)`
194
+ ` generated public/search-index.json (${(searchIndexBytes / (1024 * 1024)).toFixed(2)} MB)`
193
195
  );
194
196
  if (searchIndexBytes > MAX_INDEX_BYTES) {
195
197
  console.warn(
@@ -200,19 +202,19 @@ if (searchIndexBytes > MAX_INDEX_BYTES) {
200
202
  if (siteConfig.baseUrl) {
201
203
  const sitemapPages = await collectSitemapPagesFromContent();
202
204
  await Bun.write(
203
- `${project.distDir}/sitemap.xml`,
205
+ `${project.outputDir}/sitemap.xml`,
204
206
  generateSitemapXml(sitemapPages, siteConfig.baseUrl)
205
207
  );
206
- console.log(` generated ${project.distDir}/sitemap.xml`);
208
+ console.log(` generated ${project.outputDir}/sitemap.xml`);
207
209
 
208
210
  await Bun.write(
209
- `${project.distDir}/robots.txt`,
211
+ `${project.outputDir}/robots.txt`,
210
212
  generateRobotsTxt(siteConfig.baseUrl)
211
213
  );
212
- console.log(` generated ${project.distDir}/robots.txt`);
214
+ console.log(` generated ${project.outputDir}/robots.txt`);
213
215
  } else {
214
216
  console.log(
215
- "Warning: site/site.jsonc missing baseUrl; skipping sitemap.xml and robots.txt."
217
+ "Warning: site.jsonc missing baseUrl; skipping sitemap.xml and robots.txt."
216
218
  );
217
219
  }
218
220
 
@@ -1,12 +1,12 @@
1
1
  import { compileRuntimeAssetsOnce } from "../runtime-assets";
2
2
 
3
3
  const findTailwindInput = async (): Promise<string> => {
4
- const path = "site/styles/tailwind.css";
4
+ const path = "styles/tailwind.css";
5
5
  if (await Bun.file(path).exists()) {
6
6
  return path;
7
7
  }
8
8
  throw new Error(
9
- "Could not find Tailwind input. Expected site/styles/tailwind.css."
9
+ "Could not find Tailwind input. Expected styles/tailwind.css."
10
10
  );
11
11
  };
12
12
 
@@ -29,7 +29,7 @@ export const buildCommand = async (): Promise<number> => {
29
29
  "-i",
30
30
  tailwindInput,
31
31
  "-o",
32
- "dist/styles.css",
32
+ "public/styles.css",
33
33
  "--minify",
34
34
  ],
35
35
  { stderr: "inherit", stdout: "inherit" }
@@ -8,8 +8,7 @@ const TEMPLATE_UI_DIR = joinPath(
8
8
  "..",
9
9
  "templates",
10
10
  "default",
11
- "site",
12
- "code",
11
+ "src",
13
12
  "ui"
14
13
  );
15
14
  const TEMPLATE_RUNTIME_DIR = joinPath(
@@ -19,14 +18,13 @@ const TEMPLATE_RUNTIME_DIR = joinPath(
19
18
  "..",
20
19
  "templates",
21
20
  "default",
22
- "site",
23
- "code",
21
+ "src",
24
22
  "runtime"
25
23
  );
26
24
 
27
- const SITE_UI_DIR = joinPath("site", "code", "ui");
28
- const SITE_RUNTIME_DIR = joinPath("site", "code", "runtime");
29
- const SITE_CONFIG_PATH = joinPath("site", "site.jsonc");
25
+ const SITE_UI_DIR = joinPath("src", "ui");
26
+ const SITE_RUNTIME_DIR = joinPath("src", "runtime");
27
+ const SITE_CONFIG_PATH = "site.jsonc";
30
28
 
31
29
  const CLIENT_PARTS = [
32
30
  "layout",
@@ -144,7 +142,7 @@ const parseClientArgs = (positionals: string[]): ParsedClientArgs => {
144
142
  const ensureSiteLayout = async (): Promise<void> => {
145
143
  if (!(await Bun.file(SITE_CONFIG_PATH).exists())) {
146
144
  throw new Error(
147
- `Could not find ${SITE_CONFIG_PATH}. Run this command from an idcmd site project root.`
145
+ `Could not find ${SITE_CONFIG_PATH}. Run this command from an idcmd project root.`
148
146
  );
149
147
  }
150
148
  };
@@ -14,23 +14,23 @@ const warnIfVercelMisconfigured = async (): Promise<void> => {
14
14
  if (!raw) {
15
15
  // eslint-disable-next-line no-console
16
16
  console.warn(
17
- "Warning: vercel.json not found. Vercel static deploy expects dist/ output."
17
+ "Warning: vercel.json not found. Vercel static deploy expects public/ output."
18
18
  );
19
19
  return;
20
20
  }
21
21
 
22
22
  const record = raw as Record<string, unknown>;
23
23
  const out = record.outputDirectory;
24
- if (out !== "dist") {
24
+ if (out !== "public") {
25
25
  // eslint-disable-next-line no-console
26
26
  console.warn(
27
- `Warning: vercel.json outputDirectory is not "dist" (got ${JSON.stringify(out)}).`
27
+ `Warning: vercel.json outputDirectory is not "public" (got ${JSON.stringify(out)}).`
28
28
  );
29
29
  }
30
30
  };
31
31
 
32
32
  const warnIfBaseUrlMissing = async (): Promise<void> => {
33
- const file = Bun.file("site/site.jsonc");
33
+ const file = Bun.file("site.jsonc");
34
34
  if (!(await file.exists())) {
35
35
  return;
36
36
  }
@@ -42,13 +42,13 @@ const warnIfBaseUrlMissing = async (): Promise<void> => {
42
42
  if (!cfg.baseUrl) {
43
43
  // eslint-disable-next-line no-console
44
44
  console.warn(
45
- "Warning: site/site.jsonc missing baseUrl; sitemap.xml and robots.txt will be skipped."
45
+ "Warning: site.jsonc missing baseUrl; sitemap.xml and robots.txt will be skipped."
46
46
  );
47
47
  }
48
48
  } catch (error) {
49
49
  const message = error instanceof Error ? error.message : String(error);
50
50
  // eslint-disable-next-line no-console
51
- console.warn(`Warning: Failed to parse site/site.jsonc: ${message}`);
51
+ console.warn(`Warning: Failed to parse site.jsonc: ${message}`);
52
52
  }
53
53
  };
54
54
 
@@ -76,7 +76,7 @@ const printDeployInstructions = (): void => {
76
76
  // eslint-disable-next-line no-console
77
77
  console.log(" 2. Import the repo in Vercel");
78
78
  // eslint-disable-next-line no-console
79
- console.log(" 3. Vercel will run `bun run build` and serve `dist/`");
79
+ console.log(" 3. Vercel will run `bun run build` and serve `public/`");
80
80
  // eslint-disable-next-line no-console
81
81
  console.log("");
82
82
  };
@@ -11,16 +11,16 @@ export interface DevFlags {
11
11
  }
12
12
 
13
13
  const findTailwindInput = async (): Promise<string> => {
14
- const path = "site/styles/tailwind.css";
14
+ const path = "styles/tailwind.css";
15
15
  if (await Bun.file(path).exists()) {
16
16
  return path;
17
17
  }
18
18
  throw new Error(
19
- "Could not find Tailwind input. Expected site/styles/tailwind.css."
19
+ "Could not find Tailwind input. Expected styles/tailwind.css."
20
20
  );
21
21
  };
22
22
 
23
- const resolveTailwindOutput = (): string => "dist/styles.css";
23
+ const resolveTailwindOutput = (): string => "public/styles.css";
24
24
 
25
25
  const idcmdServerEntry = (): string =>
26
26
  // `src/server.ts` lives two levels up from `src/cli/commands/*`.
@@ -200,7 +200,7 @@ const applySubstitutions = async (args: {
200
200
  siteName: string;
201
201
  targetDir: string;
202
202
  }): Promise<void> => {
203
- await replaceInFile(joinPath(args.targetDir, "site", "site.jsonc"), (text) =>
203
+ await replaceInFile(joinPath(args.targetDir, "site.jsonc"), (text) =>
204
204
  fillSiteJsonc({
205
205
  baseUrl: args.baseUrl,
206
206
  description: args.description,
@@ -7,7 +7,7 @@ const stripLeadingSlash = (pathname: string): string =>
7
7
  pathname.startsWith("/") ? pathname.slice(1) : pathname;
8
8
 
9
9
  const tryServeFile = async (relativePath: string): Promise<Response | null> => {
10
- const file = Bun.file(`dist/${stripLeadingSlash(relativePath)}`);
10
+ const file = Bun.file(`public/${stripLeadingSlash(relativePath)}`);
11
11
  if (!(await file.exists())) {
12
12
  return null;
13
13
  }
@@ -37,9 +37,9 @@ const serveHtml = async (pathname: string): Promise<Response> => {
37
37
  };
38
38
 
39
39
  export const previewCommand = async (port: number): Promise<number> => {
40
- const exists = await Bun.file("dist/index.html").exists();
40
+ const exists = await Bun.file("public/index.html").exists();
41
41
  if (!exists) {
42
- throw new Error("dist/ not found. Run `idcmd build` first.");
42
+ throw new Error("public/ not found. Run `idcmd build` first.");
43
43
  }
44
44
 
45
45
  const server = Bun.serve({
@@ -1,7 +1,7 @@
1
1
  import { joinPath } from "./path";
2
2
 
3
- const RUNTIME_SOURCE_DIR = joinPath("site", "code", "runtime");
4
- const RUNTIME_OUTPUT_DIR = joinPath("dist", "_idcmd");
3
+ const RUNTIME_SOURCE_DIR = joinPath("src", "runtime");
4
+ const RUNTIME_OUTPUT_DIR = joinPath("public", "_idcmd");
5
5
 
6
6
  const RUNTIME_ENTRY_FILES = [
7
7
  "live-reload.ts",
@@ -21,7 +21,7 @@ export const slugFromContentFile = (file: string): string => {
21
21
  export const scanContentFiles =
22
22
  async function* scanContentFiles(): AsyncGenerator<string> {
23
23
  const { contentDir } = await getProjectPaths();
24
- // `site/content/<slug>.md`
24
+ // `content/<slug>.md`
25
25
  for await (const file of flatContentGlob.scan(contentDir)) {
26
26
  yield file;
27
27
  }
@@ -1,27 +1,24 @@
1
- const DEFAULT_SITE_DIR = "site";
2
- const DEFAULT_DIST_DIR = "dist";
1
+ const DEFAULT_OUTPUT_DIR = "public";
3
2
  const ASSET_PREFIX = "/_idcmd" as const;
4
3
  const CONTENT_DIR = "content";
5
- const PUBLIC_DIR = "assets";
4
+ const ASSETS_DIR = "assets";
6
5
  const ICONS_DIR = "assets/icons";
7
- const ROUTES_DIR = "code/routes";
6
+ const ROUTES_DIR = "src/routes";
8
7
  const SITE_CONFIG_FILE = "site.jsonc";
9
8
 
10
9
  export interface ProjectPaths {
11
10
  assetPrefix: typeof ASSET_PREFIX;
12
11
  contentDir: string;
13
- distDir: string;
12
+ outputDir: string;
14
13
  iconsDir: string;
15
- publicDir: string;
14
+ assetsDir: string;
16
15
  routesDir: string;
17
16
  siteConfigPath: string;
18
- siteDir: string | null;
19
17
  }
20
18
 
21
19
  export interface ResolveProjectPathsOptions {
22
20
  cwd?: string;
23
- distDir?: string;
24
- siteDir?: string;
21
+ outputDir?: string;
25
22
  }
26
23
 
27
24
  const trimTrailingSlash = (value: string): string =>
@@ -44,29 +41,23 @@ const joinPath = (...parts: string[]): string => {
44
41
 
45
42
  const buildPaths = (args: {
46
43
  cwd: string;
47
- distDirName: string;
48
- siteDirName: string;
49
- }): ProjectPaths => {
50
- const siteRoot = joinPath(args.cwd, args.siteDirName);
51
- return {
52
- assetPrefix: ASSET_PREFIX,
53
- contentDir: joinPath(siteRoot, CONTENT_DIR),
54
- distDir: joinPath(args.cwd, args.distDirName),
55
- iconsDir: joinPath(siteRoot, ICONS_DIR),
56
- publicDir: joinPath(siteRoot, PUBLIC_DIR),
57
- routesDir: joinPath(siteRoot, ROUTES_DIR),
58
- siteConfigPath: joinPath(siteRoot, SITE_CONFIG_FILE),
59
- siteDir: siteRoot,
60
- };
61
- };
44
+ outputDirName: string;
45
+ }): ProjectPaths => ({
46
+ assetPrefix: ASSET_PREFIX,
47
+ assetsDir: joinPath(args.cwd, ASSETS_DIR),
48
+ contentDir: joinPath(args.cwd, CONTENT_DIR),
49
+ iconsDir: joinPath(args.cwd, ICONS_DIR),
50
+ outputDir: joinPath(args.cwd, args.outputDirName),
51
+ routesDir: joinPath(args.cwd, ROUTES_DIR),
52
+ siteConfigPath: joinPath(args.cwd, SITE_CONFIG_FILE),
53
+ });
62
54
 
63
55
  export const resolveProjectPaths = (
64
56
  options: ResolveProjectPathsOptions = {}
65
57
  ): Promise<ProjectPaths> => {
66
58
  const cwd = trimTrailingSlash(options.cwd ?? process.cwd());
67
- const distDirName = options.distDir ?? DEFAULT_DIST_DIR;
68
- const siteDirName = options.siteDir ?? DEFAULT_SITE_DIR;
69
- return Promise.resolve(buildPaths({ cwd, distDirName, siteDirName }));
59
+ const outputDirName = options.outputDir ?? DEFAULT_OUTPUT_DIR;
60
+ return Promise.resolve(buildPaths({ cwd, outputDirName }));
70
61
  };
71
62
 
72
63
  let cached: Promise<ProjectPaths> | null = null;
@@ -2,7 +2,7 @@ import type { RenderLayout } from "./layout";
2
2
 
3
3
  import { renderLayout as defaultRenderLayout } from "./layout";
4
4
 
5
- const USER_LAYOUT_PATH = "site/code/ui/layout.tsx";
5
+ const USER_LAYOUT_PATH = "src/ui/layout.tsx";
6
6
 
7
7
  const loadUserLayout = async (
8
8
  filePath: string
@@ -2,7 +2,7 @@ import type { RightRailComponent } from "./right-rail";
2
2
 
3
3
  import { RightRail as defaultRightRail } from "./right-rail";
4
4
 
5
- const USER_RIGHT_RAIL_PATH = "site/code/ui/right-rail.tsx";
5
+ const USER_RIGHT_RAIL_PATH = "src/ui/right-rail.tsx";
6
6
 
7
7
  const loadUserRightRail = async (
8
8
  filePath: string
@@ -26,7 +26,7 @@ export interface SearchIndexV1 {
26
26
  documents: SearchIndexDocumentV1[];
27
27
  }
28
28
 
29
- const SEARCH_INDEX_PATH = "dist/search-index.json";
29
+ const SEARCH_INDEX_PATH = "public/search-index.json";
30
30
  const MIN_QUERY_TOKEN_LENGTH = 2;
31
31
  const DEFAULT_BODY_MAX_CHARS = 2000;
32
32
 
@@ -2,7 +2,7 @@ import type { RenderSearchPageContent } from "./page";
2
2
 
3
3
  import { renderSearchPageContent as defaultRenderSearchPageContent } from "./page";
4
4
 
5
- const USER_SEARCH_PAGE_PATH = "site/code/ui/search-page.tsx";
5
+ const USER_SEARCH_PAGE_PATH = "src/ui/search-page.tsx";
6
6
 
7
7
  const loadUserSearchPage = async (
8
8
  filePath: string
package/src/seo/server.ts CHANGED
@@ -7,12 +7,12 @@ import {
7
7
  } from "./files";
8
8
 
9
9
  export interface SeoHandlerEnv {
10
- distDir: string;
10
+ outputDir: string;
11
11
  isDev: boolean;
12
12
  staticCacheHeaders: HeadersInit;
13
13
  }
14
14
 
15
- const tryServeDistFile = async (
15
+ const tryServeOutputFile = async (
16
16
  filePath: string,
17
17
  contentType: string,
18
18
  env: SeoHandlerEnv
@@ -42,8 +42,8 @@ export const handleRobotsTxt = async (
42
42
  return undefined;
43
43
  }
44
44
 
45
- const served = await tryServeDistFile(
46
- `${env.distDir}/robots.txt`,
45
+ const served = await tryServeOutputFile(
46
+ `${env.outputDir}/robots.txt`,
47
47
  "text/plain; charset=utf-8",
48
48
  env
49
49
  );
@@ -75,8 +75,8 @@ export const handleSitemapXml = async (
75
75
  return undefined;
76
76
  }
77
77
 
78
- const served = await tryServeDistFile(
79
- `${env.distDir}/sitemap.xml`,
78
+ const served = await tryServeOutputFile(
79
+ `${env.outputDir}/sitemap.xml`,
80
80
  "application/xml; charset=utf-8",
81
81
  env
82
82
  );
@@ -59,7 +59,7 @@ export const createLiveReload = (env: LiveReloadEnv): LiveReloadController => {
59
59
  return;
60
60
  }
61
61
 
62
- console.log("Watching site/content/ for changes...");
62
+ console.log("Watching content/ for changes...");
63
63
  let snapshot = await getContentSnapshot();
64
64
 
65
65
  const poll = async (): Promise<void> => {
@@ -13,9 +13,9 @@ const mimeTypes: Record<string, string> = {
13
13
  };
14
14
 
15
15
  export interface ServeStaticEnv {
16
- distDir: string;
16
+ outputDir: string;
17
17
  isDev: boolean;
18
- publicDir: string;
18
+ assetsDir: string;
19
19
  staticCacheHeaders: HeadersInit;
20
20
  }
21
21
 
@@ -46,7 +46,7 @@ export const serveStaticFile = async (
46
46
  pathname: string,
47
47
  env: ServeStaticEnv
48
48
  ): Promise<Response | null> => {
49
- const roots = [env.distDir, env.publicDir];
49
+ const roots = [env.outputDir, env.assetsDir];
50
50
 
51
51
  for (const root of roots) {
52
52
  const served = await tryServeFileFromRoot(root, pathname, env);