Code Reuse

SkillDev tools

Use when building a UI component, PocketBase hook, page, or app feature and there is proven code to copy from the reference repos. Check here BEFORE writing UI components, PB hooks/routes, form controls, dialogs, auth flows, pagination, or realtime stores from scratch. Catalogs reusable code from pocketbase-sveltekit-starter (sk/src/lib + pb/pb_hooks) and spinspire/recipes. Components are proven but may need adaptation to the current project (runes, oat-css, $app/state).

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Code Reuse skill

What this skill tells your AI

The instructions your AI receives, as published by spinspire/pocketbase-sveltekit-starter in .agents/skills/code-reuse/SKILL.md and read by ahel’s review.

Proven, copy-ready code catalog from reference repos. Reuse before building from scratch.

Sources

RepoWhat to copyWhere it lives
pocketbase-sveltekit-starterFrontend lib + components + PB JS hookssk/src/lib, pb/pb_hooks
spinspire/recipesFrontend lib + components playground + multi-stack templatessk/, pb/, py/, rs/

⚠️ Adapt, don't paste. These use SCSS + box-icons + $app/stores + some legacy export let. Convert: $app/stores$app/state, SCSS → oat-css/app.css tokens, export let → runes ($props/$state/$derived). They are proven patterns, not drop-in code.


1. pocketbase-sveltekit-starter — frontend lib (sk/src/lib)

Core PB client (pocketbase/index.ts)

  • client — typed PocketBase instance (same-origin by default).
  • authModel — readable store on client.authStore.onChange; calls invalidateAll() on auth flips.
  • login(email, password, register?, rest?) — create-if-register then authWithPassword.
  • logout()authStore.clear().
  • save<T>(collection, record, create?) — generic create/update; auto-converts to FormData when a value is File/FileList (via object2formdata). Use for file uploads.
  • watch<T>(idOrName, queryParams?, page?, perPage?, realtime?)PageStore<T> — realtime paginated list store: subscribes to subscribe("*"), maintains result.items (update=replace, create=append, delete=filter). PageStore adds setPage()/next()/prev(); unsubscribe tears down realtime. Good upgrade candidate for our host pool/queue lists.
  • providerLogin(provider, authCollection) — OAuth2 login that backfills name/avatar from meta.
  • webauthnRegister/Login — passkey flow via @simplewebauthn/browser + /api/webauthn/* routes.

pocketbase/ui.ts

  • alertOnFailure(request) — wraps a PB request; surfaces top-level message + per-field data errors via alerts.error().

pocketbase/ components

ComponentPurpose
FileField.svelteFile-field rows with bindable toBeRemoved toggle-delete; links via client.files.getURL.
Image.sveltePB file image with { thumb } param + fallback (internal SVG or via.placeholder.com).
ImgModal.svelteThumb → full-size image lightbox in a Dialog.
Paginator.svelte« page X of Y » pager bound to a PageStore.

components/ — UI building blocks

ComponentPurpose
Alerts.svelteGlobal toasts. Exports alerts object (info/success/warning/error, timeout, html); auto-catches unhandled promise rejections. Place once in layout.
Dialog.svelteNative <dialog> modal; trigger snippet gets show; closes on backdrop click.
Link2Modal.svelteInternal link → modal via preloadData+pushState+<dialog>; invalidateAll+history.back() on close.
LoginGuard.svelteConditional render on auth (and admin via isSuperuser); otherwise snippet + optional redirect.
LoginForm.svelteSign-in/up tabs, admin checkbox, passkey, OAuth buttons from listAuthMethods().
LoginBadge.svelteAuth pill (avatar+name) → Dialog with passkey register / sign out, or sign-in.
Nav.svelteTop nav with active highlighting.
Delete.svelteConfirm-and-delete form; navigates after collection.delete(id).
FileInput.svelteStyled file input with paste capture + filename list snippet.
DateShow.svelteCircular date badge (DOW / mon+day / year).
LocalStorageStore.svelteModule ls store mirroring localStorage (JSON-parsed) + debug table.
RadioText.sveltePill radio selector; object or string-array choices; hides inputs, :has() styling.
Spinner.svelteCSS spinner; also exports activityStore(f) (store with .run()).
Stepper.svelteStep indicator; children snippet gets {data, index, total, step, next, previous}.
TabGroup/Tab/TabContent.svelteTabs via context active store.
ToggleText.sveltePure-CSS two-label toggle.

metadata.ts

  • writable({ title, headline, description }) global metadata store.

2. pocketbase-sveltekit-starter — PB JS hooks (pb/pb_hooks)

main.pb.js patterns

  • routerAdd(method, path, handler, $apis.requireAuth()) — custom routes. /api/hello (auth greeting), /api/sendmail ($app.newMailClient() + record.ignoreEmailVisibility(true)), /api/config (public, merges config.json via require(${__hooks}/util) + live settings), /api/generate (external HTTP + $filesystem.fileFromURL + RecordUpsertForm).
  • onModelCreate/onModelUpdate(e, "collection") — model hooks scoped to a collection.

util.js helpers (load via require(${__hooks}/util))

  • parseJSON(bytes) / parseJSONFile(path) — decode PB byte-array JSON from $os.readFile.
  • slugDefault(obj) — set slug to id when empty.
  • doAudit(event, request) — writes an auditlog record for collections in AUDITLOG env var; records collection/record/event/user/admin + data and original (changed keys only, via record.original().publicExport() diff).

auditlog.pb.js

  • onRecordCreateRequest/UpdateRequest/DeleteRequeste.next() then doAudit(...). Pattern: let the operation run first, then audit.

config.json

  • Static site config merged into /api/config.

3. spinspire/recipes — frontend + templates

sk/src/lib

  • pocketbase/index.ts (151 lines) — trimmed variant of the starter's: client, authModel, save+object2formdata, watch, logout. No webauthn. Uses $app/paths base.
  • pocketbase/*.sveltePaginator, LoginGuard, LoginForm, LoginBadge, ImgModal (simpler variants of the starter's).
  • components/*.svelteAlerts, DateShow, Dialog, FileInput, Nav, Spinner (subset of the starter's; same patterns).

Component playground (sk/src/routes/components/)

A dev-only route that renders any src/lib/components/*.svelte in isolation with a live exports editor:

  • +layout.svelte — lists all components via import.meta.glob("/src/lib/components/**/*.svelte"), links each to /components/{path}.
  • [...path]/+page.svelte — dynamically import()s the component and renders it inside ExportEditor.
  • ExportEditor.svelte — reads component.$$.props, renders an Inputs control per prop, binds values into a bindings object.
  • Inputs.svelte — input control (text/number/date via INPUT_TYPES in config.ts) with processor hooks.
  • config.tsremotePath writable (VSCode remote link), HTMLInputTypes type, INPUT_TYPES map.
  • Remote.svelte — form to configure the "Open in VSCode" path.

Use case: to quickly develop/test a component in isolation with interactive props. Pull the components/ route folder into any SvelteKit project.

pb/ — PocketBase/Go template

  • main.go — custom PB binary: --publicDir flag, SPA static serving, jsvm.MustRegisterMigrations, migratecmd (JS templates), hooks.Register(app).
  • hooks/hooks.go — Go audit-log + event-driven actions: reads a hooks collection (collection/event/disabled) and executes command/post actions against the record (JSON piped to stdin). Useful pattern for generic record-triggered automation.
  • entrypoint.sh — build-if-needed (go build, tygo, modd) then exec "$@".
  • tygo.yaml — Go→TypeScript type generation config.
  • pb_migrations/*.js — JS collection-snapshot migrations.

py/ (FastAPI) & rs/ (Axum)

  • py/web.py — minimal FastAPI with configurable prefix (FASTAPI_PREFIX, default /apy).
  • rs/ — Axum REST with SQLite (db.rs), file upload (upload.rs), experimental live-view (live.rs, livecrud.rs), static SPA serving.
  • Only borrow these if we add a non-PB backend; otherwise skip.

docker-compose.yml + entrypoint.sh

  • Multi-service template (pb, py, rs, sk, mb) — non-root ${UID}:${GID}, expose not ports, entrypoint initializes (builds) then runs the container command. Pattern matches our own docker setup.

.opencode/tools/sql.ts

  • A bun-based SQL tool for opencode (uses bun:sqlite/@opencode-ai/plugin); READONLY for safety. Only relevant if we adopt opencode tooling.

When to use which source

  • UI components, dialogs, forms, toasts, tabs, pagination, realtime list stores, auth UI → starter's sk/src/lib (richer; the recipes versions are trimmed copies).
  • Component playground / dev preview tool → recipes components/ route.
  • PB custom routes, model hooks, audit logging, config merging → starter's pb/pb_hooks.
  • Record-triggered automation (command/post actions), custom PB Go build, FastAPI/Axum backends, multi-service compose → recipes pb/, py/, rs/, docker-compose.yml.
  • Generic file upload create/updatesave()/object2formdata (both repos).

Adaptation checklist (apply to every copy)

  1. $app/stores$app/state (page object, not store).
  2. SCSS <style> → oat-css classes + tokens in src/app.css (--brand, --glow, --muted-text; NOT --accent/--muted which oat reserves).
  3. box-icons <i class="bx bx-*"> → inline SVG or text.
  4. Legacy export let/$: → runes ($props, $state, $derived, snippets {@render}).
  5. Rename $derived var statelive (svelte2tsx crash).
  6. client/pb import path → $lib/pb (our app).
  7. Collection names/fields → ours (events, entries, users).
  8. Typecheck (bun run check) + tests (bun test) after adapting.

Signals

GitHub stars
507
Forks
76
Last commit
Aug 2026
Advanced
Catalog kind
skill
Gateway key
code-reuse
Source
github.com/spinspire/pocketbase-sveltekit-starter