Back to blog

First Pindo post

what is excerpt ?

4 min read

Conversation engine

As of now, the frontend team manages one active product, SMS under Pindo.io, with a second service, Pindo.ai, currently in developmentβ€”and more coming soon.

As the Lead Frontend Engineer, my responsibility is to ensure that the frontend architecture scales efficiently as we continue to expand into a multi-service platform.


βœ… Strategic Moves So Far

  1. Migration to Next.js App Router
    We moved from a traditional React.js setup to Next.js with the App Router, unlocking server components, layout nesting, route groups, and improved routing flexibility.

  2. Styling: From styled-components to Tailwind CSS
    We adopted Tailwind CSS to boost DX and UI consistency while eliminating runtime CSS parsing.

  3. Rethinking Monorepo
    Initially, we explored monorepo architecture to manage services independently. However, due to the tight coupling of services under one user domain (a single Pindo organization), this was reconsidered. The services behave more like modules of one unified platform, not standalone products.


🧠 Product Philosophy

  • All services are under one Pindo umbrella.

  • A user must belong to a Pindo organization to access any service.

  • Services are modularβ€”users can opt-in or out depending on their needs.

  • Based on this, we decided to keep all services in a single Next.js application, leveraging the App Router's modular routing.


πŸ—οΈ Proposed Folder Structure

Here's the updated app structure for clarity:

src/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ layout.tsx             # Root layout
β”‚   β”œβ”€β”€ page.tsx               # Root landing page
β”‚   β”œβ”€β”€ sms/                   # Service 1
β”‚   β”‚   β”œβ”€β”€ page.tsx
β”‚   β”‚   β”œβ”€β”€ layout.tsx
β”‚   β”‚   └── components/
β”‚   β”œβ”€β”€ ai/                    # Service 2 (e.g., Pindo.ai)
β”‚   β”‚   β”œβ”€β”€ page.tsx
β”‚   β”‚   └── components/
β”‚   β”œβ”€β”€ telephony/             # Service 3
β”‚   └── settings/              # Org-wide settings
β”œβ”€β”€ shared-ui/                 # Common UI components
β”œβ”€β”€ shared-utils/              # Reusable helpers and utilities
β”œβ”€β”€ middleware.ts              # Route protection via feature flags
└── lib/                       # API clients, auth utils, etc.

πŸ₯‰ Dynamic Feature Access via Feature Flags

We will use feature flags (e.g., via @vercel/flags) to:

  • Dynamically show/hide pages and components

  • Restrict access to service routes (e.g., /telephony) based on user permissions

  • Inject flags at the middleware level using secure server-side checks based on the JWT/session

This keeps unauthorized users from accessing features they aren’t subscribed to, both visually and programmatically.


πŸ“ App Layout Representation

[Pindo Platform]
    |
    β”œβ”€β”€ Home (/) ──▢ Shared Dashboard
    β”œβ”€β”€ /sms ──────▢ SMS Service
    β”œβ”€β”€ /ai ───────▢ AI Assistant (Pindo.ai)
    β”œβ”€β”€ /telephony ──▢ Telephony Service
    β”œβ”€β”€ /settings ──▢ Org/User Settings
    └── Middleware β†’ Checks Auth + Feature Flags

🌍 High-Level Architecture

+---------------------------+
|         Browser           |
+------------+--------------+
             |
             v
+---------------------------+
|      Next.js Frontend     |
|  - App Router             |
|  - TailwindCSS            |
|  - Middleware (flags)     |
|  - Modular Services       |
+------------+--------------+
             |
             v
+---------------------------+
|         API Layer         |
|   - Auth (JWT/session)    |
|   - User Profile          |
|   - Feature Flags         |
|   - Service Data          |
+------------+--------------+
             |
             v
+---------------------------+
|         Backend           |
|  - Auth DB                |
|  - Services Logic         |
|  - Feature Control        |
|  - Billing                |
+---------------------------+

πŸ“‚ High-Level Diagram: Frontend Folder Structure

src/
β”œβ”€β”€ app/                          # Next.js App Router base
β”‚   β”œβ”€β”€ layout.tsx                # Root layout
β”‚   β”œβ”€β”€ page.tsx                  # Root homepage/dashboard
β”‚   β”‚
β”‚   β”œβ”€β”€ sms/                      # Service 1: SMS
β”‚   β”‚   β”œβ”€β”€ page.tsx
β”‚   β”‚   β”œβ”€β”€ layout.tsx
β”‚   β”‚   └── components/
β”‚   β”‚
β”‚   β”œβ”€β”€ ai/                       # Service 2: AI Assistant (Pindo.ai)
β”‚   β”‚   β”œβ”€β”€ page.tsx
β”‚   β”‚   └── components/
β”‚   β”‚
β”‚   β”œβ”€β”€ telephony/                # Service 3: Telephony
β”‚   β”‚   β”œβ”€β”€ page.tsx
β”‚   β”‚   └── components/
β”‚   β”‚
β”‚   └── settings/                 # Org/user-wide settings
β”‚       └── page.tsx
β”‚
β”œβ”€β”€ shared-ui/                   # Common UI components across all services
β”œβ”€β”€ shared-utils/                # Shared utility functions
β”œβ”€β”€ lib/                         # Auth, API clients, constants, helpers
β”œβ”€β”€ middleware.ts                # Route protection + dynamic flag checking
└── types/                       # Global TypeScript types/interfaces

⚠️ Notes & Considerations

  • Scalability: Keeping services in one app but isolated by folders and flags allows faster onboarding, testing, and deployments.

  • Security: Feature flags must be enforced both client-side (UX) and server-side (middleware + backend authorization).

  • Performance: Ensure only the needed service code is loaded (optimize with dynamic imports or route groups).