Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

118 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🏠 Thikana β€” Empower Your Local Business

One platform. Every local business.
Thikana is an all-in-one SaaS platform combining geo-based business discovery, no-code website building, inventory & order management, payments (Razorpay), and an AI-powered recommendation engine β€” all in one place.


πŸ“‘ Table of Contents

  1. Project Overview
  2. Monorepo Structure
  3. thikana-api β€” FastAPI Recommendation Engine
  4. thikana-web β€” Next.js Frontend
  5. Full System Architecture
  6. Tech Stack
  7. Environment Variables
  8. Pricing Plans

🌐 Project Overview

Thikana solves a real problem: local businesses have no single digital home on the internet. Thikana gives any shop owner β€” a neighbourhood gym, family restaurant, or corner pharmacy β€” a complete digital presence with:

  • πŸ“ Geo-based Discovery β€” hyperlocal search via geohash indexing
  • 🌐 No-Code Website Builder β€” drag-and-drop GrapesJS powered builder
  • πŸ’³ Payments β€” Razorpay integration for products, bookings & subscriptions
  • πŸ“Š Analytics β€” spending anomaly detection, predictions, and insights
  • 🀝 Social Graph β€” follow businesses, curated post feed, "Who to Follow"
  • 🏒 Franchise Management β€” multi-outlet dashboards and delegated access
  • πŸ“¦ Inventory & Orders β€” full product catalog with order email notifications

πŸ—‚ Monorepo Structure

technions-devally-2026/
β”œβ”€β”€ thikana-api/         # FastAPI recommendation & analytics backend (Python)
└── thikana-web/         # Next.js 16 full-stack frontend (JavaScript/React 19)

🐍 thikana-api β€” FastAPI Recommendation Engine

API Architecture

The API is a pure Python FastAPI microservice responsible for:

  • Computing personalised post feeds
  • Building "Who to Follow" business discovery lists
  • Running financial analytics (anomaly detection, spending insights, predictions, recommendations)

It follows a strict layered architecture β€” routes only route, all logic is in engine/ and models/.

flowchart TB
    Client([Client / Next.js])
    
    subgraph FastAPI["FastAPI App (main.py)"]
        direction TB
        MW[CORS Middleware]
        RF["/feed Router"]
        RD["/discovery Router"]
        RA["/analytics Router"]
    end
    
    subgraph Engine["engine/"]
        AS[assembler.py\nCoordinates data + scoring]
        FE[fetcher.py\nDB reads only]
        SC[scorer.py\nPure scoring logic]
    end
    
    subgraph Models["models/"]
        AD[anomaly_detector.py]
        SI[spending_insights.py]
        ER[expense_recommender.py]
        SP[spending_predictor.py]
    end
    
    subgraph DB["db/"]
        FB[firebase.py\nLive Firestore]
        MK[mock.py\nMock JSON data]
    end

    subgraph Config["config.py"]
        CFG[USE_MOCK Β· MAX_RADIUS_KM\nSCORING WEIGHTS Β· GEOHASH_PRECISION]
    end

    Client --> MW --> RF & RD & RA
    RF --> AS
    RD --> AS
    AS --> FE --> FB & MK
    AS --> SC
    RA --> AD & SI & ER & SP
    Config -.-> AS & FE & SC
Loading

API Directory Structure

thikana-api/
β”œβ”€β”€ main.py                    # FastAPI app entry point, registers routers
β”œβ”€β”€ config.py                  # Single source of truth for ALL settings
β”œβ”€β”€ requirements.txt           # Python dependencies
β”œβ”€β”€ conftest.py                # Pytest configuration
β”‚
β”œβ”€β”€ routes/                    # HTTP layer ONLY β€” no business logic
β”‚   β”œβ”€β”€ feed.py                # GET /feed/{user_id}
β”‚   β”œβ”€β”€ discovery.py           # GET /discovery/who-to-follow/{user_id}
β”‚   └── analytics.py           # GET /analytics/* (4 endpoints)
β”‚
β”œβ”€β”€ engine/                    # Recommendation engine (Feed + Discovery)
β”‚   β”œβ”€β”€ assembler.py           # Orchestrates fetcher + scorer
β”‚   β”œβ”€β”€ fetcher.py             # All DB reads go here
β”‚   β”œβ”€β”€ geohash_utils.py       # Geohash cell computation helpers
β”‚   └── scorer.py              # Pure stateless scoring (no I/O)
β”‚
β”œβ”€β”€ core/                      # Legacy engine (v1, kept for reference)
β”‚   β”œβ”€β”€ assembler.py
β”‚   β”œβ”€β”€ geohash_utils.py
β”‚   └── scorer.py
β”‚
β”œβ”€β”€ models/                    # Financial analytics models
β”‚   β”œβ”€β”€ anomaly_detector.py    # Statistical anomaly detection
β”‚   β”œβ”€β”€ spending_insights.py   # Category + behavioral analysis
β”‚   β”œβ”€β”€ expense_recommender.py # Budget + saving recommendations
β”‚   └── spending_predictor.py  # Next-month WMA forecast
β”‚
β”œβ”€β”€ db/                        # Data access layer
β”‚   β”œβ”€β”€ base.py                # Abstract DB interface
β”‚   β”œβ”€β”€ firebase.py            # Live Firestore implementation
β”‚   └── mock.py                # Mock JSON implementation
β”‚
β”œβ”€β”€ data/
β”‚   └── mock_db.json           # Local mock data for dev/tests
β”‚
└── tests/                     # Pytest test suite

API Endpoints

Method Path Tag Description
GET / Health Health check β€” returns {status: "ok", version: "2.0.0"}
GET /feed/{user_id} Feed Personalised ranked post feed
GET /discovery/who-to-follow/{user_id} Discovery Nearby businesses to follow
GET /analytics/anomalies/{user_id} Analytics Detect unusual transactions
GET /analytics/insights/{user_id} Analytics Spending habits & actionable insights
GET /analytics/recommendations/{user_id} Analytics Budget & saving strategies
GET /analytics/predictions/{user_id} Analytics Next-month spending forecast

Query Parameters for /feed/{user_id}:

Param Type Required Default Description
lat float βœ… β€” User's latitude (-90 to 90)
lon float βœ… β€” User's longitude (-180 to 180)
limit int ❌ 20 Max posts returned (1–50)

Scoring Algorithm β€” Post Feed

Each post is scored using a weighted sum of three signals:

Signal Weight Logic
Following 55% 1.0 if user follows the business, else 0.0
Location 35% Linear decay from 1.0 at 0km to 0.0 at 10km (Haversine)
Recency 10% Linear decay from 1.0 (now) to 0.0 at 168 hours (7 days)
score = (following Γ— 0.55) + (location Γ— 0.35) + (recency Γ— 0.10)
flowchart LR
    Post([Post candidate])
    F{"Is business\nfollowed?"}
    L[Distance\nHaversine km]
    R[Hours old\nsince createdAt]
    
    FS["following_signal\n1.0 or 0.0"]
    LS["location_signal\nmax(0, 1 - dist/10)"]
    RS["recency_signal\nmax(0, 1 - hrs/168)"]
    
    SUM["score =\n0.55Γ—F + 0.35Γ—L + 0.10Γ—R"]
    OUT([Score ∈ 0.0–1.0])
    
    Post --> F --> FS
    Post --> L --> LS
    Post --> R --> RS
    FS & LS & RS --> SUM --> OUT
Loading

Scoring Algorithm β€” Who to Follow

Businesses are scored for the discovery list using two signals:

Signal Weight Logic
Location 70% Linear decay 1.0 at 0km β†’ 0.0 at 10km
Activity 30% postCount / 20 (normalised, capped at 1.0)
flowchart LR
    Biz([Business candidate])
    D[Distance km\npre-computed]
    P[postCount]

    LS["location_signal\nmax(0, 1 - dist/10)"]
    AS["activity_signal\nmin(postCount,20)/20"]

    SUM["score =\n0.70Γ—L + 0.30Γ—A"]
    OUT([Score ∈ 0.0–1.0])

    Biz --> D --> LS
    Biz --> P --> AS
    LS & AS --> SUM --> OUT
Loading

Analytics Engine

Four independent, stateless models in models/:

flowchart TD
    TXN[(Transaction data\nFirestore / mock_db.json)]
    
    subgraph Analytics["models/"]
        AD["anomaly_detector.py\nβ€’ category_spike\nβ€’ rolling_spike\nβ€’ rapid_succession\nSeverity: medium / high"]
        SI["spending_insights.py\nβ€’ spending_patterns\nβ€’ category_analysis\nβ€’ saving_opportunities\nβ€’ behavioral_insights\nβ€’ recommendations"]
        ER["expense_recommender.py\nβ€’ budget_suggestions\nβ€’ timing_optimization\nβ€’ saving_opportunities\nβ€’ category_tips"]
        SP["spending_predictor.py\nβ€’ WMA forecast\nβ€’ trend: increasing/stable/decreasing\nβ€’ confidence: high/medium/low\nβ€’ lower/upper bounds"]
    end
    
    TXN --> AD & SI & ER & SP
Loading

API Data Flow Flowcharts

/feed/{user_id} β€” Build Post Feed

sequenceDiagram
    participant Client
    participant Route as routes/feed.py
    participant Asm as engine/assembler.py
    participant Fetch as engine/fetcher.py
    participant Score as engine/scorer.py
    participant DB as Firebase/Mock

    Client->>Route: GET /feed/{user_id}?lat=&lon=&limit=
    Route->>Asm: build_feed(user_id, lat, lon, limit)
    Asm->>Fetch: get_following_ids(user_id)
    Fetch->>DB: users/{user_id}/following
    DB-->>Fetch: [biz_id, ...]
    Asm->>Fetch: get_nearby_businesses(lat, lon)
    Fetch->>DB: location_index (9 geohash cells)
    DB-->>Fetch: {biz_id: distance_km}
    Note over Asm: Union: followed βˆͺ nearby βˆ’ self
    Asm->>Fetch: get_posts_for_businesses(candidates)
    Fetch->>DB: posts WHERE uid IN [...]
    DB-->>Fetch: raw posts []
    Asm->>Fetch: get_businesses_batch(candidates)
    Fetch->>DB: businesses/{biz_id} batch
    DB-->>Fetch: business metadata {}
    loop For each post
        Asm->>Score: score_post(post, following_set, lat, lon, biz_locations)
        Score-->>Asm: float score ∈ [0.0, 1.0]
    end
    Note over Asm: Sort DESC, deduplicate, slice top N
    Asm-->>Route: posts[]
    Route-->>Client: {user_id, count, posts[]}
Loading

/discovery/who-to-follow/{user_id}

sequenceDiagram
    participant Client
    participant Route as routes/discovery.py
    participant Asm as engine/assembler.py
    participant Fetch as engine/fetcher.py
    participant Score as engine/scorer.py
    participant DB as Firebase/Mock

    Client->>Route: GET /discovery/who-to-follow/{user_id}?lat=&lon=
    Route->>Asm: build_who_to_follow(user_id, lat, lon, limit)
    Asm->>Fetch: get_following_ids(user_id)
    Fetch->>DB: users/{user_id}/following
    DB-->>Fetch: already-followed set
    Asm->>Fetch: get_nearby_businesses(lat, lon)
    Fetch->>DB: location_index (geohash cells)
    DB-->>Fetch: {biz_id: distance_km}
    Note over Asm: Filter out already-followed + self
    Asm->>Fetch: get_businesses_batch(candidates)
    Fetch->>DB: businesses metadata
    DB-->>Fetch: business docs
    loop For each candidate business
        Asm->>Score: score_business_to_follow(biz, distance_km)
        Score-->>Asm: float score
    end
    Note over Asm: Sort DESC, slice top N
    Asm-->>Route: suggestions[]
    Route-->>Client: {user_id, count, suggestions[]}
Loading

API Setup & Running Locally

# 1. Navigate to the API directory
cd thikana-api

# 2. Create and activate a virtual environment
python -m venv venv
venv\Scripts\activate       # Windows
# source venv/bin/activate  # macOS/Linux

# 3. Install dependencies
pip install -r requirements.txt

# 4. Configure environment
# Copy .env.example to .env and fill in Firebase credentials (if USE_MOCK=False)
# For local dev, USE_MOCK=True in config.py uses data/mock_db.json

# 5. Run the server
uvicorn main:app --reload --port 8000

# 6. Interactive API docs
# http://localhost:8000/docs

Configuration knobs in config.py:

Variable Default Description
USE_MOCK True True = local mock JSON, False = live Firestore
MAX_RADIUS_KM 10.0 Businesses beyond this radius are ignored
GEOHASH_PRECISION 5 Precision-5 β‰ˆ 5Γ—5 km cell
RECENCY_WINDOW_HOURS 168.0 7 days β€” posts older than this score 0 on recency
POST_WEIGHT_FOLLOWING 0.55 Weight of following signal for post feed
POST_WEIGHT_LOCATION 0.35 Weight of location signal for post feed
POST_WEIGHT_RECENCY 0.10 Weight of recency signal for post feed
FOLLOW_WEIGHT_LOCATION 0.70 Weight of location signal for "Who to Follow"
FOLLOW_WEIGHT_ACTIVITY 0.30 Weight of activity signal for "Who to Follow"

βš›οΈ thikana-web β€” Next.js Frontend

Web Architecture

The frontend is a Next.js 16 (App Router) full-stack application with React 19. It uses:

  • Firebase for auth, Firestore, and Storage
  • Algolia for search indexing
  • Razorpay for payments
  • Zustand for client-side state management
  • Framer Motion for animations
  • TailwindCSS v4 for styling
  • A client-side recommendation engine in hooks/useRecommendations.js that mirrors the Python scoring logic entirely in the browser (no server round-trip needed for feed)
flowchart TB
    Browser(["Browser / User"])

    subgraph Next["Next.js 16 App - thikana-web"]
        direction TB
        PUB["Public Pages\nHome / About / Pricing / Contact"]
        AUTH["Auth Pages\nlogin Β· register"]

        subgraph Dashboard["dashboard Route Group"]
            DASH["/dashboard"]
            FEED["/feed"]
            PROFILE["/profile"]
            SEARCH["/search"]
            NOTIF["/notifications"]
            MAP["/map"]
            GST["/gst-reports"]
            WEB["/websites"]
            CREATE["/posts Β· /add-product\n/add-bulk-products"]
            CART["/cart"]
        end

        subgraph API["app/api Route Handlers"]
            APIFEED["/api/feed"]
            APIDISC["/api/discovery"]
            APIAI["/api/ai"]
            RAZORPAY["/api/razorpay"]
            MAPS["/api/maps-key"]
            EMAIL["/api/send-order-email"]
            CONTENT["/api/generate-content"]
        end
    end

    subgraph Services["External Services"]
        FB[("Firebase\nAuth + Firestore + Storage")]
        ALG["Algolia\nSearch"]
        RZ["Razorpay\nPayments"]
        GMAPS["Google Maps\nAPI"]
        GEM["Google Gemini\nAI"]
        THAPI["thikana-api\nPython FastAPI"]
    end

    Browser --> PUB & AUTH & Dashboard
    API --> FB & ALG & RZ & GMAPS & GEM & THAPI
    Dashboard --> API
Loading

Web Directory Structure

thikana-web/
β”‚
β”œβ”€β”€ app/                            # Next.js App Router
β”‚   β”œβ”€β”€ layout.js                   # Root layout (fonts, theme, auth, toaster)
β”‚   β”œβ”€β”€ page.js                     # Landing / Marketing homepage
β”‚   β”œβ”€β”€ globals.css                 # Global CSS variables & base styles
β”‚   β”‚
β”‚   β”œβ”€β”€ (auth)/                     # Unauthenticated route group
β”‚   β”‚   β”œβ”€β”€ login/page.jsx
β”‚   β”‚   └── register/
β”‚   β”‚       β”œβ”€β”€ page.jsx            # Step-based business registration
β”‚   β”‚       └── user/page.jsx       # User registration
β”‚   β”‚
β”‚   β”œβ”€β”€ (dashboard)/                # Authenticated route group
β”‚   β”‚   β”œβ”€β”€ layout.jsx              # Dashboard shell layout
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ (with-recommendations)/ # Layout with Sidebar + WhoToFollow
β”‚   β”‚   β”‚   β”œβ”€β”€ layout.jsx          # 3-col feed / 2-col default / 1-col profile
β”‚   β”‚   β”‚   β”œβ”€β”€ feed/               # Personalised post feed
β”‚   β”‚   β”‚   β”œβ”€β”€ map/                # Nearby businesses map view
β”‚   β”‚   β”‚   β”œβ”€β”€ notifications/      # Real-time notification centre
β”‚   β”‚   β”‚   β”œβ”€β”€ gst-reports/        # GST report generation
β”‚   β”‚   β”‚   β”œβ”€β”€ post/               # Individual post view
β”‚   β”‚   β”‚   β”œβ”€β”€ [username]/         # Public business profile by username
β”‚   β”‚   β”‚   └── profile/            # My profile + sub-routes
β”‚   β”‚   β”‚       β”œβ”€β”€ page.jsx        # Profile overview (176 KB β€” heavily featured)
β”‚   β”‚   β”‚       β”œβ”€β”€ analytics/      # Spending analytics dashboard
β”‚   β”‚   β”‚       β”œβ”€β”€ inventory/      # Product inventory management
β”‚   β”‚   β”‚       β”œβ”€β”€ services/       # Service listings
β”‚   β”‚   β”‚       └── settings/       # Account & business settings
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ (create)/               # Content creation
β”‚   β”‚   β”‚   β”œβ”€β”€ posts/              # Create new post
β”‚   β”‚   β”‚   β”œβ”€β”€ add-product/        # Add single product
β”‚   β”‚   β”‚   └── add-bulk-products/  # CSV bulk product import
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ cart/                   # Shopping cart & checkout
β”‚   β”‚   β”œβ”€β”€ dashboard/              # Business dashboard home
β”‚   β”‚   β”œβ”€β”€ search/                 # Algolia-powered search
β”‚   β”‚   └── websites/               # Website builder
β”‚   β”‚       └── [websiteId]/        # Builder canvas for specific site
β”‚   β”‚
β”‚   β”œβ”€β”€ about/page.js               # About page (animated)
β”‚   β”œβ”€β”€ pricing/page.js             # Pricing plans
β”‚   β”œβ”€β”€ contact/page.js             # Contact form
β”‚   β”‚
β”‚   └── api/                        # Next.js Route Handlers
β”‚       β”œβ”€β”€ feed/                   # Proxy to thikana-api /feed
β”‚       β”œβ”€β”€ discovery/              # Proxy to thikana-api /discovery
β”‚       β”œβ”€β”€ ai/                     # Google Gemini AI endpoints
β”‚       β”œβ”€β”€ generate-content/       # AI content generation
β”‚       β”œβ”€β”€ razorpay/               # Payment order creation
β”‚       β”œβ”€β”€ create-product-order/   # Product checkout
β”‚       β”œβ”€β”€ send-order-email/       # Nodemailer order emails
β”‚       β”œβ”€β”€ send-order-status-email/# Order status update emails
β”‚       β”œβ”€β”€ update-order-status/    # Order lifecycle management
β”‚       └── maps-key/               # Secure Google Maps key proxy
β”‚
β”œβ”€β”€ components/                     # React components
β”‚   β”œβ”€β”€ Navbar.js                   # Public marketing navbar (mobile-responsive)
β”‚   β”œβ”€β”€ MainNavbar.jsx              # Dashboard top navbar
β”‚   β”œβ”€β”€ Sidebar.jsx                 # Left sidebar (profile + nav links)
β”‚   β”œβ”€β”€ WhoToFollow.jsx             # Right sidebar (business suggestions)
β”‚   β”œβ”€β”€ PostCard.jsx                # Post card with likes/comments
β”‚   β”œβ”€β”€ BasicInfoForm.jsx           # Business registration step 1
β”‚   β”œβ”€β”€ BusinessInfoForm.jsx        # Business registration step 2
β”‚   β”œβ”€β”€ UserBasicInfoForm.jsx       # User registration
β”‚   β”œβ”€β”€ MapComponent.jsx            # Leaflet map component
β”‚   β”œβ”€β”€ ProfilePage.jsx             # Business public profile
β”‚   β”œβ”€β”€ PhotosGrid.jsx              # Photo gallery grid
β”‚   β”œβ”€β”€ CartContext.jsx             # Shopping cart state & logic
β”‚   β”œβ”€β”€ PaymentForm.jsx             # Razorpay payment UI
β”‚   β”œβ”€β”€ ConnectRazorpay.jsx         # Razorpay account connection
β”‚   β”œβ”€β”€ ImageUpload.jsx             # S3 image upload component
β”‚   β”œβ”€β”€ ThemeSwitcher.jsx           # Dark/light mode toggle
β”‚   β”‚
β”‚   β”œβ”€β”€ auth/                       # Auth-related components
β”‚   β”œβ”€β”€ builder/                    # Website builder components (GrapesJS)
β”‚   β”œβ”€β”€ canvas/                     # Builder canvas wrapper
β”‚   β”œβ”€β”€ form-builder/               # Drag-and-drop form builder
β”‚   β”œβ”€β”€ inventory/                  # Inventory management components
β”‚   β”œβ”€β”€ product/                    # Product display components
β”‚   β”œβ”€β”€ profile/                    # Profile sub-components
β”‚   β”‚   └── NearbyBusinessMap.jsx   # Leaflet map for nearby businesses
β”‚   β”œβ”€β”€ registry/                   # Business registry components
β”‚   β”œβ”€β”€ search/                     # Algolia search UI components
β”‚   └── ui/                         # Radix UI primitive wrappers
β”‚
β”œβ”€β”€ hooks/                          # Custom React hooks
β”‚   β”œβ”€β”€ useAuth.js                  # Firebase auth context
β”‚   β”œβ”€β”€ useRecommendations.js       # useFeed + useWhoToFollow (client-side engine)
β”‚   β”œβ”€β”€ useGetPosts.js              # Firestore posts fetching
β”‚   β”œβ”€β”€ useGetUser.js               # Current user data
β”‚   β”œβ”€β”€ useGetUserPosts.js          # User's own posts
β”‚   β”œβ”€β”€ useLikePosts.js             # Like/unlike actions
β”‚   β”œβ”€β”€ useAutosave.js              # Builder auto-save
β”‚   └── useBusinessIdForMember.js   # Business ID resolving for team members
β”‚
β”œβ”€β”€ lib/                            # Utility libraries
β”‚   β”œβ”€β”€ firebase.js                 # Firebase client SDK init
β”‚   β”œβ”€β”€ firebase-admin.js           # Firebase Admin SDK (server-side)
β”‚   β”œβ”€β”€ notifications.js            # Full notification system
β”‚   β”œβ”€β”€ inventory-operations.js     # Inventory CRUD with Firebase
β”‚   β”œβ”€β”€ website-operations.js       # Website builder save/publish
β”‚   β”œβ”€β”€ followeringAction.js        # Follow/unfollow business logic
β”‚   β”œβ”€β”€ firestoreWrites.js          # Batch write helpers
β”‚   β”œβ”€β”€ geohash.js                  # Geohash encoding
β”‚   β”œβ”€β”€ date-utils.js               # Date formatting utilities
β”‚   β”œβ”€β”€ business-utils.js           # Business data helpers
β”‚   β”œβ”€β”€ business-user.js            # Business-user relationship
β”‚   β”œβ”€β”€ userStatus.js               # Online/offline presence
β”‚   β”œβ”€β”€ ai/                         # AI-related libs
β”‚   β”œβ”€β”€ data/                       # Static data / seed data
β”‚   β”œβ”€β”€ payment/                    # Razorpay helpers
β”‚   β”œβ”€β”€ publish/                    # Website publish logic
β”‚   └── stores/                     # Zustand stores
β”‚       β”œβ”€β”€ builderStore.js         # Website builder state (23 KB)
β”‚       β”œβ”€β”€ formBuilderStore.js     # Form builder state
β”‚       β”œβ”€β”€ chatStore.js            # Chat state
β”‚       β”œβ”€β”€ historyStore.js         # Builder undo/redo history
β”‚       └── uiStore.js              # Global UI state
β”‚
β”œβ”€β”€ context/                        # React context providers
β”‚   └── ThemeContext.js             # Dark/Light theme provider
β”‚
β”œβ”€β”€ constants/                      # App-wide constants
β”œβ”€β”€ utils/                          # Pure utility functions
β”œβ”€β”€ public/                         # Static assets
β”œβ”€β”€ next.config.mjs                 # Next.js configuration
β”œβ”€β”€ package.json                    # Dependencies & scripts
└── biome.json                      # Biome linter/formatter config

Pages & Routes

flowchart LR
    Root(["HOME /"])
    About["/about"]
    Pricing["/pricing"]
    Contact["/contact"]

    Login["/login"]
    Register["/register"]
    RegUser["/register/user"]

    Dashboard["/dashboard"]
    Feed["/feed"]
    Profile["/profile"]
    Analytics["/profile/analytics"]
    Inventory["/profile/inventory"]
    Services["/profile/services"]
    Settings["/profile/settings"]
    PubProfile["/:username (public profile)"]
    Notif["/notifications"]
    Map["/map"]
    GST["/gst-reports"]
    Search["/search"]
    Cart["/cart"]

    Posts["/posts"]
    AddProd["/add-product"]
    BulkProd["/add-bulk-products"]

    Websites["/websites"]
    Builder["/websites/websiteId"]

    Root --- About
    Root --- Pricing
    Root --- Contact
    Root --- Login
    Root --- Register
    Register --- RegUser
    Root --- Dashboard
    Dashboard --- Feed
    Dashboard --- Profile
    Profile --- Analytics
    Profile --- Inventory
    Profile --- Services
    Profile --- Settings
    Dashboard --- PubProfile
    Dashboard --- Notif
    Dashboard --- Map
    Dashboard --- GST
    Dashboard --- Search
    Dashboard --- Cart
    Dashboard --- Posts
    Dashboard --- AddProd
    Dashboard --- BulkProd
    Dashboard --- Websites
    Websites --- Builder
Loading

Key Features

Feature Description Tech
Business Registration Multi-step form with MSME/GST/PAN verification Firebase, React Hook Form, Zod
Feed Ranked posts from followed + nearby businesses useRecommendations.js, Firestore, Geohash
Who to Follow Nearby businesses user doesn't follow yet Haversine scoring, Firestore
Map Discovery Interactive map of businesses within 10 km Leaflet, React-Leaflet, Google Maps
Website Builder No-code drag-and-drop site builder GrapesJS, Zustand, Immer
Form Builder Drag-and-drop form creation dnd-kit, Zustand
Inventory Management Product catalog with CRUD + bulk CSV upload Papa Parse, Firestore
Order Management Full lifecycle β€” pending β†’ confirmed β†’ delivered Nodemailer (email), Razorpay
Payments Razorpay checkout with signature verification Razorpay SDK
Notifications Real-time in-app + WhatsApp + Email notifications Firestore onSnapshot, Nodemailer
Analytics Dashboard Spending anomalies, insights, predictions Recharts, thikana-api
GST Reports Auto-generated GST compliance reports jsPDF, jspdf-autotable
Algolia Search Instant indexed search across businesses Algolia InstantSearch
AI Content Generation Auto-generate post captions / descriptions Google Gemini AI
QR Codes Business QR code generation react-qr-code
Dark Mode Full dark/light theme switch next-themes, CSS variables
Mobile Responsive Hamburger nav, responsive layouts TailwindCSS v4

Component Map

flowchart TD
    Root["RootLayout (layout.js)\nThemeProvider Β· AuthProvider Β· Toaster"]

    PRE["Public Routes\nNavbar + Footer"]
    HOME["page.js\nLanding Page"]
    ABT["about/page.js"]
    PRC["pricing/page.js"]

    DLAY["\(dashboard\)/layout.jsx\nMainNavbar"]
    RLAY["\(with-recommendations\)/layout.jsx\n3-col | 2-col | 1-col"]

    FEED_PAGE["/feed/page.jsx\nPostCard list"]
    PROF["/profile/page.jsx\nFull business dashboard\nInventory Β· Analytics Β· Services Β· Settings"]
    NOTIF["/notifications/page.jsx"]
    MAP["/map/page.jsx"]
    SRCH["/search/page.jsx"]

    SB["Sidebar.jsx\nUser info + nav links"]
    WTF["WhoToFollow.jsx\nuseWhoToFollow hook"]
    NBM["NearbyBusinessMap.jsx\nLeaflet + Google Maps"]

    BUILDER["/websites/\[id\]/page.jsx\nWebsite Builder Canvas"]
    BST["builderStore.js\nZustand"]

    Root --> PRE & DLAY
    PRE --> HOME & ABT & PRC
    DLAY --> RLAY
    RLAY --> SB & FEED_PAGE & WTF
    RLAY --> PROF & NOTIF & MAP & SRCH
    SB --- NBM
    DLAY --> BUILDER
    BUILDER --- BST
Loading

State Management

flowchart LR
    subgraph Zustand["Zustand Stores (lib/stores/)"]
        BS[builderStore\nCanvas elements\nSelected el Β· Undo history\nPublish state]
        FS[formBuilderStore\nForm fields\nDrag state]
        HS[historyStore\nUndo / Redo stack]
        USS[uiStore\nSidebar open state\nModal state]
        CS[chatStore\nChat messages\nSocket]
    end

    subgraph Context["React Context"]
        AUTH[AuthProvider\nuseAuth hook\nFirebase user state]
        THEME[ThemeProvider\ndark/light mode]
        CART[CartContext\nCart items\nTotal Β· Checkout]
    end

    subgraph LocalHooks["Custom Hooks"]
        UF[useFeed\nPosts + scores]
        UW[useWhoToFollow\nBusiness suggestions]
        UP[useGetPosts\nFirestore pagination]
        UL[useLikePosts\nOptimistic likes]
        UAS[useAutosave\nBuilder debounced save]
    end
Loading

Web Data Flow Flowcharts

Authentication Flow

sequenceDiagram
    participant User
    participant UI as Login/Register Page
    participant Auth as useAuth Hook
    participant FB as Firebase Auth
    participant FS as Firestore

    User->>UI: Enter credentials
    UI->>Auth: signIn(email, password)
    Auth->>FB: signInWithEmailAndPassword()
    FB-->>Auth: UserCredential
    Auth->>FS: getDoc(users/{uid})
    FS-->>Auth: User profile data
    Auth-->>UI: Authenticated user
    UI->>UI: Redirect to /dashboard
Loading

Post Feed Data Flow (Client-Side Recommendation Engine)

flowchart TD
    A(["User opens /feed"]) --> B["useAuth: get userId"]
    B --> C["navigator.geolocation\nget lat / lon"]
    C --> D["Firestore: users/uid/following\nGet following IDs"]
    D --> E["Encode geohash, compute 9 neighbor cells"]
    E --> F["Firestore: location_index/cell\nGet nearby business IDs"]
    F --> G{"nearbyIds empty?"}
    G -- Yes --> H["Fallback: scan all businesses\nHaversine filter <= 10 km"]
    G -- No --> I
    H --> I["Union: following + nearby - self"]
    I --> J["Batch fetch business metadata\nfrom Firestore in groups of 10"]
    J --> K["Batch fetch posts WHERE uid IN candidates\norderedBy createdAt DESC"]
    K --> L["Score each post:\n0.55 x following + 0.35 x location + 0.10 x recency"]
    L --> M["Deduplicate, sort DESC, slice top N"]
    M --> N(["Render PostCard list"])
Loading

Payment / Order Flow

sequenceDiagram
    participant User
    participant Cart as CartContext
    participant API as /api/razorpay
    participant RZ as Razorpay
    participant FB as Firestore
    participant Email as /api/send-order-email

    User->>Cart: Add product β†’ Checkout
    Cart->>API: POST /api/razorpay {amount, currency}
    API->>RZ: Create Order (server-side)
    RZ-->>API: {order_id, amount}
    API-->>Cart: Razorpay order details
    Cart->>RZ: Open Razorpay Checkout (client)
    User->>RZ: Complete payment
    RZ-->>Cart: payment_id, signature
    Cart->>API: POST /api/razorpay (verify signature)
    API-->>Cart: Payment verified βœ…
    Cart->>FB: Write order document
    Cart->>Email: Send order confirmation email (Nodemailer)
    Email-->>User: Order confirmation πŸ“§
Loading

Notification System Flow

flowchart LR
    TRIG(["Trigger: Order / Follow / System"])
    ADD["addNotification / sendNotificationToUser"]
    FS[("Firestore\nusers/uid/notifications")]
    SNAP["onSnapshot listener\nin notification page"]
    UI(["Notification Bell + List"])
    WA["sendWhatsAppNotification\nvia /api/notification-whatsapp"]
    EM["sendEmailNotification\nvia /api/notification-email"]

    TRIG --> ADD
    ADD --> FS
    ADD --> WA
    ADD --> EM
    FS --> SNAP --> UI
Loading

Web Setup & Running Locally

# 1. Navigate to the web directory
cd thikana-web

# 2. Install dependencies
npm install

# 3. Configure environment variables
# Create .env.local (see Environment Variables section below)

# 4. Run the development server
npm run dev
# β†’ http://localhost:3000

# 5. (Optional) Seed sample posts to Firestore
node seed-posts.mjs

# 6. Lint and format
npm run lint       # Biome check
npm run format     # Biome format --write

πŸ— Full System Architecture

flowchart TB
    subgraph Client["Browser (User)"]
        NC[Next.js Client Components\nReact 19]
    end

    subgraph NextServer["Next.js Server (thikana-web)"]
        SC[Server Components\nSSR / RSC]
        RH[Route Handlers\napp/api/*]
    end

    subgraph PyAPI["thikana-api (FastAPI)"]
        FP[Feed + Discovery\nRecommendation Engine]
        AP[Analytics Engine\nSpending Models]
    end

    subgraph Firebase["Firebase (Google Cloud)"]
        AUTH[Firebase Auth\nJWT / Email+Password]
        FS_DB[(Firestore\nPrimary DB)]
        ST[Firebase Storage\nImages / Assets]
    end

    subgraph Algolia["Algolia"]
        IDX[Business + Post\nSearch Index]
    end

    subgraph Razorpay["Razorpay"]
        PAY[Payments API\nOrders + Webhooks]
    end

    subgraph Google["Google APIs"]
        MAPS[Maps JS API\nGeolocation]
        GEM[Gemini AI\nContent Generation]
    end

    subgraph Email["Email (Nodemailer)"]
        SMTP[SMTP Server\nOrder Emails]
    end

    NC <-->|REST / WS| NextServer
    NC -->|Client SDK| Firebase
    SC -->|Admin SDK| Firebase
    RH -->|HTTP| PyAPI
    RH -->|SDK| Razorpay
    RH -->|API Key| Google
    RH -->|SMTP| Email
    NC -->|InstantSearch| Algolia
Loading

πŸ›  Tech Stack

thikana-api

Layer Technology
Runtime Python 3.11+
Web Framework FastAPI 0.100+
ASGI Server Uvicorn
Validation Pydantic v2
Database Firebase Firestore (via firebase-admin)
Spatial pygeohash (geohash encoding)
Analytics pandas, numpy, scipy, scikit-learn
Testing pytest
Config python-dotenv

thikana-web

Layer Technology
Framework Next.js 16 (App Router)
UI Library React 19
Styling TailwindCSS v4 + Custom CSS
Animations Framer Motion
Icons Lucide React
UI Primitives Radix UI (via shadcn)
State Zustand + Immer
Forms React Hook Form + Zod
Database Firebase Firestore
Auth Firebase Auth
Storage Firebase Storage
Search Algolia InstantSearch
Payments Razorpay
Maps Leaflet / React-Leaflet + Google Maps
AI Google Gemini (@google/generative-ai)
Charts Recharts
PDF jsPDF + jspdf-autotable
Email Nodemailer
DnD dnd-kit
Linter Biome
Fonts Bricolage Grotesque (headings) + Manrope (body)

πŸ” Environment Variables

thikana-api .env

# Only needed if USE_MOCK=False in config.py
GOOGLE_APPLICATION_CREDENTIALS=../serviceAccountKey.json

thikana-web .env

# Firebase Client SDK
NEXT_PUBLIC_FIREBASE_API_KEY=
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
NEXT_PUBLIC_FIREBASE_PROJECT_ID=
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
NEXT_PUBLIC_FIREBASE_APP_ID=

# Firebase Admin SDK (server-side)
FIREBASE_SERVICE_ACCOUNT_KEY=   # JSON string or path

# Algolia
NEXT_PUBLIC_ALGOLIA_APP_ID=
NEXT_PUBLIC_ALGOLIA_SEARCH_KEY=
ALGOLIA_ADMIN_KEY=

# Razorpay
RAZORPAY_KEY_ID=
RAZORPAY_KEY_SECRET=
NEXT_PUBLIC_RAZORPAY_KEY_ID=

# Google Maps
GOOGLE_MAPS_API_KEY=

# Google Gemini AI
GEMINI_API_KEY=

# Email (Nodemailer)
EMAIL_HOST=
EMAIL_PORT=
EMAIL_USER=
EMAIL_PASS=

# thikana-api URL
NEXT_PUBLIC_API_URL=http://localhost:8000

πŸ’° Pricing Plans

Plan Price Key Features
Starter Free forever Geo-discovery profile, No-code website builder, Razorpay payments, Up to 50 products, Basic order management, Notifications
Pro $29/month Everything in Starter + Custom domain & SSL, Unlimited products, Recurring subscriptions, Invoice management, Advanced analytics, Algolia priority search
Franchise $99/month Everything in Pro + Unlimited outlets, Delegated owner logins, Centralized franchise dashboard, Cross-outlet analytics, Webhook + API access, Dedicated onboarding
Enterprise Custom Contact Sales β€” white-labelling, B2B supplier integrations, custom SLA

πŸ“„ Additional Documentation

File Description
thikana-api/API_DOCUMENTATION.md Full REST API reference with request/response examples
thikana-api/FRONTEND_INTEGRATION.md Guide for frontend engineers integrating the recommendation API
thikana-api/ANALYTICS_API_FRONTED_INTEG.md Analytics API frontend integration guide
thikana-web/UI_DESIGN_SYSTEM.md Thikana's design tokens, typography, colour palette
thikana-web/FRONTEND_INTEGRATION.md Frontend-specific API integration notes

Β© 2026 Thikana Technologies Pvt. Ltd. β€” Built with ❀️ for local businesses.

About

Thikana is a SaaS platform combining business discovery, website building, commerce, and payments into a single ecosystem.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages