Digital Advertising Platform for Screen Networks

AdSpot connects advertisers with digital screen publishers. Create targeted campaigns, manage screen networks, process payments, and track real-time analytics — all from a single platform.

NestJS React 18 TypeScript Prisma ORM MySQL Socket.io Redis Ant Design Tailwind CSS

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.

What is DOOH Advertising? Digital Out-of-Home advertising uses digital screens in public spaces (malls, restaurants, gyms, transit hubs) to display targeted ads. AdSpot automates the entire workflow from campaign creation to billing.

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.

┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐ │ React Frontend │ │ NestJS Backend │ │ Database │ │ │ │ │ │ │ │ - React 18 + Vite │────►│ - REST API │────►│ - MySQL 8.0 │ │ - Redux Toolkit │ │ - WebSocket │ │ - Prisma ORM │ │ - Ant Design │◄────│ - JWT Auth │ │ - Redis Cache │ │ - Tailwind CSS │ │ - File Upload │ │ │ └───────────────────┘ └───────────────────┘ └───────────────────┘ │ ┌───────────┬───────────┐ │ │ ┌────┴────┐ ┌────┴────┐ ┌────┴─────┐ │ Stripe │ │ PayPal │ │ Razorpay │ └─────────┘ └─────────┘ └──────────┘

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

1
Sign Up

Create account & add funds

2
Upload Media

Images or videos

3
Create Campaign

Target screens & set budget

4
Go Live

Ads display on screens

5
Track Results

Views, spend & ROI

For Publishers

1
Register

Create publisher account

2
Add Screens

Register with code

3
Set Location

City, venue & coordinates

4
Display Ads

Screen shows campaigns

5
Earn Revenue

Request payouts

Campaign Lifecycle

1

Draft

Advertiser creates a campaign, selects media, targets screens by location/venue type, sets daily and total budgets, and configures timeslot schedules.

2

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.

3

Monitoring

Advertisers track views, spend, and performance via the analytics dashboard. Daily budgets automatically reset at configured times.

4

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

PropertyDescription
Name & DescriptionCampaign title and details
MediaLinked approved media asset (image or video)
Date RangeStart and end dates for the campaign
Total BudgetMaximum total spend for the campaign
Daily BudgetMaximum daily spend (resets automatically)
Target ScreensSelected screens filtered by location and venue type
Schedule TypeALWAYS_ON or SCHEDULED with timeslot rules
TimezoneTimezone for schedule calculations
StatusDRAFTACTIVEPAUSEDCOMPLETED

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
Budget Protection Campaigns automatically pause when daily or total budgets are exhausted, preventing overspend. Daily budgets reset at the configured time each day.

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:

1

Generate Code

Publisher creates a new screen entry and receives a unique registration code.

2

Enter Code on Device

The physical screen device uses the code to authenticate and link to the publisher's account.

3

Configure Details

Set resolution, orientation, venue type, city/region, and GPS coordinates.

Screen Properties

PropertyDescription
ResolutionWidth and height in pixels
Orientationlandscape or portrait
Venue TypeRETAIL, RESTAURANT, CAFE, GYM, TRANSIT, OFFICE, HOSPITAL, MALL, HOTEL, OTHER
LocationCity, region, venue name, latitude/longitude
Statusactive, inactive, maintenance
Access CodeAuthentication 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

1
Upload

Advertiser uploads media

2
Pending

Awaits admin review

3
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

1

Checkout Session

Advertiser initiates a payment. The backend creates a checkout session with the selected gateway (Stripe, PayPal, or Razorpay).

2

Payment Processing

User completes payment on the gateway's hosted page. Supports multiple currencies (default: USD).

3

Webhook Confirmation

Payment gateway sends a webhook to confirm the transaction. Raw body verification ensures security.

4

Balance Update

User's account balance is credited. Transaction is recorded in the payment history.

Webhook Security Stripe and Razorpay webhooks use signature verification. The backend processes webhook payloads before JSON parsing to preserve the original payload for signature validation.

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.

BenefitEarly BirdRegular
Platform Fee5%15%
Publisher Revenue Share85%70%
Trial Credit$25None
Setup FeeFreeStandard
Duration12 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, or approved
  • 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.

TokenExpiryUsage
Access Token24 hoursSent as Bearer token in the Authorization header
Refresh Token7 daysUsed to obtain a new access token without re-login

Auth Endpoints

POST/api/auth/registerRegister a new user account
POST/api/auth/loginLogin and receive tokens
POST/api/auth/refreshRefresh access token
GET/api/auth/profileGet current user profile
GET/api/auth/verify-email/:tokenVerify email address
Public Endpoints Some endpoints are marked as public and don't require authentication. These include the landing page content, public screen display, and health checks.

API Endpoints

Users

GET/api/usersList all users (Admin)
GET/api/users/:idGet user by ID
PATCH/api/users/:idUpdate user profile
PATCH/api/users/:id/balanceUpdate user balance (Admin)
DELETE/api/users/:idDelete user (Admin)

Campaigns

GET/api/campaignsList campaigns
POST/api/campaignsCreate new campaign
GET/api/campaigns/:idGet campaign details
PATCH/api/campaigns/:idUpdate campaign
PATCH/api/campaigns/:id/statusChange campaign status
PATCH/api/campaigns/:id/scheduleUpdate timeslot schedule
DELETE/api/campaigns/:idDelete campaign

Screens

GET/api/screensList screens
POST/api/screensRegister new screen
GET/api/screens/:idGet screen details
PATCH/api/screens/:idUpdate screen
POST/api/screens/ns/registerRegister screen by code
POST/api/screens/:id/heartbeatSend screen heartbeat

Media

GET/api/mediaList media assets
POST/api/media/uploadUpload media file
GET/api/media/:idGet media details
PATCH/api/media/:id/approveApprove media (Admin)
DELETE/api/media/:idDelete media

Analytics

GET/api/analytics/overviewDashboard overview stats
GET/api/analytics/campaigns/:idCampaign analytics
GET/api/analytics/screens/:idScreen analytics
POST/api/analytics/record-viewRecord a campaign view

Payments

POST/api/payments/checkoutCreate checkout session
POST/api/payments/webhook/stripeStripe webhook handler
POST/api/payments/webhook/paypalPayPal webhook handler
POST/api/payments/webhook/razorpayRazorpay webhook handler
GET/api/payments/transactionsTransaction history

Publisher

GET/api/publisher/dashboardPublisher dashboard data
GET/api/publisher/earningsEarnings overview
POST/api/publisher/payoutsRequest a payout
GET/api/publisher/analyticsPublisher analytics

Locations

GET/api/locations/citiesList cities
GET/api/locations/regionsList regions
GET/api/locations/venue-kindsList venue types

i18n

GET/api/i18n/languagesList available languages
POST/api/i18n/languagesCreate language (Admin)
GET/api/i18n/translationsGet translations
POST/api/i18n/translations/bulkBulk update translations

System

GET/api/healthBasic health check
GET/api/health/databaseDatabase connectivity check
GET/api/health/fullComprehensive system health
GET/api/docsThis documentation page

Project Structure

adspot_project/ ├── api/ # Backend (NestJS) │ ├── controllers/ # Standalone controllers (health, docs) │ ├── modules/ # Feature modules │ │ ├── auth/ # JWT auth, guards, decorators │ │ ├── users/ # User CRUD & management │ │ ├── campaigns/ # Campaign lifecycle │ │ ├── screens/ # Screen registration & heartbeats │ │ ├── media/ # File upload & approval │ │ ├── analytics/ # View tracking & metrics │ │ ├── payments/ # Stripe, PayPal & Razorpay gateways │ │ ├── charging/ # Rate management & billing │ │ ├── publisher/ # Publisher earnings & payouts │ │ ├── i18n/ # Languages & translations │ │ ├── landing/ # Landing page CMS │ │ ├── locations/ # Cities, regions, venue types │ │ ├── early-bird/ # Early bird program │ │ └── logging/ # Activity audit logs │ ├── database/ # Database adapters & factory │ ├── prisma/ # Prisma service wrapper │ ├── seeders/ # Admin & data seeders │ ├── services/ # Email, logging, initialization │ ├── shared/ # DTOs, types, response helpers │ ├── filters/ # Exception filters │ └── middleware/ # Logging middleware ├── src/ # Frontend (React) │ ├── components/ # Reusable UI components │ │ ├── layout/ # Header, sidebar, navigation │ │ ├── landing/ # Landing page components │ │ └── ui/ # Shared UI elements │ ├── pages/ # Page components │ │ ├── admin/ # Admin dashboard pages │ │ ├── advertiser/ # Advertiser pages │ │ ├── publisher/ # Publisher pages │ │ ├── auth/ # Login, register, verify │ │ └── screen/ # Screen display pages │ ├── store/ # Redux store & slices │ ├── services/ # API service layer │ ├── hooks/ # Custom React hooks │ ├── contexts/ # React contexts (i18n, theme) │ └── lib/ # API client & utilities ├── prisma/ # Schema & migrations ├── public/ # Static assets & locales ├── Dockerfile # Multi-stage Docker build ├── docker-compose.yml # MySQL, Redis, App services └── vercel.json # Vercel serverless config

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

ServiceURL
Frontend (Vite)http://localhost:5173
Backend APIhttp://localhost:3001
Swagger Docshttp://localhost:3001/api/docs
Prisma Studiohttp://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

ServicePortDescription
app3002 (API), 5174 (Dev)Application server
mysql3307MySQL 8.0 database
redis6379Redis 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
Vercel Entry Point The serverless handler at 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

ModelDescription
UserUsers with roles, balances, and early bird status
CampaignAdvertising campaigns with scheduling and budgets
ScreenDigital displays with location and heartbeat data
MediaUploaded content with approval workflow
CampaignScreenJunction table linking campaigns to screens
ScreenRatePricing rules with multipliers and peak hours
ChargingTransactionPer-view charge records with rate details
PaymentTransactionGateway payment records (Stripe/PayPal/Razorpay)
TransactionBalance transactions (deposits, charges, refunds)
LanguageSupported languages with RTL configuration
TranslationKey-value translation entries by namespace
ActivityLogAudit 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?
Campaigns are billed per view using a dynamic rate calculation. The final rate is determined by multiplying the base rate by location and time multipliers. Charges are recorded in 10-second intervals. When a campaign's daily or total budget is exhausted, it automatically pauses to prevent overspend. Daily budgets reset at the configured time each day.
How do I register a new screen?
As a publisher, go to your Screen Management dashboard and create a new screen entry. You'll receive a unique registration code. Enter this code on the physical screen device to link it to your account. Then configure the screen's resolution, orientation, venue type, and location details.
What payment methods are supported?
AdSpot supports Stripe, PayPal, and Razorpay payment gateways. Advertisers can add funds to their account balance using any of these gateways. The admin can configure gateway credentials and switch between test/live modes from the admin dashboard.
How does the media approval process work?
When an advertiser uploads media (images or videos), it enters a "Pending" state. An admin reviews the media and either approves or rejects it with a reason. Only approved media can be used in campaigns. This ensures all content meets platform quality and policy standards.
Can I target specific locations for my campaign?
Yes! Campaigns can target screens by city, region, and venue type (retail, restaurant, cafe, gym, transit, office, hospital, mall, hotel). You can also use timeslot scheduling to control when your ads appear on specific days and hours.
What is the Early Bird program?
The Early Bird program offers special benefits to users who join during the prelaunch period. Benefits include reduced platform fees (5% vs 15%), higher publisher revenue share (85% vs 70%), $25 trial credit, and no setup fees. The program runs for 12 months from enrollment.
How does screen heartbeat monitoring work?
Active screens periodically send heartbeat signals to the server, updating their last_active timestamp. This allows the platform to track which screens are online or offline in real-time. Publishers can monitor screen status from their dashboard and receive alerts about connectivity issues.
Does AdSpot support multiple languages?
Yes. AdSpot has a comprehensive i18n system with database-backed translations. It supports RTL languages (Arabic, Hebrew, etc.) with automatic layout direction switching. Admins can manage languages, translations, and track translation completion status from the admin panel.
How are publisher earnings calculated?
Publishers earn revenue based on views displayed on their screens. The revenue share is determined by the platform fee (default 15%, or 5% for early bird users). Publishers can view their earnings, track performance per screen, and request payouts via bank transfer from their dashboard.
What are the deployment options?
AdSpot supports three deployment options: (1) Docker Compose for self-hosted environments with MySQL and Redis containers, (2) Vercel for serverless deployment using the included vercel.json configuration, and (3) standalone Docker containers for custom infrastructure. The project includes a multi-stage Dockerfile for optimized production builds.
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.

Can the landing page be customized without code changes?
Yes! AdSpot includes a full landing page CMS. Admins can edit hero slides, benefits, features, testimonials, upcoming features, and how-it-works steps directly from the admin dashboard. Content changes are stored in the database and reflected immediately on the public landing page.