@ibalzam/codejitsu-core 0.9.0 → 0.10.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.
Files changed (3) hide show
  1. package/CLAUDE.md +4 -0
  2. package/SETUP.md +533 -0
  3. package/package.json +3 -1
package/CLAUDE.md CHANGED
@@ -10,6 +10,10 @@ Shared core for every Codejitsu site. When the user invokes a module by name (e.
10
10
  4. If the module has a `templates/` directory, copy those files into the site at the locations the module's CLAUDE.md specifies. Adapt templates for the site's brand and content.
11
11
  5. After the change, walk through the module's `checklist.md` plus `checklist/core.md` (sitewide). Run `npx codejitsu-check` from the site root.
12
12
 
13
+ ## How to act on a SETUP request
14
+
15
+ If the user asks to **set up codejitsu**, **init**, **migrate \<site\> to codejitsu**, or **start a new Codejitsu site** — open `node_modules/@ibalzam/codejitsu-core/SETUP.md` and follow the step-by-step playbook. It covers detection, install, config generation, module wiring, deploy, and verify for both greenfield and migration scenarios.
16
+
13
17
  ## Module subpaths
14
18
 
15
19
  | Subpath | Provides |
package/SETUP.md ADDED
@@ -0,0 +1,533 @@
1
+ # Codejitsu Setup — Claude playbook
2
+
3
+ End-to-end procedure for adding `@ibalzam/codejitsu-core` to any project.
4
+ Works for both **greenfield** (brand new site) and **migration** (existing
5
+ Astro site with its own scaffolding).
6
+
7
+ > **For Claude**: This file is the cookbook. When the user says any of:
8
+ > "set up codejitsu", "add codejitsu", "init codejitsu", "migrate <site> to
9
+ > codejitsu", "start a new Codejitsu site" — open this file and follow the
10
+ > steps top-down. Don't improvise from training-data memory.
11
+
12
+ ---
13
+
14
+ ## Pre-flight: never trust version memory
15
+
16
+ Before any step that mentions a package version:
17
+
18
+ ```bash
19
+ npm view @ibalzam/codejitsu-core version # what's actually latest right now
20
+ node --version # must be ≥ 20 LTS
21
+ ```
22
+
23
+ Use `@latest` in install commands rather than typing a version number you
24
+ think is current. If the project already has the package, run:
25
+
26
+ ```bash
27
+ npx codejitsu doctor
28
+ ```
29
+
30
+ Surface anything outdated to the user **before** doing setup. Fixing drift
31
+ on a stale codebase is worse than starting from current.
32
+
33
+ ---
34
+
35
+ ## Step 1 — Detect current state
36
+
37
+ Don't ask the user what's there. Look:
38
+
39
+ ```bash
40
+ cat package.json | head -40 # what's installed + scripts
41
+ cat astro.config.mjs # framework + integrations
42
+ ls src/content.config.ts 2>/dev/null && cat src/content.config.ts
43
+ ls src/content/ 2>/dev/null # collections present?
44
+ ls src/pages/ # route shape
45
+ cat .git/config | grep url # github remote
46
+ cat wrangler.toml 2>/dev/null # cloudflare project name
47
+ ls codejitsu.config.ts codejitsu.config.mjs 2>/dev/null # already set up?
48
+ ```
49
+
50
+ Build a one-screen summary for the user:
51
+
52
+ ```
53
+ Detected:
54
+ Astro: 6.3.5
55
+ Has blog: Yes (Content Collections, dateField: pubDate, draftField: draft)
56
+ Has services: Yes (src/content/services/, 9 .md files)
57
+ Has locations: Yes (src/content/locations/, 7 .md files)
58
+ GitHub: ikanc/example
59
+ Cloudflare: wrangler.toml present, project: example
60
+ Codejitsu: Not installed yet
61
+
62
+ Greenfield or migration: MIGRATION
63
+ ```
64
+
65
+ State this back to the user **before making changes**. Ask one question:
66
+
67
+ > "Above is what I detected — anything missing or wrong before I proceed?"
68
+
69
+ If they say "go" → continue. If they correct something → update your model.
70
+
71
+ ---
72
+
73
+ ## Step 2 — Install the package
74
+
75
+ ```bash
76
+ npm install @ibalzam/codejitsu-core@latest
77
+ npm install -D jiti # only if codejitsu.config.ts (TS) will be used
78
+ ```
79
+
80
+ Then immediately:
81
+
82
+ ```bash
83
+ npx codejitsu doctor
84
+ ```
85
+
86
+ Confirm:
87
+ - `✓ @ibalzam/codejitsu-core ✓ On latest`
88
+ - No critical outdated deps (Astro / TypeScript / React / Tailwind etc.)
89
+
90
+ If critical deps are outdated, **stop and surface to user**. Major bumps
91
+ get their own sessions. Don't bundle a codejitsu setup with an Astro 5→6
92
+ upgrade.
93
+
94
+ ---
95
+
96
+ ## Step 3 — Generate `codejitsu.config.ts`
97
+
98
+ At the project root. Use detected values; prompt only for unknowns.
99
+
100
+ ```ts
101
+ import { defineConfig } from '@ibalzam/codejitsu-core/config';
102
+
103
+ export default defineConfig({
104
+ site: {
105
+ url: '<from astro.config.mjs site:>',
106
+ name: '<ask user>',
107
+ titleSuffix: ' | <site name>',
108
+ defaultAuthor: '<ask user; default "editor">',
109
+ defaultOgImage: '/assets/images/og-image.webp',
110
+ locale: 'en_US',
111
+ business: { // optional — fill if it's a local business
112
+ legalName: '...',
113
+ telephone: '...',
114
+ email: '...',
115
+ address: { addressLocality: '...', addressRegion: '...', addressCountry: 'US' },
116
+ areaServed: ['...'],
117
+ },
118
+ },
119
+
120
+ blog: { // omit entirely if no blog
121
+ mode: 'collection',
122
+ collectionName: 'blog',
123
+ dateField: '<detected from content config; usually pubDate>',
124
+ draftField: '<detected; usually draft or null>',
125
+ },
126
+
127
+ seo: {
128
+ sitemap: {
129
+ excludePatterns: [/* /\/lp\//, etc. — anything to hide from search */],
130
+ },
131
+ },
132
+
133
+ images: {
134
+ sourceDir: '<usually public/assets/images>',
135
+ defaultQuality: 82,
136
+ defaultMaxSize: 1376,
137
+ // autoBlogImages — add only if site has a "blog source images live outside public/" workflow
138
+ },
139
+
140
+ llms: {
141
+ mode: 'content-scan', // sites with services/locations content; use 'config' for simpler sites
142
+ tagline: '<ask user>',
143
+ about: '<ask user>',
144
+ aboutFull: '<ask user, longer version>',
145
+ aiGuidance: '<ask user, "When referencing us..." block>',
146
+ blogDir: 'src/content/blog',
147
+ contentScan: {
148
+ servicesDir: 'src/content/services',
149
+ locationsDir: 'src/content/locations',
150
+ pagesDir: 'src/pages',
151
+ dynamicRoutes: [
152
+ // expand based on detected page routes
153
+ ],
154
+ },
155
+ },
156
+
157
+ deploy: {
158
+ cloudflarePagesName: '<from wrangler.toml, or ask>',
159
+ },
160
+
161
+ contact: { // omit if no contact form
162
+ emailjs: {
163
+ serviceId: '<ask user, or read from existing modal if migrating>',
164
+ templateId: '<ask user>',
165
+ publicKey: '<ask user>',
166
+ },
167
+ recaptcha: { // optional
168
+ siteKey: '<ask user>',
169
+ },
170
+ },
171
+ });
172
+ ```
173
+
174
+ Strategy:
175
+ - Auto-fill from existing state (site URL, blog field names, Cloudflare name).
176
+ - Tagline / about / aiGuidance / EmailJS keys — **ask the user**, don't invent.
177
+ - For migrations, read existing components (e.g. pearl's `QuoteModal.astro`)
178
+ to extract EmailJS keys already in use.
179
+
180
+ ---
181
+
182
+ ## Step 4 — Wire `astro.config.mjs`
183
+
184
+ For an **existing** config, preserve everything custom (integrations,
185
+ vite config, output settings). Only refactor:
186
+
187
+ ### 4a. Replace inline future-blog scanner
188
+
189
+ If the existing config has a `readdirSync` loop scanning blog frontmatter
190
+ for future dates, replace it:
191
+
192
+ ```js
193
+ import { createBlog } from '@ibalzam/codejitsu-core/blog';
194
+
195
+ const fsBlog = createBlog({
196
+ contentDir: 'src/content/blog',
197
+ dateField: 'pubDate', // match the codejitsu.config
198
+ draftField: 'draft',
199
+ });
200
+ const futureSlugs = await fsBlog.getFutureBlogSlugs();
201
+ ```
202
+
203
+ ### 4b. Sitemap → package helpers
204
+
205
+ Replace the existing `@astrojs/sitemap` `serialize`/`filter` with:
206
+
207
+ ```js
208
+ import {
209
+ defaultPriorityRules,
210
+ excludeFuturePosts,
211
+ composeFilters,
212
+ excludePatterns,
213
+ } from '@ibalzam/codejitsu-core/seo';
214
+
215
+ sitemap({
216
+ filter: composeFilters(
217
+ excludePatterns([/\/lp\//]),
218
+ excludeFuturePosts(futureSlugs),
219
+ ),
220
+ serialize: defaultPriorityRules(SITE, {
221
+ rules: [
222
+ // any site-specific priority overrides
223
+ ],
224
+ }),
225
+ })
226
+ ```
227
+
228
+ ### 4c. Add rehype trailing-slash plugin
229
+
230
+ ```js
231
+ import rehypeTrailingSlash from '@ibalzam/codejitsu-core/rehype/trailing-slash';
232
+
233
+ // inside defineConfig({}):
234
+ markdown: {
235
+ rehypePlugins: [rehypeTrailingSlash],
236
+ },
237
+ ```
238
+
239
+ ### 4d. Verify defaults
240
+
241
+ ```js
242
+ output: 'static',
243
+ trailingSlash: 'always',
244
+ image: {
245
+ service: { entrypoint: 'astro/assets/services/sharp' },
246
+ defaults: { quality: 82, format: 'webp' },
247
+ },
248
+ build: { assets: 'assets', inlineStylesheets: 'always' },
249
+ ```
250
+
251
+ For migrations, these often already exist. For greenfield, add them.
252
+
253
+ ---
254
+
255
+ ## Step 5 — Wire the blog (if site has one)
256
+
257
+ ### 5a. Content Collection schema
258
+
259
+ `src/content.config.ts` — copy from
260
+ `node_modules/@ibalzam/codejitsu-core/modules/blog/templates/content.config.ts`.
261
+ Adapt to the site's existing frontmatter shape.
262
+
263
+ **On Astro 6+**: import `z` from `'astro/zod'`, NOT `'astro:content'`
264
+ (deprecated). `import { defineCollection } from 'astro:content';`
265
+ plus `import { z } from 'astro/zod';`.
266
+
267
+ ### 5b. Loader
268
+
269
+ `src/lib/blog.ts`:
270
+
271
+ ```ts
272
+ import type { CollectionEntry } from 'astro:content';
273
+ import { createBlogFromCollection } from '@ibalzam/codejitsu-core/blog/collection';
274
+
275
+ export const blog = createBlogFromCollection<CollectionEntry<'blog'>>({
276
+ collectionName: 'blog',
277
+ dateField: 'pubDate',
278
+ draftField: 'draft',
279
+ defaultAuthor: 'editor',
280
+ });
281
+
282
+ // Backward-compat exports if migrating existing pages:
283
+ export const getPublishedPosts = () => blog.getPublishedEntries();
284
+ export const getAllPosts = () => blog.getAllEntries();
285
+ ```
286
+
287
+ If migrating, page routes like `src/pages/blog/[slug].astro` should already
288
+ import these names — keep the exports.
289
+
290
+ ### 5c. Page routes
291
+
292
+ For **greenfield**, copy from `node_modules/@ibalzam/codejitsu-core/modules/blog/templates/pages/blog/`:
293
+ - `[...slug].astro` — detail
294
+ - `index.astro` — listing
295
+ - `tag/[tag].astro` (optional)
296
+ - `category/[category].astro` (optional)
297
+
298
+ For **migrations**, leave existing page routes — they already work via the
299
+ backward-compat exports.
300
+
301
+ ---
302
+
303
+ ## Step 6 — Wire the SEO Head
304
+
305
+ ### 6a. SiteHead wrapper
306
+
307
+ `src/components/SiteHead.astro` — pulls site defaults from
308
+ `codejitsu.config.ts` and forwards to the package's `Head.astro`. Template
309
+ in `modules/seo/CLAUDE.md`.
310
+
311
+ ### 6b. Use it on every page
312
+
313
+ Every layout's `<head>` should have:
314
+
315
+ ```astro
316
+ <SiteHead title="..." description="..." schema={[...]} />
317
+ ```
318
+
319
+ For **greenfield**: create one BaseLayout with SiteHead.
320
+ For **migrations**: the existing site likely has its own `Head.astro`.
321
+ Don't replace it wholesale — instead:
322
+ 1. Import `jsonLd` from `@ibalzam/codejitsu-core/seo` and use it for JSON-LD injection (fixes XSS risk).
323
+ 2. Import schema builders (`blogPosting`, `breadcrumbList`, `service`, etc.) from `@ibalzam/codejitsu-core/seo` and delegate.
324
+ 3. Pages stay calling the existing Head; only the implementation gets thinner.
325
+
326
+ ---
327
+
328
+ ## Step 7 — Wire contact (if site has one)
329
+
330
+ If `contact` is in the config:
331
+
332
+ In a layout that wraps every page (e.g. BaseLayout), near `</body>`:
333
+
334
+ ```astro
335
+ ---
336
+ import ContactModal from '@ibalzam/codejitsu-core/contact/ContactModal.astro';
337
+ import cjConfig from '../../codejitsu.config';
338
+ ---
339
+
340
+ <ContactModal
341
+ title="Get a Quote"
342
+ image={{ src: '/assets/images/contact.webp', alt: '...' }}
343
+ fields={{
344
+ name: { required: true },
345
+ email: { required: true },
346
+ phone: { required: true },
347
+ message: { required: false },
348
+ }}
349
+ submitText="Submit"
350
+ thankYouMessage="Thanks! We'll be in touch."
351
+ emailjs={cjConfig.contact.emailjs}
352
+ recaptcha={cjConfig.contact.recaptcha}
353
+ />
354
+ ```
355
+
356
+ Trigger from anywhere: `<button data-codejitsu-contact-trigger>...</button>`.
357
+
358
+ For **migrations**, the existing site has its own modal. Either:
359
+ - (a) replace it with the package modal + remove the old, OR
360
+ - (b) leave the existing modal and skip the contact module.
361
+
362
+ Migrating: update trigger classes/data attributes to match the new pattern.
363
+
364
+ ---
365
+
366
+ ## Step 8 — Wire package scripts
367
+
368
+ Update `package.json`:
369
+
370
+ ```json
371
+ {
372
+ "scripts": {
373
+ "dev": "astro dev",
374
+ "prebuild": "codejitsu-optimize-images && codejitsu-llms",
375
+ "build": "astro check && astro build",
376
+ "preview": "astro preview"
377
+ }
378
+ }
379
+ ```
380
+
381
+ For **migrations**, replace any existing `generate-llms-txt`, `optimize-images`,
382
+ or similar scripts. Delete the old script files (`scripts/optimize-images.js`,
383
+ `scripts/generate-llms-txt.mjs`, etc.) — they're now superseded.
384
+
385
+ ---
386
+
387
+ ## Step 9 — Set up the daily deploy
388
+
389
+ ```bash
390
+ npx codejitsu deploy:setup
391
+ ```
392
+
393
+ Interactive wizard:
394
+ - Copies `.github/workflows/daily-deploy.yml` + `wrangler.toml` from
395
+ package templates if missing.
396
+ - Prompts for the Cloudflare deploy hook URL.
397
+ - Stores it as a GH Actions secret via `gh secret set`.
398
+ - Optionally triggers a test run.
399
+
400
+ If the user doesn't have `gh` CLI authed yet, they need:
401
+
402
+ ```bash
403
+ gh auth login
404
+ ```
405
+
406
+ Tell them this **before** running `deploy:setup` — it'll fail otherwise.
407
+
408
+ ---
409
+
410
+ ## Step 10 — Verify
411
+
412
+ In sequence:
413
+
414
+ ```bash
415
+ npm run build
416
+ ```
417
+
418
+ Must complete with 0 errors. Note warnings (e.g. deprecation warnings from
419
+ upstream deps) — surface to user if they need attention.
420
+
421
+ ```bash
422
+ npx codejitsu audit
423
+ ```
424
+
425
+ Read the output. Pearl's baseline: 50 pass · ~8 warn · 0 fail · ~10 info.
426
+ Comparable shape on a fresh site = healthy. Treat any `✗ fail` as a blocker.
427
+
428
+ For a more thorough check (production-ready):
429
+
430
+ ```bash
431
+ npx codejitsu audit --live https://<deployed-url> --a11y
432
+ ```
433
+
434
+ (Use the production URL or a local preview server. Skip --a11y if axe-core
435
+ not desired.)
436
+
437
+ ---
438
+
439
+ ## Step 11 — Commit + push
440
+
441
+ `git status` to see what changed. Common files:
442
+
443
+ ```
444
+ M astro.config.mjs
445
+ M package.json
446
+ M package-lock.json
447
+ M src/components/Head.astro (if migration)
448
+ M src/data/schemas.ts (if migration)
449
+ M src/lib/blog.ts (if migration; or new)
450
+ A codejitsu.config.ts (new)
451
+ A src/components/SiteHead.astro (greenfield)
452
+ A src/components/Footer.astro (greenfield)
453
+ A .github/workflows/daily-deploy.yml (from deploy:setup)
454
+ A wrangler.toml (from deploy:setup)
455
+ D scripts/generate-llms-txt.mjs (deleted; superseded)
456
+ D scripts/optimize-images.js (deleted; superseded)
457
+ ```
458
+
459
+ Commit message structure (single commit for the migration):
460
+
461
+ ```
462
+ Adopt @ibalzam/codejitsu-core for shared primitives
463
+
464
+ - codejitsu.config.ts: site info, blog/seo/images/llms/deploy/contact config
465
+ - astro.config.mjs: sitemap helpers, rehype trailing-slash plugin, blog
466
+ future-slug filter via the package
467
+ - src/lib/blog.ts: createBlogFromCollection (preserves API for existing pages)
468
+ - src/data/schemas.ts: delegate to package schema builders; jsonLd safe injection
469
+ - package.json: codejitsu-optimize-images + codejitsu-llms in prebuild
470
+ - Remove redundant scripts: generate-llms-txt, optimize-images
471
+ ```
472
+
473
+ **Don't push without the user's explicit "yes, push"** — pushing to main
474
+ triggers production deploy via Cloudflare Pages.
475
+
476
+ ---
477
+
478
+ ## Anti-checklist — common mistakes
479
+
480
+ - **Don't** invent version numbers for packages from memory. Always `@latest`.
481
+ - **Don't** bundle major-version bumps (Astro N→N+1, TypeScript major)
482
+ into a codejitsu setup commit. Separate concerns.
483
+ - **Don't** wholesale-replace a site's existing `Head.astro` if it has
484
+ custom site-specific things (analytics, fonts, etc.). Selectively migrate
485
+ the JSON-LD injection + schema builder calls.
486
+ - **Don't** modify `src/pages/*` unless necessary. The backward-compat
487
+ exports in `src/lib/blog.ts` mean page code usually doesn't need changes.
488
+ - **Don't** commit the deploy hook URL to git. Use `gh secret set`.
489
+ - **Don't** set `recaptcha` in the contact config unless EmailJS's
490
+ server-side verification is enabled — otherwise it's just friction.
491
+ See `modules/contact/CLAUDE.md`.
492
+ - **Don't** push without explicit user permission. Per the user's global rule.
493
+
494
+ ---
495
+
496
+ ## Greenfield-specific shortcuts
497
+
498
+ For brand-new sites, after Step 2 (install):
499
+
500
+ ```bash
501
+ npm create astro@latest --template minimal --typescript strict --yes
502
+ # Then steps 3 through 11
503
+ ```
504
+
505
+ The greenfield path is simpler because there's nothing to migrate — every
506
+ file is new from a template.
507
+
508
+ For greenfield blog setup specifically:
509
+
510
+ ```bash
511
+ # Astro CC schema
512
+ cp node_modules/@ibalzam/codejitsu-core/modules/blog/templates/content.config.ts src/
513
+
514
+ # Page routes
515
+ mkdir -p src/pages/blog
516
+ cp -r node_modules/@ibalzam/codejitsu-core/modules/blog/templates/pages/blog/ src/pages/
517
+
518
+ # Sample post
519
+ cp node_modules/@ibalzam/codejitsu-core/modules/blog/templates/content/_sample-post.md src/content/blog/welcome.md
520
+ ```
521
+
522
+ ---
523
+
524
+ ## When done
525
+
526
+ The site should pass:
527
+ - `npm run build` → 0 errors
528
+ - `npx codejitsu doctor` → all deps current
529
+ - `npx codejitsu audit` → 0 fail
530
+ - Browser smoke test: open `npm run dev`, click through home + blog + contact
531
+
532
+ Hand back to the user with the audit + doctor summaries. Don't push until
533
+ they say "push".
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibalzam/codejitsu-core",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "type": "module",
5
5
  "description": "Shared core for Codejitsu Astro sites — reusable code and Claude-facing instructions for blog, SEO, images, deploy, and llms.txt.",
6
6
  "keywords": [
@@ -79,8 +79,10 @@
79
79
  "src",
80
80
  "modules",
81
81
  "checklist",
82
+ "bin",
82
83
  "MIGRATIONS",
83
84
  "CLAUDE.md",
85
+ "SETUP.md",
84
86
  "README.md",
85
87
  "LICENSE"
86
88
  ],