ADR-001: Frontend Foundation Phase
Status: Implemented
Date: 2024-01-XX
Authors: Foundation Phase Implementation
Context
The frontend monorepo supports multiple domains:
- Personal website
- QRACK (QR-based container management)
- Discart-me (marketplace — production, MUST NOT be affected)
The codebase had significant duplication in:
- GraphQL request handling (duplicated across
qrackApi.ts, discartMeApi.ts, boxhubApi.ts)
- Authentication logic (separate contexts for each domain with nearly identical logic)
This created maintenance burden and risk of inconsistencies between domains.
Decision
Implement Phase 1: Foundation — introduce shared infrastructure to reduce duplication without changing user-facing behavior or touching production systems (Discart-me).
What Was Created
1. Shared GraphQL Client
File: src/lib/api/core/graphqlClient.ts
- Framework-agnostic GraphQL request handler
- Centralizes fetch, headers, Authorization, error handling
- Configurable via
GraphQLClientConfig
- Supports domain-specific logging via
logPrefix
- Accepts optional endpoint override, custom headers, fetch options
Benefits:
- Single source of truth for GraphQL requests
- Consistent error handling across domains
- Easier to add features (retries, caching, etc.) in the future
2. QRACK API Refactored
File: src/lib/qrackApi.ts
graphqlRequest function now wraps shared client
- All function signatures preserved (backward compatible)
- All error messages and logs preserved
- Configured with
[qrackApi] log prefix
Preserved:
- Function signatures
- Returned data shapes
- Error messages
- Development logs
3. Generic Authentication Feature
Files:
src/features/auth/types.ts — type definitions
src/features/auth/AuthProvider.tsx — generic provider
src/features/auth/useAuth.ts — domain-specific hook
src/features/auth/providers/QrackAuthProvider.tsx — QRACK-specific wrapper
src/features/auth/hooks/useQrackAuth.ts — compatibility layer
Features:
- Domain-configurable via
AuthConfig
- Manages token, user state, loading state
- Encapsulates localStorage/session handling
- Token validation on load
- App access checking
- NO UI components (pure logic only)
Configuration:
{
domain: 'qrack' | 'discart-me',
appCode: 'QRACK' | 'DISCARD_ME',
storageKeyPrefix: 'qrack' | 'discart',
loginFn: (email, password) => Promise<AuthResponse>,
registerFn: (payload) => Promise<AuthResponse>,
getMeFn: (token) => Promise<User>,
}
4. QRACK Migration
Changes:
components/qrack/QrackAuthShell.tsx — now uses new QrackAuthProvider
- All QRACK pages updated to import
useQrackAuth from new location
- Compatibility layer maintains exact same interface
Result:
- QRACK works exactly as before
- Same login/logout behavior
- Same token persistence
- Same protected route behavior
What Was Intentionally NOT Refactored
Discart-me
- Completely untouched — still uses
DiscartAuthProvider from src/context/DiscartAuthContext.tsx
- No imports changed
- No behavior changes
- Verification: No QRACK code referenced in
app/discart-me/
Other APIs
discartMeApi.ts — not refactored (will be done in Phase 2)
boxhubApi.ts — not refactored (will be done in Phase 2)
UI Components
- No UI refactoring
- No route changes
- No visual changes
- No component restructuring
Old Contexts
src/context/QrackAuthContext.tsx — kept but not used (will be removed in Phase 2)
src/context/DiscartAuthContext.tsx — untouched, still in production use
Architecture Decisions
1. Compatibility Layer
Decision: Created useQrackAuth compatibility hook instead of forcing pages to use useAuth('qrack') directly.
Rationale:
- Maintains exact same interface (
hasQrackAccess boolean, etc.)
- Zero risk of breaking existing pages
- Can be removed in Phase 2 after verification
2. Domain Configuration
Decision: Used configuration object pattern for AuthProvider instead of separate providers per domain.
Rationale:
- Reduces code duplication
- Makes it easy to add new domains
- Keeps logic centralized while allowing domain-specific behavior
3. Framework-Agnostic GraphQL Client
Decision: Created pure TypeScript client with no React dependencies.
Rationale:
- Can be used in any context (React, Node.js, etc.)
- Easier to test
- Clearer separation of concerns
Known Follow-ups for Phase 2
- Migrate Discart-me to use shared GraphQL client
- Refactor
discartMeApi.ts to use graphqlClient
- Preserve all error handling and CORS logic
- Migrate Discart-me to use generic auth (optional)
- Only if beneficial (may have domain-specific requirements)
- Must be done carefully to avoid production issues
- Migrate BoxHub (if still active)
- Similar pattern to QRACK migration
- Remove old contexts
- Delete
src/context/QrackAuthContext.tsx
- Document migration path for Discart-me if applicable
- Remove compatibility layer
- Update QRACK pages to use
useAuth('qrack') directly
- Remove
useQrackAuth hook
- Component extraction (if needed)
- Extract shared UI components
- Standardize form patterns
Success Criteria
✅ QRACK works exactly as before
✅ Discart-me works exactly as before
✅ Code duplication reduced
✅ Foundation ready for Phase 2
✅ No visual or routing changes
✅ No breaking changes
Testing Recommendations
- QRACK:
- Discart-me:
Risks Mitigated
- Production Impact: Discart-me completely untouched
- Breaking Changes: Compatibility layer maintains interface
- Visual Changes: No UI modifications
- Route Changes: No routing modifications
Notes
- This phase focused on invisible infrastructure only
- User experience should be identical
- Foundation is now in place for Phase 2 refactoring
- All changes are backward compatible