Production marketing site for GiX System AI — a deep-tech company building machine-learning models and intelligent EDA solutions for semiconductor engineering.
Built with Next.js 16 (App Router), React 19, TypeScript, and Tailwind CSS v4. Deployed on Vercel. Contact inquiries are delivered via Brevo transactional email.
| Production | gixsystem-ai.com |
| Repository | github.com/iamjarif/gix-system-ai-website |
| Vercel project | boston-semiconductor/gix-system-ai-website |
- Quick start
- Environment variables
- Scripts
- Project structure
- Architecture
- Where to change things
- Design system
- Canvas animation
- Contact form & email
- SEO & metadata
- Deployment
- Conventions
- Troubleshooting
Requirements: Node.js 20+, npm 10+
git clone https://github.com/iamjarif/gix-system-ai-website.git
cd gix-system-ai-website
npm install
cp .env.example .env.local # then fill in Brevo values (see below)
npm run dev # http://localhost:3000The landing page is at /. Internal developer routes:
| Route | Purpose | Indexed |
|---|---|---|
/ |
Public landing page | Yes |
/tokens |
Design token reference (colors, type, spacing) | No |
/canvas |
Intelligence field sampler preview | No |
Run npm run lint and npm run build before pushing changes.
Copy .env.example to .env.local for local development. Never commit .env.local.
| Variable | Scope | Description |
|---|---|---|
BREVO_API_KEY |
Server | Brevo API key for transactional email |
BREVO_SENDER_EMAIL |
Server | Verified sender address in Brevo |
BREVO_SENDER_NAME |
Server | Display name on outbound mail (e.g. GiX System AI) |
CONTACT_RECIPIENT_EMAIL |
Server | Inbox that receives website enquiries |
All four are required for the contact form to work. Without them, POST /api/contact returns 503.
These must also be set in the Vercel project (Production and Preview environments). The sender address must be verified in the Brevo dashboard before mail will deliver.
| Command | Description |
|---|---|
npm run dev |
Start Next.js dev server |
npm run build |
Production build |
npm run start |
Serve production build locally |
npm run lint |
ESLint (Next.js config) |
npm run favicons |
Regenerate theme-aware favicons from public/gix-logo.png |
npm run deploy:preview |
Deploy preview to Vercel |
npm run deploy |
Deploy production to Vercel |
gix-system-ai-website/
├── app/ # Next.js App Router
│ ├── layout.tsx # Root layout — fonts, JSON-LD, Lenis, global shell
│ ├── page.tsx # Homepage — composes section components only
│ ├── globals.css # Design tokens (@theme) + global styles
│ ├── api/contact/route.ts # Contact form API → Brevo
│ ├── sitemap.ts # Public sitemap (homepage only)
│ ├── robots.ts # Crawl rules (blocks /api, /tokens, /canvas)
│ ├── opengraph-image.tsx # OG share image (1200×630)
│ ├── twitter-image.tsx # Twitter/X share image
│ ├── error.tsx # Route-level error boundary
│ ├── global-error.tsx # Root error boundary
│ ├── not-found.tsx # 404 page
│ ├── tokens/page.tsx # Internal design token gallery
│ └── canvas/page.tsx # Internal canvas sampler QA page
│
├── components/
│ ├── sections/ # Landing page sections (one file per section)
│ │ ├── Nav.tsx # Fixed navigation + mobile panel
│ │ ├── Hero.tsx # Hero + intelligence field background
│ │ ├── WhatWeBuild.tsx # Three pillar cards
│ │ ├── Process.tsx # LEARN → PREDICT → ACT pipeline
│ │ ├── Capabilities.tsx # Capability groups grid
│ │ ├── WhyGix.tsx # Value proposition list
│ │ ├── FinalCta.tsx # Contact section wrapper
│ │ ├── ContactForm.tsx # Client-side form island
│ │ └── Footer.tsx # Footer rail + contact info
│ ├── canvas/ # Intelligence field animation (isolated subsystem)
│ ├── ui/ # Shared primitives (Button, Container, BrandWordmark, …)
│ ├── json-ld.tsx # Organization + WebSite structured data
│ ├── lenis-provider.tsx # Smooth scroll (Lenis)
│ ├── section-snap.tsx # Section snap scrolling
│ ├── anchor-navigation.tsx # In-page anchor nav
│ ├── reveal-init.tsx # Scroll-reveal observer bootstrap
│ ├── go-to-top.tsx # Back-to-top control
│ └── site-enhancements.tsx # Deferred client enhancements (smooth cursor)
│
├── hooks/ # Shared React hooks
├── lib/
│ ├── site.ts # SITE_NAME, SITE_URL, tagline, description, keywords
│ ├── metadata.ts # Root Metadata export for layout
│ ├── constants.ts # All visible site copy + nav links + footer data
│ ├── contact.ts # Form validation + honeypot
│ ├── brevo.ts # Brevo client + HTML/text email templates
│ └── utils.ts # cn() — clsx + tailwind-merge
│
├── types/index.ts # Shared TypeScript interfaces
├── public/ # Static assets (logo, favicons)
├── scripts/generate-favicons.mjs # Favicon generation script
└── next.config.ts # Security headers, image formats
app/page.tsx is intentionally thin. It imports section components in scroll order and wires global client behaviors (RevealInit, SectionSnap, AnchorNavigation, GoToTop). Do not put section markup directly in page.tsx — add or edit files under components/sections/.
| Layer | Pattern |
|---|---|
| Section shells | Server components by default |
| Interactivity | 'use client' only where needed (canvas, forms, scroll, cursor) |
| Contact form | ContactForm.tsx client island inside server-rendered FinalCta.tsx |
| Site copy | Centralized in lib/constants.ts — not hardcoded in JSX |
- Lenis (
components/lenis-provider.tsx) — smooth scrolling, loaded in root layout - Section snap (
components/section-snap.tsx) — locks to section IDs defined inSNAP_SECTION_IDS(lib/constants.ts) - Reveal (
hooks/use-reveal.ts+reveal-init.tsx) — intersection-observer fade-in on scroll - Smooth cursor — deferred via
site-enhancements.tsxto stay off the critical path
The animated background in Hero and Final CTA is a self-contained canvas subsystem under components/canvas/. It crossfades between seven stage samplers as the user scrolls. See Canvas animation.
| Task | Location |
|---|---|
| Company name, tagline, canonical URL | lib/site.ts |
| Hero / section headlines & body copy | lib/constants.ts |
| Nav links, footer links, contact details | lib/constants.ts → NAV_LINKS, FOOTER_* |
| SEO defaults (title template, OG, robots) | lib/metadata.ts, lib/site.ts |
| Structured data (JSON-LD) | components/json-ld.tsx |
| Contact form labels & messages | lib/constants.ts → FINAL_CTA_COPY |
| Form validation rules | lib/contact.ts |
| Email HTML design | lib/brevo.ts → buildHtmlBody() |
| Brand colors & typography tokens | app/globals.css |
| Animation tuning (columns, thresholds) | components/canvas/constants.ts |
| Security headers | next.config.ts |
| Favicons | public/gix-logo.png → run npm run favicons |
Brand name: The official company name is GiX System AI (no “s” in System). Use SITE_NAME from lib/site.ts rather than hardcoding strings.
All visual values live in app/globals.css using Tailwind v4 @theme:
- Colors — Brand primary (
#064D98), accent (#3A8ADE), dark neutrals (ink,panel,line), plus semantic aliases (surface-*,text-*,border-*) - Typography — Fluid
@utilityclasses (text-display-xl,text-heading-l,text-body-m,text-eyebrow-s, …) withclamp()between 375px and 1440px viewports - Spacing — 4px base scale (
spacing-1= 4px throughspacing-56= 224px) - Radius — Sharp by default (
rounded-none)
Rule: Use token-backed Tailwind classes in components. Avoid hardcoded hex or pixel values.
Preview every token at /tokens during development.
Fonts are loaded via next/font (Geist Sans + Geist Mono) in app/layout.tsx.
Isolated under components/canvas/:
| File | Role |
|---|---|
samplers.ts |
Pure math — stage samplers (fData … fSilicon) for the seven-step narrative |
constants.ts |
Column counts, scroll thresholds, sticky offsets, crossfade tuning |
field-canvas.tsx |
Canvas renderer + requestAnimationFrame loop (client) |
canvas-preview.tsx |
Dev preview wrapper used on /canvas |
IntelligenceField.tsx |
Public export alias for FieldCanvas |
Stage narrative: data → simulation → AI → optimization → automation → decision → silicon.
Verify sampler visuals at /canvas before shipping animation changes.
ContactForm (client)
→ POST /api/contact
→ parseContactForm() lib/contact.ts validation + honeypot
→ sendContactInquiryEmail() lib/brevo.ts Brevo transactional API
- Honeypot field:
website— silently accepted if filled (bot trap) - Reply-To: Set to the visitor's submitted email so replying goes directly to them
- Email template: HTML + plain-text bodies built in
lib/brevo.ts - Subject line:
New Website Enquiry — [Visitor Name]
To test locally, fill .env.local with valid Brevo credentials and submit the form at #contact.
| Asset | File |
|---|---|
| Root metadata | lib/metadata.ts → imported in app/layout.tsx |
| Homepage overrides | app/page.tsx → export const metadata |
| Sitemap | app/sitemap.ts |
| Robots | app/robots.ts |
| OG / Twitter images | app/opengraph-image.tsx, app/twitter-image.tsx |
| JSON-LD | components/json-ld.tsx |
- Canonical domain:
https://gixsystem-ai.com(defined inlib/site.ts) - Internal routes
/tokensand/canvasarenoindexviarobots.ts - Security headers (HSTS, X-Frame-Options, etc.) are set in
next.config.ts
The project is linked to boston-semiconductor/gix-system-ai-website on Vercel. Connect this GitHub repo in the Vercel dashboard for automatic deploys on push to main.
npm run deploy:preview # preview deployment
npm run deploy # production deploymentEnsure all environment variables from Environment variables are configured in Vercel for both Production and Preview.
npm run lint— no errorsnpm run build— succeeds- Brevo env vars set on Vercel
- Sender email verified in Brevo
- Spot-check contact form on preview URL
| Area | Convention |
|---|---|
| Components | PascalCase files; explicit {ComponentName}Props interfaces |
| Hooks / utilities | kebab-case files (use-reveal.ts); camelCase exports |
'use client' |
Only where browser APIs or interactivity are required |
| Class merging | cn() from lib/utils.ts (clsx + tailwind-merge) |
| Site copy | lib/constants.ts — keep JSX free of long strings |
| Types | Shared interfaces in types/index.ts |
| Imports | @/ path alias (configured in tsconfig.json) |
| Symptom | Likely cause | Fix |
|---|---|---|
| Contact form returns 503 | Missing env vars | Fill .env.local or Vercel env settings |
| Contact form returns 502 | Brevo API error | Check API key, sender verification, Brevo logs |
| Emails not arriving | Unverified sender | Verify BREVO_SENDER_EMAIL in Brevo dashboard |
| Canvas not animating | Client component boundary | Ensure field is inside a 'use client' tree |
| Scroll snap feels wrong | Section ID mismatch | Align section id attributes with SNAP_SECTION_IDS |
| Token class not applying | Missing @theme entry |
Add primitive in app/globals.css, check /tokens |
| Build fails on Next.js APIs | Stale training data | Read node_modules/next/dist/docs/ for this Next.js version |
Private repository — © GiX System AI. All rights reserved.