Ticketing & reporting platform with Telegram bot integration.
graph TB
subgraph User
A["š¤ Agent (Web)"]
B["š± Pelapor (Telegram)"]
end
subgraph Apps
C["š apps/web<br/>SvelteKit Portal"]
D["š¤ apps/bot<br/>Telegram Bot"]
end
subgraph Packages
E["š¦ @trak/services<br/>Domain Logic"]
F["šļø @trak/database<br/>Schema + Client"]
G["š· @trak/shared<br/>Types"]
end
subgraph Infrastructure
H["š PostgreSQL"]
I["š .bot-sessions/<br/>File Session"]
end
A -->|"HTTPS"| C
B -->|"Telegram API"| D
C --> E
D --> E
E --> F
F --> H
D --> I
C --> G
E --> G
H -.->|"LISTEN/NOTIFY"| D
linkStyle 0,1 stroke:#666
Alur Data:
sequenceDiagram
actor P as Pelapor (Telegram)
participant B as apps/bot
participant S as @trak/services
participant D as PostgreSQL
participant W as apps/web
Note over P,W: Registrasi
P->>B: /start
B->>S: validateInviteCode(code)
S->>D: cek invite_codes
D-->>S: valid
S-->>B: { valid, inviteCodeId }
B->>S: createReporter(telegramId, inviteCodeId)
S->>D: insert reporters
B-->>P: ā
Selamat datang
Note over P,W: Laporan
P->>B: /report ā title ā body ā kategori ā lampiran
B->>S: createReport(reporterId, title, body, categoryId)
S->>D: insert reports
B->>S: addReportAttachment(fileId, storageUrl)
S->>D: insert report_attachments
B-->>P: ā
Laporan terkirim (TKT-XXXX)
Note over P,W: Update Status + Notifikasi
W->>S: updateTicketStatus(id, newStatus, userId)
S->>D: update reports + insert status_histories
W->>S: createNotification(reporterTelegramId, message)
S->>D: insert notifications
Note over S: pg_notify('notifications', payload)
S-->>D: SELECT pg_notify(...)
D-->>B: š LISTEN notifications
B->>S: markNotificationRead(notificationId)
S->>D: update notifications set is_read = true
B-->>P: š Status tiket diperbarui
trak/
āāā apps/
ā āāā web/ # SvelteKit portal (agent dashboard)
ā āāā bot/ # Telegram bot (pelapor)
āāā packages/
ā āāā database/ # Drizzle schema, migrations, client
ā āāā services/ # Domain logic layer (shared across apps)
ā āāā shared/ # Types, constants
āāā .env # Global DATABASE_URL
āāā docs/decisions/ # Architecture Decision Records
āāā ...
# Install dependencies
pnpm install
# Setup environment
cp .env.example .env
cp apps/bot/.env.example apps/bot/.env
# Push database schema
pnpm db:push
# (Opsional) Seed data
pnpm db:seed
# Start development (web + bot)
pnpm dev
| Script | Description |
|---|---|
pnpm dev |
Start semua workspace di dev mode |
pnpm build |
Build semua workspace |
pnpm preview |
Preview production build (web) |
pnpm lint |
Lint semua workspace via turbo |
pnpm check |
Type check semua workspace (svelte-check) |
pnpm test:unit |
Unit test (vitest) |
pnpm test:e2e |
E2E test (Playwright) |
pnpm format |
Format semua file dengan prettier |
pnpm db:push |
Push schema ke database |
pnpm db:generate |
Generate migration files |
pnpm db:migrate |
Apply migration |
pnpm db:studio |
Buka Drizzle Studio |
pnpm db:seed |
Seed database |
Root .env (dibaca oleh semua apps):
DATABASE_URL="postgres://root:mysecretpassword@localhost:5432/local"
apps/web/.env:
ORIGIN=http://localhost:5173
BETTER_AUTH_SECRET=<your-secret>
apps/bot/.env:
TELEGRAM_BOT_TOKEN=<your-bot-token>
Lihat docs/decisions/monorepo.md untuk penjelasan kenapa pake monorepo + turborepo.