The project follows Next.js App Router conventions with a clear separation of concerns: theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/gcsconsultores/gcs-website/llms.txt
Use this file to discover all available pages before exploring further.
app/ directory owns routing and server-side logic, components/ owns the UI, and lib/ owns shared data and utilities. Nothing crosses those boundaries without a deliberate reason.
Directory Tree
Key Architectural Decisions
Single source of truth in lib/site-data.ts
All business content — navigation items, solutions, sectors, strategic centers, insights, company contact details, and social proof metrics — is exported as typed TypeScript constants from a single file. Section components import only what they need. This means a content update (new sector, revised headline, changed phone number) requires editing exactly one file. No component owns raw content strings.
Autonomous section components
Each entry in
components/sections/ is a self-contained React component responsible for one visible section of the page. Sections read their own data from lib/site-data.ts and use their own internal sub-components. app/page.tsx only assembles sections in order — it contains no data, no logic, and no styles. Reordering, hiding, or replacing a section requires moving a single import line.Server Actions for form submission
The contact form uses the Next.js
'use server' directive in app/actions/lead-actions.ts instead of a separate REST API route. The submitLead() Server Action performs server-side Zod validation using the same leadSchema that validates the form on the client (defense in depth), then calls sendToCrm(). Switching CRM providers (HubSpot, Salesforce, Zoho, Pipedrive) requires changing only the sendToCrm() adapter function and the CRM_API_URL / CRM_API_KEY environment variables.AI SDK streaming with DefaultChatTransport
The
SallyChat widget uses @ai-sdk/react’s useChat hook, which communicates with app/api/sally/route.ts over a streaming HTTP connection. The route calls streamText() with google/gemini-3-flash via the Vercel AI Gateway and returns a UIMessageStreamResponse. The client receives tokens incrementally, producing a real-time typing effect without additional infrastructure.Notable Files
lib/schemas.ts — Shared Zod Validation
The same Zod schema (leadSchema) is used by both the contact form’s client-side validation and the submitLead() Server Action’s server-side check. This guarantees that the validation rules are never out of sync between layers. The schema also enforces the dataConsent: z.literal(true) field, which is required for compliance with Colombia’s Ley 1581 de 2012 (personal data protection).
lib/analytics.ts — Decoupled Event Tracking
The trackEvent() function is the single integration point for analytics. It writes to window.dataLayer (compatible with Google Tag Manager / GA4) and logs to the console in development. No section component imports a GTM or GA4 SDK directly; they only call trackEvent(). Adding a new analytics provider — PostHog, Mixpanel, Amplitude — requires a change in one file.
app/globals.css — Design Token Registry
All design tokens (brand colors, semantic colors, border radii, typography variables) are declared in a single @theme inline block using Tailwind CSS v4 syntax. This file is the authoritative source for the visual identity; component classes like bg-brand-navy or text-brand-lime are generated directly from these tokens.
components.json is the shadcn/ui configuration file. It specifies the component style (base-nova), Tailwind CSS file path, CSS variable strategy, path aliases, and icon library (Lucide). When adding new shadcn/ui components with npx shadcn add <component>, this file controls where generated files are placed and how they are styled.