Files
GearBox/.planning/phases/18-global-items-public-profiles/18-01-PLAN.md

7.8 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
18-global-items-public-profiles 01 execute 1
src/db/schema.ts
src/shared/schemas.ts
src/shared/types.ts
src/db/global-items-seed.json
true
GLOB-01
GLOB-02
PROF-01
PROF-03
truths artifacts key_links
globalItems table exists with brand, model, category, weightGrams, priceCents, imageUrl, description, createdAt columns
itemGlobalLinks junction table exists linking items to globalItems
users table has displayName, avatarUrl, bio nullable columns
setups table has isPublic boolean column defaulting to false
Zod schemas exist for global item search, item linking, profile update, and setup visibility
Types are inferred from Zod schemas and Drizzle tables, not manually duplicated
path provides contains
src/db/schema.ts globalItems, itemGlobalLinks tables + users profile cols + setups isPublic globalItems
path provides contains
src/shared/schemas.ts searchGlobalItemsSchema, linkItemSchema, updateProfileSchema searchGlobalItemsSchema
path provides contains
src/shared/types.ts GlobalItem, ItemGlobalLink, UpdateProfile, LinkItem types GlobalItem
path provides min_lines
src/db/global-items-seed.json Initial bikepacking gear catalog seed data 20
from to via pattern
src/shared/types.ts src/db/schema.ts Drizzle $inferSelect globalItems.$inferSelect
from to via pattern
src/shared/types.ts src/shared/schemas.ts Zod z.infer z.infer.*updateProfileSchema
Define all schema foundations for Phase 18: new database tables (globalItems, itemGlobalLinks), column additions to users (profile fields) and setups (isPublic), Zod validation schemas, TypeScript types, and seed data file.

Purpose: Every subsequent plan depends on these schema definitions. Defining contracts first prevents the scavenger hunt anti-pattern. Output: Updated schema.ts, schemas.ts, types.ts, and global-items-seed.json

<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/18-global-items-public-profiles/18-CONTEXT.md @.planning/phases/18-global-items-public-profiles/18-RESEARCH.md

@src/db/schema.ts @src/shared/schemas.ts @src/shared/types.ts

Task 1: Schema tables and column additions src/db/schema.ts src/db/schema.ts Add `boolean` to the drizzle-orm/pg-core imports (per D-01, D-12).

Add the globalItems table per D-01:

  • id: serial("id").primaryKey()
  • brand: text("brand").notNull()
  • model: text("model").notNull()
  • category: text("category")
  • weightGrams: doublePrecision("weight_grams")
  • priceCents: integer("price_cents")
  • imageUrl: text("image_url")
  • description: text("description")
  • createdAt: timestamp("created_at").defaultNow().notNull()

Add the itemGlobalLinks junction table per D-02:

  • id: serial("id").primaryKey()
  • itemId: integer("item_id").notNull().references(() => items.id, { onDelete: "cascade" }).unique() — each user item links to at most one global item
  • globalItemId: integer("global_item_id").notNull().references(() => globalItems.id, { onDelete: "cascade" })

Extend the users table per D-08 — add three nullable text columns:

  • displayName: text("display_name")
  • avatarUrl: text("avatar_url")
  • bio: text("bio")

Extend the setups table per D-12 — add:

  • isPublic: boolean("is_public").notNull().default(false)

Place new tables after setupItems section. Export all new tables.

After schema changes, run bun run db:generate to create the migration, then bun run db:push to verify it applies cleanly. bun run db:generate 2>&1 | tail -5 <acceptance_criteria> - grep -q "globalItems" src/db/schema.ts - grep -q "itemGlobalLinks" src/db/schema.ts - grep -q "displayName" src/db/schema.ts - grep -q "isPublic" src/db/schema.ts - grep -q "boolean" src/db/schema.ts </acceptance_criteria> All four schema additions (globalItems table, itemGlobalLinks table, users profile columns, setups isPublic) are defined and exported. Migration generated successfully.

Task 2: Zod schemas, types, and seed data src/shared/schemas.ts, src/shared/types.ts, src/db/global-items-seed.json src/shared/schemas.ts, src/shared/types.ts **schemas.ts** — Add the following Zod schemas at the end of the file:
  1. searchGlobalItemsSchema per D-04 and D-16:

    z.object({ q: z.string().optional() })
    
  2. linkItemSchema per D-18:

    z.object({ globalItemId: z.number().int().positive() })
    
  3. updateProfileSchema per D-08, D-21:

    z.object({
      displayName: z.string().max(100).optional(),
      avatarUrl: z.string().optional(),
      bio: z.string().max(500).optional(),
    })
    
  4. Update the existing updateSetupSchema to include isPublic per D-12, D-14: Add isPublic: z.boolean().optional() to the existing schema object.

  5. Update the existing createSetupSchema if it exists — add isPublic: z.boolean().optional().default(false).

types.ts — Add type exports:

  • export type GlobalItem = typeof globalItems.$inferSelect; (import globalItems, itemGlobalLinks from schema)
  • export type ItemGlobalLink = typeof itemGlobalLinks.$inferSelect;
  • export type SearchGlobalItems = z.infer<typeof searchGlobalItemsSchema>;
  • export type LinkItem = z.infer<typeof linkItemSchema>;
  • export type UpdateProfile = z.infer<typeof updateProfileSchema>;

global-items-seed.json — Create per D-06, D-07. Array of 15-20 bikepacking gear items covering categories like bags (frame bags, handlebar bags, saddle bags), shelters (tents, bivvies, tarps), sleep systems (sleeping bags, pads), cooking, hydration, and lighting. Each object has: brand, model, category, weightGrams, priceCents, description. Use real product names and approximate specs (e.g., Revelate Designs Terrapin, Apidura Expedition Handlebar Pack, Sea to Summit Spark SP1, MSR PocketRocket 2, Nemo Tensor Ultralight). Do NOT include id or createdAt. bun run lint 2>&1 | tail -5 <acceptance_criteria> - grep -q "searchGlobalItemsSchema" src/shared/schemas.ts - grep -q "linkItemSchema" src/shared/schemas.ts - grep -q "updateProfileSchema" src/shared/schemas.ts - grep -q "GlobalItem" src/shared/types.ts - grep -q "UpdateProfile" src/shared/types.ts - test -f src/db/global-items-seed.json </acceptance_criteria> Zod schemas cover global item search, item linking, profile update, and setup visibility. Types inferred from schemas and Drizzle tables. Seed file has 15-20 bikepacking items with real product names.

- `bun run lint` passes with no errors - `grep -c "export const" src/db/schema.ts` shows new table exports - `bun run db:generate` creates a clean migration - Seed JSON is valid: `node -e "JSON.parse(require('fs').readFileSync('src/db/global-items-seed.json','utf8'))"`

<success_criteria> Schema.ts has globalItems, itemGlobalLinks, user profile columns, and setup isPublic. Schemas.ts has all new Zod validators. Types.ts exports all new types. Seed JSON file exists with 15-20 items. Lint passes. </success_criteria>

After completion, create `.planning/phases/18-global-items-public-profiles/18-01-SUMMARY.md`