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
- 01Server-first App Router — sections are async Server Components that read their copy at render time; only leaf interactive bits (the contact form, hero video, ui/ primitives) are Client Components
- 02Fully static output — every locale-scoped page declares generateStaticParams() and pre-renders to static HTML at build time; the only server-rendered route is the SMTP contact handler
- 03Single source of truth for imagery (common/image-data.ts) — static imports give next/image intrinsic dimensions and a blur placeholder for free; raw /public paths are kept separate for non-image media
- 04Theming is one @theme inline block mapping Tailwind utilities to CSS variables, defined once on a permanent .dark root — no light theme, no toggle
- 05Build-once-deploy-as-is CI/CD — the Vercel build artifact from CI is uploaded and deployed unchanged, so there's no drift between what's checked and what ships; production deploys sit behind a manual GitHub Environment approval gate, with a workflow_dispatch rollback to any prior deployment