TECHNICAL SPECIFICATION DOCUMENT · TSD-2025-RMC-001
Riviera Maya
Construction Co.
Web Blueprint
01
Information Architecture
Root / Homepage
/
Hero with aerial drone footage, elevator pitch, project highlights, trust signals
Proyectos / Projects
/proyectos
Filterable project gallery by type, location, status
Project Detail
/proyectos/[slug]
Full gallery, specs table, testimonial, location map, CTA contact
Servicios / Services
/servicios
Service overview, benefits grid, process timeline
Construcción Residencial
/servicios/residencial
Proyectos Comerciales
/servicios/comercial
Desarrollos Turísticos
/servicios/turistico
Remodelación
/servicios/remodelacion
Nosotros / About
/nosotros
Company story, team, certifications, values, timeline
Equipo
/nosotros/equipo
Blog / Insights
/blog
Construction tips, Riviera Maya real estate news, guides for investors
Article Detail
/blog/[slug]
Category Archive
/blog/categoria/[cat]
Contacto / Contact
/contacto
Multi-step lead form, WhatsApp CTA, Google Maps embed, social links
Legal Pages
/privacidad · /terminos
02
User Journey Mapping
🏠 Journey A — International Investor (EN) · Google → Quote Request
1
Organic Search
Google EN “construction company Riviera Maya”
2
Homepage
Drone hero + trust metrics → EN toggle
3
Projects Gallery
Filter by “Residential”, view 3 projects
4
Project Detail
Gallery, specs, budget range, testimonial
5
Contact Form
Budget + timeline multi-step form
✓
Lead Captured
CRM + WhatsApp auto-reply
Avg. 4.2 pages / session
Target CVR: 3.5%
Avg. session: 6–9 min
High-value lead type
📱 Journey B — Local Homeowner (ES) · WhatsApp Link → Portfolio Browse → Call
1
WhatsApp Referral
Friend shares link on mobile
2
Homepage Mobile
Swipeable project cards, sticky WA button
3
Servicios
Scroll “Remodelación” section
4
Cotización Rápida
Single-page quick quote widget
✓
Click-to-Call
tel: deep link + WA chat open
Mobile-only journey
Target CVR: 6%
Session: 2–4 min
High-freq lead type
🔍 Journey C — Hotel Developer (B2B) · Blog SEO → Trust Loop → RFP Form
1
Blog Article
“Costos construcción hotelera Tulum 2025”
2
Related Articles
Internal linking loop: 3 articles
3
Servicios Turístico
Case studies, certifications, team
4
Nosotros + Team
Credibility layer: 15+ yrs, certifications
5
RFP Form
File upload + detailed project brief
✓
Enterprise Lead
Email + CRM + sales notification
Avg. 7.8 pages / session
Target CVR: 1.8%
Session: 15–25 min
Highest-value lead
03
Data Architecture
Project
CMS Collection
idUUIDPrimary key
slugStringURL slug, unique, auto-gen
title_es / title_enStringi18n titles
typeEnumresidential|commercial|hotel|remodel
statusEnumcompleted|in_progress|upcoming
locationStringTulum|Playa del Carmen|Cancún…
coordinatesGeoPointlat/lng for map embed
area_m2NumberTotal built area
duration_monthsNumberConstruction time
budget_rangeEnumbudget|mid|premium|luxury
images[]Asset[]Gallery (before/after)
hero_video_urlStringDrone footage, optional
description_es/enRichTextFull project narrative
client_testimonial_idFK → TestimonialOptional
tags[]String[]SEO + filter tags
featuredBooleanHomepage highlight
published_atDateTimeISO 8601
Service
CMS Collection
idUUIDPrimary key
slugStringURL path segment
name_es / name_enStringDisplay name
iconSVG AssetService icon
short_desc_es/enStringCard summary (140 chars)
body_es/enRichTextFull content
process_steps[]JSON[]{step, title, desc}
related_projects[]FK → Project[]Cross-ref
Testimonial
CMS
idUUID
client_nameStringDisplay name
client_locationStringCity, Country
avatarAssetPhoto, optional
quote_es / quote_enTextMax 300 chars
ratingInt 1–5Star rating
project_idFK → ProjectOptional link
Lead
DB Only · Private
idUUID
name / email / phoneStringPII — encrypted at rest
project_typeEnumSame as Project.type
budget_rangeEnum
messageTextSanitized
sourceEnumcontact|project|rfp|widget
utm_*StringCampaign tracking
statusEnumnew|contacted|qualified|closed
created_atDateTimeAuto-set server-side
BlogPost
CMS CollectionSEO Engine
id / slugUUID/StringUnique URL
title_es / title_enStringMax 60 chars for SEO
excerpt_es/enString155 chars meta desc
body_es / body_enRichTextMDX or Portable Text
cover_imageAsset1200×630 OG standard
author_idFK → TeamMemberSchema.org author
category / tags[]String / String[]Taxonomy
reading_time_minNumberAuto-calculated
published_at / updated_atDateTimeFor sitemap + schema
04
API Surface Definition
Authentication Strategy
Public read endpoints → No auth required (CDN cached). Write endpoints (lead submission) → API route with CSRF token + rate limiting (10 req/min/IP). Admin endpoints → JWT Bearer + role-based (admin|editor). CMS API → CMS service token in server-side env only, never exposed to client.
CSRF ProtectionJWT AdminRate Limit: 10 rpmHoneypot FieldsreCAPTCHA v3
Internal API Routes (Next.js /api)
POST
/api/leads
Submit contact / quote / RFP form. Validates schema (Zod), stores to DB, sends notification email, triggers WhatsApp webhook.
🔒 CSRF + reCAPTCHA + Rate Limit
GET
/api/projects?type=&location=&status=&page=
Filtered, paginated project list for gallery. Cached at edge for 60s.
🌐 Public · Cache-Control: max-age=60
GET
/api/projects/[slug]
Single project detail. ISR revalidation on CMS publish hook.
🌐 Public · ISR revalidate: 60s
GET
/api/blog?category=&page=&lang=
Paginated blog listing with i18n filtering.
🌐 Public
POST
/api/revalidate
CMS webhook trigger — revalidates ISR pages on content publish.
🔒 Secret header: X-Revalidate-Token
GET
/api/sitemap.xml
Dynamic sitemap generation with all published projects, blog posts, service pages. Updated on each revalidation.
🌐 Public
External Integrations
📱 WhatsApp Business API
Send automated reply to new leads within 30s. Template messages in ES + EN. Webhook endpoint: /api/webhooks/whatsapp. Auth: Meta App Secret verification.
📧 Email (Resend / SendGrid)
Transactional email for lead notifications (to sales team) + confirmation (to client). DKIM + SPF configured on domain. Templates in React Email.
📊 Google Analytics 4
Event tracking: form_start, form_submit, whatsapp_click, phone_click, project_view, gallery_interact. Server-side GA4 Measurement Protocol for key conversion events.
🗺️ Google Maps Platform
Maps JavaScript API for project location display. Geocoding API for address normalization. Static Maps API for OG image fallback. Key restricted to domain.
📷 Cloudinary / Imgix
Image CDN with automatic WebP/AVIF conversion, responsive srcset generation, lazy loading. Transformation API for thumbnail generation.
🔔 CRM (HubSpot / Pipedrive)
Lead pushed via REST API on form submit. Contact deduplication, deal creation, owner assignment by project type. Webhook for status sync back.
05
Component Inventory (30+ UI Components)
| # | Component | Category | Purpose | Key Props |
|---|---|---|---|---|
| 01 | NavBar | Layout | Sticky top nav with logo, links, language toggle, CTA button. Transparent on hero, solid on scroll. | transparent, lang, ctaLabel |
| 02 | Footer | Layout | 4-column footer: logo+tagline, sitemap links, contact info, social icons + legal links. | columns[], socialLinks[] |
| 03 | HeroSection | Page Section | Full-viewport drone video hero with overlaid headline, subline, dual CTAs (Contact / Projects). | videoUrl, headline, ctaPrimary, ctaSecondary |
| 04 | ProjectCard | Card | Image-first card: project thumbnail, type badge, location, title, hover overlay with CTA. | project, variant (compact|full) |
| 05 | ProjectGallery | Page Section | Masonry or CSS grid of ProjectCards. Includes filter bar (type, location, status). Infinite scroll or pagination. | projects[], filters, layout |
| 06 | FilterBar | Controls | Pill-style filter buttons for project gallery. Animated active state. URL-synced state. | options[], active, onChange |
| 07 | ImageLightbox | Overlay | Full-screen image gallery with swipe support, keyboard nav, image counter, close button. | images[], initialIndex, onClose |
| 08 | BeforeAfterSlider | Interactive | Drag slider revealing before/after project images. Touch-enabled for mobile. | before, after, labels |
| 09 | StatsBar | Trust Signal | Animated counters: years experience, projects completed, m² built, satisfaction rate. | stats[], animate |
| 10 | TestimonialCarousel | Trust Signal | Swipeable testimonial carousel with avatar, quote, stars, client info. Auto-advance every 6s. | testimonials[], autoplay |
| 11 | ServiceCard | Card | Icon + service name + 2-line description + “Ver más” link. Hover lift effect. | service, iconSize, variant |
| 12 | ProcessTimeline | Page Section | Numbered horizontal or vertical steps showing construction process. Animated on scroll. | steps[], orientation |
| 13 | ContactForm | Form | Multi-step form: Step 1 (project type) → Step 2 (details + budget) → Step 3 (contact info). Progress indicator. | onSubmit, steps[], lang |
| 14 | QuickQuoteWidget | Form | Single-page condensed form for mobile journeys. 4 fields max. Sticky on mobile scroll. | onSubmit, lang |
| 15 | WhatsAppFAB | CTA | Floating WhatsApp button. Opens WA with pre-filled message. Visible on all pages. Pulse animation. | phone, message, position |
| 16 | MapEmbed | Media | Google Maps embed for project location or office. Lazy-loaded iframe with placeholder. | coordinates, zoom, marker |
| 17 | VideoPlayer | Media | Inline video player with custom controls. Autoplay muted on hero, click-to-play elsewhere. Poster image fallback. | src, poster, autoplay, muted |
| 18 | LanguageToggle | i18n | ES / EN switcher in navbar. Preserves current path. Stores preference in localStorage. | current, onChange |
| 19 | Breadcrumb | Navigation | Schema.org-marked breadcrumb trail on inner pages. Auto-generated from route structure. | items[], schema |
| 20 | SectionTitle | Typography | Eyebrow label + h2 heading + optional subline. Centered or left-aligned variants. | eyebrow, title, subtitle, align |
| 21 | TeamMemberCard | Card | Photo + name + role + brief bio + LinkedIn link. Used on Nosotros/Equipo page. | member, variant (compact|full) |
| 22 | CertBadge | Trust Signal | Certification or award logo badge with tooltip. Grid layout on Nosotros page. | image, name, year, href |
| 23 | BlogCard | Card | Cover image + category tag + reading time + title + excerpt + author + date. Linked card. | post, variant (featured|standard) |
| 24 | ArticleBody | Content | Rich text renderer for blog posts. Handles headings, callouts, image embeds, tables, code blocks. | content, lang |
| 25 | TableOfContents | Navigation | Sticky sidebar ToC for long blog articles. Auto-generated from h2/h3 headings. Active state on scroll. | headings[], stickyOffset |
| 26 | RelatedPosts | Content | 3-card row of related blog articles at end of post. Based on category + tags. | posts[], currentId |
| 27 | ProjectSpecsTable | Data | Key/value table: area, duration, type, location, budget range, certifications. On project detail page. | specs{} |
| 28 | StickyContactBar | CTA | Bottom-fixed bar on mobile with phone, WA, and form buttons. Hides on desktop. | phone, whatsapp, formHref |
| 29 | CookieBanner | Legal | GDPR-lite cookie consent banner. Accept/Reject. Stores decision in localStorage. Blocks GA until accepted. | onAccept, onReject, lang |
| 30 | SkeletonLoader | UX | Animated shimmer placeholder for ProjectCard, BlogCard, TeamCard during data fetch. | variant, count, height |
| 31 | ScrollProgress | UX | Thin progress bar at top of viewport indicating scroll depth. Used on blog articles. | color, height |
| 32 | AnchorButton | Atom | Primary / secondary / ghost button variants. Loading state spinner. Accessible aria labels. | variant, size, loading, href, onClick |
| 33 | FormInput / Select / Textarea | Atom | Branded form field atoms with floating label, error state, helper text. Used in all forms. | label, error, required, disabled |
| 34 | Toast / AlertBanner | Feedback | Success/error/warning toasts for form submit feedback. Auto-dismiss after 5s. | type, message, duration |
| 35 | SEOHead | Meta | Next.js Metadata component wrapper. Injects title, description, OG tags, canonical, hreflang, schema JSON-LD per page. | meta{}, schema{}, lang |
06
Page Blueprints (Wireframe Descriptions)
🏠 Homepage Template: home
NavBar100vw × 72px · transparent→solid
HeroSection — Full Viewport Video100vw × 100vh
StatsBar — Animated Counters100% × 96px
Featured Projects Grid (3 cards)12-col grid
Services Overview (icon cards)4-col grid
Process Timeline (5 steps)horizontal scroll mobile
Testimonial Carouselsingle-col centered
CTA Band — Contact / WhatsAppfull-bleed bg accent
Blog Preview (3 latest posts)3-col grid
Footer4-col · 240px
📐 Project Detail Template: project-detail
NavBarsolid · with breadcrumb below
BreadcrumbHome › Proyectos › [Name]
Hero Image / Video (16:9)100% × auto · drone shot
Project Title + Type Badge + Locationh1 + meta row
Project Description (RichText)prose · max-w 680px
Image Gallery (masonry)click → Lightbox
Before/After Sliderif applicable
Testimonial Quoteif linked
ProjectSpecsTablesticky sidebar
MapEmbed300px map
Quick Contact CTAform or WA button
Related Projects (3 cards)same type/location
Footerstandard
📞 Contact Page Template: contact
NavBarsolid
Page Hero (h1 + subline)short · 280px · bg image blur
Multi-Step ContactForm3 steps · progress bar
Contact Info Blockphone · email · address
WhatsApp Direct Linklarge CTA button
Office Hourstable L-V 8–18h
Social LinksIG · FB · YT · LinkedIn
MapEmbed (Office Location)full-width 400px
Footerstandard
📝 Blog Article Template: article
NavBar + ScrollProgress barsolid
Article Header: category, title h1, excerpt, author, date, reading timecentered · max-w 720px
Cover Image1200×630 · aspect-video
ArticleBody (RichText)prose · 680px max-w
TableOfContentssticky top-24 sidebar
Lead Magnet CTAinline sidebar card
RelatedPosts (3 cards)same category
Footerstandard
07
Technology Stack Recommendation
Frontend
Next.js 15App Router, ISR, i18n routing
TypeScriptType safety + DX
Tailwind CSS v4Utility-first, JIT
Framer MotionScroll animations, transitions
React Hook Form + ZodForm handling + validation
CMS
Sanity.io v3Structured content, GROQ, live preview, i18n plugin
Portable TextRich text serialization
Sanity StudioCustom admin UI embedded at /studio
Database
Neon PostgreSQLServerless, branching, for leads + analytics
Drizzle ORMType-safe queries, migrations
Upstash RedisRate limiting + session cache
Hosting & CDN
VercelEdge network, ISR, preview deployments
Cloudflare CDNAdditional edge caching, DDoS protection
CloudinaryImage CDN: WebP/AVIF, transformations
Dev & Ops
GitHub + ActionsCI/CD, preview environments
SentryError tracking + performance monitoring
PlaywrightE2E tests: forms, navigation, i18n
BiomeLinting + formatting
Email / Comms
ResendTransactional email API
React EmailBranded email templates
Meta WA Business APIWhatsApp auto-response
Analytics
Google Analytics 4Event tracking, conversions
Vercel AnalyticsPrivacy-first Web Vitals
Google Search ConsoleSEO performance
HotjarHeatmaps on contact + project pages
08
Performance Benchmarks
<1.2s
LCP — Largest Contentful Paint
Google threshold: <2.5s · Target: <1.2s
<100ms
INP — Interaction to Next Paint
Google threshold: <200ms
<0.05
CLS — Cumulative Layout Shift
Google threshold: <0.1 · Target: <0.05
95+
Lighthouse Score (mobile)
Perf · Accessibility · Best Practices · SEO
📦 Bundle Targets
Initial JS bundle: <150KB gzipped
Total page weight (homepage): <800KB
Hero video: lazy-loaded, poster first, <4MB
Images: WebP/AVIF via Cloudinary, lazy-loaded
Fonts: preconnect + font-display:swap + subset
Total page weight (homepage): <800KB
Hero video: lazy-loaded, poster first, <4MB
Images: WebP/AVIF via Cloudinary, lazy-loaded
Fonts: preconnect + font-display:swap + subset
⚡ Caching Strategy
Static pages (SSG): CDN cache indefinitely + ISR revalidation
API routes (GET): Cache-Control max-age=60, s-maxage=300
Images: Cache-Control: max-age=31536000, immutable
Lead API (POST): no-store
HTML: stale-while-revalidate
API routes (GET): Cache-Control max-age=60, s-maxage=300
Images: Cache-Control: max-age=31536000, immutable
Lead API (POST): no-store
HTML: stale-while-revalidate
📱 Mobile-First Optimizations
Responsive images with srcset + sizes
Video: preload=none on mobile, autoplay only on desktop
Touch targets: min 44×44px
Sticky contact bar replaces sidebar CTA on mobile
Critical CSS inlined; non-critical deferred
Video: preload=none on mobile, autoplay only on desktop
Touch targets: min 44×44px
Sticky contact bar replaces sidebar CTA on mobile
Critical CSS inlined; non-critical deferred
🌐 Connectivity Resilience
Service Worker: cache shell + API responses offline
Progressive image loading: blur placeholder → full res
Form: optimistic UI + retry logic on network failure
WhatsApp CTA: native app deep link (no JS dependency)
Progressive image loading: blur placeholder → full res
Form: optimistic UI + retry logic on network failure
WhatsApp CTA: native app deep link (no JS dependency)
09
SEO Framework
URL Convention
— Lowercase, kebab-case slugs only
— Spanish as primary locale (no /es/ prefix)
— English at /en/[path] (hreflang alternate)
— No trailing slashes
— Max 3 path segments depth
Examples:
/proyectos/villa-residencial-tulum-2024
/servicios/construccion-comercial
/blog/costos-construccion-riviera-maya-2025
/en/projects/villa-residential-tulum-2024
Hreflang Strategy
<link rel=”alternate” hreflang=”es-MX”
href=”https://domain.mx/proyectos/[slug]” />
<link rel=”alternate” hreflang=”en”
href=”https://domain.mx/en/projects/[slug]” />
<link rel=”alternate” hreflang=”x-default”
href=”https://domain.mx/proyectos/[slug]” />
Canonical Tags
— All pages have explicit canonical
— Paginated archives: canonical → page 1
— Filter combinations: canonical → base /proyectos
— Avoid duplicate content on /en/ variants
Robots & Crawl Control
User-agent: *
Disallow: /studio/
Disallow: /api/
Disallow: /privacidad
Disallow: /terminos
Sitemap: https://domain.mx/api/sitemap.xml
Meta Structure Template
title: “{Project Name} — Construcción en
{Location} | {Company}”
Max: 60 chars
description: “{150-char benefit-driven description
including location + service keyword}”
Max: 155 chars
og:title: same as title
og:description: same as description
og:image: 1200×630 Cloudinary-served image
og:type: website | article
og:locale: es_MX | en_US
Schema.org JSON-LD (per page)
Homepage → LocalBusiness + Organization
{
“@type”: “GeneralContractor”,
“name”: “…”,
“address”: { “@type”: “PostalAddress”,
“addressLocality”: “Playa del Carmen”,
“addressRegion”: “Quintana Roo”,
“addressCountry”: “MX” },
“geo”: { “latitude”: …, “longitude”: … },
“aggregateRating”: { “@type”:
“AggregateRating”, “ratingValue”: “4.9” }
}
Project Detail → CreativeWork + ItemList
Blog Article → Article + BreadcrumbList
Services → Service + HowTo (process steps)
Breadcrumbs → BreadcrumbList (all inner pages)
Target Keyword Clusters
Primary:
“construcción Riviera Maya”
“empresa constructora Tulum”
“construction company Playa del Carmen”
Long-tail:
“cuánto cuesta construir casa Riviera Maya”
“constructora hotel boutique Tulum”
“residential construction Playa del Carmen”
Local modifiers:
Tulum · Playa del Carmen · Akumal ·
Puerto Morelos · Bacalar · Cancún
🗺️ Dynamic Sitemap Generation
Sitemap generated at /api/sitemap.xml via Next.js route handler. Includes: all published projects (with lastmod from published_at), all blog posts (with lastmod from updated_at), all service pages, all static pages. Priority values: homepage 1.0, services 0.9, projects 0.8, blog 0.7, static 0.3. Changefreq: homepage=weekly, projects=monthly, blog=weekly. Submitted automatically to Google Search Console via Indexing API on each ISR revalidation trigger.
TSD-2025-RMC-001 · Platform Architecture Blueprint · Generated for Figma Make Implementation
Senior Platform Architect · Web Infrastructure Division
Senior Platform Architect · Web Infrastructure Division
