PROJECT OVERVIEW:
The project, named 'FontMatch', is a gamified web and mobile application designed to help developers and designers find the perfect coding font. The current problem is the tedious and often overwhelming process of selecting a font for coding environments (IDEs, text editors). FontMatch solves this by transforming font selection into an engaging experience through interactive games, side-by-side comparisons, and personalized recommendations. The core value proposition is to make font discovery enjoyable, efficient, and tailored to individual user preferences and technical needs.
TECH STACK:
- Frontend: Next.js (App Router for structure and features like Server Components, dynamic routes, API routes), React, TypeScript, Tailwind CSS (for utility-first styling), shadcn/ui (for accessible, composable components).
- Backend: Next.js API Routes or a separate Node.js/Express server (if complexity increases significantly, but aiming for integrated API routes for MVP).
- Database: PostgreSQL (or a compatible alternative like Supabase's DB) with Drizzle ORM for type-safe database interactions.
- Authentication: NextAuth.js (for robust and flexible authentication, supporting email/password, OAuth providers like Google, GitHub).
- State Management: React Context API for global state, component-local state for UI elements.
- Routing: Next.js App Router.
- Deployment: Vercel.
- Other Libraries: `react-icons` or `lucide-react` for icons, `react-select` or shadcn/ui's combobox for font selection dropdowns, potentially a charting library like Recharts if font analysis metrics are visualized.
DATABASE SCHEMA:
1. `users` table:
- `id` (UUID, primary key)
- `email` (VARCHAR, unique, not null)
- `username` (VARCHAR, unique, not null)
- `hashedPassword` (VARCHAR, nullable for OAuth)
- `createdAt` (TIMESTAMP, default NOW())
- `updatedAt` (TIMESTAMP, default NOW())
- `premium` (BOOLEAN, default false)
- `avatarUrl` (VARCHAR, nullable)
2. `fonts` table:
- `id` (SERIAL, primary key)
- `name` (VARCHAR, unique, not null)
- `source` (VARCHAR, e.g., 'Google Fonts', 'Custom')
- `weights` (JSONB, array of available weights, e.g., ['regular', 'bold'])
- `styles` (JSONB, array of available styles, e.g., ['normal', 'italic'])
- `tags` (TEXT[], e.g., ['monospace', 'serif', 'sans-serif', 'display'])
- `previewImageUrl` (VARCHAR, nullable, URL to a sample image)
- `googleFontsUrl` (VARCHAR, nullable, direct link to Google Fonts page)
3. `userFontPreferences` table:
- `id` (SERIAL, primary key)
- `userId` (UUID, foreign key to `users.id`, not null)
- `fontId` (INTEGER, foreign key to `fonts.id`, not null)
- `preferenceScore` (INTEGER, 1-5, based on user interactions)
- `lastInteractedAt` (TIMESTAMP, default NOW())
- `CONSTRAINT unique_user_font UNIQUE (userId, fontId)`
4. `gameSessions` table:
- `id` (SERIAL, primary key)
- `userId` (UUID, foreign key to `users.id`, not null)
- `gameType` (VARCHAR, e.g., 'pairwise', 'rating')
- `startedAt` (TIMESTAMP, default NOW())
- `completedAt` (TIMESTAMP, nullable)
- `score` (INTEGER, nullable)
5. `gameChoices` table:
- `id` (SERIAL, primary key)
- `sessionId` (INTEGER, foreign key to `gameSessions.id`, not null)
- `choice1FontId` (INTEGER, foreign key to `fonts.id`, not null)
- `choice2FontId` (INTEGER, foreign key to `fonts.id`, not null)
- `userSelectedId` (INTEGER, foreign key to `fonts.id`, not null) // ID of the font the user selected
- `createdAt` (TIMESTAMP, default NOW())
CORE FEATURES & USER FLOW:
1. Authentication:
- Flow: User visits the site -> Clicks 'Sign Up' or 'Log In' -> Presented with options (Email/Password, Google, GitHub) -> Enters credentials or redirects to OAuth provider -> Returns to app, authenticated.
- Backend: NextAuth.js handles session management, credential verification, and OAuth callbacks.
- Edge Case: Handle invalid credentials, OAuth errors, session expiration.
2. Font Discovery (Game: Pairwise Comparison):
- Flow: Authenticated user navigates to 'Play' -> Selects 'Pairwise Comparison' game -> App fetches two random, unrated fonts (or fonts relevant to user's profile) -> Displays them side-by-side with a code snippet ('AaBbCc123...') -> User clicks their preferred font -> App records the choice (`gameChoices`), updates `userFontPreferences` for the winning font (increment score/interactions), and fetches two new fonts -> User can play until they choose to stop or complete a set number of rounds.
- UI: Two prominent font previews, clear 'Choose This Font' buttons, a progress indicator (e.g., 'Round 5/20'), 'Skip' button, 'End Game' button.
- Backend: API route (`/api/games/pairwise/next`) fetches font pairs and records choices.
- Edge Case: What if a user has rated all available fonts? What if database query returns fewer than 2 fonts?
3. Personalized Recommendations:
- Flow: User navigates to 'Profile' or 'Recommendations' -> App queries `userFontPreferences` for the logged-in user, ordering by `preferenceScore` DESC -> Displays the top N preferred fonts.
- Additional Logic: Implement a basic recommendation algorithm (e.g., collaborative filtering if data grows, or content-based filtering based on font tags if user prefers certain tags).
- UI: Display preferred fonts with their details, possibly a "Why you might like this" explanation.
- Backend: API route (`/api/user/recommendations`) fetches and processes preference data.
- Edge Case: User has no preferences yet (display a prompt to play games).
4. Font Detail & Comparison View:
- Flow: User can click on any font (from recommendations, search results, or game) to see a dedicated detail page.
- Content: Full character set preview, available weights/styles, links to source (e.g., Google Fonts), user reviews/ratings (future feature), direct side-by-side comparison with another selected font.
- UI: Large preview area, clear display of metadata, comparison tool.
- Backend: API routes (`/api/fonts/[id]`) to fetch single font details, potentially (`/api/fonts/compare?fontA=X&fontB=Y`).
- Edge Case: Font details not available, broken image links.
5. Search & Filtering:
- Flow: User enters a font name or keyword (e.g., 'monospace', 'boxy') into a search bar -> App queries the `fonts` table using text search (e.g., `ILIKE` in PostgreSQL) and filters by tags -> Displays matching fonts.
- UI: Search input, results list, filtering options (e.g., by tag, by weight).
- Backend: API route (`/api/fonts/search?q=...&tags=...`).
API & DATA FETCHING:
- Use Next.js API Routes (`/pages/api/...` or `app/api/...` in App Router) for backend logic.
- Data Fetching: Utilize Server Components for initial data loads where possible (e.g., fetching user profile on dashboard load). Client Components will use `fetch` or libraries like SWR/React Query for dynamic data, mutations, and interactive elements.
- API Examples:
- GET `/api/fonts`: Fetch a list of fonts (paginated, filterable).
- GET `/api/fonts/[id]`: Fetch details for a specific font.
- GET `/api/games/pairwise/next`: Fetch a pair of fonts for the comparison game.
- POST `/api/games/choices`: Record a user's choice from a game session.
- GET `/api/user/preferences`: Get the current user's preferred fonts.
- POST `/api/auth/signup`, `POST /api/auth/login`, etc. (handled by NextAuth.js).
- Request/Response Bodies: JSON format. Example POST `/api/games/choices` body: `{ sessionId: 123, choice1FontId: 5, choice2FontId: 8, userSelectedId: 5 }`. Response: `{ success: true, updatedPreferences: {...} }`.
COMPONENT BREAKDOWN (Next.js App Router):
- `app/layout.tsx`: Root layout (HTML, Head, Body, global providers, Tailwind CSS setup).
- `app/(auth)/layout.tsx`: Auth pages layout (shared styling).
- `app/(auth)/signin/page.tsx`: Sign-in form component.
- `app/(auth)/signup/page.tsx`: Sign-up form component.
- `app/layout.tsx`: Main application layout (Navbar, Sidebar/Footer if applicable).
- `app/(app)/dashboard/page.tsx`: User dashboard. Displays overview, recent activity, quick links. Fetches user data via Server Component.
- `app/(app)/play/page.tsx`: Main game selection page. Links to different game types.
- `app/(app)/play/pairwise/page.tsx`: The pairwise font comparison game. Uses Client Components for game logic and interaction.
- `components/game/FontPairDisplay.tsx`: Renders two font previews side-by-side.
- `components/game/GameControls.tsx`: Buttons for selection, skipping, ending.
- `components/game/ProgressBar.tsx`: Shows game progress.
- `app/(app)/fonts/page.tsx`: Browse/Search fonts page. Includes search bar and filter components.
- `components/font/FontCard.tsx`: Displays a single font summary in a list.
- `components/font/SearchBar.tsx`: Input for searching fonts.
- `components/filter/TagFilter.tsx`: Filter options by tags.
- `app/(app)/fonts/[fontId]/page.tsx`: Detailed view of a single font.
- `components/font/FontDetailView.tsx`: Displays all font information.
- `components/font/CharacterPreview.tsx`: Shows full character set.
- `components/font/ComparisonTool.tsx`: Allows comparison with another font.
- `app/(app)/profile/page.tsx`: User profile page. Shows preferences, saved fonts, game history.
- `components/profile/PreferenceList.tsx`: Lists user's most preferred fonts.
- `components/profile/GameHistory.tsx`: Shows past game sessions.
- `components/ui/Button.tsx`: Reusable button component (from shadcn/ui).
- `components/ui/Input.tsx`: Reusable input component (from shadcn/ui).
- `components/ui/Card.tsx`: Reusable card component (from shadcn/ui).
- `components/layout/Navbar.tsx`: Top navigation bar.
- `components/layout/Footer.tsx`: Footer.
UI/UX DESIGN & VISUAL IDENTITY:
- Style: "Minimalist Clean with Typographic Flair". Focus on clarity, readability, and showcasing the fonts themselves.
- Color Palette:
- Primary: Deep Navy (`#0A192F`)
- Secondary: Light Gray (`#8892B0`)
- Accent: Teal (`#64FFDA`)
- Background: Off-White (`#CCD6F6`)
- Card/Surface: Slightly darker off-white or very light gray (`#E6EDFF`)
- Typography:
- Headings: A clean, modern sans-serif like Inter or Poppins (use sparingly).
- Body Text: Highly readable sans-serif like Inter or Open Sans for UI text.
- Font Previews: The actual fonts being showcased.
- Layout: Generous whitespace, clear visual hierarchy. Use a 12-column grid system (Tailwind's default). Sections are well-defined with clear headings. Responsive design prioritizing mobile-first, then scaling up.
- Visual Elements: Subtle use of gradients for accent elements or backgrounds. Focus on clean lines and well-spaced elements. Icons should be simple and consistent (e.g., Lucide icons).
ANIMATIONS:
- Page Transitions: Subtle fade-in/fade-out using Next.js's built-in router or a library like `Framer Motion` for more complex transitions between pages.
- Element Transitions: Smooth transitions on hover effects for buttons and cards (e.g., slight scale-up, color change).
- Loading States: Use shimmering placeholders (skeleton loaders) or subtle spinners (from shadcn/ui) while data is being fetched.
- Game Animations: Smooth transitions when new font pairs appear, subtle feedback animations when a user clicks a font.
EDGE CASES:
- Authentication: Handling expired sessions, redirecting unauthenticated users to login, secure password handling.
- Empty States: Displaying user-friendly messages and calls-to-action when lists are empty (e.g., 'No preferred fonts yet. Play a game to start!', 'No search results found.').
- Data Validation: Ensuring user inputs (sign-up forms, search queries) are valid before submission. Server-side validation for API routes.
- Font Availability: Gracefully handle cases where font files might be missing or links are broken.
- API Errors: Implementing global error handling for API requests, showing informative messages to the user.
- Rate Limiting: For API routes, especially those related to user actions, to prevent abuse.
SAMPLE/MOCK DATA:
1. Font: Fira Code
- Preview Text: "The quick brown fox jumps over the lazy dog. 0123456789 !@#$%^&*()_+=-[]{}|;':\",./<>?"
- Weights: ['Regular', 'Bold', 'Light']
- Tags: ['monospace', 'programming', 'ligatures', 'sans-serif']
- Source: Google Fonts
2. Font: JetBrains Mono
- Preview Text: "The quick brown fox jumps over the lazy dog. 0123456789 !@#$%^&*()_+=-[]{}|;':\",./<>?"
- Weights: ['Extralight', 'Light', 'Regular', 'Medium', 'Bold']
- Tags: ['monospace', 'programming', 'geometric', 'sans-serif']
- Source: JetBrains
3. Font: Source Code Pro
- Preview Text: "The quick brown fox jumps over the lazy dog. 0123456789 !@#$%^&*()_+=-[]{}|;':\",./<>?"
- Weights: ['ExtraLight', 'Light', 'Normal', 'Bold']
- Tags: ['monospace', 'programming', 'slab-serif']
- Source: Adobe Fonts
4. Font: Dank Mono
- Preview Text: "The quick brown fox jumps over the lazy dog. 0123456789 !@#$%^&*()_+=-[]{}|;':\",./<>?"
- Weights: ['Regular']
- Tags: ['monospace', 'programming', 'commercial', 'italic']
- Source: Custom
5. Font: Operator Mono
- Preview Text: "The quick brown fox jumps over the lazy dog. 0123456789 !@#$%^&*()_+=-[]{}|;':\",./<>?"
- Weights: ['Light', 'Regular', 'Medium', 'Bold']
- Tags: ['monospace', 'programming', 'commercial', 'ligatures']
- Source: Adobe Fonts
6. User Preference Example (for `userFontPreferences` table):
- `userId`: 'user-uuid-123'
- `fontId`: 1 (Fira Code)
- `preferenceScore`: 5
- `lastInteractedAt`: '2023-10-27T10:00:00Z'
7. User Preference Example:
- `userId`: 'user-uuid-123'
- `fontId`: 2 (JetBrains Mono)
- `preferenceScore`: 4
- `lastInteractedAt`: '2023-10-27T10:05:00Z'
8. Game Session Example (for `gameSessions` table):
- `id`: 50
- `userId`: 'user-uuid-123'
- `gameType`: 'pairwise'
- `startedAt`: '2023-10-27T09:50:00Z'
- `completedAt`: '2023-10-27T10:10:00Z'
- `score`: 15
9. Game Choice Example (for `gameChoices` table):
- `sessionId`: 50
- `choice1FontId`: 1 (Fira Code)
- `choice2FontId`: 3 (Source Code Pro)
- `userSelectedId`: 1
- `createdAt`: '2023-10-27T09:55:00Z'
10. TURKISH TRANSLATIONS (for UI elements):
- Sign Up: Kayıt Ol
- Log In: Giriş Yap
- Email: E-posta
- Password: Şifre
- Play Game: Oyun Oyna
- Your Profile: Profilin
- Font Comparison: Font Karşılaştırma
- Next Font Pair: Sonraki Font Çifti
- Choose This Font: Bu Fontu Seç
- Skip: Atla
- End Game: Oyunu Bitir
- Recommendations: Öneriler
- Search Fonts: Font Ara
- Filter by Tag: Etikete Göre Filtrele
- Compare Fonts: Fontları Karşılaştır
- Browse All Fonts: Tüm Fontlara Göz At
- Save Preference: Tercihi Kaydet
- Game History: Oyun Geçmişi
- Settings: Ayarlar
- Logout: Çıkış Yap
- Welcome, [Username]!: Hoş geldin, [Kullanıcı Adı]!
- No fonts found: Hiç font bulunamadı.
- Start playing to get recommendations!: Öneri almak için oynamaya başla!
- Error loading fonts: Fontlar yüklenirken bir hata oluştu.
- You have selected: Sen seçtin
- Available Weights: Mevcut Kalınlıklar
- View on Google Fonts: Google Fonts'ta Görüntüle
- Select another font for comparison: Karşılaştırma için başka bir font seç