Overview

AirAds is a hyperlocal vendor discovery and advertising platform that helps customers find the right nearby business at the moment they need it — through map, list, augmented-reality and voice-driven search. It serves two sides of a local marketplace: consumers browsing deals, reels and vendor profiles around them, and business owners who claim, run and promote their listings. The product is delivered as seven coordinated sub-apps — a Django REST backend, three React portals (admin, vendor, customer), a planned Flutter mobile client, a shared infrastructure repository and a documentation repository — all developed as proprietary AmalAxis work.

Walkthrough

A short product walkthrough of AirAds.

Problem

Local discovery has a cold-start problem: a directory is worthless until it is dense with accurate businesses, yet no owner will hand-enter their listing into an empty platform. AirAds solves this with a claim-to-own model — the catalogue is pre-seeded from Google Places and GeoNames, deduplicated, and then handed to real owners who claim and enrich their entries. Layered on top are harder problems: ranking results by genuine local relevance rather than raw proximity, enforcing strict geographic and role-based access so a city manager only ever touches their own city's data, protecting personally identifiable information end-to-end, and moving vendor video (reels) into object storage without blocking the request path. The system had to reconcile these concerns across a single backend feeding three distinct front-ends and, eventually, a mobile app.

System Design

The backend is a Django 5.1 + Django REST Framework monolith organised into sixteen-plus focused apps — accounts, vendors, discovery, geo, reels, subscriptions, payments, audit, governance, imports, notifications, tags, analytics and the portal-specific vendor_portal/user_portal — exposing roughly 98 endpoints. Authentication uses djangorestframework-simplejwt, with a separate CustomerUserJWTAuthentication class so consumer/vendor tokens are isolated from admin tokens, and JWTs carry geo claims that drive scoping. GeoDjango over PostgreSQL + PostGIS backs spatial queries, with Redis serving as both cache and Celery broker for asynchronous work (notifications, imports, video processing) scheduled via django-celery-beat. PII classified as restricted is encrypted at rest with AES-256-GCM via the cryptography library, masked in display and kept out of logs; drf-spectacular generates the OpenAPI schema and Daphne serves ASGI.

Integrations are deliberate and load-bearing. Stripe (Checkout, customer portal, webhooks) powers the tiered subscription model — Silver, Gold, Diamond and Platinum — whose multipliers feed directly into result ranking. Twilio handles SMS/OTP authentication. Vendor reels and imagery are uploaded to DigitalOcean Spaces (S3-compatible) through django-storages and boto3, using a direct-to-storage pattern that hands the API only an s3_key and duration, with a local MEDIA_ROOT fallback for development. Google Places supplies both the seeding pipeline and per-vendor enrichment, guarded by a documented deduplication strategy.

The three front-ends share a stack — React 18, TypeScript 5, Vite, Zustand for client state and TanStack Query v5 for server state, axios, react-hook-form with Zod validation, Recharts, Lucide icons and a custom "AirAd DLS" design system — but diverge by role. The admin dashboard adds Leaflet maps, CSV import via PapaParse and diff viewing for audited changes; the vendor portal integrates Stripe Elements, Lottie and date pickers for promotions; the customer portal leans on Google Maps, Framer Motion, Swiper and a TikTok-style reels feed. The planned Flutter mobile app (Riverpod, Go Router, Dio, on-device AR and speech_to_text, FCM push) reuses the same API contract. Everything is containerised with Docker Compose behind an Nginx reverse proxy, shipped to DigitalOcean App Platform across development, staging and production, with GitLab CI/CD running lint, Semgrep, TruffleHog secret scanning and tests, plus scripted backups and disaster recovery.

A geospatial platform: map-based discovery served from spatial indexes, with campaign and billing services over a shared, replicated data tier.

CLIENTS
Web App (React + Vite)
EDGE
CDNNginx / Load Balancer
API GATEWAY
API Gateway (Django REST)
SERVICES
Auth & AccountsGeo Search & DiscoveryAd CampaignsBillingNotifications
ASYNC · REALTIME
Task Workers (Celery)
DATA
PostgreSQL + PostGISRedisObject Storage (S3)
EXTERNAL
StripeTwilioMaps

High-level architecture — abstracted for confidentiality; no internal endpoints, hostnames, or credentials are shown.

How It Works

01/04
01

Customer vendor discovery

A customer search resolves to a geo-filtered PostGIS query, is scored by the ranking engine, and is rendered as AR, map or list.

  1. 1The customer app issues a search (text, tag, voice or map viewport) with the user's location
  2. 2The discovery/geo apps run a PostGIS spatial query filtered to the correct geographic scope
  3. 3Candidate vendors are scored: Intent Match 30%, Distance 25%, Promotion 15%, Engagement 15%, Subscription Multiplier 15%
  4. 4Ranked, paginated results return with profiles, active deals and reels
  5. 5The client renders them as an AR camera overlay, an interactive map or an infinite-scroll list
02

Vendor claim and progressive activation

Pre-seeded listings are claimed by owners, approved by geo-scoped admins, then advanced through the activation ladder.

  1. 1Businesses are pre-seeded from Google Places and GeoNames, then deduplicated
  2. 2An owner searches for their listing and submits a claim request
  3. 3A geo-scoped admin reviews and approves or rejects the claim, writing an audit entry
  4. 4On approval the vendor advances CLAIM to ENGAGEMENT to MONETIZATION to GROWTH to RETENTION
  5. 5Subscription tier and feature gates unlock discounts, reels and the voice bot
03

Vendor reel upload

Videos are uploaded direct to DigitalOcean Spaces, registered by metadata, then processed asynchronously by Celery.

  1. 1The vendor selects or records a short video in the portal
  2. 2The client uploads the file directly to DigitalOcean Spaces and receives an s3_key
  3. 3It posts metadata (s3_key plus duration_seconds) to the reels endpoint
  4. 4A Celery worker processes the asset asynchronously
  5. 5Once processing completes the reel becomes visible to customers
04

Geo-scoped admin operations

Every admin action is authenticated, role-checked, scope-filtered, executed and audited.

  1. 1An admin authenticates and receives a JWT carrying role and geo claims
  2. 2Every request passes a role check against the RBAC matrix (SUPER_ADMIN to SUB_ADMIN to CITY_MANAGER and below)
  3. 3Queries are automatically filtered to the actor's geographic scope
  4. 4The CRUD operation executes
  5. 5The mutation is recorded in the audit log with actor, IP, request ID and before/after state

Key Features

  • Multi-modal discovery: AR overlay, interactive map, list and natural-language voice search
  • Claim-to-own vendor model seeded from Google Places and GeoNames with deduplication
  • Relevance ranking blending intent, distance, promotion, engagement and subscription tier
  • Hierarchical RBAC with geographic scoping across eleven-plus roles
  • Tiered Stripe subscriptions (Silver/Gold/Diamond/Platinum) gating features and ranking weight
  • Direct-to-Spaces reel uploads with asynchronous Celery processing
  • Time-boxed discounts and promotions with scheduling and live countdowns
  • AES-256-GCM encryption of restricted PII plus full audit logging of every mutation

Outcomes

  • Delivered a production-ready backend and three React portals from a single, versioned API contract, with a Flutter client planned against the same endpoints
  • Consolidated ~98 endpoints across sixteen-plus Django apps behind unified JWT auth with dual admin/customer authentication and geo-claim scoping
  • Solved the directory cold-start problem via a Google Places/GeoNames seeding-and-claim pipeline with an explicit deduplication strategy
  • Established defence-in-depth: AES-256-GCM PII encryption, comprehensive audit logging, and CI-integrated Semgrep and TruffleHog scanning

More work