Skip to content

System Architecture

DoCurious is a React 19 single-page application built with TypeScript, Vite 7, Zustand for state management, and Tailwind CSS 4 for styling. It follows a mock-first architecture -- every feature works with client-side mock APIs, and each module can be individually swapped to a real backend.

Tech Stack

Frontend

LayerTechnologyVersion
FrameworkReact19.2.0
LanguageTypeScript5.9.3
Build ToolVite7.2.4
StylingTailwind CSS4.1.18
State ManagementZustand5.0.11
RoutingReact Router7.13.0
FormsReact Hook Form7.71.1
i18nreact-i18next14.1.2
ChartsRecharts3.7.0
TestingVitest + Testing Library4.0.18
LintingESLint + Prettier9.39.1 / 3.8.1
DocumentationVitePress + TypeDoc1.6.4 / 0.28.17
StorybookStorybook10.2.8

Backend (server/)

LayerTechnologyVersion
FrameworkExpress4.21
LanguageTypeScript5.7
ORMPrisma6.3
DatabasePostgreSQL17
ValidationZod3.24
Authjsonwebtoken + bcryptjs9.0 / 2.4
Securityhelmet8.0
TestingVitest + Supertest4.0 / 7.2

See Backend Architecture for the full server documentation.

Architecture Diagram

Layer-by-Layer

Types (src/types/ -- 32 files)

Every domain entity has a dedicated type file. All types are re-exported through src/types/index.ts as a barrel.

FileDomain
common.types.tsBaseEntity, UUID, ApiResponse<T>, PaginatedResponse<T>, PaginationParams
auth.types.tsLoginCredentials, AuthTokens, AuthState
user.types.tsUser, UserRole (9 roles), AccountTier, ConsentStatus
challenge.types.tsChallenge, ChallengeInstance, TrackRecord, TrackRecordEntry
community.types.tsCommunity (6 types), CommunityPost, FeedType
gamification.types.tsBadge, XPEvent, LevelDefinition, UserStreak
school.types.tsSchool, Class, Assignment, StudentProgress
vendor.types.tsVendor, VendorAccountStatus, VendorApprovalStatus
featureFlag.types.tsFeatureFlag, TargetingRule, FlagEvaluationContext
wallet.types.tsWalletTransaction, Payout, WalletSummary
challengeSeries.types.tsSeries, SeriesStatus, SeriesOrder
notification.types.tsNotification, NotificationPreferences
gift.types.tsGift sending/receiving types
explore.types.tsCuratedView, SavedListItem, search types
portfolio.types.tsPortfolio/scrapbook types
event.types.tsChallenge events and registrations
learningPath.types.tsLearning path progression
dealersChoice.types.tsDealer's Choice game mechanics
reflection.types.tsSEL reflection prompts and responses
admin.types.tsAdmin roles, permissions, audit log
invitation.types.tsChallenge invitations
payment.types.tsStripe payment integration types
sharing.types.tsCross-community sharing
onboarding.types.tsOnboarding flow state
legal.types.tsConsent, cookie preferences
location.types.tsGeocoding and map types
report.types.tsContent reporting/flagging
review.types.tsChallenge reviews
order.types.tsOrder management
coupon.types.tsCoupon/discount types
communityGoal.types.tsCooperative community goals

API Layer (src/api/ -- ~50 files)

The API layer uses a dual-implementation pattern. Each domain has a mock implementation (*.api.ts) and a real implementation (*.real.api.ts). The barrel export (src/api/index.ts) selects between them based on VITE_USE_MOCK_API.

typescript
// src/api/index.ts — switching pattern
import { apiConfig } from './config'
import { challengeApi as mockChallengeApi } from './challenge.api'
import { realChallengeApi } from './challenge.real.api'

export const challengeApi = apiConfig.useMockApi
  ? mockChallengeApi
  : realChallengeApi

25 API modules: auth, user, challenge, trackRecord, explore, community, gift, school, notification, gamification, learningPath, portfolio, event, communityGoal, payment, emailVerification, invitation, reflection, onboarding, sharing, admin, dealersChoice, wallet, series (real only).

See API Layer for full documentation.

Adapters (src/adapters/)

The adapter layer maps between SQL backend responses (snake_case, bigint IDs, UPPER_CASE enums) and FE types (camelCase, UUID strings, lowercase enums). Entity adapters: challenge, vendor, series, portfolio, wallet.

See Adapter Guide for full documentation.

Stores (src/store/ -- 30 stores)

Zustand stores with selectors for optimized re-renders. All stores and selectors are re-exported through src/store/index.ts.

Production stores (26): useAuthStore, useUserStore, useChallengeStore, useTrackRecordStore, useExploreStore, useCommunityStore, useGiftStore, useSchoolStore, useNotificationStore, useGamificationStore, useLearningPathStore, usePortfolioStore, useCommunityGoalStore, useVendorStore, useInvitationStore, useOnboardingStore, useShareStore, useAdminStore, useDealersChoiceStore, useLegalStore, useWalletStore, useCheckoutStore, useReflectionStore, useVendorTeamStore, useImpersonationStore, useToastStore.

Infrastructure stores (4): useFeatureFlagStore, useDemoModeStore, useDebugPanelStore (dev-only), useNetworkLogStore (dev-only).

See Store Patterns for full documentation.

Custom Hooks (src/hooks/)

HookPurpose
useFeatureFlag(flagKey)Evaluates a feature flag for the current user by bridging auth store (user context) with the feature flag store (evaluation). Returns { enabled, value, isLoading }.
useLocation()Manages user location state with 4 strategies: saved location (localStorage), user profile location, browser geolocation API, manual address input. Returns location, radius, permission status, and control functions.
useAddressSearch()Address autocomplete hook that provides suggestions and place selection via the location API.

Utilities (src/lib/)

FileExportsPurpose
utils.tscn(...inputs)Tailwind CSS class merge utility. Combines clsx (conditional classes) with tailwind-merge (deduplication). Used throughout all components.
contextHelpers.ts18 functionsPure functions for the multi-context user model. Includes buildContextsFromLegacyRole (bridge for old single-role data), hasContext, getRoleInContext, getAvailableContexts, role checks (isSchoolAdmin, isPlatformAdmin, isVendor, hasLinkedChildren, isTier1), and getContextHomeRoute. Used by auth store selectors, ContextGuard, and ParentGuard.

Components (src/components/ -- 26 directories, ~148 components)

Component directories organized by domain:

DirectoryPurpose
account/Account management (notification preferences)
admin/Admin-only components (ImpersonationBar)
challenge/ChallengeCard, ChallengeGrid, finalization (7-step wizard)
common/ErrorBoundary, Skeleton, FeatureGate, CookieConsentBanner, GuidedTour
community/CommunityCard, FeedPost, MemberList, GoalCard, AssignChallengeModal
debug/Debug Panel (dev-only, 6 tabs)
demo/DemoModeBar (sales presentation mode)
explore/DealersChoice, FilterPanel, CalendarView, EventCard
filters/FilterSidebar, FilterModal, AppliedFilters
gamification/BadgeCard, LevelProgress, StreakDisplay, JourneyMap, LeaderboardTable
gift/GiftCard, GiftModal, GiftPermissionSettings
invitation/InvitationCard, InviteModal
layout/AppLayout, Header, Sidebar, TopNav, CartDrawer, ContextSwitcher
learningPaths/PathCard, PathProgress
notifications/NotificationCenter
payment/PaymentForm, StripeCheckout, CheckoutModal
portfolio/PortfolioCard, PortfolioBuilder
review/TrackRecordReviewModal
school/CSVRosterImport, TeacherReflectionConfig, ReflectionDefaults
search/SearchTrigger, SearchFilterBar, LocationFilter
social/ShareButton, BatchShareModal, BlockUserButton, CommunityModTools, JoinRequestFlow
themeEditor/EditorShell, 6 editor panels, 5 control primitives, PreviewPanel
trackRecord/EntryCard, MediaUpload, TrackRecordView, DocumentationGuideModal
ui/22 themed UI primitives (Button, Card, Dialog, Table, etc.)

Pages (src/pages/ -- 189 pages)

Route-level components organized by domain: auth/, challenges/, communities/, explore/, gifts/, school/, admin/ (85+ toolkit pages), vendor/, parent/, learningPaths/, portfolio/, profile/, account/, and public/ (compliance pages).

Routes (src/routes/)

React Router v7 with createBrowserRouter. 195 routes with lazy loading via React.lazy(). Seven guard types: AuthGuard, RoleGuard, TierGuard, AgeGuard, ConsentGuard, ContextGuard, ParentGuard (plus AdminRoleGuard for granular admin permissions).

See Routes & Guards for patterns and guard documentation, or the Route Map for the complete auto-generated listing.

Key Architectural Patterns

Mock-First API

Every API module has both a mock (*.api.ts) and real (*.real.api.ts) implementation. The app defaults to mocks (VITE_USE_MOCK_API defaults to true unless explicitly set to 'false'). This enables:

  • Full frontend development without a backend
  • Demo mode with pre-seeded data
  • Gradual backend integration per module

Selector-Based Store Access

Stores export memoized selector functions to prevent unnecessary re-renders:

typescript
// Define selectors alongside the store
export const selectChallenges = (state: ChallengeStore) => state.challenges
export const selectMyChallenges = (state: ChallengeStore) => state.myChallenges

// Use in components
const challenges = useChallengeStore(selectChallenges)

Lazy Loading

All page components are lazy-loaded with React.lazy() and wrapped in Suspense with a PageSkeleton fallback and ErrorBoundary:

tsx
const Dashboard = lazy(() =>
  import('../pages/Dashboard').then(m => ({ default: m.Dashboard }))
)

function LazyPage({ children }: { children: React.ReactNode }) {
  return (
    <ErrorBoundary>
      <Suspense fallback={<PageSkeleton />}>
        {children}
      </Suspense>
    </ErrorBoundary>
  )
}

Guard Composition

Route guards compose naturally by nesting:

tsx
<AuthGuard>
  <RoleGuard roles={['teacher', 'school_admin']}>
    <TierGuard>
      <LazyPage><SomePage /></LazyPage>
    </TierGuard>
  </RoleGuard>
</AuthGuard>

Theme via CSS Variables

The theme system applies configuration as CSS custom properties on :root, allowing any component to reference theme tokens without importing the theme:

css
.card {
  background: var(--background);
  border: var(--theme-card-border-width) solid var(--border);
  border-radius: var(--theme-card-radius);
  box-shadow: var(--theme-card-shadow);
}

Backend Layer

The backend is a full Express server in server/ with 130+ REST endpoints, JWT authentication, role-based access control, and Prisma ORM. It follows a Routes → Controllers → Services → Prisma pattern across 18 domain services.

See the Backend section for complete documentation:

See Also

Feature Guides

Operations

Role Guides

DoCurious Platform Documentation