WINDOW LAND
Premium glass & aluminium for Dubai's skyline.
Full-stack monorepo for a Dubai-based premium glass and aluminium installation company. Next.js marketing site (25 pages) + admin panel, Node.js Express CMS API, and a Python FastAPI quote calculator — all wired through a Turborepo monorepo with CI/CD.

From brief to production system.
The client had no online presence and was losing leads to competitors who showed up in 'glass installation Dubai' searches. They needed a site that visually matched their premium positioning, an admin panel non-technical staff could update without engineers, a quote calculator for inbound leads, and serious UAE-market SEO.
Architected as a Turborepo monorepo with three deployable services: a Next.js 14 frontend (25 pages, animations, admin panel with JWT auth), a Node.js Express API for content management, and a Python FastAPI microservice for quote calculations. GSAP and Framer Motion for the luxe feel. Full LocalBusiness JSON-LD and geo-targeting for UAE search.
Production-ready site at window-land.vercel.app awaiting windowland.ae DNS cutover. Admin team can update services and project galleries without a developer. Quote engine and WhatsApp lead capture wired and tested.
How it shipped, week by week.
Discovery
Calls with the Dubai-based CEO. Mapped services, gathered brand assets, wrote the IA and SEO keyword plan for UAE.
Frontend
Monorepo scaffolding, Next.js App Router, design system, all 25 marketing pages with GSAP animations on the hero and section reveals.
Admin + API
JWT auth flow, role-based admin panel, Express CMS API with MongoDB models, image upload pipeline through Cloudinary.
Quote engine
Python FastAPI microservice for square-meter quote calculations, with Postgres for pricing tables versioned over time.
SEO + ship
LocalBusiness JSON-LD, sitemap, OG images, GitHub Actions CI workflows, Vercel + Railway deploy guide handed to client.
What it does. How it's built.
Features
- 25-page marketing site with cinematic Dubai imagery
- Admin panel with JWT auth and role-based access
- Python-powered quote calculator (m², material, finish)
- Project gallery with category filters
- Service catalog organized by vertical
- Multi-channel contact (WhatsApp, email, phone)
- LocalBusiness JSON-LD for Google rich results
- Cloudinary-backed media pipeline
- GSAP scroll animations + Framer Motion page transitions
Architecture
- 01Turborepo monorepo with shared TypeScript types
- 02apps/web — Next.js 14 App Router + Tailwind
- 03apps/api — Node.js Express + MongoDB Atlas
- 04apps/python — FastAPI quote service + Neon Postgres
- 05Upstash Redis for rate limiting + session cache
- 06Cloudinary for image CDN with automatic transforms
- 07GitHub Actions CI: typecheck, lint, build per app
- 08Vercel for frontend, Railway for backend services
Annotated excerpts.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from db import get_pricing_for
app = FastAPI()
class QuoteRequest(BaseModel):
service: str # e.g. "curtain_wall"
width_m: float
height_m: float
finish: str # "powder_coated" | "anodised" | "polished"
glass_type: str # "tempered" | "laminated" | "low_e"
@app.post("/quote")
async def quote(req: QuoteRequest):
area = req.width_m * req.height_m
if area <= 0 or area > 200:
raise HTTPException(400, "Area out of range")
pricing = await get_pricing_for(req.service)
if pricing is None:
raise HTTPException(404, "Service not priced")
finish_mult = pricing["finish_multipliers"][req.finish]
glass_mult = pricing["glass_multipliers"][req.glass_type]
base_aed = pricing["base_aed_per_m2"] * area
total_aed = round(base_aed * finish_mult * glass_mult, 2)
return {
"service": req.service,
"area_m2": round(area, 2),
"total_aed": total_aed,
"pricing_version": pricing["version"],
}import { jwtVerify, type JWTPayload } from "jose";
import { cookies } from "next/headers";
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET!);
export type Role = "admin" | "editor" | "viewer";
export interface AdminClaims extends JWTPayload {
sub: string;
role: Role;
}
export async function getAdmin(required?: Role): Promise<AdminClaims> {
const token = (await cookies()).get("admin_token")?.value;
if (!token) throw new Error("Not authenticated");
const { payload } = await jwtVerify<AdminClaims>(token, SECRET);
if (required && rank(payload.role) < rank(required)) {
throw new Error(`Requires ${required}, has ${payload.role}`);
}
return payload;
}
function rank(r: Role) {
return { viewer: 0, editor: 1, admin: 2 }[r];
}Ali built our entire web presence from scratch — three services in one repo, all working together. The admin panel means my team can update content without ever calling a developer. Exactly what we needed to compete in the Dubai market.
Continue browsing
Have a project like this in mind? Let's talk.
Send me a brief and I'll respond within 24 hours.