feat: add OpenTelemetry observability, Faro frontend monitoring, remove legacy Next.js app

- Add OpenTelemetry SDK with tracing, metrics, and OTLP export for API and worker
- Integrate Grafana Faro for frontend real-user monitoring
- Instrument health checks, database, Bull queues, and HTTP exception filter
- Add Grafana dashboard JSON for service overview
- Remove deprecated apps/web-nj (Next.js) — fully replaced by Vite+React frontend
- Update nginx config with OTEL collector proxy
- Minor UI fixes in schema viewer, category components, and subscription flow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sase Dev
2026-02-16 17:20:49 +00:00
parent 87d8eea298
commit dcbeb83ccc
113 changed files with 2745 additions and 7351 deletions

View File

@@ -37,7 +37,7 @@
```
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
Next.js 16 │────▶│ NestJS 10 │────▶│ PostgreSQL 17│
Vite/React19 │────▶│ NestJS 10 │────▶│ PostgreSQL 17│
│ (port 3000) │ │ (port 4000) │ └──────────────┘
└─────────────┘ │ │────▶┌──────────────┐
│ │ │ Redis 7.4 │
@@ -50,9 +50,9 @@
```
**Three runtime processes** managed by PM2:
1. `sase-api` — NestJS API server (2 instances, cluster mode)
2. `sase-web`Next.js frontend (2 instances, cluster mode)
3. `sase-worker` — Background job processor (1 instance, fork mode)
1. `sase-api` — NestJS API server (fork mode)
2. `sase-web`Vite/React frontend (fork mode)
3. `sase-worker` — Background job processor (fork mode)
---
@@ -60,9 +60,9 @@
| Layer | Technology |
|-------|-----------|
| **Frontend** | Next.js 16, React 19, TypeScript 5.7 |
| **Frontend** | Vite 6.3, React 19, TanStack Router 1.120, TypeScript 5.7 |
| **Styling** | Tailwind CSS 4, shadcn/ui (Radix primitives) |
| **State** | Zustand, TanStack React Query 5 |
| **State** | Zustand 5, TanStack React Query 5 |
| **Backend** | NestJS 10.4, TypeScript |
| **Database** | PostgreSQL 17, Drizzle ORM 0.41 |
| **Cache** | Redis 7.4, ioredis |
@@ -70,7 +70,7 @@
| **Payments** | Iyzico (card), EFT (bank transfer with receipt upload) |
| **Storage** | MinIO (S3-compatible) |
| **Jobs** | BullMQ (Redis-backed queues) |
| **Testing** | Vitest 3, Playwright 1.58 |
| **Testing** | Vitest 3, Playwright 1.50 |
| **Linting** | Biome |
| **CI/CD** | GitHub Actions |
| **Process Mgmt** | PM2 |
@@ -115,23 +115,29 @@ sase.tr/
│ │ ├── drizzle.config.ts
│ │ └── vitest.config.ts
│ │
│ └── web/ # Next.js frontend
│ └── web/ # Vite + React frontend
│ └── src/
│ ├── app/ # App Router pages
│ ├── layout.tsx # Root layout (Inter font, providers)
│ ├── (auth)/ # Public auth pages
│ │ ── (dashboard)/ # Protected dashboard pages
│ ├── main.tsx # Entry point (RouterProvider, QueryClient)
├── routeTree.gen.ts # Auto-generated TanStack route tree
├── routes/ # TanStack Router file-based routes
│ │ ── __root.tsx # Root layout
│ │ ├── index.tsx # Landing page
│ │ ├── _auth.tsx # Auth layout (login, register, etc.)
│ │ ├── dashboard.tsx # Dashboard layout (protected)
│ │ └── dashboard/ # Dashboard subroutes
│ ├── components/ # React components
│ │ ├── layout/ # Sidebar, Header, MobileNav
│ │ ├── admin/ # DailyChart
│ │ ├── schema/ # SchemaViewer, HotspotOverlay, PartsPanel
│ │ ├── subscription/ # BrandSelector
│ │ ├── vehicles/ # VehicleCard
│ │ ── categories/ # CategoryTree
│ │ ├── vehicles/ # VehicleCard, VinInput
│ │ ── categories/ # CategoryTree, CategoryGrid
│ │ ├── payment/ # PaymentContent
│ │ └── settings/ # SettingsContent
│ ├── hooks/ # Custom hooks (useAuth, useParts, useSchemaInteraction)
│ ├── lib/ # api-client, auth-client, query-client, i18n, utils
│ ├── stores/ # Zustand stores (auth, schema, i18n)
│ ├── lib/ # api-client, auth-client, i18n, toast, user-settings, category-icons
│ ├── stores/ # Zustand stores (auth, schema)
│ ├── messages/ # i18n JSON (tr.json, en.json)
│ └── proxy.ts # Auth middleware for protected routes
│ └── remotion/ # Animated demo video generation
├── packages/
│ ├── shared/ # Shared types, Zod schemas, utilities
@@ -433,52 +439,67 @@ emexCategoryTranslations
### Routes & Pages
#### Public
| Path | Page | Description |
|------|------|-------------|
| `/` | Home | Landing page with features and pricing CTA |
| `/pricing` | Pricing | Plan comparison (1/2/3 brand, full package) |
| `/login` | Login | Email/password + Google OAuth |
| `/register` | Register | Account creation |
| `/forgot-password` | Forgot Password | Email-based recovery |
| `/reset-password` | Reset Password | Token-based password reset |
**Router:** TanStack Router (file-based, auto-generated route tree)
#### Dashboard (Protected)
| Path | Page | Description |
|------|------|-------------|
| `/dashboard/search` | VIN Search | Main VIN decoder input |
| `/dashboard/search/parts` | Parts Search | Parts search results |
| `/dashboard/history` | History | Past VIN decode searches |
| `/dashboard/subscription` | Subscription | Plan selection & brand picker |
| `/dashboard/subscription/pay` | Payment | Card (Iyzico) or EFT payment |
| `/dashboard/billing` | Billing | Payment history & receipts |
| `/dashboard/settings` | Settings | Profile, Security, Connections, Referral, Account tabs |
| `/dashboard/vehicles/[id]` | Vehicle | Vehicle details |
| `/dashboard/vehicles/[id]/categories/[categoryId]` | Parts Viewer | Interactive schema + parts table |
#### Public
| Path | Route File | Description |
|------|------------|-------------|
| `/` | `routes/index.tsx` | Landing page with features and pricing CTA |
| `/pricing` | `routes/pricing.tsx` | Plan comparison (1/2/3 brand, full package) |
| `/about` | `routes/about.tsx` | About page |
| `/contact` | `routes/contact.tsx` | Contact page |
| `/blog` | `routes/blog.tsx` | Blog page |
| `/demo` | `routes/demo.tsx` | Demo page |
| `/privacy` | `routes/privacy.tsx` | Privacy policy |
| `/terms` | `routes/terms.tsx` | Terms of service |
| `/kvkk` | `routes/kvkk.tsx` | KVKK (Turkish data protection) |
#### Auth (Layout: `_auth.tsx`)
| Path | Route File | Description |
|------|------------|-------------|
| `/login` | `routes/_auth/login.tsx` | Email/password + Google OAuth |
| `/register` | `routes/_auth/register.tsx` | Account creation |
| `/forgot-password` | `routes/_auth/forgot-password.tsx` | Email-based recovery |
| `/reset-password` | `routes/_auth/reset-password.tsx` | Token-based password reset |
#### Dashboard (Protected, Layout: `dashboard.tsx`)
| Path | Route File | Description |
|------|------------|-------------|
| `/dashboard` | `routes/dashboard/index.tsx` | Dashboard home |
| `/dashboard/search` | `routes/dashboard/search.tsx` | VIN Search — main VIN decoder input |
| `/dashboard/history` | `routes/dashboard/history.tsx` | Past VIN decode searches |
| `/dashboard/subscription` | `routes/dashboard/subscription/index.tsx` | Plan selection & brand picker |
| `/dashboard/subscription/pay` | `routes/dashboard/subscription/pay.tsx` | Card (Iyzico) or EFT payment |
| `/dashboard/billing` | `routes/dashboard/billing.tsx` | Payment history & receipts |
| `/dashboard/settings` | `routes/dashboard/settings.tsx` | Profile, Security, Connections, Referral, Account tabs |
| `/dashboard/vehicles/$id` | `routes/dashboard/vehicles_/$id/index.tsx` | Vehicle details |
| `/dashboard/vehicles/$id/categories/$categoryId` | `routes/dashboard/vehicles_/$id/categories_/$categoryId.tsx` | Interactive schema + parts table |
#### Admin (Role-based)
| Path | Page | Description |
|------|------|-------------|
| `/dashboard/admin` | Dashboard | Stats overview with charts |
| `/dashboard/admin/users` | Users | User management |
| `/dashboard/admin/payments` | Payments | EFT approval workflow |
| `/dashboard/admin/referrals` | Referrals | Referral program tracking |
| `/dashboard/admin/analytics` | Analytics | Daily query statistics |
| Path | Route File | Description |
|------|------------|-------------|
| `/dashboard/admin` | `routes/dashboard/admin/index.tsx` | Stats overview with charts |
| `/dashboard/admin/users` | `routes/dashboard/admin/users.tsx` | User management |
| `/dashboard/admin/payments` | `routes/dashboard/admin/payments.tsx` | EFT approval workflow |
| `/dashboard/admin/referrals` | `routes/dashboard/admin/referrals.tsx` | Referral program tracking |
| `/dashboard/admin/analytics` | `routes/dashboard/admin/analytics.tsx` | Daily query statistics |
### Components
| Component | Location | Description |
|-----------|----------|-------------|
| **Sidebar** | `components/layout/sidebar.tsx` | Desktop nav with active route highlighting, admin section |
| **Header** | `components/layout/header.tsx` | Top bar with language toggle (TR/EN), user info, logout |
| **MobileNav** | `components/layout/mobile-nav.tsx` | Drawer navigation for mobile |
| **SchemaViewer** | `components/schema/schema-viewer.tsx` | Interactive parts diagram with zoom/pan/fullscreen |
| **HotspotOverlay** | `components/schema/hotspot-overlay.tsx` | SVG overlay for clickable part regions |
| **PartsPanel** | `components/schema/parts-panel.tsx` | Parts table with OEM codes, synced with schema |
| **SchemaToolbar** | `components/schema/schema-toolbar.tsx` | Zoom/reset/fullscreen controls |
| **BrandSelector** | `components/subscription/brand-selector.tsx` | Brand grid with plan-enforced max selection |
| **VehicleCard** | `components/vehicles/vehicle-card.tsx` | Vehicle info card (VIN, brand, model, year) |
| **VinInput** | `components/vehicles/vin-input.tsx` | VIN entry input component |
| **CategoryTree** | `components/categories/category-tree.tsx` | Recursive expandable category hierarchy |
| **CategoryGrid** | `components/categories/category-grid.tsx` | Grid layout for category browsing |
| **DailyChart** | `components/admin/daily-chart.tsx` | Daily VIN decode stats chart |
| **PaymentContent** | `components/payment/payment-content.tsx` | Payment form and flow |
| **SettingsContent** | `components/settings/settings-content.tsx` | User settings panel content |
**UI primitives** from `@sase/ui`: Button, Card, Input, Label, Badge, Dialog, Tabs, Separator, Skeleton
@@ -490,12 +511,13 @@ emexCategoryTranslations
|-------|------|-------|
| **Auth** | `stores/auth.store.ts` | `user`, `isLoading` |
| **Schema** | `stores/schema.store.ts` | `highlightedPartId`, `selectedPartId`, `zoom`, `panX/Y`, `isFullscreen` |
| **i18n** | `lib/i18n.ts` | `locale` ("tr" / "en"), persisted to localStorage |
**i18n** (`lib/i18n.ts`): `locale` ("tr" / "en"), persisted to localStorage
### Data Fetching
**Client:** Custom `ApiClient` class (`lib/api-client.ts`)
- Base URL: `/api` (proxied via Next.js rewrites)
- Base URL: `/api` (proxied via Vite dev server)
- Methods: `get<T>`, `post<T>`, `patch<T>`, `delete<T>`, `upload<T>`
- Credentials: cookies (automatic)
- Error handling: `ApiError` with code + status
@@ -562,8 +584,8 @@ emexCategoryTranslations
| Process | Instances | Mode | Port | Memory |
|---------|-----------|------|------|--------|
| `sase-api` | 2 | cluster | 4000 | 512MB |
| `sase-web` | 2 | cluster | 3000 | 512MB |
| `sase-api` | 1 | fork | 4000 | 512MB |
| `sase-web` | 1 | fork | 3000 | 512MB |
| `sase-worker` | 1 | fork | — | 256MB |
---
@@ -673,4 +695,4 @@ pm2 reload all # Zero-downtime reload
---
*Generated: 2026-02-12 | Branch: v2*
*Generated: 2026-02-15 | Branch: v2*