scribe-cms 0.0.1

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 (96) hide show
  1. package/README.md +150 -0
  2. package/dist/cli/index.cjs +2303 -0
  3. package/dist/cli/index.cjs.map +1 -0
  4. package/dist/cli/index.d.ts +3 -0
  5. package/dist/cli/index.d.ts.map +1 -0
  6. package/dist/cli/index.js +2289 -0
  7. package/dist/cli/index.js.map +1 -0
  8. package/dist/index.cjs +2268 -0
  9. package/dist/index.cjs.map +1 -0
  10. package/dist/index.js +2238 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/runtime.cjs +1216 -0
  13. package/dist/runtime.cjs.map +1 -0
  14. package/dist/runtime.js +1207 -0
  15. package/dist/runtime.js.map +1 -0
  16. package/dist/src/config/load-config.d.ts +10 -0
  17. package/dist/src/config/load-config.d.ts.map +1 -0
  18. package/dist/src/config/load-env.d.ts +3 -0
  19. package/dist/src/config/load-env.d.ts.map +1 -0
  20. package/dist/src/config/resolve-config.d.ts +13 -0
  21. package/dist/src/config/resolve-config.d.ts.map +1 -0
  22. package/dist/src/core/alias-helpers.d.ts +7 -0
  23. package/dist/src/core/alias-helpers.d.ts.map +1 -0
  24. package/dist/src/core/builtin-fields.d.ts +38 -0
  25. package/dist/src/core/builtin-fields.d.ts.map +1 -0
  26. package/dist/src/core/field.d.ts +60 -0
  27. package/dist/src/core/field.d.ts.map +1 -0
  28. package/dist/src/core/introspect-schema.d.ts +20 -0
  29. package/dist/src/core/introspect-schema.d.ts.map +1 -0
  30. package/dist/src/core/slug-aliases.d.ts +27 -0
  31. package/dist/src/core/slug-aliases.d.ts.map +1 -0
  32. package/dist/src/core/types.d.ts +261 -0
  33. package/dist/src/core/types.d.ts.map +1 -0
  34. package/dist/src/create-project.d.ts +10 -0
  35. package/dist/src/create-project.d.ts.map +1 -0
  36. package/dist/src/create-scribe.d.ts +11 -0
  37. package/dist/src/create-scribe.d.ts.map +1 -0
  38. package/dist/src/hash/page-hash.d.ts +7 -0
  39. package/dist/src/hash/page-hash.d.ts.map +1 -0
  40. package/dist/src/history/record-revision.d.ts +12 -0
  41. package/dist/src/history/record-revision.d.ts.map +1 -0
  42. package/dist/src/i18n/build-url.d.ts +14 -0
  43. package/dist/src/i18n/build-url.d.ts.map +1 -0
  44. package/dist/src/i18n/resolve-document.d.ts +12 -0
  45. package/dist/src/i18n/resolve-document.d.ts.map +1 -0
  46. package/dist/src/i18n/translation-index.d.ts +7 -0
  47. package/dist/src/i18n/translation-index.d.ts.map +1 -0
  48. package/dist/src/index.d.ts +18 -0
  49. package/dist/src/index.d.ts.map +1 -0
  50. package/dist/src/loader/create-loader.d.ts +17 -0
  51. package/dist/src/loader/create-loader.d.ts.map +1 -0
  52. package/dist/src/loader/normalize-en.d.ts +3 -0
  53. package/dist/src/loader/normalize-en.d.ts.map +1 -0
  54. package/dist/src/loader/parse-mdx.d.ts +7 -0
  55. package/dist/src/loader/parse-mdx.d.ts.map +1 -0
  56. package/dist/src/redirects/build-redirects.d.ts +17 -0
  57. package/dist/src/redirects/build-redirects.d.ts.map +1 -0
  58. package/dist/src/redirects/translation-index.d.ts +4 -0
  59. package/dist/src/redirects/translation-index.d.ts.map +1 -0
  60. package/dist/src/redirects/types.d.ts +6 -0
  61. package/dist/src/redirects/types.d.ts.map +1 -0
  62. package/dist/src/runtime.d.ts +5 -0
  63. package/dist/src/runtime.d.ts.map +1 -0
  64. package/dist/src/sitemap/generate-sitemap.d.ts +5 -0
  65. package/dist/src/sitemap/generate-sitemap.d.ts.map +1 -0
  66. package/dist/src/sitemap/join-base-url.d.ts +3 -0
  67. package/dist/src/sitemap/join-base-url.d.ts.map +1 -0
  68. package/dist/src/sitemap/types.d.ts +39 -0
  69. package/dist/src/sitemap/types.d.ts.map +1 -0
  70. package/dist/src/storage/sqlite.d.ts +9 -0
  71. package/dist/src/storage/sqlite.d.ts.map +1 -0
  72. package/dist/src/storage/translations.d.ts +58 -0
  73. package/dist/src/storage/translations.d.ts.map +1 -0
  74. package/dist/src/translate/gemini-client.d.ts +15 -0
  75. package/dist/src/translate/gemini-client.d.ts.map +1 -0
  76. package/dist/src/translate/page-translator.d.ts +24 -0
  77. package/dist/src/translate/page-translator.d.ts.map +1 -0
  78. package/dist/src/translate/prompts/translation-prompt.d.ts +14 -0
  79. package/dist/src/translate/prompts/translation-prompt.d.ts.map +1 -0
  80. package/dist/src/translate/resolve-translate-config.d.ts +10 -0
  81. package/dist/src/translate/resolve-translate-config.d.ts.map +1 -0
  82. package/dist/src/translate/worklist.d.ts +19 -0
  83. package/dist/src/translate/worklist.d.ts.map +1 -0
  84. package/dist/src/validate/validate-project.d.ts +16 -0
  85. package/dist/src/validate/validate-project.d.ts.map +1 -0
  86. package/dist/src/validate/validate-relations.d.ts +19 -0
  87. package/dist/src/validate/validate-relations.d.ts.map +1 -0
  88. package/dist/src/validate/validate-slug-suffix.d.ts +12 -0
  89. package/dist/src/validate/validate-slug-suffix.d.ts.map +1 -0
  90. package/dist/studio/server.cjs +673 -0
  91. package/dist/studio/server.cjs.map +1 -0
  92. package/dist/studio/server.d.ts +7 -0
  93. package/dist/studio/server.d.ts.map +1 -0
  94. package/dist/studio/server.js +664 -0
  95. package/dist/studio/server.js.map +1 -0
  96. package/package.json +70 -0
package/README.md ADDED
@@ -0,0 +1,150 @@
1
+ # Scribe
2
+
3
+ Typed, file-based CMS for multilingual MDX. English source files on disk, locale translations in SQLite, Zod schemas, Gemini-powered translation, and a framework-agnostic runtime API.
4
+
5
+ Scribe has no framework dependency — it reads files and SQLite in-process and works with any Node-based stack (Next.js, Astro, Remix, SvelteKit, a static-site script, …). Examples in these docs use Next.js, but nothing about Scribe is Next-specific.
6
+
7
+ **Docs:** [Getting started](./docs/getting-started.md) · [Configuration](./docs/configuration.md) · [Writing content](./docs/content.md) · [Runtime API](./docs/runtime-api.md) · [Translation](./docs/translation.md)
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pnpm add scribe-cms zod better-sqlite3
13
+ ```
14
+
15
+ Set `GEMINI_API_KEY` when using `scribe translate`.
16
+
17
+ ## Quickstart
18
+
19
+ ### 1. Define the config
20
+
21
+ ```ts
22
+ // scribe.config.ts (at your project root)
23
+ import path from "node:path";
24
+ import { fileURLToPath } from "node:url";
25
+ import { z } from "zod";
26
+ import { defineConfig, defineContentType, field } from "scribe-cms";
27
+
28
+ const blogSchema = z.object({
29
+ title: field.translatable(z.string().min(1)),
30
+ description: field.translatable(z.string().min(50)),
31
+ author: field.relation("author"),
32
+ tags: field.structural(z.array(z.string()).default([])),
33
+ });
34
+
35
+ const authorSchema = z.object({
36
+ name: field.structural(z.string().min(1)),
37
+ });
38
+
39
+ export default defineConfig({
40
+ rootDir: path.dirname(fileURLToPath(import.meta.url)),
41
+ // contentDir: "content" (default)
42
+ // store: ".scribe/store.sqlite" (default)
43
+ locales: ["en", "fr"],
44
+ // defaultLocale: "en" (default)
45
+ types: [
46
+ defineContentType({
47
+ id: "blog",
48
+ path: "/blog/{slug}", // routable: gets URLs, sitemap, redirects
49
+ schema: blogSchema,
50
+ slugStrategy: "localized", // translated slugs per locale (default: "fixed")
51
+ orderBy: "-publishedAt", // default sort for list()
52
+ }),
53
+ defineContentType({
54
+ id: "author", // no path: reference-only type
55
+ contentDir: "authors", // default would be "author"
56
+ schema: authorSchema,
57
+ }),
58
+ ],
59
+ });
60
+ ```
61
+
62
+ Content lives in `content/blog/*.mdx` and `content/authors/*.mdx`. The file
63
+ name is the EN slug. Frontmatter is validated against the schema; the built-in
64
+ fields `publishedAt`, `updatedAt`, `noindex`, `aliases`, `redirect_to`, and
65
+ `canonicalPath` are available on every type without declaring them.
66
+
67
+ ### 2. Field markers
68
+
69
+ - `field.translatable(schema)` — sent to the translator for each locale.
70
+ - `field.structural(schema)` — EN-only; merged from EN into every locale document.
71
+ - `field.relation(typeId, options?)` — EN slug reference(s) to another type.
72
+ Constraints go in the options (not chained Zod methods):
73
+ `field.relation("glossary", { multiple: true, max: 8, optional: true })`.
74
+ Validated by `scribe validate`, dereferenced with `related()`.
75
+
76
+ ### 3. Read content
77
+
78
+ ```ts
79
+ import { createScribe } from "scribe-cms/runtime"; // bundler-safe entry; plain "scribe-cms" works in scripts
80
+ import config from "./scribe.config";
81
+
82
+ const scribe = createScribe(config);
83
+
84
+ // Lists & lookups
85
+ scribe.blog.list("fr"); // sorted docs for a locale
86
+ scribe.blog.get("my-post"); // exact slug lookup, no fallback
87
+ const r = scribe.blog.resolve("my-post", "fr"); // aliases + redirects + EN fallback
88
+ // r = { document, actualLocale, shouldRedirectTo?, canonicalPath? }
89
+
90
+ // Routing helpers
91
+ scribe.blog.staticParams(); // all { locale, slug } pairs to prerender
92
+ scribe.blog.alternates(doc); // hreflang map: locale → path
93
+ scribe.blog.translation(doc, "fr"); // the same doc in another locale (or null)
94
+ scribe.blog.url(doc.slug, "fr"); // path from the type's template
95
+
96
+ // Relations (fully typed from the schema)
97
+ scribe.blog.related(doc, "author"); // AuthorDoc — non-null, validated at build time
98
+
99
+ // Sitemap
100
+ await scribe.sitemap({ baseUrl: "https://example.com" }); // entries with hreflang alternates
101
+ ```
102
+
103
+ Typed accessors (`scribe.blog`, `scribe.author`, …) and `related()` return types
104
+ are inferred from the config — no codegen.
105
+
106
+ ### 4. Translate & validate
107
+
108
+ ```bash
109
+ scribe status # EN docs + translation coverage
110
+ scribe validate # schemas, relations, aliases, sqlite consistency
111
+ scribe translate --locale fr # translate stale/missing pages (Gemini)
112
+ scribe translate --preset active
113
+ scribe history blog my-post fr # revision timeline
114
+ scribe studio # read-only local admin UI
115
+ ```
116
+
117
+ Translations are stored in `.scribe/store.sqlite` keyed by a hash of the EN
118
+ translatable content, so `scribe translate` only re-translates what changed.
119
+
120
+ ## Framework integration
121
+
122
+ Scribe runs anywhere Node does — see
123
+ [Runtime API → Framework integration](./docs/runtime-api.md#framework-integration).
124
+ The short version:
125
+
126
+ - Use `scribe-cms/runtime` in app code, `scribe-cms` in build scripts/CLI.
127
+ - Keep `better-sqlite3` (a native module) external to your bundler
128
+ (e.g. Next.js `serverExternalPackages`, Vite `ssr.external`).
129
+ - Gate builds: `"build": "scribe validate && <your framework build>"`.
130
+ - Redirects: `buildAllContentRedirects(project)` produces
131
+ `{ source, destination, permanent }` rules from aliases, `redirect_to`, and
132
+ cross-locale slugs — map them to your framework's redirect config.
133
+
134
+ ## Publish to npm
135
+
136
+ From the monorepo root (builds, tests, then publishes):
137
+
138
+ ```bash
139
+ npm login # once, if needed
140
+ pnpm publish:npm
141
+ ```
142
+
143
+ From this package directory:
144
+
145
+ ```bash
146
+ pnpm build
147
+ pnpm publish:npm # runs npm publish --access public
148
+ ```
149
+
150
+ Site: [scribe.genlook.app](https://scribe.genlook.app)