Load this file before changing the bundled macOS Help Book, the public website or user guide, help screenshots, command-palette help entries, or Help menu behavior.
docs/ is the GitHub Pages root, served at jayjay.hewig.dev (see docs/CNAME):
docs/index.htmlis the landing page with the FAQ (/#faq), linked fromREADME.md.docs/guide.html+docs/guide.cssare the user guide; screenshots live indocs/imgsand double as Help Book sources.docs/llms.txtis the machine-readable project summary;docs/sitemap.xmlanddocs/robots.txtcover indexing.docs/appcast.xmlis the Sparkle update feed — owned by the release flow; load Release Workflow before touching it.
When a user-facing feature ships, update together: the guide page, the llms.txt summary if the feature list changed, the FAQ if it answers a common question, and the Help Book (below) which reuses the same content and screenshots.
docs/guide.htmlanddocs/guide.cssare the public web guide.shell/mac/Resources/JayJayHelpBookis the editable Help Book source. It intentionally does not end in.help, because Spotlight/Help Services can discover source.helpbundles and make Tips try to read the workspace path, which is sandbox-denied.build/help.noindex/JayJay.helpis the generated macOS Help Book that Xcode embeds into the app. The.noindexparent keeps Spotlight from treating the generated build artifact as another candidate Help Book.- Shared Help styling starts in
docs/help-common.css. - Help Book-specific styling starts in
docs/help-book.css. scripts/build-help-book.shcopiesshell/mac/Resources/JayJayHelpBooktobuild/help.noindex/JayJay.help, concatenates the shared CSS and Help Book CSS intosty/help.css, copiesdocs/help.js, converts source screenshots to downscaled Help Book JPEGs, updates the Help Book version checksum, and rebuildsJayJay.helpindexwithhiutil.- Use
just shell::helpto rebuild only the Help Book, andjust runto rebuild the app, reset JayJay Help caches, and launch the debug app.
- Keep Help pages conservative: simple HTML, relative paths, one
sty/help.cssstylesheet link, and JPEG screenshots inside the Help Book. Do not use an XHTML public doctype with an external DTD URL; Tips' sandbox can treat the DTD fetch as an out-of-book navigation and leave the page blank. - WebP screenshots are fine as source assets under
docs/imgs, anddocs/imgs/home.pngis the home source; the Help Book uses JPEG output fromscripts/build-help-book.sh. - Keep
CFBundleHelpBookName,HPDBookTitle, and the SwiftHelpBook.bookTitlestring in sync. - Any content or asset change must change the Help Book
CFBundleVersion; the build script appends a content checksum for this. - Do not edit generated copied CSS in the Help Book as the only source. Edit
docs/help-common.cssordocs/help-book.css, then run the build script.
Register the embedded Help Book bundle, not the containing app bundle:
guard let helpBookURL = Bundle.main.url(forResource: "JayJay", withExtension: "help") else {
return false
}
let registerStatus = AHRegisterHelpBookWithURL(helpBookURL as CFURL)
let gotoStatus = AHGotoPage("JayJay Manual" as CFString, relativePath as CFString, nil)Do not pass Bundle.main.bundleURL to AHRegisterHelpBookWithURL. On macOS 26, the Help UI is hosted by Tips.app with bundle id com.apple.helpviewer. Registering the app bundle can return noErr while the Help window renders blank from a debug app in DerivedData because the Help host cannot read the app-bundle Help Book path.
- JayJay Help cache commonly lives under
~/Library/Group Containers/group.com.apple.helpviewer.content/Library/Caches/dev.hewig.jayjay.dev.hewig.jayjay.manual*<version>.help. just shell::reset-help-cachekillsTips/tipsd/helpd, removes JayJay Help Viewer caches, clearshelpdcache databases, and removes JayJay-only registered-book entries from~/Library/Preferences/com.apple.help.plist.just rundepends on it.just shell::debug-helpprints source-vs-generated-vs-embedded Help Book versions, image formats, cache paths, Spotlight Help Book records, registered Help books, and recentTips/helpdlogs. Run it after opening Help when the Help window is blank or stale.- A stale or corrupted cache can show old screenshots or old CSS even when the app bundle is correct.
- A blank Help window is not always cache. Check system logs for sandbox denials or read failures:
/usr/bin/log show --last 5m --style compact --predicate 'eventMessage CONTAINS "JayJay.help" OR eventMessage CONTAINS "dev.hewig.jayjay"'When debugging Help Viewer:
- Run
just shell::buildand confirm the generated Help Book and embedded app bundle have the same Help BookCFBundleVersion. - Run
just shell::reset-help-cache, then confirmfind "$HOME/Library/Group Containers/group.com.apple.helpviewer.content/Library/Caches" -maxdepth 2 -iname '*jayjay*' -printis empty andjust shell::debug-helpreports no JayJay registered-book records before Help is opened again. - Launch the built app and open Help from JayJay's Help menu. Do not inspect only the source HTML in a browser; Help Viewer reads the embedded Help Book.
- If it is stale or blank, run
just shell::debug-helpimmediately before rebuilding again. Compare source and embedded Help Book versions, check for non-JPEG screenshots, and read the recentTips/helpdlog section. - If
AHRegisterHelpBookWithURLandAHGotoPageboth returnnoErrbut Help is blank, suspect Help Viewer sandbox/cache behavior first; verify Swift is registeringBundle.main.url(forResource: "JayJay", withExtension: "help"), notBundle.main.bundleURL. - If logs mention
Sandbox: Tips deny file-read-data .../shell/mac/Resources/JayJay.helporoutside the sandbox, a source.helpbundle has been reintroduced orhelpdis still holding a stale registered-book record. The repo should only containResources/JayJayHelpBook; runjust shell::reset-help-cache, rebuild, and confirmmdfind 'kMDItemCFBundleIdentifier == "dev.hewig.jayjay.manual"'does not point at the workspace source tree andjust shell::debug-helpdoes not show JayJay entries incom.apple.help.plist.
Before calling Help Book work done:
- Run
just shell::help. - Run
just run. - Open
Help > JayJay Helpfrom the running app. - Verify the sidebar, dark/light screenshots, and topic links in the system Help window, not only in a browser.
- If the Help window is blank, first confirm Swift registers
JayJay.helpdirectly, then inspect logs before changing cache logic.