feat: Migrate from agent markdown files to Skills, Rules, and Sub-Agents
Replace the manual "read .claude/agents/*.md" workflow with native Claude Code features for a more efficient, scalable development experience: - **Skills** (.claude/skills/): 7 auto-discovered slash commands (/requirements, /architecture, /frontend, /backend, /qa, /deploy, /help) with forked sub-agents for heavy tasks and inline execution for interactive ones - **Rules** (.claude/rules/): 4 modular rule files (general, frontend, backend, security) auto-applied based on file context - **Sub-Agents** (.claude/agents/): Lightweight configs for frontend-dev, backend-dev, and qa-engineer with model, tool, and turn limit settings - **Context Engineering**: Layered context loading, context isolation via forked skills, built-in context recovery after compaction, and "always read, never guess" rules to prevent hallucinated code references - **CLAUDE.md**: Auto-loaded project context replacing PROJECT_CONTEXT.md - **Feature tracking**: features/INDEX.md as persistent state across sessions - **Production guides**: docs/production/ for error tracking, security, performance, database optimization, and rate limiting - **Init Mode**: /requirements detects empty PRD and bootstraps full project setup (PRD + all feature specs) from a single project description Removed: 6 monolithic agent files, PROJECT_CONTEXT.md, HOW_TO_USE_AGENTS.md, TEMPLATE_CHANGELOG.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# Database Optimization
|
||||
|
||||
## 1. Indexing
|
||||
|
||||
Create indexes on columns used in WHERE, ORDER BY, or JOIN clauses:
|
||||
|
||||
```sql
|
||||
-- Without index: ~500ms at 100k rows
|
||||
SELECT * FROM tasks WHERE user_id = 'abc123' ORDER BY created_at DESC;
|
||||
|
||||
-- After creating index: <10ms
|
||||
CREATE INDEX idx_tasks_user_id_created ON tasks(user_id, created_at DESC);
|
||||
```
|
||||
|
||||
**Rule of thumb:** If a column appears in WHERE or ORDER BY and the table will have >1000 rows, add an index.
|
||||
|
||||
Always include indexes in your migration SQL alongside CREATE TABLE.
|
||||
|
||||
## 2. Avoid N+1 Queries
|
||||
|
||||
The most common performance problem with ORMs and query builders:
|
||||
|
||||
```typescript
|
||||
// Bad: N+1 (1 query for users + N queries for tasks)
|
||||
const { data: users } = await supabase.from('users').select('*')
|
||||
for (const user of users) {
|
||||
const { data: tasks } = await supabase
|
||||
.from('tasks')
|
||||
.select('*')
|
||||
.eq('user_id', user.id)
|
||||
}
|
||||
|
||||
// Good: Single query with join (1 query total)
|
||||
const { data } = await supabase
|
||||
.from('users')
|
||||
.select('*, tasks(*)')
|
||||
```
|
||||
|
||||
## 3. Always Limit Results
|
||||
|
||||
Never return unbounded results from the database:
|
||||
|
||||
```typescript
|
||||
// Bad: Returns ALL rows
|
||||
const { data } = await supabase.from('tasks').select('*')
|
||||
|
||||
// Good: Returns max 50 rows
|
||||
const { data } = await supabase.from('tasks').select('*').limit(50)
|
||||
|
||||
// Better: Paginated
|
||||
const { data } = await supabase
|
||||
.from('tasks')
|
||||
.select('*')
|
||||
.range(0, 49) // First 50 rows
|
||||
```
|
||||
|
||||
## 4. Caching Strategy
|
||||
|
||||
For data that changes rarely (dashboard stats, config, categories):
|
||||
|
||||
```typescript
|
||||
import { unstable_cache } from 'next/cache'
|
||||
|
||||
export const getCategories = unstable_cache(
|
||||
async () => {
|
||||
const { data } = await supabase.from('categories').select('*')
|
||||
return data
|
||||
},
|
||||
['categories'], // Cache key
|
||||
{ revalidate: 3600 } // Refresh every hour
|
||||
)
|
||||
```
|
||||
|
||||
**When to cache:**
|
||||
- Data that changes less than once per hour
|
||||
- Expensive aggregation queries
|
||||
- Data shared across all users (not user-specific)
|
||||
|
||||
**When NOT to cache:**
|
||||
- User-specific data that changes frequently
|
||||
- Real-time data (use Supabase Realtime instead)
|
||||
|
||||
## 5. Select Only What You Need
|
||||
|
||||
```typescript
|
||||
// Bad: Fetches all columns
|
||||
const { data } = await supabase.from('users').select('*')
|
||||
|
||||
// Good: Fetches only needed columns
|
||||
const { data } = await supabase.from('users').select('id, name, avatar_url')
|
||||
```
|
||||
Reference in New Issue
Block a user