# Claude Code Notes ## Running Tests Use `bun run test:cov` to run all tests with coverage. This runs both unit tests and e2e tests that require a database connection. - `bun run test:cov` - Run all tests with coverage (preferred) - `bun run test:unit:cov` - Run only unit tests with coverage (no database required) ## Database Scripts Use the wrapper scripts instead of running dbmate directly: - `./scripts/db-dump` - Dump schema without random `\restrict` tokens - `./scripts/db-migrate` - Run migrations and dump clean schema PostgreSQL 17.6+ adds random `\restrict`/`\unrestrict` lines to pg_dump output (CVE-2025-8714 fix), causing schema.sql to show as changed on every dump. These scripts strip those lines. ## Development Server Before starting the dev server, check if it's already running: - Use `lsof -i :6827` or check for existing background tasks - The dev server runs on port 6827 (may fall back to 6828 if port is in use) - Start with `bun run --cwd apps/publisher-dashboard dev` or `devenv up` ## Pull Requests This repo uses Gitea (git.rev.iq) with the `tea` CLI for pull requests: - Use the `/gitea` skill when creating PRs - tea 0.10.1 is pinned in `nix/tea.nix` (0.11.x has TTY bugs) - Always specify `-r igm/publisher-dashboard` flag (SSH remote auto-detection doesn't work) ## sed Syntax (GNU coreutils) This project uses GNU coreutils via devenv, so use standard GNU sed syntax: - In-place edit: `sed -i 's/old/new/g' file` - Use `|` as delimiter when patterns contain `/`: `sed -i 's|old/path|new/path|g' file` - For multiple files: `for f in *.txt; do sed -i 's/old/new/g' "$f"; done` - Do NOT use BSD sed syntax (`sed -i ''`) - we have GNU sed available ## SvelteKit resolve() Usage Use `resolve()` from `$app/paths` for type-safe navigation. The patterns are: ### Static routes - use resolve() directly ```svelte href={resolve("/auth/login")} href={resolve("/dashboard")} ``` ### Dynamic routes - use two-argument form ```svelte href={resolve("/dashboard/[slug]", { slug: orgSlug })} href={resolve("/account/org-invites/[inviteId]", { inviteId: String(invite.id) })} ``` ### Login redirects - use gotoLogin helper For redirecting to login with a return URL, use the helper from `$lib/utils/navigation`: ```typescript import { gotoLogin } from "$lib/utils/navigation"; gotoLogin(page.url.pathname); ``` This helper uses resolve() internally and handles the query string correctly. ### Navigation arrays - use `as const` with route patterns For type-safe navigation arrays, define routes as literal strings with `as const`: ```typescript const navItems = [ { route: "/dashboard/[slug]/settings", icon: Settings, label: "General" }, { route: "/dashboard/[slug]/settings/members", icon: Users, label: "Members" }, ] as const; ``` Then use resolve with params: ```svelte {#each navItems as item (item.route)} {/each} ``` ### Runtime strings - skip resolve, use eslint-disable When paths are fully dynamic (e.g., server-provided redirects), skip resolve: ```typescript // eslint-disable-next-line svelte/no-navigation-without-resolve goto(redirectUrl); ```