Load when starting work in 10x-Mapmaster or when unsure about project standards...
Project standards and constraints for 10x-Mapmaster.
Announce: "I'm checking codebase-conventions to ensure I follow project standards."
src/ # Vue 3 frontend (presentation only)
āāā components/ # Reusable components
ā āāā game/ # Game-specific components
ā āāā map/ # MapLibre components
ā āāā ui/ # shadcn-vue components
āāā composables/ # Shared reactive logic
ā āāā game/ # Game-related composables
ā āāā map/ # Map-related composables
āāā stores/ # Pinia stores
āāā views/ # Page-level components
āāā lib/ # Utilities, API, types
ā āāā api/ # RPC call wrappers
ā āāā places/ # Place-related utilities
āāā types/ # TypeScript types
āāā i18n/ # Translations
supabase/
āāā db/ # Database source files
ā āāā schema/ # Tables, types, RLS policies
ā āāā game_logic/ # Internal functions (scoring, questions)
ā ā āāā functions/ # Function definitions
ā ā āāā data/ # Seed data
ā āāā public/ # Player-facing RPC entrypoints
ā āāā functions/
āāā functions/ # Deno edge functions
āāā migrations/ # Generated (never edit directly)
āāā seeds/ # Development data
āāā tests/ # pgTAP tests
openspec/ # Specifications
āāā specs/ # Capability specs
āāā changes/ # Active change proposals
docs/ # Human-readable documentation
| Type | Convention | Example |
|---|---|---|
| Files (frontend) | kebab-case | game-session.ts, PlaceView.vue |
| Vue components | PascalCase | GameActive.vue, PlacesLayer.vue |
| Composables | camelCase with use prefix |
useMapCamera, useGameMap |
| Pinia stores | camelCase with use...Store |
useGameSessionStore |
| SQL identifiers | snake_case | game_sessions, user_id |
| SQL keywords | UPPERCASE | SELECT, FROM, WHERE |
| Database functions | snake_case | start_game, play_turn |
| TypeScript types | PascalCase | GameSession, Candidate |
Player descriptions are limited to 200 characters:
-- Enforced by database constraint
CONSTRAINT check_description_length
CHECK (char_length(description) <= 200)
Valid answers are strictly typed:
CREATE TYPE answer_value AS ENUM('yes', 'no', 'not_sure');
yes / no - For both questions AND guessesnot_sure - ONLY for questions, never for guessesCREATE TYPE game_session_status AS ENUM(
'active', -- Game in progress
'won', -- System guessed correctly
'ended', -- Max turns reached without win
'needs_submission' -- Awaiting player to submit correct place
);
-- CORRECT style
SELECT
p.id,
p.name,
1 - (p.embedding <=> v_query) AS similarity
FROM places p
JOIN place_traits pt ON pt.place_id = p.id
WHERE p.status = 'active'
AND similarity > 0.5
ORDER BY similarity DESC
LIMIT 10;
-- WRONG: lowercase keywords, SELECT *
select * from places where status = 'active'
Rules:
SELECT, FROM, WHERE, JOIN, ORDER BYplaces, user_id, created_atSELECT *)any in application code// CORRECT
export function useMapCamera(): UseMapCameraReturn {
const center = ref<{ lng: number; lat: number }>({ lng: 0, lat: 20 })
// ...
return { center, flyTo, isAnimating }
}
// WRONG
export function useMapCamera() { // Missing return type
const center: any = ref({ lng: 0, lat: 20 }) // any usage
// ...
}
Max 200 lines per file. If larger, split:
feat/, fix/, chore/, docs/feat: add candidate scoring function
fix: prevent camera feedback loop
chore: update dependencies
docs: add algorithm documentation
supabase/db/bun run db:rebuild (generates migration + resets)supabase test dbsrc/bun run type-checkbun run test:unitSee references/glossary.md for domain term definitions.