Introduction
AdSpot is a full-stack, multi-tenant digital out-of-home (DOOH) advertising platform. It provides a marketplace where advertisers can create and manage campaigns displayed on digital screens owned by publishers, while admins oversee the entire ecosystem.
Key Highlights
Targeted Advertising
Target campaigns by city, region, venue type, and time slots for maximum impact.
Automated Billing
Per-view charging with dynamic rate multipliers, daily budgets, and real-time spend tracking.
Real-time Monitoring
Socket.io-powered live screen heartbeats, campaign status updates, and instant analytics.
Multi-language Support
Full i18n with RTL support, database-backed translations, and admin translation management.
Architecture
AdSpot follows a modular monolith architecture with clear separation between frontend and backend, connected via RESTful APIs and WebSocket channels.
Tech Stack
Frontend
- React 18 + TypeScript
- Vite (build tool & HMR)
- Ant Design (UI components)
- Tailwind CSS (utility styling)
- Redux Toolkit (state management)
- React Router v7 (routing)
- Socket.io Client (real-time)
- Recharts (data visualization)
Backend
- NestJS v11 + Express
- TypeScript (strict mode)
- Prisma ORM (type-safe queries)
- MySQL 8.0 (primary database)
- Redis (optional caching)
- Passport + JWT (auth)
- Socket.io (WebSockets)
- Multer (file uploads)
DevOps & Tools
- Docker + Docker Compose
- Vercel (serverless deploy)
- Prisma Migrations
- ESLint + TypeScript checks
- Swagger / OpenAPI docs
- Nodemailer (SMTP email)
- Supabase Storage (optional)
- bcrypt (password hashing)
Features
Campaign Management
Create, schedule, and track advertising campaigns with timeslot scheduling, location targeting, and budget controls.
Screen Network
Register digital screens with code-based onboarding, heartbeat monitoring, and real-time status tracking.
Media Library
Upload images and videos with admin approval workflow. Manage media assets across campaigns.
Analytics Dashboard
Real-time view tracking, revenue metrics, screen performance, and campaign ROI analysis.
Payment Processing
Integrated Stripe, PayPal, and Razorpay gateways with webhook handling, balance management, and transaction history.
Dynamic Pricing
Per-view charging with location multipliers, peak hour pricing, and configurable rate management.
Multi-role Access
Dedicated dashboards for Admin, Advertiser, and Publisher roles with granular permission controls.
Internationalization
Database-driven i18n with RTL support, bulk translation management, and import/export capabilities.
Early Bird Program
Time-limited prelaunch offers with reduced fees, higher revenue shares, and trial credits for early adopters.
Landing Page CMS
Admin-editable landing page with hero slides, benefits, features, testimonials, and how-it-works sections.
Location Targeting
Configurable cities, regions, and venue types for precise geographic campaign targeting.
Activity Logging
Comprehensive audit trail with IP tracking, user agent logging, and configurable retention policies.
How It Works
AdSpot operates as a three-sided marketplace connecting advertisers, publishers, and an admin platform.
For Advertisers
Sign Up
Create account & add funds
Upload Media
Images or videos
Create Campaign
Target screens & set budget
Go Live
Ads display on screens
Track Results
Views, spend & ROI
For Publishers
Register
Create publisher account
Add Screens
Register with code
Set Location
City, venue & coordinates
Display Ads
Screen shows campaigns
Earn Revenue
Request payouts
Campaign Lifecycle
Draft
Advertiser creates a campaign, selects media, targets screens by location/venue type, sets daily and total budgets, and configures timeslot schedules.
Active
Campaign goes live during scheduled times. Ads are displayed on assigned screens. Each view is tracked and charged against the campaign budget in real-time.
Monitoring
Advertisers track views, spend, and performance via the analytics dashboard. Daily budgets automatically reset at configured times.
Completion
Campaign ends when the date range expires or budget is exhausted. Final analytics and spend reports are available for review.
Use Cases
Retail Stores
Display promotional ads on in-store screens. Target specific locations, schedule ads during peak shopping hours, and track foot traffic impact.
Restaurants & Cafes
Digital menu boards and promotional displays. Schedule lunch specials during morning hours and dinner deals in the afternoon.
Gyms & Fitness
Target health-conscious audiences with fitness products, supplements, and wellness brand advertisements.
Transit Hubs
High-traffic locations like bus stations and airports. Maximize impressions with always-on campaigns targeting commuters.
Hotels & Hospitality
Lobby and common area displays for local attractions, restaurant recommendations, and event promotions.
Office Buildings
Corporate lobby displays for B2B advertising, tenant announcements, and professional service promotions.
Shopping Malls
Directory screens and promotional displays across multiple zones. Target by floor, wing, or venue type within the mall.
Healthcare
Waiting room displays in hospitals and clinics. Promote health services, pharmaceuticals, and wellness programs.
User Roles & Permissions
ADMIN Administrator
- Full system access and configuration
- User management (create, edit, deactivate, adjust balances)
- Media content approval and rejection
- Screen and campaign oversight
- Payment gateway configuration (Stripe/PayPal/Razorpay)
- Location management (cities, regions, venue types)
- Language and translation management
- Landing page CMS editing
- Activity log review and audit
- Early bird program configuration
- Rate and charging management
- Publisher payout approval
ADVERTISER Advertiser
- Create and manage advertising campaigns
- Upload media (images/videos) for approval
- Configure timeslot scheduling and location targeting
- Set daily and total budget limits
- Add funds via Stripe, PayPal, or Razorpay
- View campaign analytics and ROI metrics
- Track spending and transaction history
- Monitor real-time campaign performance
PUBLISHER Publisher
- Register and manage digital screens
- Set screen location, venue type, and coordinates
- Monitor screen heartbeat and online status
- View earnings and revenue analytics
- Request payouts (bank transfer)
- Track screen occupancy and view metrics
- Generate and manage screen access codes
Campaign Management
Campaigns are the core of AdSpot. Advertisers create campaigns to display their media content on targeted digital screens.
Campaign Properties
| Property | Description |
|---|---|
| Name & Description | Campaign title and details |
| Media | Linked approved media asset (image or video) |
| Date Range | Start and end dates for the campaign |
| Total Budget | Maximum total spend for the campaign |
| Daily Budget | Maximum daily spend (resets automatically) |
| Target Screens | Selected screens filtered by location and venue type |
| Schedule Type | ALWAYS_ON or SCHEDULED with timeslot rules |
| Timezone | Timezone for schedule calculations |
| Status | DRAFT → ACTIVE → PAUSED → COMPLETED |
Timeslot Scheduling
Campaigns can be configured to display only during specific hours and days of the week. Each timeslot rule specifies:
- Days of week — Select specific days (Monday through Sunday)
- Start time / End time — Hour-based display window
- Timezone support — All schedules are timezone-aware
Screen Management
Screens are digital displays registered by publishers that show advertising campaigns to viewers.
Screen Registration
Publishers register screens using a code-based system:
Generate Code
Publisher creates a new screen entry and receives a unique registration code.
Enter Code on Device
The physical screen device uses the code to authenticate and link to the publisher's account.
Configure Details
Set resolution, orientation, venue type, city/region, and GPS coordinates.
Screen Properties
| Property | Description |
|---|---|
| Resolution | Width and height in pixels |
| Orientation | landscape or portrait |
| Venue Type | RETAIL, RESTAURANT, CAFE, GYM, TRANSIT, OFFICE, HOSPITAL, MALL, HOTEL, OTHER |
| Location | City, region, venue name, latitude/longitude |
| Status | active, inactive, maintenance |
| Access Code | Authentication code for screen device (regeneratable) |
Heartbeat System
Active screens send periodic heartbeat signals to the server, updating their last_active timestamp. This allows the platform to track screen online/offline status in real-time and alert publishers to connectivity issues.
Media Library
The media library stores all advertising content (images and videos) uploaded by advertisers.
Approval Workflow
Upload
Advertiser uploads media
Pending
Awaits admin review
Approved
Ready for campaigns
- Supported formats: JPEG, PNG, GIF, MP4, AVI
- Maximum file size: 10MB (configurable)
- Admins can approve or reject media with reasons
- Only approved media can be used in campaigns
- Users can only view and manage their own media
Analytics & Reporting
AdSpot provides comprehensive analytics for all user roles.
Tracked Metrics
Views
Total views, view duration, views per screen, and views per campaign with time-series data.
Revenue
Revenue per view, total revenue, daily revenue, and revenue breakdown by screen/campaign.
Performance
Campaign ROI, screen occupancy rates, trend analysis, and comparative performance metrics.
Time Periods
Analytics can be filtered by predefined periods (7d, 30d, 90d) or custom date ranges. Each role sees metrics relevant to their perspective:
- Admin: System-wide analytics, total revenue, user growth
- Advertiser: Campaign performance, spend tracking, ROI
- Publisher: Earnings, screen performance, occupancy metrics
Payment System
AdSpot integrates with Stripe, PayPal, and Razorpay for secure payment processing.
Payment Flow
Checkout Session
Advertiser initiates a payment. The backend creates a checkout session with the selected gateway (Stripe, PayPal, or Razorpay).
Payment Processing
User completes payment on the gateway's hosted page. Supports multiple currencies (default: USD).
Webhook Confirmation
Payment gateway sends a webhook to confirm the transaction. Raw body verification ensures security.
Balance Update
User's account balance is credited. Transaction is recorded in the payment history.
Charging & Rate Management
AdSpot uses a per-view charging model with dynamic rate calculation.
Rate Calculation
Final Rate = Base Rate × Location Multiplier × Time Multiplier Example: Base Rate: $0.05 per view Location Multiplier: 1.5x (mall location) Time Multiplier: 2.0x (peak hours 9AM-5PM) ──────────────────────────────── Final Rate: $0.15 per view
Charging Features
- 10-second billing intervals — Charges calculated per view period
- Peak hour pricing — Configurable peak hours (default 9AM-5PM) with time multiplier
- Location-based pricing — Different rates for different venue types
- Budget validation — Prevents charging when daily/total budgets are exhausted
- Audit trail — Every charge is recorded with rate details for transparency
Early Bird Program
A time-limited prelaunch program offering special benefits to early adopters.
| Benefit | Early Bird | Regular |
|---|---|---|
| Platform Fee | 5% | 15% |
| Publisher Revenue Share | 85% | 70% |
| Trial Credit | $25 | None |
| Setup Fee | Free | Standard |
| Duration | 12 months | - |
Admins can configure the program end date, available slots, pricing, and benefit percentages via the admin dashboard.
Internationalization (i18n)
AdSpot supports multiple languages with full RTL (right-to-left) layout support.
Features
- Database-backed translations — All translations stored in the database, not JSON files
- Namespace organization — Translations grouped by feature area
- Status tracking — Each translation marked as
missing,translated,needs_review, orapproved - Bulk operations — Import/export translations, bulk updates
- RTL support — Automatic layout direction switching for Arabic, Hebrew, etc.
- Completion stats — Track translation coverage per language
- Locale file sync — Validate and sync with frontend locale files
API Overview
The AdSpot API follows RESTful conventions with a global /api prefix. All responses are wrapped in a standard format:
{
"success": true,
"message": "Operation completed successfully",
"data": { ... }
}
Pagination
List endpoints return paginated results with metadata:
{
"success": true,
"data": [ ... ],
"meta": {
"total": 150,
"page": 1,
"limit": 20,
"hasNext": true,
"hasPrev": false
}
}
Authentication
The API uses JWT (JSON Web Token) for authentication with access and refresh token support.
| Token | Expiry | Usage |
|---|---|---|
| Access Token | 24 hours | Sent as Bearer token in the Authorization header |
| Refresh Token | 7 days | Used to obtain a new access token without re-login |
Auth Endpoints
API Endpoints
Users
Campaigns
Screens
Media
Analytics
Payments
Publisher
Locations
i18n
System
Project Structure
Environment Setup
Create a .env file in the project root with the following variables:
# Database DATABASE_URL=mysql://username:password@localhost:3306/adspot_db DATABASE_TYPE=mysql MYSQL_HOST=localhost MYSQL_PORT=3306 MYSQL_USERNAME=your_username MYSQL_PASSWORD=your_password MYSQL_DATABASE=adspot_db # JWT Authentication JWT_SECRET=your-secret-key JWT_EXPIRES_IN=7d # Server PORT=3001 NODE_ENV=development # URLs API_BASE_URL=http://localhost:3001 FRONTEND_URL=http://localhost:5173 # File Upload UPLOAD_MAX_SIZE=10485760 UPLOAD_ALLOWED_TYPES=image/jpeg,image/png,image/gif,video/mp4,video/avi # Payment Gateways STRIPE_SECRET_KEY=sk_test_xxx STRIPE_WEBHOOK_SECRET=whsec_xxx PAYPAL_CLIENT_ID=xxx PAYPAL_CLIENT_SECRET=xxx RAZORPAY_KEY_ID=rzp_test_xxx RAZORPAY_KEY_SECRET=xxx RAZORPAY_WEBHOOK_SECRET=xxx # Email (SMTP) SMTP_HOST=smtp.example.com [email protected] SMTP_PASS=your_password # Supabase Storage (optional) SUPABASE_URL=https://xxx.supabase.co SUPABASE_ANON_KEY=xxx # Redis (optional) REDIS_PASSWORD=redis_password
Installation
Prerequisites
- Node.js 20+
- npm or yarn
- MySQL 8.0 (or Docker)
- Redis (optional, for caching)
Quick Start
# Clone and install git clone <repository-url> cd adspot_project npm install # Setup database npm run prisma:generate npm run prisma:migrate:deploy # Seed initial data npm run seed:admin # Admin user only npm run seed:all # All seed data # Start development npm run dev
Development
Commands
# Run both frontend and backend npm run dev # Run frontend only (Vite) npm run client:dev # Run backend only (NestJS) npm run server:dev # Open Prisma Studio (database GUI) npm run prisma:studio
Development URLs
| Service | URL |
|---|---|
| Frontend (Vite) | http://localhost:5173 |
| Backend API | http://localhost:3001 |
| Swagger Docs | http://localhost:3001/api/docs |
| Prisma Studio | http://localhost:5555 |
Build
# Production build (frontend + backend) npm run build:production # Frontend only npm run build:frontend # Backend only npm run build:backend # Start production server npm run start
Deployment
Docker Compose (Recommended)
# Start all services docker-compose up -d # View logs docker-compose logs -f # Stop services docker-compose down # Rebuild and start docker-compose up -d --build
Docker Services
| Service | Port | Description |
|---|---|---|
| app | 3002 (API), 5174 (Dev) | Application server |
| mysql | 3307 | MySQL 8.0 database |
| redis | 6379 | Redis cache |
Docker Standalone
# Build image npm run docker:build # Run container npm run docker:run
Vercel (Serverless)
The project includes a vercel.json configuration for serverless deployment:
# Install Vercel CLI npm i -g vercel # Deploy vercel
api/index.ts bootstraps NestJS on each cold start and reuses the instance for subsequent requests.
Database
Migration Commands
# Create a new migration npm run prisma:migrate # Apply migrations to production npm run prisma:migrate:deploy # Reset database (deletes all data!) npm run prisma:migrate:reset # Custom migration scripts npm run migrate:run npm run migrate:status npm run migrate:rollback npm run migrate:history
Seeding
# Seed admin user npm run seed:admin # Seed all data npm run seed:all # Clear all seed data npm run seed:clear # Reset and reseed npm run seed:reset
Key Models
| Model | Description |
|---|---|
User | Users with roles, balances, and early bird status |
Campaign | Advertising campaigns with scheduling and budgets |
Screen | Digital displays with location and heartbeat data |
Media | Uploaded content with approval workflow |
CampaignScreen | Junction table linking campaigns to screens |
ScreenRate | Pricing rules with multipliers and peak hours |
ChargingTransaction | Per-view charge records with rate details |
PaymentTransaction | Gateway payment records (Stripe/PayPal/Razorpay) |
Transaction | Balance transactions (deposits, charges, refunds) |
Language | Supported languages with RTL configuration |
Translation | Key-value translation entries by namespace |
ActivityLog | Audit trail with IP and user agent tracking |
Code Quality
# Run ESLint npm run lint # TypeScript type check npm run check
Frequently Asked Questions
How does campaign billing work?
How do I register a new screen?
What payment methods are supported?
How does the media approval process work?
Can I target specific locations for my campaign?
What is the Early Bird program?
How does screen heartbeat monitoring work?
Does AdSpot support multiple languages?
How are publisher earnings calculated?
What are the deployment options?
How do I run database migrations?
Use Prisma CLI commands: npm run prisma:migrate to create a new migration, npm run prisma:migrate:deploy to apply migrations to production. After any schema change, always run npm run prisma:generate to regenerate the Prisma client.