.cursor/skills/fantasia-electron-preload/SKILL.md
Extends or fixes renderer-facing Electron APIs exposed through the preload script and contextBridge. Use when adding IPC-like surface area, typing window.faContentBridgeAPIs, editing src-electron/contentBridgeAPIs, or extending shared IPC channel names in electron-ipc-bridge.ts.
npx skillsauth add vishiri/fantasia-archive fantasia-electron-preloadInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
src-electron/electron-preload.ts builds apiObject and calls contextBridge.exposeInMainWorld('faContentBridgeAPIs', apiObject).window.faContentBridgeAPIs — typed in src/globals.d.ts.src-electron/contentBridgeAPIs/ (e.g. faWindowControlAPI.ts, appDetailsAPI.ts, faKeybindsAPI.ts for persisted shortcut overrides via FA_KEYBINDS_IPC).ipcRenderer.invoke with ipcMain.handle and Promise-returning methods on faContentBridgeAPIs. Synchronous ipcRenderer.sendSync (or other blocking IPC) is not forbidden but is a last resort — use only when there is no remotely reasonable async alternative; note the exception in a short comment or PR review.src-electron/electron-ipc-bridge.ts holds canonical channel strings (export const objects, e.g. FA_DEVTOOLS_IPC, FA_USER_SETTINGS_IPC, FA_WINDOW_CONTROL_IPC, FA_APP_DETAILS_IPC, FA_EXTRA_ENV_IPC). Preload-side code that uses ipcRenderer.invoke and main-side ipcMain.handle must use these constants — never duplicate string literals across files.mainScripts/ipcManagement/register*Ipc.ts module that wires ipcMain.handle with the same constants, and ensure startup invokes that registrar (today startApp() in mainScripts/appManagement.ts calls the existing registrars).contentBridgeAPIs/*.ts module and pass those strings to ipcRenderer.invoke.types/I_<Name>.ts (or extend an existing interface).electron-ipc-bridge.ts, implement mainScripts/ipcManagement/register*Ipc.ts (or extend an existing registrar), and invoke it from app startup (today startApp() in mainScripts/appManagement.ts).src-electron/contentBridgeAPIs/<name>.ts exporting a plain object matching that interface.electron-preload.ts and add it to apiObject with a stable key (camelCase, consistent with existing keys).Window['faContentBridgeAPIs'] in src/globals.d.ts with the new key and interface.src-electron/contentBridgeAPIs/_tests/ (and mainScripts/ipcManagement/_tests/ for new IPC registrars) following existing *.vitest.test.ts patterns. yarn testbatch:verify enforces 100% v8 coverage on src-electron (vitest-tests.mdc, vitest/vitest.electron.config.mts).nodeIntegration in the renderer to “just make it work”; keep privileged code in main or preload as appropriate.electron APIs such as shell; use IPC to main (registerFaExtraEnvIpc, registerFaExternalLinksIpc, registerFaWindowControlIpc, registerFaDevToolsIpc, registerFaAppDetailsIpc, and similar) instead of importing packages like app-root-path in contentBridgeAPIs/.ipcRenderer.invoke (faWindowControlAPI, faDevToolsControlAPI, appDetailsAPI.getProjectVersion, extraEnvVariablesAPI.getSnapshot with memoized promises for one round trip per load); do not reintroduce @electron/remote without a documented reason.src-electron/shared/ and wire parsing in register*Ipc.ts — see fantasia-electron-main IPC payload validation (Zod) and faUserSettingsPatchSchema.ts / registerFaUserSettingsIpc.ts.S_FaKeybinds, and faKeybinds persistence over IPC.types/)interface / type declarations in repository-root types/ (import with app/types/...). Prefer one domain-oriented module per feature area with brief JSDoc on exports (see types/I_appMenusDataList.ts). Do not add colocated <filename>.types.ts under src/, src-electron/, or .storybook-workspace/. Ambient augmentations for third-party modules also live under types/ and are loaded with a side-effect import from the owning boot file or src/stores/index.ts (see types/piniaModuleAugmentation.ts)..js), TypeScript (.ts), Vue (.vue), and JSON (.json, .jsonc, .json5) files, enforce expanded multi-line object literals via ESLint (object-curly-newline + object-property-newline) and keep files auto-fixable with eslint --fix.development
Splits working tree changes into logical Git commits with conventional messages (feat, fix, test, chore, refactor, style, docs). Proposes commits one at a time and waits for explicit user approval before each git commit. Use when the user asks to commit, split commits, stage by topic, or use conventional / semantic commit messages.
development
Aligns AI suggestions with Fantasia Archive as a worldbuilding database manager: projects, documents, and in-app concepts. Use when designing UX, data models, menus, or copy that should match the product purpose.
development
Runs and extends Fantasia Archive tests: Vitest unit tests vs Playwright component and E2E tests, including rebuild-before-Playwright rules and file naming. Use when writing tests, debugging CI, or when the user mentions Vitest, Playwright, component tests, or e2e.
development
Designs SQLite usage in Fantasia Archive’s Electron main process: file locations under userData, native better-sqlite3 module constraints, and migrations. Use when editing electron-main database code, schema, or persistence paths.