This README was generated with Antigravity (Google DeepMind AI) from repository analysis and the project documentation.
Read this in another language: Español · 中文
MaiAn is a B2B multiplatform application that connects wholesale distributors with retailers. It combines native client apps for different user profiles with a centralized, secure, and scalable backend built to grow with new business features.
The project is developed by dsqrwym (technical identifier) / MaiAn (brand name).
Try the web clients with the following test accounts:
Client
Demo
Email
Username
Password
Retailer (standard)
Open Standard
standard@maian.com
standard
Standard123
Wholesaler (enterprise)
Open Enterprise
enterprise@maian.com
enterprise
Enterprise123
These shared accounts are intended for demonstration only. Please do not change their credentials or delete shared demo data.
Modular NestJS 11 + Fastify backend, deployable in single, cluster, or pm2 mode.
Full authentication: registration, email verification, role-based login (standard, enterprise, admin), refresh token with rotation, per-device session management, and password reset.
PostgreSQL 17 as primary persistence. Two Redis instances: one for cache / sessions / rate-limit, one for BullMQ queues.
Role-based access control with CASL.
Full category management: hierarchical, public/private, with multilingual translations.
Full product management: variants, multilingual translations, associated files.
File upload and retrieval with local storage driver and Cloudflare R2 / S3-compatible driver. Image processing with sharp; PDF generation with pdfmake.
Locations API: countries, provinces, cities, ISO numeric currencies.
Internal employee account creation for wholesalers (support, delivery, warehouse).
Administrator account creation by SUPERADMIN.
Complete Docker Compose setup: backend, PostgreSQL 17, two Redis, optional Cloudflare Tunnel.
Kotlin Multiplatform frontend with modules: shared, standard, enterprise, admin, business, iosApp.
Frontend–backend integration for auth, categories, products, files, and locations.
Database schema already covers carts, orders, messages, notifications, deliveries, and business relationships.
standard module : authentication and main structure are present, but business feature coverage is less complete than enterprise.
business module : reusable business component layer (categories, media, rich text editor), not a fully standalone client.
End-to-end order flow (API + client apps).
In-app chat / messaging system fully connected in the frontend.
Production-ready push notification system.
Sales statistics and analytics dashboards.
Geolocation and maps (planned for a future release).
Located at Backend/backend-api. Uses a modular NestJS architecture with Fastify as the HTTP adapter.
Active modules in AppModule
AuthModule · LocationsModule · CaslModule · UserModule · EnterpriseModule · AdminModule · CategoryModule · ProductsModule · FilesModule · MailModule · CacheRedisModule · ScheduleTaskModule · MyI18nModule · MyThrottlerModule
The backend also includes global exception filters, a unified response interceptor, structured logging with Pino, and centralized JWT configuration. Supports three process modes: single, native Node cluster, and pm2.
Authentication & sessions
Retailer and wholesaler registration.
Email verification code.
Role-based login: standard, enterprise, admin.
httpOnly cookie for refresh token (web flow) with rotation and CSRF protection.
Password reset.
Session deletion and per-device session management.
Email / username availability check.
Paginated user search with filters.
Admin creation by SUPERADMIN.
Wholesaler employee creation: support, delivery, warehouse.
Categories : create, list, search, edit, delete, hierarchies, public/private visibility, multilingual translations.
Products : create, list, detail, edit, delete, sale variants, multilingual translations, associated files.
multipart upload.
Real MIME-type validation.
Safe filename generation.
Local storage driver.
Cloudflare R2 / S3-compatible driver (@aws-sdk).
Image processing via sharp.
PDF document generation via pdfmake.
Countries, provinces per country, cities per province.
Currencies by ISO numeric code.
Technology
Role
NestJS 11
Application framework
Fastify 5
High-performance HTTP adapter
Drizzle ORM
Primary ORM and migrations
PostgreSQL 17
Primary database
Redis 7
Cache, sessions, rate-limit, BullMQ queues
JWT / Passport
Authentication
CASL
Attribute-based access control
Swagger
API documentation
Pino
Structured logging
BullMQ
Async job queues
Nodemailer
Email delivery
nestjs-i18n
Internationalisation
typia / nestia
Type-safe validation and serialisation (fully migrated from class-validator)
sharp
Image processing
pdfmake
PDF generation
Validation and sanitisation policy
The backend distinguishes between two field types:
User input fields (name, companyName, description, etc.): require semantic sanitisation + strict validation before storage.
System fields (deviceName, langCode, timezone, etc.): must not be aggressively rewritten; validation is flexible or omitted for semantic normalisation.
A malformed value must never break business logic, persistence, or authorisation.
Managed via Drizzle ORM . The full SQL schema is in Base_de_datos/schema.sql and is automatically imported by Docker Compose when the PostgreSQL container starts.
Users · Configurations · Addresses · User sessions · Verification tokens · Categories (with translations) · Products (with variants) · Product–category relations · Files · Carts · Orders and order lines · Discounts · Deliveries (with timeline) · Chats · Messages · Notifications · Countries · Provinces · Cities · Currencies
Row Level Security enabled on multiple tables.
Comprehensive indexes, constraints, and foreign-key relations.
Automatic user_id generation per role.
Preloaded reference data: currencies, countries, provinces, cities, and base categories.
The database schema is ahead of some API and client layers.
Located at Frontend/Maian. Built with Kotlin Multiplatform and Compose Multiplatform .
Platform
Details
Android
minSdk 24, compileSdk 37
iOS
Native via iosApp entry point
Desktop
JVM / Swing
Web
Kotlin/Wasm
Module
Description
shared
Common base: Ktor HTTP client, token storage, repositories (auth, category, products, file, location, user), shared theme, i18n, timezone, reusable UI components, file upload support
standard
Retailer client: login, registration, home screen, Koin DI, navigation
enterprise
Wholesaler client (most mature): login, registration, category CRUD, product CRUD, table/grid views
admin
Admin panel: login, category management, user repository, own DI and navigation
business
Reusable business layer: category forms and lists, rich text editor, media picker and manager
iosApp
iOS entry point (SwiftUI wrapper)
Icons : Compose Material Icons (Core + Extended).
Font : MiSans (bundled as a font resource).
Dependency
Version
Kotlin
2.3.21
Compose Multiplatform
1.11.0
Android Gradle Plugin
9.2.1
Android compileSdk
37
Android minSdk
24
Ktor
3.5.0
Koin
4.2.1
Kotlinx Coroutines
1.11.0
Kotlinx Serialization JSON
1.11.0
Kotlinx DateTime
0.8.0
Coil 3
3.4.0
Haze
2.0.0-alpha02
Infrastructure & Deployment
docker-compose.yml uses optional profiles to control which services start:
Service
Profile
Description
backend
(always active)
NestJS API; supports single, cluster, pm2 modes
postgres
postgres, local-infra
PostgreSQL 17; auto-imports all SQL seeds from Base_de_datos/
redis-cache
redis, local-infra
Redis 7 for cache, sessions, and rate-limit
redis-bull
redis, local-infra
Redis 7 dedicated to BullMQ queues
cloudflared
cloudflared
Cloudflare Tunnel for secure public exposure
Quick start (full local stack, no tunnel):
COMPOSE_PROFILES=postgres,redis docker compose up -d
Environment configuration
Configuration is split into two files:
File
Contents
.env (project root)
Compose profiles, ports, process mode, local PostgreSQL and Redis credentials
Backend/backend-api/.env
Application secrets: JWT keys, S3/R2 keys, SMTP credentials, etc.
Use the corresponding .env.example files as templates.
Cloud-compatible services
PostgreSQL : Supabase or any managed PostgreSQL — set MAIAN_DATABASE_URL and remove the postgres profile.
Redis : any external Redis — set MAIAN_REDIS_CACHE_URL and MAIAN_REDIS_BULL_URL.
File storage : Cloudflare R2 or any S3-compatible service.
Public exposure : Cloudflare Tunnel (cloudflared profile).
Dependency Reference — Backend
Package
Version
@aws-sdk/client-s3
^3.1063.0
@aws-sdk/lib-storage
^3.1063.0
@casl/ability
^6.8.1
@fastify/cookie
^11.0.2
@fastify/helmet
^13.0.2
@fastify/multipart
^9.4.0
@fastify/secure-session
8.2.0
@fastify/static
^9.1.3
@keyv/redis
^5.1.6
@nest-lab/throttler-storage-redis
^1.2.0
@nestia/core
^11.2.1
@nestia/e2e
^11.2.1
@nestia/fetcher
^11.2.1
@nestjs-modules/mailer
^2.3.6
@nestjs/bullmq
^11.0.4
@nestjs/cache-manager
^3.1.2
@nestjs/common
^11.1.24
@nestjs/config
^4.0.4
@nestjs/core
^11.1.24
@nestjs/jwt
^11.0.2
@nestjs/mapped-types
^2.1.1
@nestjs/passport
^11.0.5
@nestjs/platform-express
^11.1.24
@nestjs/platform-fastify
^11.1.24
@nestjs/schedule
^6.1.3
@nestjs/swagger
^11.4.4
@nestjs/throttler
^6.5.0
bcrypt
^6.0.0
bullmq
^5.78.0
cache-manager
^7.2.8
cache-manager-redis-store
^3.0.1
cross-env
^10.1.0
decimal.js
^10.6.0
drizzle-orm
^0.45.2
fastify
^5.8.5
file-type
^22.0.1
handlebars
^4.7.9
ioredis
^5.11.1
keyv
^5.6.0
libphonenumber-js
^1.13.6
lru-cache
^11.5.1
mime-types
^3.0.2
nestjs-i18n
^10.8.4
nestjs-pino
^4.6.1
nodemailer
^8.0.10
passport
0.7.0
passport-custom
^1.1.1
passport-jwt
^4.0.1
pdfmake
^0.3.10
pg
^8.21.0
pino
^9.14.0
pino-pretty
^13.1.3
piscina
^5.1.4
postgres
^3.4.9
reflect-metadata
^0.2.2
rxjs
^7.8.2
sharp
^0.34.5
typia
^12.1.1
Package
Version
@nestia/benchmark
^11.2.1
@nestia/sdk
^11.2.1
@nestjs/cli
^11.0.21
@nestjs/schematics
^11.1.0
@nestjs/testing
^11.1.24
@swc/cli
^0.7.10
@swc/core
^1.15.40
@types/bcrypt
^6.0.0
@types/express
^5.0.6
@types/jest
^30.0.0
@types/mime-types
^3.0.1
@types/node
^24.13.1
@types/nodemailer
^7.0.11
@types/passport
^1.0.17
@types/passport-jwt
^4.0.1
@types/pdfmake
^0.3.3
@types/pg
^8.20.0
@types/supertest
^6.0.3
@typescript-eslint/eslint-plugin
^8.60.1
@typescript-eslint/parser
^8.60.1
dotenv
^17.4.2
drizzle-kit
^0.31.10
eslint
^9.39.4
eslint-config-prettier
^10.1.8
eslint-plugin-prettier
^5.5.6
globals
^16.5.0
jest
^30.4.2
nestia
^11.2.1
prettier
^3.8.3
source-map-support
^0.5.21
supertest
^7.2.2
ts-jest
^29.4.11
ts-loader
^9.6.0
ts-node
^10.9.2
ts-patch
^3.3.0
tsc-alias
^1.8.17
tsconfig-paths
^4.2.0
tsx
^4.22.4
typescript
~6.0.3
typescript-eslint
^8.60.1
Dependency Reference — Frontend
All versions sourced from Frontend/Maian/gradle/libs.versions.toml.
Alias
Plugin ID
Version
androidApplication / androidLibrary
com.android.application / com.android.library
9.2.1
composeMultiplatform
org.jetbrains.compose
1.11.0
composeCompiler
org.jetbrains.kotlin.plugin.compose
2.3.21
kotlinMultiplatform
org.jetbrains.kotlin.multiplatform
2.3.21
kotlinxSerialization
org.jetbrains.kotlin.plugin.serialization
2.3.21
Package
Version
androidx.activity:activity-compose
1.13.0
androidx.core:core-ktx
1.18.0
androidx.security:security-crypto
1.1.0
org.jetbrains.androidx.lifecycle:lifecycle-viewmodel
2.10.0
org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose
2.10.0
org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-navigation3
2.10.0
org.jetbrains.androidx.savedstate:savedstate
1.4.0
org.jetbrains.androidx.window:window-core
1.5.1
Package
Version
io.ktor:ktor-client-core
3.5.0
io.ktor:ktor-client-content-negotiation
3.5.0
io.ktor:ktor-serialization-kotlinx-json
3.5.0
io.ktor:ktor-client-auth
3.5.0
io.ktor:ktor-client-logging
3.5.0
io.ktor:ktor-client-okhttp (Android)
3.5.0
io.ktor:ktor-client-darwin (iOS)
3.5.0
io.ktor:ktor-client-cio (Desktop)
3.5.0
io.ktor:ktor-client-js (Web)
3.5.0
Dependency injection — Koin
Package
Version
io.insert-koin:koin-core
4.2.1
io.insert-koin:koin-compose-viewmodel
4.2.1
Package
Version
org.jetbrains.kotlinx:kotlinx-coroutines-swing
1.11.0
org.jetbrains.kotlinx:kotlinx-serialization-json
1.11.0
org.jetbrains.kotlinx:kotlinx-datetime
0.8.0
org.jetbrains.kotlinx:kotlinx-collections-immutable
0.4.0
Package
Version
io.coil-kt.coil3:coil-compose
3.4.0
io.coil-kt.coil3:coil-network-ktor3
3.4.0
io.github.vinceglb:filekit-core
0.13.0
io.github.vinceglb:filekit-dialogs-compose
0.13.0
io.github.vinceglb:filekit-coil
0.13.0
io.github.kdroidfilter:composemediaplayer
0.10.0
io.github.alexzhirkevich:compottie-lite
2.2.0
UI components & experience
Package
Version
dev.chrisbanes.haze:haze
2.0.0-alpha02
dev.chrisbanes.haze:haze-blur
2.0.0-alpha02
com.eygraber:compose-placeholder-material3
1.0.12
dev.zt64.compose.pipette:compose-pipette
2.0.0
sh.calvin.reorderable:reorderable
3.1.0
io.github.dokar3:sonner
0.3.9
net.engawapg.lib:zoomable
2.12.0
io.github.khubaibkhan4:alert-kmp
2.0.0
com.patrykandpatrick.vico:compose
3.2.1
com.patrykandpatrick.vico:compose-m3
3.2.1
org.jetbrains.compose.material:material-icons-core
1.7.3
org.jetbrains.compose.material:material-icons-extended
1.7.3
org.jetbrains.compose.ui:ui-tooling
1.11.0
org.slf4j:slf4j-simple
2.0.18
Package
Version
org.jetbrains.androidx.navigation:navigation-compose
2.9.2
androidx.navigation3:navigation3-runtime
1.1.2
org.jetbrains.androidx.navigation3:navigation3-ui
1.1.1
org.jetbrains.compose.material3.adaptive:adaptive-navigation3
1.3.0-beta01
Package
Version
androidx.paging:paging-common
3.4.0-rc01
androidx.paging:paging-compose
3.4.0-rc01
Package
Version
ua.wwind.table-kmp:table-core
1.9.0
Package
Version
com.russhwolf:multiplatform-settings
1.3.0
io.github.luca992.libphonenumber-kotlin:libphonenumber
0.1.9
com.sanctionco.jmail:jmail
2.1.0
com.ionspin.kotlin:bignum
0.3.10
Package
Version
io.github.ismai117:KScan
0.9.1
com.google.zxing:core
3.5.4
com.google.zxing:javase
3.5.4
com.journeyapps:zxing-android-embedded
4.3.0
com.github.sarxos:webcam-capture
0.3.12
Package
Version
io.github.kevinnzou:compose-webview-multiplatform
2.0.3
Package
Version
com.mohamedrejeb.richeditor:richeditor-compose
1.0.0-rc14