Charts Prototypes
Concentric Analytics Prototype is a multi-tenant analytics dashboard built as an assignment for Infinite Locus, showcasing modern web development practices with Next.js and TypeScript. It features multi-tenant routing, seamless localization powered by intlayer, static data visualizations, and a polished login page. The project demonstrates a clean, scalable architecture suited for real-world analytics applications.

Concentric Analytics Prototype is a full-featured analytics dashboard components developed as a technical assignment for Infinite Locus. Built with Next.js and TypeScript, the project serves as a proof-of-concept for a scalable, multi-tenant analytics platform — demonstrating how modern web technologies can be combined to deliver a clean, production-ready user experience.
Key Features
- Multi-tenant routing: The application supports isolated routing per tenant, enabling a single deployment to serve multiple organizations with distinct data contexts and URL namespaces.
- Localization with intlayer: Internationalization is handled via intlayer, providing a structured, type-safe approach to managing translations and locale-aware content across the dashboard.
- Static charts: The dashboard includes pre-rendered data visualizations that illustrate key analytics metrics, offering a clear and immediate overview of business performance.
- Login page: A dedicated authentication entry point provides a polished, user-friendly login experience consistent with the overall design language of the application.
Tech Stack
The prototype is built on Next.js, leveraging its App Router for flexible, file-based routing and server-side rendering capabilities. TypeScript is used throughout the codebase to enforce type safety and improve developer experience, while intlayer handles all localization concerns in a structured, maintainable way.
Overall, Concentric Analytics Prototype reflects a commitment to clean architecture, developer ergonomics, and a thoughtful user experience — making it a strong foundation for a production analytics product.
A tenant is a route segment, a theme, and a feature list
Multi-tenancy here isn't a database column checked on every query — it's the URL. Every page lives under src/app/[tenant]/[locale]/..., so the tenant is resolved before a single component renders, not inferred from a session afterward. Each tenant record (tenant.ts) carries its own theme object — primaryColor, secondaryColor, font, radius, spacing — and its own features array (charts, integrations, notifications, users), so two tenants hitting the same route can render genuinely different colors, corner radii, and navigation depending on what's actually in their config, not just their data.
The two demo tenants make this concrete: orgA gets a warm/gray theme with just the charts feature, orgB gets the inverse palette plus users and notifications on top. Same codebase, same route tree, different config file — that's the whole mechanism.
tenantConfig.ts loads that map from public/tenant.json with an in-memory cache and a hardcoded fallback config baked into the module itself, so a missing or malformed file degrades to two working demo tenants instead of a broken build. Login is tenant-scoped too — src/data/users.ts's demo accounts (admin, and one test user per org) each carry a tenant field, so authenticating as orgA's test user doesn't grant access to orgB's dashboard.
What 'per-tenant, per-locale routing' costs to get right
Nesting locale under tenant ([tenant]/[locale]/page.tsx) rather than the more common [locale]/[tenant] order was a deliberate choice for this prototype: tenant identity gates everything else — theme, feature flags, auth — so it has to resolve first in the segment tree, with locale as a property of that tenant's session rather than a peer of it.
