# nazmulxdev/ecospark-hub architecture

> Architecture diagram of the GitHub repository nazmulxdev/ecospark-hub, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/nazmulxdev/ecospark-hub
- Repository: https://github.com/nazmulxdev/ecospark-hub

## Overview

1. **Runtime and entrypoints**
   - This is a TypeScript REST API built on **Node.js + Express**, with `src/app.ts` assembling middleware/routes and `src/server.ts` starting the HTTP server.
   - `src/routes/index.ts` is the main composition point that mounts all feature routers under the API namespace.

2. **Layered request flow**
   - The codebase follows a clear **route → controller → service → Prisma** pattern.
   - Controllers handle HTTP concerns, services hold business logic, and Prisma is the single persistence boundary to PostgreSQL.
   - Validation is enforced at the edge with **Zod** via per-module validation files and the `ValidateRequest` middleware.

3. **Domain module boundaries**
   - Each business area is isolated in its own module under `src/modules/`: `auth`, `users`, `idea`, `vote`, `comment`, `watchlist`, `category`, `blog`, `member`, `admin`, `payment`, and `ideaPurchase`.
   - These modules are not just route groups; they represent distinct domain boundaries with their own controllers, services, constants, utils, and validation schemas.

4. **Authentication and authorization**
   - Authentication is handled through **Better Auth** (`src/lib/auth.ts`) rather than a hand-rolled token system.
   - Authorization is layered on top with `AuthMiddelware`, using role-based access control for **USER / MEMBER / ADMIN** flows.
   - The app also extends Express types in `src/types/express`, which suggests request-scoped auth/session/user data is injected into handlers.

5. **Core content workflow**
   - The central domain is the **Idea** lifecycle: drafts are created by members, submitted for review, then moved through **UNDER_REVIEW → APPROVED / REJECTED**.
   - Public reads are separated from privileged writes: approved ideas are exposed publicly, while member/admin endpoints cover creation, edits, review, and moderation.
   - Slug-based access is used for idea and blog retrieval, indicating a human-friendly URL layer on top of database IDs.

6. **Community interaction features**
   - The platform’s engagement layer is split into **votes, comments, and watchlists**.
   - Votes are tracked as a dedicated model and module, comments support nested replies, and watchlists let users save ideas for later access.
   - These features are all idea-centric and depend on the authenticated user context, so they sit downstream of auth and upstream of Prisma.

7. **Payments and monetization**
   - Payments are implemented as a separate subsystem with **Stripe** integration in `src/config/stripe.config.ts` and payment logic in `src/modules/payment` plus `src/modules/ideaPurchase`.
   - The architecture includes both direct purchase and pay-later/resume-payment flows, and the README indicates status transitions such as **UNPAID → PENDING → PAID**.
   - `payment.cron.ts` suggests there is also background reconciliation or cleanup logic beyond synchronous HTTP requests.
   - Stripe webhooks are a critical inbound boundary: payment state is finalized asynchronously from Stripe back into the database.

8. **Membership and admin operations**
   - Membership is modeled as its own domain with application and dashboard endpoints, distinct from general user features.
   - Admin features cover user-role management, membership-request review, and analytics/dashboard data.
   - This implies a higher-privilege operational plane that reads across multiple domain models rather than owning a separate datastore.

9. **Media and file handling**
   - Image uploads are handled with **multer** at the request boundary and persisted to **Cloudinary**.
   - The presence of `deleteUploadedFileFromGlobalErrorHandler.ts` shows uploaded files are cleaned up on failure, so file handling is integrated with global error recovery rather than left to controllers.

10. **Data model and persistence**
   - Prisma is the single ORM, with schema split across domain files in `prisma/schema/*.prisma` and migrations under `prisma/migrations`.
   - The schema reflects the product’s major aggregates: `User`, `Idea`, `Category`, `Vote`, `Comment`, `Watchlist`, `Blog`, `IdeaPayment`, `IdeaPurchase`, `MembershipPayment`, and `Member`.
   - PostgreSQL is the main system of record; there are no signs of additional primary datastores.

11. **Cross-cutting infrastructure**
   - The repo uses centralized configuration modules for environment, Prisma, Stripe, Cloudinary, and multer, which keeps external-service wiring out of feature modules.
   - `QueryBuilder` indicates shared support for pagination, filtering, search, and sorting across list endpoints.
   - `generateSlug` and shared response helpers (`AppResponse`, `AppErrorResponse`) show the API enforces consistent output and URL conventions across modules.

12. **Error handling and resilience**
   - Errors are normalized through dedicated handlers for **Prisma, Zod, JWT, Multer, syntax, Better Auth, and system errors**.
   - `GlobalErrorHandler` is the final boundary, translating internal failures into the repository’s standard response shape and optionally cleaning up uploaded files.
   - This makes error handling a first-class architectural concern rather than an ad hoc controller responsibility.

13. **Operational packaging**
   - The presence of `vercel.json` suggests deployment is intended to work in a Vercel-hosted environment, even though the app is structured as a conventional Express server.
   - `src/scripts/seed.ts` and the Prisma migration history indicate the project has an explicit database lifecycle: generate, migrate, seed, then run the API.

14. **High-level data flow**
   - Requests enter through Express routes, pass through validation and auth middleware, hit controllers, then business logic in services, and finally read/write PostgreSQL via Prisma.
   - Side effects branch out to Stripe, Cloudinary, and Better Auth where needed, while webhooks and cron jobs feed asynchronous state back into the same database.

Main entry points: [`src/routes/index.ts`](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/routes/index.ts) (Route mount), [`src/lib/prisma.ts`](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/lib/prisma.ts) (Prisma client), [`src/app.ts`](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/app.ts) (App setup), [`src/middlewares/AuthMiddelware.ts`](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/middlewares/AuthMiddelware.ts) (Auth guard)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Runtime"]
  node_src_index["Main entry<br/>bootstrap<br/>[index.ts]"]
  node_src_server["HTTP server<br/>[server.ts]"]
  node_src_app["App setup<br/>express app<br/>[app.ts]"]
  node_routes_index["Route mount<br/>router composition<br/>[index.ts]"]
end

subgraph group_domains["Domain modules"]
  node_auth_module["Auth<br/>domain module"]
  node_idea_module["Ideas<br/>domain module"]
  node_engagement_module["Engagement<br/>domain module"]
  node_content_module["Content<br/>domain module"]
  node_member_module["Membership<br/>domain module"]
  node_be_member_module["Apply member<br/>domain module"]
  node_admin_module["Admin<br/>domain module"]
  node_payment_module["Payments<br/>domain module"]
  node_idea_purchase_module["Idea purchase<br/>domain module"]
end

subgraph group_infra["Infrastructure"]
  node_auth_lib["Better Auth<br/>auth provider<br/>[auth.ts]"]
  node_prisma_lib["Prisma client<br/>orm client<br/>[prisma.ts]"]
  node_validate_request["Validate req<br/>middleware<br/>[ValidateRequest.ts]"]
  node_auth_middleware["Auth guard<br/>middleware<br/>[AuthMiddelware.ts]"]
  node_error_stack["Error stack<br/>error handling"]
  node_cloudinary["Cloudinary<br/>external storage"]
  node_stripe["Stripe<br/>external payments<br/>[stripe.config.ts]"]
end

subgraph group_data["Data layer"]
  node_prisma_schema["Prisma schema<br/>database schema<br/>[schema.prisma]"]
  node_prisma_migrations["Migrations"]
  node_seed_script["Seed data<br/>data bootstrap<br/>[seed.ts]"]
end

node_src_index -->|"starts"| node_src_server
node_src_server -->|"loads"| node_src_app
node_src_app -->|"mounts"| node_routes_index
node_routes_index -->|"routes"| node_auth_module
node_routes_index -->|"routes"| node_idea_module
node_routes_index -->|"routes"| node_engagement_module
node_routes_index -->|"routes"| node_content_module
node_routes_index -->|"routes"| node_member_module
node_routes_index -->|"routes"| node_be_member_module
node_routes_index -->|"routes"| node_admin_module
node_routes_index -->|"routes"| node_payment_module
node_routes_index -->|"routes"| node_idea_purchase_module
node_auth_module -->|"authn"| node_auth_lib
node_auth_module -->|"stores"| node_prisma_lib
node_idea_module -->|"validates"| node_validate_request
node_idea_module -->|"guards"| node_auth_middleware
node_idea_module -->|"persists"| node_prisma_lib
node_engagement_module -->|"guards"| node_auth_middleware
node_engagement_module -->|"persists"| node_prisma_lib
node_content_module -->|"reads"| node_prisma_lib
node_member_module -->|"guards"| node_auth_middleware
node_member_module -->|"persists"| node_prisma_lib
node_be_member_module -->|"validates"| node_validate_request
node_be_member_module -->|"persists"| node_prisma_lib
node_admin_module -->|"guards"| node_auth_middleware
node_admin_module -->|"reads/writes"| node_prisma_lib
node_payment_module -->|"charges"| node_stripe
node_payment_module -->|"persists"| node_prisma_lib
node_idea_purchase_module -->|"coordinates"| node_payment_module
node_idea_purchase_module -->|"persists"| node_prisma_lib
node_src_app -->|"uses"| node_validate_request
node_src_app -->|"uses"| node_auth_middleware
node_src_app -->|"finalizes"| node_error_stack
node_src_app -->|"uploads"| node_cloudinary
node_src_app -->|"webhooks"| node_stripe
node_src_app -->|"depends on"| node_prisma_lib
node_prisma_lib -->|"schema"| node_prisma_schema
node_prisma_schema -->|"evolves via"| node_prisma_migrations
node_prisma_schema -->|"bootstraps"| node_seed_script

click node_src_index "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/index.ts"
click node_src_server "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/server.ts"
click node_src_app "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/app.ts"
click node_routes_index "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/routes/index.ts"
click node_auth_module "https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/auth"
click node_idea_module "https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/idea"
click node_member_module "https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/member"
click node_be_member_module "https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/beMember"
click node_admin_module "https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/admin"
click node_payment_module "https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/payment"
click node_idea_purchase_module "https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/ideaPurchase"
click node_auth_lib "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/lib/auth.ts"
click node_prisma_lib "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/lib/prisma.ts"
click node_validate_request "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/middlewares/ValidateRequest.ts"
click node_auth_middleware "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/middlewares/AuthMiddelware.ts"
click node_error_stack "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/middlewares/GlobalErrorHandler.ts"
click node_cloudinary "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/config/cloudinary.config.ts"
click node_stripe "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/config/stripe.config.ts"
click node_prisma_schema "https://github.com/nazmulxdev/ecospark-hub/blob/main/prisma/schema/schema.prisma"
click node_prisma_migrations "https://github.com/nazmulxdev/ecospark-hub/tree/main/prisma/migrations"
click node_seed_script "https://github.com/nazmulxdev/ecospark-hub/blob/main/src/utils/seed.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_src_index,node_src_server,node_src_app,node_routes_index toneBlue
class node_auth_module,node_idea_module,node_engagement_module,node_content_module,node_member_module,node_be_member_module,node_admin_module,node_payment_module,node_idea_purchase_module toneAmber
class node_auth_lib,node_prisma_lib,node_validate_request,node_auth_middleware,node_error_stack,node_cloudinary,node_stripe toneMint
class node_prisma_schema,node_prisma_migrations,node_seed_script toneRose
```

## Components

### Runtime

Express entrypoints and request pipeline

- [Main entry](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/index.ts): bootstrap · Process start and server launch · `src/index.ts`
- [HTTP server](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/server.ts): server · Starts the Express app · `src/server.ts`
- [App setup](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/app.ts): express app · Assembles middleware and app-level wiring · `src/app.ts`
- [Route mount](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/routes/index.ts): router composition · Mounts feature routers under the API namespace · `src/routes/index.ts`

### Domain modules

Feature boundaries under src/modules

- [Auth](https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/auth): domain module · Authentication and session flow · `src/modules/auth`
- [Ideas](https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/idea): domain module · Idea lifecycle and moderation workflow · `src/modules/idea`
- **Engagement**: domain module · Votes, comments, and watchlists around ideas
- **Content**: domain module · Categories and blog publishing
- [Membership](https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/member): domain module · Member area and membership state · `src/modules/member`
- [Apply member](https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/beMember): domain module · Membership application flow · `src/modules/beMember`
- [Admin](https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/admin): domain module · Privileged moderation and dashboard operations · `src/modules/admin`
- [Payments](https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/payment): domain module · Stripe-backed payment lifecycle and reconciliation · `src/modules/payment`
- [Idea purchase](https://github.com/nazmulxdev/ecospark-hub/tree/main/src/modules/ideaPurchase): domain module · Idea purchase and payment linkage · `src/modules/ideaPurchase`

### Infrastructure

Shared integrations, middleware, and error handling

- [Better Auth](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/lib/auth.ts): auth provider · Central authentication integration · `src/lib/auth.ts`
- [Prisma client](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/lib/prisma.ts): orm client · Single database access boundary · `src/lib/prisma.ts`
- [Validate req](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/middlewares/ValidateRequest.ts): middleware · Edge validation for request payloads · `src/middlewares/ValidateRequest.ts`
- [Auth guard](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/middlewares/AuthMiddelware.ts): middleware · Role-based access control for user, member, and admin flows · `src/middlewares/AuthMiddelware.ts`
- [Error stack](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/middlewares/GlobalErrorHandler.ts): error handling · Normalized handlers and global failure boundary · `src/middlewares/GlobalErrorHandler.ts`
- [Cloudinary](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/config/cloudinary.config.ts): external storage · Image upload persistence · `src/config/cloudinary.config.ts`
- [Stripe](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/config/stripe.config.ts): external payments · Payment gateway integration and webhook source · `src/config/stripe.config.ts`

### Data layer

Prisma schemas, migrations, and seed lifecycle

- [Prisma schema](https://github.com/nazmulxdev/ecospark-hub/blob/main/prisma/schema/schema.prisma): database schema · Domain models and enums split across Prisma files · `prisma/schema/schema.prisma`
- [Migrations](https://github.com/nazmulxdev/ecospark-hub/tree/main/prisma/migrations): database migrations · Schema evolution history · `prisma/migrations`
- [Seed data](https://github.com/nazmulxdev/ecospark-hub/blob/main/src/utils/seed.ts): data bootstrap · Initial database population · `src/utils/seed.ts`

## Connections

- Main entry → HTTP server: starts · Bootstraps the HTTP server
- HTTP server → App setup: loads · Server uses the configured Express app
- App setup → Route mount: mounts · App delegates API routing to the route composer
- Route mount → Auth: routes · Mounts auth endpoints
- Route mount → Ideas: routes · Mounts idea endpoints
- Route mount → Engagement: routes · Mounts voting, commenting, and watchlist endpoints
- Route mount → Content: routes · Mounts categories and blog endpoints
- Route mount → Membership: routes · Mounts member endpoints
- Route mount → Apply member: routes · Mounts membership application endpoints
- Route mount → Admin: routes · Mounts admin endpoints
- Route mount → Payments: routes · Mounts payment endpoints
- Route mount → Idea purchase: routes · Mounts idea purchase endpoints
- Auth → Better Auth: authn · Uses Better Auth for authentication
- Auth → Prisma client: stores · Persists user/session state through Prisma
- Ideas → Validate req: validates · Idea inputs are checked at the edge
- Ideas → Auth guard: guards · Member/admin actions require authorization
- Ideas → Prisma client: persists · Reads and writes ideas through Prisma
- Engagement → Auth guard: guards · Engagement actions require authenticated users
- Engagement → Prisma client: persists · Votes, comments, and watchlists use Prisma
- Content → Prisma client: reads · Categories and blogs are fetched from the database
- Membership → Auth guard: guards · Member area is privilege-aware
- Membership → Prisma client: persists · Membership state is stored via Prisma
- Apply member → Validate req: validates · Membership application payloads are validated
- Apply member → Prisma client: persists · Membership requests are written to the database
- Admin → Auth guard: guards · Admin functions are role-restricted
- Admin → Prisma client: reads/writes · Admin workflows span multiple models
- Payments → Stripe: charges · Stripe handles payment processing and webhooks
- Payments → Prisma client: persists · Payment state is finalized in Prisma
- Idea purchase → Payments: coordinates · Idea purchase flows depend on payment state
- Idea purchase → Prisma client: persists · Purchase linkage is stored in Prisma
- App setup → Validate req: uses · Request validation is applied in the app layer
- App setup → Auth guard: uses · Authorization is applied globally or per route
- App setup → Error stack: finalizes · Global error handling terminates the request pipeline
- App setup → Cloudinary: uploads · File handling is wired through Cloudinary
- App setup → Stripe: webhooks · Payment webhooks re-enter the app boundary
- App setup → Prisma client: depends on · Application data flows through Prisma
- Prisma client → Prisma schema: schema · Client is generated from the Prisma schema
- Prisma schema → Migrations: evolves via · Schema changes are tracked by migrations
- Prisma schema → Seed data: bootstraps · Seed data aligns with the schema
