Architecture Overview¶
Tech stack¶
| Concern | Choice | Version | Cite |
|---|---|---|---|
| Framework | React | ^18.3.1 | package.json |
| Language | TypeScript | ^5.5.3 | package.json (devDep); tsconfig.json |
| Bundler | Vite | ^5.4.1 | package.json; vite.config.ts |
| Build plugin | @vitejs/plugin-react-swc |
^3.5.0 | vite.config.ts |
| Module system | ESM ("type": "module") |
n/a | package.json |
| Routing | react-router-dom |
^6.26.2 | package.json; src/App.tsx |
| Server-state cache | @tanstack/react-query |
^5.56.2 | package.json; src/App.tsx |
| Forms | react-hook-form + @hookform/resolvers + zod |
latest | package.json |
| CSS | Tailwind 3 + tailwindcss-animate + class-variance-authority |
^3.4.11 | tailwind.config.ts |
| UI primitives | shadcn/ui (Radix UI under the hood) | varies | src/components/ui/*.tsx; components.json |
| Icons | lucide-react |
^0.462.0 | package.json |
| Toasts | sonner + shadcn toast |
^1.5.0 | package.json |
| Charts | recharts |
^2.12.7 | package.json |
| Date | date-fns |
^3.6.0 | package.json |
| Linter | ESLint 9 (flat config) + eslint-plugin-react-hooks + eslint-plugin-react-refresh + typescript-eslint |
latest | eslint.config.js |
There is no Prettier / pre-commit hook configured.
Source structure¶
admin_console_R/
├── index.html # Vite entry; loads /src/main.tsx; includes gpteng.co/gptengineer.js script (note in security.md)
├── vite.config.ts # dev server on :8080; allowedHosts includes admin.someli.ai; alias @ → src; HMR overlay disabled
├── eslint.config.js # ESLint 9 flat config
├── tailwind.config.ts # darkMode 'class'; SF Pro Display font stack; design-token-driven HSL palette via CSS vars
├── tsconfig.json + tsconfig.app.json + tsconfig.node.json
├── components.json # shadcn CLI config (alias, css path)
├── postcss.config.js # autoprefixer + tailwind
├── package.json
├── package-lock.json + yarn.lock + bun.lockb # three lockfiles — see dependencies-inventory.md
├── public/ # static assets (logo, dashboard.jpg)
└── src/
├── main.tsx # React 18 createRoot bootstrap
├── App.tsx # router + global providers (QueryClient, AuthProvider, TooltipProvider, Toasters)
├── index.css # global Tailwind + CSS variables
├── App.css # leftover, mostly empty
├── vite-env.d.ts # vite type augmentation
├── components/
│ ├── auth/
│ │ ├── LoginForm.tsx
│ │ └── ProtectedRoute.tsx
│ ├── layout/
│ │ ├── AppLayout.tsx # sidebar + main content shell
│ │ └── Sidebar.tsx # nav items, logout, account switcher
│ ├── shared/ # small reusable bits
│ └── ui/ # 50 shadcn primitives (Radix wrappers)
├── config/
│ └── env.ts # typed env var accessor
├── context/
│ └── AuthContext.tsx # user/token state, login/logout/checkAuth
├── hooks/
│ ├── useAuth.tsx # convenience wrapper around AuthContext
│ ├── use-mobile.tsx
│ └── use-toast.ts
├── lib/ # cn() utility etc.
├── pages/
│ ├── Accounts.tsx + Accounts.css
│ ├── AffiliateMarketing.tsx
│ ├── CustomerService.tsx
│ ├── Index.tsx
│ ├── Login.tsx
│ ├── MyProfile.tsx
│ ├── NotFound.tsx
│ ├── Personnel.tsx
│ └── Prompts.tsx
└── services/
└── api.ts # 184 lines — fetch wrapper + ~25 named API methods
Entry point — src/main.tsx / src/App.tsx¶
main.tsx does the React 18 createRoot(...).render(<App />). App.tsx composes the provider stack:
<QueryClientProvider>
<TooltipProvider>
<BrowserRouter>
<AuthProvider>
<Toaster />
<Sonner />
<Routes>
<Route path="/" element={<Navigate to="/login" replace />} />
<Route path="/login" element={<Login />} />
<Route path="/accounts" element={<ProtectedRoute><AppLayout><Accounts /></AppLayout></ProtectedRoute>} />
{/* ... */}
</Routes>
</AuthProvider>
</BrowserRouter>
</TooltipProvider>
</QueryClientProvider>
Every protected route is wrapped in ProtectedRoute → AppLayout → <Page />. The repetition is verbose but explicit. A refactor to a single <ProtectedRoutes> layout-route would tighten this without changing behaviour.
Build process¶
- Dev:
npm run dev→vite→http://localhost:8080(port set invite.config.ts) - Production build:
npm run build→vite build→dist/ - Dev-mode build (for staging?):
npm run build:dev→vite build --mode development
There is no npm run start / npm run preview invoked anywhere; production hosting strategy is not documented in-repo (see build-and-deploy.md).
Largest files¶
(sample by inspection; full count would need find ... -exec wc -l)
src/services/api.ts— 184 linessrc/context/AuthContext.tsx— ~150 linessrc/pages/Accounts.tsx— verify; likely the largest page (table + filters + modals)- All
src/components/ui/*.tsx— generated shadcn files, usually 40-200 lines each
No file is in the 1000+ LoC range typical of the backend repos. This is healthy.
Dead / commented code¶
src/components/layout/Sidebar.tsxhas a commented-outPromptsnav item (despite the route being mounted). Either un-comment or delete.index.htmlcontains:<!-- IMPORTANT: DO NOT REMOVE THIS SCRIPT TAG OR THIS VERY COMMENT! -->followed by<script src="https://cdn.gpteng.co/gptengineer.js" type="module"></script>. This is the Lovable.dev runtime tag — see security.md.
Coding conventions¶
- TypeScript with
strictmode (verify intsconfig.app.json— strict is default off in many starter templates; check) - React function components only
- Naming: PascalCase for components, camelCase for utilities; file names match component names
- Imports prefer the
@/alias over relative paths cn()(fromsrc/lib/utils.ts) for conditional class merging- Toasts via
useToast()(src/hooks/use-toast.ts) which forwards to shadcn<Toaster>; Sonner is also mounted inApp.tsxbut theuseToastroute is the primary one used