Aug 2026 — Present

Dream Elevators (Pvt) Ltd — Marketing Website

A single-page company profile and projects showcase for a vertical transportation company — "We Lift Your Dream."

Marketing site for Dream Elevators (Pvt) Ltd — a single-page company profile (hero, about, vision & mission, chairman's message, services, projects, why-choose, contact, FAQ) plus a projects listing page. Server-first App Router with typed i18n content, an SMTP-backed contact/newsletter pipeline, and a build-once-deploy-as-is CI/CD pipeline to Vercel.

Tech Stack

Core Framework

  • Next.js 16 (App Router, Turbopack)
  • React 19
  • TypeScript (strict) — tsc --noEmit + next typegen in CI

Styling & UI

  • Tailwind CSS v4 (@theme tokens), tw-animate-css for keyframes
  • Base UI for most controls; Radix UI + cmdk power the phone-input country picker
  • lucide-react, react-icons

Forms & Email

  • react-phone-number-input, sonner toasts, client-side validation
  • Nodemailer over SMTP, called from a route handler
  • dotted-map — a dotted world map rendered to SVG on the server

Content & i18n

  • File-based JSON dictionaries, no CMS
  • Typed loader keyed by route locale (next/root-params)

Tooling & CI/CD

  • ESLint 9, Prettier, prettier-plugin-tailwindcss
  • pnpm 10
  • GitHub Actions — CI (format/lint/typecheck/build) + CD (Vercel build artifact, manual production approval, smoke test, rollback workflow)

Features

Marketing Site

  • Single-page company profile — hero, about, vision & mission, chairman's message, services, projects, why-choose, contact, FAQ
  • A separate projects listing page
  • Hero swaps a portrait mobile image for a desktop one at the sm breakpoint
  • Contact section renders a dotted-map SVG as a faint full-bleed background, computed once and module-cached

Contact & Newsletter

  • Contact form and newsletter signup share one SMTP transport that degrades gracefully — returns null (not an error) when SMTP env vars are unset, so client-side validation still works
  • Both routes rate-limit per IP + email (contact: 5/5min, newsletter: 3/hour) and reply with 429 + Retry-After when throttled
  • Every request/response state surfaces as a sonner toast
  • Admin notification + customer acknowledgement emails on both pipelines

Internationalization

  • proxy.ts middleware redirects any non-prefixed, non-asset path to a locale prefix, resolved from Accept-Language
  • getDictionary(namespace) resolves the active locale from route params and dynamically imports the matching JSON, typed at the call site
  • Adding a locale is additive — extend the locale list, add a dictionaries-map branch, drop in a mirrored i18n/<locale>/ folder

Architecture & Design Patterns