skills/project-setup/SKILL.md
Reference documentation for the just-recordings project architecture, conventions, and setup patterns. Use this when onboarding, adding new features, or needing to understand how the layers connect.
npx skillsauth add TravisBumgarner/claude-brain project-setupInstall 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.
npm workspaces defined in root package.json. Key packages:
packages/
shared/ - Zod schemas, types, auth utilities (published as @just-recordings/shared)
api/ - Express backend, Drizzle ORM, S3 integration
web/ - React + Vite frontend, MUI, Zustand, TanStack Query
npm run dev:web # docker-compose + API + web (concurrently)
npm run build # all packages
npm run test # vitest across all packages
npm run typecheck # tsc across all packages
npm run lint # biome lint
npm run lint:fix # biome lint --write
npm run db:generate # drizzle-kit generate (migrations)
npm run db:migrate # run migrations
.husky/pre-commit runs sequentially:
npm run lint (biome)npm run typecheck (tsc)npm test (vitest)All three must pass before a commit goes through.
biome.json at root. Key settings:
__tests__/ files, migrations, Storybook stories.claude/ is a git submodule from https://github.com/travisbumgarner/claude-brain.git. Clone with:
git clone --recurse-submodules <repo-url>
# or after clone:
git submodule update --init --recursive
tsconfig.base.json at root: ES2022 target, strict mode, declaration maps. Each package extends it.
@just-recordings/shared)Zod schemas are the single source of truth for types. Define the schema, infer the type:
// packages/shared/src/api/recordings.ts
export const recordingSchema = z.object({
id: z.string().uuid(),
name: z.string(),
duration: z.number(),
// ...
})
export type Recording = z.infer<typeof recordingSchema>
Schemas live in packages/shared/src/api:
responses.ts - ErrorCode enum, ApiResponse<T> type, error messagesrecordings.ts - Recording entity, CRUD request/response schemasshares.ts - RecordingShare entity, share request/response schemasusers.ts - User entity, /me response schemaAll error codes defined in packages/shared/src/api/responses.ts as a const object:
export const ErrorCode = {
UNAUTHORIZED: 'UNAUTHORIZED',
NOT_FOUND: 'NOT_FOUND',
// ...
} as const
export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode]
Every error code must have a corresponding entry in errorMessages (enforced by test).
{
".": "./dist/index.js",
"./api": "./dist/api/index.js",
"./styles": "./dist/styles/index.js",
"./auth": "./dist/auth/index.js"
}
Routes follow validate-then-process with typed context:
// packages/api/src/routes/shares/create.ts
export interface CreateShareValidationContext {
userId: string
recordingId: string
shareType: ShareType
}
export async function validate(req, res): Promise<Context | null> {
// 1. Check auth (requireUserId)
// 2. Validate params (isValidUUID)
// 3. Validate body
// 4. Check ownership/permissions
// Return null on failure (response already sent), context on success
}
export async function processRequest(req, res, context): Promise<void> {
// Business logic using validated context
sendSuccess(res, { data }, 201)
}
export async function handler(req, res): Promise<void> {
const context = await validate(req, res)
if (!context) return
await processRequest(req, res, context)
}
All responses use a consistent envelope:
// Success
{ success: true, data: { ... } }
// Error
{ success: false, errorCode: 'ERROR_CODE' }
Helper functions in packages/api/src/routes/shared/responses.ts:
sendSuccess(res, data, status?) // 200
sendBadRequest(res, errorCode?) // 400
sendUnauthorized(res) // 401
sendForbidden(res) // 403
sendNotFound(res, errorCode?) // 404
sendInternalError(res) // 500
sendError(res, errorCode, status) // custom
Simple example of the full pattern — packages/api/src/routes/users.ts:
router.get('/me', requireAuth, standardRateLimit, async (req, res) => {
const authReq = req as AuthenticatedRequest
if (!authReq.user) { sendUnauthorized(res); return }
const user = await getOrCreateUserByAuth({
authId: authReq.user.authId,
email: authReq.user.email || '',
})
sendSuccess(res, { id: user.id, email: user.email, ... })
})
Schema in packages/api/src/db/schema.ts. Three tables:
Config: packages/api/drizzle.config.ts, migrations in packages/api/drizzle/.
Commands: npm run db:generate, npm run db:migrate, npm run db:studio.
packages/api/src/middleware/auth.ts:
supabase.auth.getUser(token) to verify JWT{ authId, userId, email } to req.userAuth client in packages/web/src/auth/client.ts (Supabase anon key). Service in packages/web/src/auth/service.ts:
login(email, password) - signInWithPassword()signup(email, password) - signUp() (email confirmation required)logout() - signOut()getToken() - Returns access_token for API callsresetPassword(email) - Password reset flowEach resource gets a file in packages/web/src/api/. Pattern:
// packages/web/src/api/users.ts
export const getMe = async (): Promise<ApiResponse<User>> => {
try {
const result = await authenticatedFetch(`${config.apiBaseUrl}/users/me`)
if ('success' in result) return result // Error already parsed
const json = await result.json()
return { success: true, data: json.data }
} catch {
return { success: false, errorCode: 'INTERNAL_ERROR' }
}
}
authenticatedFetch (in packages/web/src/api/shared.ts) handles:
{ success: false, errorCode }Queries in packages/web/src/hooks/queries/, mutations in packages/web/src/hooks/mutations/.
// packages/web/src/hooks/queries/useCurrentUser.ts
export function useCurrentUser() {
const { data: authUser } = useAuthUser()
return useQuery({
queryKey: queryKeys.currentUser,
queryFn: async () => {
const response = await getMe()
if (!response.success) throw new ApiError(response.errorCode)
return response.data
},
enabled: !!authUser,
})
}
Modals use Preact Signals for global state. Structure:
packages/web/src/sharedComponents/Modal/
Modal.consts.tsx - MODAL_ID enum
components/
DefaultModal.tsx - Base modal wrapper (MUI Modal, 500px, close button)
ShareModal.tsx - Share link management
ConfirmationModal.tsx - Yes/no confirmation
RenderModal.tsx - Switch on activeModalSignal.value.id
index.tsx - Export
To add a new modal:
MODAL_ID in Modal.consts.tsxcomponents/ with props interface including id: typeof MODAL_ID.YOUR_MODALRenderModal.tsx switchActiveModal union in RenderModal.tsxactiveModalSignal.value = { id: MODAL_ID.YOUR_MODAL, ...props }packages/web/src/stores/)packages/shared/src/api/packages/api/src/db/schema.ts, run db:generatepackages/api/src/db/queries/packages/api/src/routes/, register in routerpackages/web/src/api/packages/web/src/hooks/queries/ or mutations/packages/web/src/pages/ or sharedComponents/development
Use this agent when designing visual interfaces, creating design systems, building component libraries, or refining user-facing aesthetics requiring expert visual design, interaction patterns, and accessibility considerations. Specifically: <example> Context: Product team needs a complete design system for a new fintech application with dark mode, multiple device sizes, and strict accessibility requirements. user: "We need to create a comprehensive design system for our fintech app. Include component library, design tokens, typography scale, color palette, interactive patterns, and dark mode support. Must meet WCAG 2.1 AA." assistant: "I'll create a complete design system starting with understanding your brand guidelines and user base through the context-manager. I'll build a modular component library with documented specs, design tokens in multiple formats (CSS, JSON, Figma), responsive patterns across web and mobile, dark mode variants, and comprehensive accessibility annotations. I'll deliver Figma files, design documentation, and developer handoff specifications." <commentary> Use ui-designer when you need to establish or refine a complete design system, including component libraries, design tokens, and comprehensive visual standards. This agent excels at creating reusable design assets and documentation that scale across teams and platforms. </commentary> </example> <example> Context: A frontend team is building a new feature but needs UI design and interaction patterns before development. user: "Design the booking flow for our travel app. Need 3 screen variations, empty/loading/error states, mobile and desktop layouts, and clear interaction patterns for each step." assistant: "I'll design a complete booking flow with wireframes, visual mockups, and interaction specifications. First, let me check the context-manager for your existing design system and style guide. Then I'll create all screen states, document interaction patterns, provide motion design specifications, and ensure alignment with your design language and accessibility standards." <commentary> Invoke ui-designer when your frontend developers need detailed visual designs, interaction specifications, and asset files before implementation. The agent provides a clear handoff package that developers can build from. </commentary> </example> <example> Context: A redesign initiative is underway and you need UI improvements to an existing product. user: "Our dashboard needs a visual refresh. The functionality is fine but the UX feels dated. Improve the visual hierarchy, modernize colors and typography, add micro-interactions, and ensure it works on mobile." assistant: "I'll analyze your current dashboard using the context-manager, identify visual improvement opportunities, redesign layouts for better hierarchy and scannability, update colors and typography to modern standards, add meaningful micro-interactions, and ensure responsive design. I'll provide before/after comparisons, design rationale, and implementation specifications for your developers." <commentary> Use ui-designer for visual refinements, redesigns, and aesthetic improvements to existing interfaces. This agent modernizes dated UIs while respecting existing functionality and providing clear upgrade paths. </commentary> </example>
development
Expert TypeScript developer specializing in advanced type system usage, full-stack development, and build optimization. Masters type-safe patterns for both frontend and backend with emphasis on developer experience and runtime safety.
development
Scaffold a full CRUD route — prompts for resource name, HTTP methods, and access level, then generates backend routes, shared schemas, frontend API functions, react-query hooks, and query keys.
development
Audit the codebase against all setup skills (00-09). Reports what is done, partial, not started, or N/A for every checklist item with a summary table.