Claude-skill-registry data-architecture
Single source of truth patterns, facts.ts structure, type safety, and data helper functions. Use when working with project data or adding new facts.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/data-architecture-skill" ~/.claude/skills/majiayu000-claude-skill-registry-data-architecture-509431 && rm -rf "$T"
manifest:
skills/data/data-architecture-skill/SKILL.mdsource content
Data Architecture Skill
Overview
This project uses a single source of truth pattern for all data. All personal information, project details, and configuration data is centralized in typed data files.
Core Principle: Single Source of Truth
Rule: Never hardcode personal data. Always reference data files.
// ❌ WRONG - Hardcoded data const email = "me@omerakben.com"; const name = "Omer Akben"; // ✅ CORRECT - Reference data file import { facts } from "@/data/facts"; const email = facts.contact.email; const name = facts.personal.name; ```typescript ## Data File Structure ### Primary Data Files ```typescript src/data/ ├── facts.ts # Personal info, skills, experience ├── projects.ts # Project catalog with metadata └── ... # Other data files src/config/ └── assistantFaq.ts # FAQ and intent libraries ```typescript ## facts.ts Architecture **Location:** `src/data/facts.ts` ### Structure Overview ```typescript export const facts = { personal: { name: string; title: string; location: LocationInfo; bio: string; tagline: string; }, contact: { email: string; phone: string; github: string; linkedin: string; calendly: string; }, professional: { experience: Experience[]; education: Education[]; skills: Skill[]; certifications: Certification[]; workAuthorization: WorkAuthorization; // Added 2025-11-02 }, preferences: { timezone: string; availability: string; } }; ```typescript ### Type Definitions ```typescript interface LocationInfo { city: string; state: string; country: string; timezone: string; } interface Experience { id: string; company: string; position: string; startDate: string; endDate: string | 'Present'; description: string; technologies: string[]; achievements: string[]; } interface Skill { id: string; name: string; category: SkillCategory; level: SkillLevel; yearsOfExperience: number; } interface WorkAuthorization { status: string; officialTitle: string; sponsorshipRequired: boolean; employmentRestrictions: boolean; eligibleEmployers: string; proofDocument: string; summary: string; } ```typescript ### Work Authorization Data **Added:** November 2, 2025 **Location:** `facts.professional.workAuthorization` ```typescript workAuthorization: { status: "U.S. Permanent Resident (Green Card)", officialTitle: "Lawful Permanent Resident (LPR)", sponsorshipRequired: false, employmentRestrictions: false, eligibleEmployers: "Any U.S. employer", proofDocument: "Form I-551 (Permanent Resident Card)", summary: "Authorized to work for any U.S. employer without restrictions or sponsorship requirements." } ```typescript **Usage:** AI agent references this when answering recruiter questions ## projects.ts Architecture **Location:** `src/data/projects.ts` ### Structure ```typescript export interface Project { id: string; slug: string; title: string; tagline: string; description: string; longDescription: string; technologies: Technology[]; category: ProjectCategory; featured: boolean; showcase: boolean; liveUrl?: string; githubUrl?: string; imageUrl: string; metrics?: ProjectMetrics; testimonials?: Testimonial[]; } export const projects: Project[] = [ // Array of all projects ]; ```typescript ### Helper Functions ```typescript // Get projects by category export function getProjectsByCategory(category: ProjectCategory): Project[] { return projects.filter(p => p.category === category); } // Get featured projects export function getFeaturedProjects(): Project[] { return projects.filter(p => p.featured); } // Get project by slug export function getProjectBySlug(slug: string): Project | undefined { return projects.find(p => p.slug === slug); } // Get all technologies used export function getAllTechnologies(): Technology[] { const techSet = new Set<Technology>(); projects.forEach(p => p.technologies.forEach(t => techSet.add(t))); return Array.from(techSet); } ```typescript ### Usage Pattern ```typescript import { projects, getFeaturedProjects, getProjectBySlug } from "@/data/projects"; // In component const featured = getFeaturedProjects(); const project = getProjectBySlug(params.slug); ```typescript ## Type Safety Patterns ### 1. Const Assertions ```typescript export const SKILL_CATEGORIES = [ 'Frontend', 'Backend', 'DevOps', 'AI/ML', ] as const; export type SkillCategory = typeof SKILL_CATEGORIES[number]; // Type is: 'Frontend' | 'Backend' | 'DevOps' | 'AI/ML' ```typescript ### Benefits - Autocomplete in IDE - Type checking - Single source for both runtime and types ### 2. Branded Types ```typescript type ProjectId = string & { readonly __brand: 'ProjectId' }; type UserId = string & { readonly __brand: 'UserId' }; // Prevents mixing up IDs function getProject(id: ProjectId) { /* ... */ } function getUser(id: UserId) { /* ... */ } // TypeScript error: types are incompatible const projectId: ProjectId = 'proj_123' as ProjectId; const userId: UserId = 'user_456' as UserId; getProject(userId); // ❌ Error! ```typescript ### 3. Discriminated Unions ```typescript type Education = | { type: 'degree'; university: string; degree: string; major: string; } | { type: 'bootcamp'; program: string; completion: string; } | { type: 'certification'; name: string; issuer: string; }; function formatEducation(edu: Education): string { switch (edu.type) { case 'degree': return `${edu.degree} in ${edu.major} from ${edu.university}`; case 'bootcamp': return `${edu.program}`; case 'certification': return `${edu.name} by ${edu.issuer}`; } } ```typescript ## Zod Validation Integration ### Schema Definitions **Location:** `src/lib/agent-tools/schemas.ts` ```typescript import { z } from 'zod'; export const ContactSchema = z.object({ name: z.string().min(1), email: z.string().email(), company: z.string().optional(), message: z.string().min(10), }); export type Contact = z.infer<typeof ContactSchema>; ```typescript ### Runtime Validation ```typescript // API route handler export async function POST(request: Request) { const body = await request.json(); // Validate with Zod const result = ContactSchema.safeParse(body); if (!result.success) { return Response.json({ success: false, error: result.error.format(), }, { status: 400 }); } // Type-safe data access const { name, email, company, message } = result.data; // ... } ```typescript ### Benefits of Zod - Runtime validation - Type inference from schemas - Detailed error messages - Parse, transform, and validate in one step ## AI Agent Data Integration ### Knowledge Base **Location:** `src/lib/agent-knowledge-base.ts` The AI agent consumes data from facts.ts: ```typescript import { facts } from '@/data/facts'; export const agentKnowledgeBase = ` # Core Identity Name: ${facts.personal.name} Title: ${facts.personal.title} Location: ${facts.personal.location.city}, ${facts.personal.location.state} # Work Authorization Status: ${facts.professional.workAuthorization.status} Sponsorship Required: ${facts.professional.workAuthorization.sponsorshipRequired} # Skills ${facts.professional.skills.map(s => `- ${s.name} (${s.level})`).join('\n')} # Contact Email: ${facts.contact.email} LinkedIn: ${facts.contact.linkedin} `; ```typescript ### Benefits - Single source ensures consistency - Updates to facts.ts automatically flow to AI - No hardcoded data in agent prompts ### Tool Implementations AI agent tools reference data files: ```typescript // src/app/api/tools/get-contact/route.ts import { facts } from '@/data/facts'; export async function POST() { return Response.json({ success: true, data: { email: facts.contact.email, linkedin: facts.contact.linkedin, github: facts.contact.github, calendly: facts.contact.calendly, } }); } ```typescript ## Adding New Data ### Step 1: Update Type Definition ```typescript // src/data/facts.ts interface Facts { personal: PersonalInfo; contact: ContactInfo; professional: ProfessionalInfo; newSection: NewSectionType; // Add new section } ```typescript ### Step 2: Add Data ```typescript export const facts: Facts = { // ... existing data newSection: { field1: 'value1', field2: 'value2', } }; ```typescript ### Step 3: Update AI Knowledge Base ```typescript // src/lib/agent-knowledge-base.ts export const agentKnowledgeBase = ` ...existing content... # New Section ${facts.newSection.field1} ${facts.newSection.field2} `; ```typescript ### Step 4: Add Tests ```typescript // src/data/facts.test.ts describe('facts.newSection', () => { it('should have required fields', () => { expect(facts.newSection.field1).toBeDefined(); expect(facts.newSection.field2).toBeDefined(); }); }); ```typescript ## Data Validation Patterns ### 1. Email Validation ```typescript import { z } from 'zod'; const EmailSchema = z.string() .email('Invalid email format') .toLowerCase() .trim(); // Usage const email = EmailSchema.parse('USER@EXAMPLE.COM'); // Result: 'user@example.com' ```typescript ### 2. URL Validation ```typescript const UrlSchema = z.string() .url('Invalid URL format') .refine(url => url.startsWith('https://'), { message: 'URL must use HTTPS' }); ```typescript ### 3. Date Validation ```typescript const DateSchema = z.string() .regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be YYYY-MM-DD') .refine(date => !isNaN(Date.parse(date)), { message: 'Invalid date' }); ```typescript ### 4. Enum Validation ```typescript const SkillLevelSchema = z.enum([ 'Beginner', 'Intermediate', 'Advanced', 'Expert' ]); type SkillLevel = z.infer<typeof SkillLevelSchema>; ```typescript ## Helper Function Patterns ### 1. Filter Helpers ```typescript // Get items by property export function getByCategory<T extends { category: string }>( items: T[], category: string ): T[] { return items.filter(item => item.category === category); } // Get items by multiple criteria export function getByFilters<T>( items: T[], filters: Partial<T> ): T[] { return items.filter(item => { return Object.entries(filters).every(([key, value]) => { return item[key as keyof T] === value; }); }); } ```typescript ### 2. Sort Helpers ```typescript // Sort by date export function sortByDate<T extends { date: string }>( items: T[], order: 'asc' | 'desc' = 'desc' ): T[] { return [...items].sort((a, b) => { const dateA = new Date(a.date).getTime(); const dateB = new Date(b.date).getTime(); return order === 'asc' ? dateA - dateB : dateB - dateA; }); } // Sort by property export function sortBy<T, K extends keyof T>( items: T[], key: K, order: 'asc' | 'desc' = 'asc' ): T[] { return [...items].sort((a, b) => { if (a[key] < b[key]) return order === 'asc' ? -1 : 1; if (a[key] > b[key]) return order === 'asc' ? 1 : -1; return 0; }); } ```typescript ### 3. Transform Helpers ```typescript // Group by property export function groupBy<T, K extends keyof T>( items: T[], key: K ): Record<string, T[]> { return items.reduce((acc, item) => { const groupKey = String(item[key]); if (!acc[groupKey]) acc[groupKey] = []; acc[groupKey].push(item); return acc; }, {} as Record<string, T[]>); } // Map to lookup object export function toMap<T extends { id: string }>( items: T[] ): Record<string, T> { return items.reduce((acc, item) => { acc[item.id] = item; return acc; }, {} as Record<string, T>); } ```typescript ## Testing Data Integrity ### Unit Tests ```typescript // src/data/facts.test.ts import { facts } from './facts'; describe('facts.ts data integrity', () => { it('should have valid email', () => { expect(facts.contact.email).toMatch(/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/); }); it('should have all required skills', () => { expect(facts.professional.skills.length).toBeGreaterThan(0); facts.professional.skills.forEach(skill => { expect(skill.name).toBeTruthy(); expect(skill.category).toBeTruthy(); expect(skill.level).toBeTruthy(); }); }); it('should have valid work authorization', () => { const { workAuthorization } = facts.professional; expect(workAuthorization.status).toBeTruthy(); expect(typeof workAuthorization.sponsorshipRequired).toBe('boolean'); expect(typeof workAuthorization.employmentRestrictions).toBe('boolean'); }); }); ```typescript ### Zod Schema Tests ```typescript import { ContactSchema } from './schemas'; describe('ContactSchema validation', () => { it('should accept valid contact', () => { const valid = { name: 'John Doe', email: 'john@example.com', message: 'Hello, this is a test message.', }; const result = ContactSchema.safeParse(valid); expect(result.success).toBe(true); }); it('should reject invalid email', () => { const invalid = { name: 'John Doe', email: 'not-an-email', message: 'Hello, world', }; const result = ContactSchema.safeParse(invalid); expect(result.success).toBe(false); }); }); ```typescript ## Common Mistakes ### Mistake 1: Hardcoding Data ```typescript // ❌ WRONG function Header() { return <h1>Omer Akben - AI Engineer</h1>; } // ✅ CORRECT import { facts } from '@/data/facts'; function Header() { return <h1>{facts.personal.name} - {facts.personal.title}</h1>; } ```typescript ### Mistake 2: Inconsistent Data Format ```typescript // ❌ WRONG - Different date formats { startDate: '2024-01-01', endDate: 'January 2024', } // ✅ CORRECT - Consistent ISO format { startDate: '2024-01-01', endDate: '2024-01-31', } ```typescript ### Mistake 3: No Validation ```typescript // ❌ WRONG - Assumes data is valid const user = JSON.parse(request.body); saveUser(user); // ✅ CORRECT - Validate first const result = UserSchema.safeParse(JSON.parse(request.body)); if (result.success) { saveUser(result.data); } ```typescript ## Data Update Checklist When adding or updating data: - [ ] Update type definitions first - [ ] Add/modify data in facts.ts or projects.ts - [ ] Update AI knowledge base if needed - [ ] Add helper functions if beneficial - [ ] Write unit tests for new data - [ ] Verify AI agent responses still accurate - [ ] Check that related tools still work - [ ] Update documentation if structure changed ## Quick Reference ```typescript // Import data import { facts } from '@/data/facts'; import { projects, getProjectBySlug } from '@/data/projects'; // Access data const email = facts.contact.email; const name = facts.personal.name; const project = getProjectBySlug('portfolio'); // Validate with Zod const result = Schema.safeParse(data); if (result.success) { // Use result.data } // Helper pattern export function getFiltered<T>(items: T[], predicate: (item: T) => boolean): T[] { return items.filter(predicate); } ```typescript ## Related Files - `src/data/facts.ts` - Single source of truth for personal data - `src/data/projects.ts` - Project catalog with helpers - `src/lib/agent-knowledge-base.ts` - AI agent data integration - `src/lib/agent-tools/schemas.ts` - Zod validation schemas - `src/config/assistantFaq.ts` - FAQ and intent libraries