All Sites - Foundation Meta Document¶
Version: 2.1.0
Date: 2026-01-21
Purpose: Shared configuration, assets, and block library for all company-solution suite sites
Design Philosophy: CICD (Canonical, Idempotent, Commutative, Decomposable)
Static Build Pattern (CRITICAL)¶
The product-domain retrieval and mutation model now lives under docs/products/.
This shared foundation document should only retain cross-site rules. Product-specific retrieval behavior, product collections, properties, and related mutation patterns should be documented in the product domain.
For current product-domain guidance, see:
docs/products/retrieval-intents.mddocs/products/mutation-intents.mddocs/products/properties.mddocs/products/product-collections.md
Deployment Architecture¶
Decision: Hybrid Path-Based with Independent Apps (Option C)¶
Adopted: 2026-01-21
Rationale: Best balance of SEO (single domain authority), operational flexibility (independent deploys), and risk containment (isolated failures).
Scope & Intent¶
This architecture means:
- Not one giant runtime app.
- Yes one unified web experience under a single host (www.omnivoltaic.com) with independent deployable apps behind it.
- Each site remains its own build/deploy unit, but navigation, branding, and governance are shared.
URL Structure¶
| Site | Path | App Folder | Cloudflare Pages Project |
|---|---|---|---|
| Company Hub | www.omnivoltaic.com/ |
apps/isr/company |
company.omnivoltaic.pages.dev |
| Off-Grid | www.omnivoltaic.com/off-grid |
apps/isr/off-grid |
off-grid.omnivoltaic.pages.dev |
| Cross-Grid | www.omnivoltaic.com/cross-grid |
apps/isr/cross-grid |
cross-grid.omnivoltaic.pages.dev |
| Productive Use | www.omnivoltaic.com/productive |
apps/isr/productive |
productive.omnivoltaic.pages.dev |
| E-Mobility | www.omnivoltaic.com/mobility |
apps/isr/mobility |
mobility.omnivoltaic.pages.dev |
Architecture Principles¶
- Single Domain: All sites served under
www.omnivoltaic.comfor consolidated SEO authority - Independent Apps: Each site is a separate Next.js static export with its own Cloudflare Pages project
- Path Routing: Cloudflare Workers routes paths to appropriate Pages projects
- Independent Deploys: Each app can be deployed/rolled back independently
- Shared Design System: All apps import from
@dirac/uxi-design-systemfor brand consistency - Canonical URL Policy: Path URLs are canonical (
/off-grid,/cross-grid, etc.); any subdomain aliases must301to canonical paths - One-Page-One-Canonical: Every indexable page declares exactly one canonical URL
SEO Governance (Mandatory)¶
- Canonical strategy:
- Canonical format:
https://www.omnivoltaic.com/<site>/<page> - If aliases exist (for campaigns or migration), enforce permanent redirects to canonical paths.
- Search Console ownership:
- Maintain Domain property for
omnivoltaic.comto track all subdomains and protocols. - Sitemaps:
- Keep sitemap index at root host (for example:
https://www.omnivoltaic.com/sitemap.xml). - Include each site section sitemap (
/off-grid/sitemap.xml,/mobility/sitemap.xml, etc.). - Internal linking:
- Cross-site links should point to canonical path URLs, not Pages
.pages.devorigins. - Section quality parity:
- Every section must meet quality standards; weak sections can be evaluated independently by search systems even under one host.
Operations Governance (Mandatory)¶
- Monorepo build isolation:
- Each Pages project should use path-based build triggers (watch paths) to avoid unnecessary full-suite rebuilds.
- Rollback isolation:
- Roll back the affected site project only; do not roll back unrelated sections.
- Current platform boundary:
- Cloudflare Pages currently documents a maximum of 5 projects per monorepo.
- Current suite already uses 5 projects (
company,off-grid,cross-grid,productive,mobility). - Growth plan trigger:
- If a 6th site is added, perform architecture review before implementation (split repo strategy or alternative deployment topology).
Next.js Configuration (Per App)¶
Each ISR app must configure:
// next.config.js
const nextConfig = {
output: 'export',
trailingSlash: true,
images: { unoptimized: true },
basePath: '/off-grid', // Set per app (empty for company)
};
basePath values:
- company: (empty string - root)
- off-grid: /off-grid
- cross-grid: /cross-grid
- productive: /productive
- mobility: /mobility
Cloudflare Workers Router¶
export default {
async fetch(request) {
const url = new URL(request.url);
const path = url.pathname;
if (path.startsWith('/off-grid')) return fetch('https://off-grid.omnivoltaic.pages.dev' + path);
if (path.startsWith('/mobility')) return fetch('https://mobility.omnivoltaic.pages.dev' + path);
if (path.startsWith('/cross-grid')) return fetch('https://cross-grid.omnivoltaic.pages.dev' + path);
if (path.startsWith('/productive')) return fetch('https://productive.omnivoltaic.pages.dev' + path);
return fetch('https://company.omnivoltaic.pages.dev' + path); // default: company hub
}
}
Build Commands¶
# From monorepo root
pnpm --filter company build # → apps/isr/company/out/
pnpm --filter off-grid build # → apps/isr/off-grid/out/
pnpm --filter cross-grid build # → apps/isr/cross-grid/out/
pnpm --filter productive build # → apps/isr/productive/out/
pnpm --filter mobility build # → apps/isr/mobility/out/
Deployment Workflow¶
- Push to GitHub → Triggers Cloudflare Pages auto-build for changed app(s)
- Build →
pnpm install && pnpm --filter <app> build - Deploy → Static
out/folder deployed to Pages CDN - Route → Cloudflare Worker routes requests to correct Pages project
Cross-Site Navigation¶
Shared header component must use absolute paths (not relative) for cross-site links:
// ✅ Correct - works across all sites
<a href="/off-grid">Off-Grid Solutions</a>
<a href="/mobility">E-Mobility</a>
// ❌ Wrong - relative paths break across sites
<a href="../off-grid">Off-Grid Solutions</a>
Rejected Alternatives¶
| Option | Why Rejected |
|---|---|
| A: Single Integrated App | All-or-nothing deploys; one bug blocks all sites; no independent scaling |
| B: Subdomain-based | Subdomains treated as separate sites by Google; dilutes SEO authority |
External References¶
- Cloudflare Pages monorepos: https://developers.cloudflare.com/pages/configuration/monorepos/
- Cloudflare Workers CI/CD monorepo guidance: https://developers.cloudflare.com/workers/ci-cd/builds/advanced-setups/
- Google Search Console Domain property (domain + subdomains): https://support.google.com/webmasters/answer/10431861?hl=en
- Google site names behavior (domain/subdomain, not subdirectory): https://developers.google.com/search/docs/appearance/site-names
- Google site reputation abuse clarification (sections can be treated independently): https://developers.google.com/search/blog/2024/11/site-reputation-abuse
Solution Site Pattern (Canonical and Idempotent)¶
Philosophy: This pattern is canonical (not derived from other sites) and idempotent (produces consistent results regardless of application history).
Applies To: All solution sites (off-grid, cross-grid, mobility, productive)
Site Structure¶
Pages (Required):
1. Root (/) → Redirect to /products/
2. Products grid (/products)
3. Product detail (/products/[slug])
4. Articles grid (/articles)
5. Article detail (/articles/[slug])
Configuration File: src/config/site.ts
export const SITE_NAME = 'Solution Name';
export const SITE_TAGLINE = 'Brief description';
export const BFF_URL = 'https://dirac-fed-dev.omnivoltaic.com/marketing';
export const PRODUCT_COLLECTIONS = ['collection-key-1', 'collection-key-2'];
export const navigation = [
{ name: 'Products', href: '/products' },
{ name: 'Articles', href: '/articles' },
];
export const footerNavigation = {
company: [
{ name: 'Company Home', href: 'https://omnivoltaic.com' },
{ name: 'About Us', href: '#' },
{ name: 'Careers', href: '#' },
{ name: 'Press', href: '#' },
{ name: 'Contact', href: 'https://forms.office.com/r/45vCYswcf4' },
],
resources: [
{ name: 'Become a Partner', href: 'https://forms.office.com/r/45vCYswcf4' },
{ name: 'Datasheets', href: '#' },
{ name: 'Knowledge Base', href: '#' },
],
connect: [
{ name: 'LinkedIn', href: 'https://www.linkedin.com/company/omnivoltaic/' },
{ name: 'X / Twitter', href: 'https://x.com/omnivoltaic' },
{ name: 'Facebook', href: 'https://www.facebook.com/omnivoltaic' },
{ name: 'Instagram', href: 'https://www.instagram.com/omnivoltaic' },
],
solutions: [
{ name: 'E-Mobility', href: '/mobility' },
{ name: 'Off-Grid Energy', href: '/off-grid' },
{ name: 'Cross-Grid', href: '/cross-grid' },
{ name: 'Productive Use', href: '/productive' },
],
};
Products Grid Page (/products)¶
Purpose: Multi-collection product showcase with collapsible sections.
Layout: - Dark theme (bg-gray-900) - Header: Logo + navigation (Products, Articles) - Hero section with site name and tagline - Product collections displayed as collapsible sections
Collapsible Sections:
- Each collection wrapped in native <details>/<summary> element
- First collection open by default (open={index === 0})
- Remaining collections collapsed
- Chevron indicator rotates on expand/collapse
- Collection heading shows: name + product count
Product Card:
- Product image (mainMedia from BFF)
- Product name
- Collection badge (collection name)
- "View Details" link → /products/[productKey]
Grid Layout: - Responsive: 1 col (mobile) → 2 cols (sm) → 3 cols (lg) → 4 cols (xl) - Gap: gap-x-6 gap-y-10
Data Source: BFF getProductCollections query
query GetProductCollections {
getProductCollections {
name
collectionKey
products {
name
productKey
mainMedia
}
}
}
Footer: Default footer (see Default Footer section)
Product Detail Page (/products/[slug])¶
Purpose: Product details with Bill of Properties (BoP) and Bill of Materials (BoM) hierarchy.
Layout: - Dark theme - Minimal header: Logo + back link - Two-column layout: - Left: Image gallery (mainMedia + additional images) - Right: Product info sections (decomposable)
CICD Pattern: Decomposable sections + composition
Atomic Section: Product Properties (BoP)¶
Purpose: Always-visible product specifications table
Content: - Section heading: "Product Properties" (cyan #00FFFF) - Hairline divider (border-gray-800) - BoP table: key-value pairs from BFF - Format: Property name (left) | Value (right) - Table style: Tailwind prose tables
Data Source:
bop { key value }
Visual Treatment: - No expand/collapse (always visible for quick scanning) - Clean table layout with alternating row backgrounds - Property keys in gray-400, values in white
Atomic Section: Items Included (BoM)¶
Purpose: Expandable list of product components
Content:
- Hairline divider
- Section heading: "Items Included" (cyan #00FFFF)
- BoM list as expandable disclosure (<details>/<summary>)
- Each item: thumbnail (40x40) + item name + quantity
- First item open by default
Data Source:
bom { name quantity thumbnail }
Interaction:
- Native <details> element for accessibility
- Chevron indicator rotates on expand/collapse
- First item open to show affordance
Atomic Section: Product CTAs¶
Purpose: Download and quote request actions
Content: - Download Datasheet (secondary button) - Request Quote (primary button)
Button Styles:
- Secondary: Gray outline, white text, hover → cyan
- Primary: Navy bg, cyan border/text (.cta-button-primary)
Links:
- Datasheet: /datasheets/[productKey].pdf or Cloudinary URL
- Quote: Partnership form https://forms.office.com/r/45vCYswcf4 with pre-filled product name
Composition: Product Detail Page (Full)¶
Structure: 1. Minimal header (Logo + back link) 2. Two-column layout: - Left: Image gallery - Right: - Product name (h1, cyan) - Product Properties section (atomic, always visible) - Items Included section (atomic, expandable) - Product CTAs section (atomic) 3. Minimal footer (copyright only)
Data Source: BFF getProduct query
query GetProduct($productKey: String!) {
getProduct(productKey: $productKey) {
name
mainMedia
bop { key value }
bom { name quantity thumbnail }
}
}
CICD Properties: - Canonical: Each section self-contained - Idempotent: Same data = same page - Commutative: Section order can be changed (design decision) - Decomposable: Can omit sections (e.g., no BoM if product has none, no CTAs on preview pages)
Articles Grid Page (/articles)¶
Purpose: Article collection showcase.
Layout: - Dark theme - Header: Logo + navigation (Products, Articles) - Hero section with "Articles" heading - Article grid
Article Card: - Hero image (from article frontmatter) - Category badge (eyebrow-badge class) - Article title - Excerpt (first 150 chars of body) - Published date - Author name - "Read More →" link (secondary-link class)
Grid Layout: - Responsive: 1 col (mobile) → 2 cols (md) → 3 cols (lg) - Gap: gap-8
Data Source: Transitional local article artifacts in oves-sites/docs/articles/*.md
- Collection intent currently staged in docs/articles/collections/*.yaml
- Parse YAML frontmatter + markdown body
- Cleaned article artifacts must be persisted into CMS through the BFF
Footer: Default footer
Article Detail Page (/articles/[slug])¶
Purpose: Full article view with typography-focused layout.
Layout: - Dark theme - Minimal header: Logo only (no navigation links) - Centered content column (max-w-4xl) - Prose typography (Lato Hairline, weight 100)
Content Structure: - Category badge (eyebrow-badge) - Article title (text-4xl, cyan #00FFFF) - Subtitle (if present) - Metadata bar: Author name, published date - Hero image (full-width, 16:9 aspect) - Article body (markdown → HTML, prose classes) - Feature image (if present, mid-article)
Typography: - Headings: Montserrat, cyan #00FFFF - Body: Lato Hairline (weight 100), light gray - Links: text-indigo-400 (prose-a class) - Code blocks: syntax highlighting
Footer: Minimal footer (copyright only)
Theme & Styling¶
CSS Import Order (MANDATORY - Cascade Intent)
/**
* CSS Import Order - CICD Compliance
*
* NOT commutative: Order defines cascade layers
* Idempotent: Same order = same result on re-application
* Decomposable: Each layer is atomic, can be reasoned about independently
*
* Intent Labels:
* - Layers 1-3: Foundation (Tailwind base system)
* - Layer 4: Accumulative (adds brand tokens without conflicts)
* - Layer 5: Corrective (overrides for site-specific needs)
*/
/* Layer 1: Reset - Browser defaults → consistent baseline */
@import 'tailwindcss/base';
/* Layer 2: Components - Reusable UI patterns (buttons, cards, forms) */
@import 'tailwindcss/components';
/* Layer 3: Utilities - Atomic classes (text-*, bg-*, flex, grid, etc.) */
@import 'tailwindcss/utilities';
/* Layer 4: Brand Tokens (Accumulative) - Design system colors, typography, spacing */
@import './oves-brand.css';
/* Layer 5: Theme Overrides (Corrective) - Site-specific final say on conflicts */
@import './theme-overrides.css';
Brand Colors: - Primary: Cyan #00FFFF (headings, CTAs, links hover) - Secondary: Navy #002552 (backgrounds, CTA default) - Neutrals: Gray scale (50-950)
Typography: - Headings: Montserrat (sans-serif) - Body: Lato (sans-serif) - Article body: Lato Hairline (weight 100)
Component Classes:
- .cta-button-primary — primary CTA button (navy bg, cyan border/text)
- .secondary-link — text link with hover (white → cyan)
- .eyebrow-badge — category badge (cyan text, subtle ring)
Next.js Configuration¶
next.config.js:
const nextConfig = {
output: 'export', // Static site generation
trailingSlash: true, // /products/ not /products
images: { unoptimized: true }, // Cloudinary handles optimization
basePath: '/solution-name', // e.g., '/off-grid', '/mobility'
};
layout.tsx:
- Favicon: https://res.cloudinary.com/oves/image/upload/v1657359850/logos/oves_logo_round_h50_jg8h8m.png
- Metadata: site name, description, Open Graph tags
Build & Deploy¶
Static Export:
pnpm --filter solution-site build
# Generates out/ folder with static HTML/CSS/JS
Cloudflare Pages: - One project per site (off-grid.omnivoltaic.pages.dev) - Auto-deploy on Git push - Cloudflare Workers router for path-based routing
Dev Ports: - Company: 3100 - Mobility: 3101 - Off-Grid: 3102 - Cross-Grid: 3103 - Productive: 3104
Pre-Deployment Checklist¶
Purpose: Comprehensive checklist ensuring all sites are production-ready before deploying to Cloudflare Pages.
Phase 1: Data Sources & Content Governance¶
Products (BFF Source)
- [ ] Product collection intent documented in docs/products/product-collections.md
- [ ] Product collection images uploaded to Cloudinary (placeholder URLs replaced with actual images)
- [ ] Product collection images added to app code as static/local references (until BFF collections endpoint implemented)
- [ ] BFF getProductCollections query tested and returning stable data
- [ ] Product slugs normalized (ampersands → "and", lowercased)
- [ ] Product images hosted on Cloudinary with proper transformations
- [ ] BoP (Bill of Properties) and BoM (Bill of Materials) data complete for all products
Articles (Local → BFF Migration)
- [ ] All staged articles in oves-sites/docs/articles/*.md conform to the article-domain contract
- [ ] Article collection images uploaded to Cloudinary
- [ ] Article slugs normalized per slug rules (ampersands → "and")
- [ ] Hero images selected and hosted on Cloudinary
- [ ] Feature images selected where applicable
- [ ] Article metadata complete: articleKey, title, subtitle, author, publishedAt, categories, tags
- [ ] Article collections defined in docs/articles/collections/*.yaml
- [ ] Cleaned article artifacts persisted into CMS through BFF
- [ ] Local article access code remains scaffold-compatible during transition
Phase 2: Site Implementation & Consistency¶
Per-Site Checklist (Apply to: company, off-grid, cross-grid, mobility, productive)
- [ ] Site spec complete in oves-sites/docs/sites/<site>.md
- [ ] next.config.js configured: output: 'export', correct basePath, trailingSlash: true
- [ ] src/config/site.ts defines: SITE_NAME, BFF_URL, PRODUCT_COLLECTIONS, navigation, footerNavigation
- [ ] Header: logo + nav links only (no CTA buttons)
- [ ] Footer: Contact → partnership form URL, Become a Partner → partnership form URL
- [ ] Theme CSS imports: tailwindcss → oves-brand.css → theme-overrides.css
- [ ] Brand colors verified: cyan (#00FFFF), navy (#002552)
- [ ] Typography: Montserrat (headings), Lato (body)
- [ ] All pages return 200 in dev mode
- [ ] pnpm build succeeds with output: 'export'
- [ ] Generated out/ folder contains all expected routes
Cross-Site Consistency
- [ ] Article detail pages use identical layout across all sites
- [ ] Product detail pages use identical BoP/BoM hierarchy across all sites
- [ ] Footer widgets match all-sites.md Default Footer spec
- [ ] Footer "Solutions" widget present on ALL sites with links to all 4 solution sites (mandatory)
- [ ] Company homepage includes 4 solution sections with CTAs to each sub-site (mandatory)
- [ ] All site-specific deviations documented in respective docs/sites/<site>.md
Phase 3: Content Quality & Editorial¶
Articles - [ ] All articles reviewed for technical accuracy - [ ] Spelling and grammar checked - [ ] Product names use correct trademarks (OVES™, LUMN™, ovCamp™, etc.) - [ ] External links verified (no 404s) - [ ] Images have descriptive alt text - [ ] Code blocks have language hints for syntax highlighting - [ ] Frontmatter complete and valid YAML
Visual Assets
- [ ] Hero images: 1920x1080 minimum, optimized for web
- [ ] Feature images: 800x600 recommended, Cloudinary transformations applied
- [ ] Product images: Cloudinary URLs with c_fill transformation
- [ ] Logo usage: primary logo in headers, no logo proliferation in content
Phase 4: Technical Readiness¶
Build & Deploy
- [ ] All apps/isr/* apps build successfully: pnpm --filter <app> build
- [ ] No out/ folders committed to Git (build artifacts excluded via .gitignore)
- [ ] Cloudflare Pages projects created for each app (5 total)
- [ ] GitHub integration configured for auto-deploy
- [ ] Cloudflare Workers router deployed with path-based routing
SEO & Performance
- [ ] Canonical URLs defined for all pages (path-based: /off-grid, /mobility, etc.)
- [ ] Sitemap generated for each app
- [ ] Meta descriptions written for all pages
- [ ] Open Graph images configured
- [ ] Lighthouse performance score > 90 (desktop)
Operational
- [ ] Session journals updated in dirac-uxi/.session.md and oves-sites/.session.md
- [ ] Architecture decisions codified in all-sites.md
- [ ] All experiments cleaned up and documented (no "quick and dirty" code in production)
- [ ] Deployment runbook created (if not using Cloudflare auto-deploy)
Article Development Strategy¶
Article-domain guidance no longer belongs in this shared foundation document.
Use these article-domain documents instead:
docs/articles/object-intents.mddocs/articles/collection-intents.mddocs/articles/cms-persistence.md
The key cleanup rule is:
- local article markdown and local collection YAML are staging artifacts
- cleaned article-domain artifacts must be persisted into CMS through the BFF
- current scaffold compatibility may continue temporarily, but should not define long-term authority
Theme System Architecture¶
Design Workflow (Mandatory)¶
Two-Stage Process:
1. Design Intent → Document in oves-sites/docs/shared/all-sites.md (this file)
2. Implementation → Code in packages/uxi-design-system/themes/oves-brand.css
3. Application → Apps explicitly import theme via @import "@dirac/uxi-design-system/themes/oves-brand.css"
Implementation Requirements (Mandatory)¶
❌ NEVER use ad-hoc inline styles or arbitrary Tailwind utilities for themed elements
✅ ALWAYS use designated theme classes:
| Element Type | Theme Class | DON'T Use |
|---|---|---|
| Primary CTA Buttons | .cta-button-primary |
bg-indigo-500, hover:bg-indigo-400 |
| Secondary Links | .secondary-link |
text-indigo-400 hover:text-indigo-300 |
| Category/Eyebrow Badges | .eyebrow-badge |
bg-gray-800 px-3 py-1 text-gray-300 |
| Article Body Content | .article-body |
text-gray-300 with inline font-weight |
| Headings (h1-h6) | Auto-applied via theme | text-white override |
| Navigation/Footer Links | Auto-applied via theme | Custom hover colors |
Enforcement: - Code reviews must verify theme class usage - New UI elements → Update this doc → Add to theme CSS → Use class - No exceptions without explicit approval and documentation
Brand Assets¶
Logos¶
- Primary Logo (Header):
https://res.cloudinary.com/oves/image/upload/v1657359850/logos/oves_logo_words_h50_w3axpd.png - Logo Round/Mark:
https://res.cloudinary.com/oves/image/upload/v1657359850/logos/oves_logo_round_h50_jg8h8m.png
Favicon¶
- Favicon (All Sites):
https://res.cloudinary.com/oves/image/upload/v1657359850/logos/oves_logo_round_h50_jg8h8m.png - Format: PNG, 50x50px (scales to standard favicon sizes)
- Implementation: Add to Next.js layout metadata or HTML
<head>
Note: Logo files are hosted on Cloudinary account oves
Brand Colors¶
- Primary (Logo Brand Color): Cyan (#00FFFF) - matches OVES logo
- Secondary: Navy Blue (#002552) - logo background
- Neutrals: Gray scale (50-950)
- Accent: Light cyan (#5DFFFF)
- Dark Mode: Native support required
Note: All title colors, primary CTAs, and brand elements should use the logo cyan color (#00FFFF) for consistency
UI Component Styling¶
Primary CTA Buttons¶
Design Intent:
- Default State:
- Background: Navy Blue (#002552)
- Text: Cyan (#00FFFF)
- Border: 2px solid Cyan (#00FFFF)
- Hover State:
- Background: Cyan (#00FFFF)
- Text: Navy Blue (#002552)
- Border: 2px solid Cyan (#00FFFF)
- Transition: 0.3s ease for smooth color toggle
- Class Name: .cta-button-primary (for implementation reference)
Link Hover Behavior¶
Design Intent: - Header Navigation Links: On hover → Cyan (#00FFFF) - Footer Links (all sections): On hover → Cyan (#00FFFF) - Principle: Consistent brand highlight color across all interactive text elements
Title/Heading Colors¶
Design Intent: - All headings (h1-h6): Cyan (#00FFFF) - Footer widget titles (h3): Cyan (#00FFFF) - same as other section titles - Eyebrow labels: Cyan (#00FFFF) - Principle: Logo color used for all prominent text elements to reinforce brand identity
Secondary Links¶
Design Intent:
- Appearance: Plain text link (no border, no background)
- Default State: White text
- Hover State: Cyan (#00FFFF) text
- Usage: Non-primary navigation links (e.g., "View Solutions →")
- Class Name: .secondary-link (for implementation reference)
Eyebrow Badges¶
Design Intent:
- Appearance: Rounded pill/badge above hero titles
- Text: Cyan (#00FFFF)
- Background: Transparent or subtle dark
- Border: Thin ring in muted color (no hover effect)
- Usage: Taglines or category labels (e.g., "Electrify the World!")
- Behavior: Static (no hover interaction)
- Class Name: .eyebrow-badge (for implementation reference)
Article Body Text¶
Design Intent: - Font: Lato Hairline (weight 100) for paragraphs and list items - Font Size: Base (16px) - Color: Light gray (rgb(229, 231, 235)) - Line Height: Relaxed for readability - Usage: Article detail page body content - Principle: Ultra-light weight creates elegant reading experience on dark backgrounds
Block Theming Pattern¶
Purpose: Enable reusable blocks to adapt to light or dark contexts via explicit opt-in props rather than ad-hoc class overrides.
Theme Prop Convention¶
All themeable blocks MUST support a theme prop with these values:
| Value | Background | Text Primary | Text Secondary | Accent Color | Default |
|---|---|---|---|---|---|
'light' |
white/gray-50 | gray-900 | gray-500/600 | indigo | Yes |
'dark' |
gray-900 | white | gray-300/400 | cyan | No |
Implementation Rules:
1. Default to 'light' — backward compatible with existing light-mode usages
2. Explicit opt-in — consumers must pass theme="dark" for dark contexts
3. No CSS cascade reliance — theme switching via conditional class application, not parent dark-mode class inheritance
4. Accent color alignment — dark mode uses cyan (#00FFFF) to match brand; light mode uses indigo
Themeable Blocks¶
| Block | Theme Support | Notes |
|---|---|---|
ProductGridSimple |
theme?: 'light' \| 'dark' |
Product listing grid with badge support |
ProductDetailExpandable |
theme?: 'light' \| 'dark' |
Product detail with expandable sections |
Usage Example (dark-mode company site):
<ProductGridSimple products={products} theme="dark" />
<ProductDetailExpandable {...productProps} theme="dark" />
Adding Theme Support to New Blocks:
1. Add theme?: 'light' | 'dark' to props interface
2. Default to 'light' in destructuring
3. Create isDark = theme === 'dark' helper
4. Apply conditional classes: isDark ? 'bg-gray-900 text-white' : 'bg-white text-gray-900'
5. Document in this table above
Collapsible UI Pattern¶
Purpose: Enable multi-section pages to collapse/expand sections without JavaScript, improving scannability for long lists.
Native HTML Pattern¶
Use native <details>/<summary> elements — zero JS, fully accessible, keyboard-navigable.
<details open={isFirstSection} className="group">
<summary className="cursor-pointer list-none flex items-center justify-between">
<span>Section Title</span>
<svg className="w-5 h-5 transition-transform group-open:rotate-180" ...>
<path d="M19 9l-7 7-7-7" />
</svg>
</summary>
{/* Section content */}
</details>
Styling Rules:
- list-none — removes default disclosure triangle
- group-open:rotate-180 — chevron rotates 180° when open
- First section open by default; remaining sections collapsed
Current Usage: - Off-grid products grid — collapsible product collection sections
Contact Information¶
Social Media¶
- LinkedIn: https://www.linkedin.com/company/omnivoltaicglobal
- Twitter/X: https://x.com/Omnivoltaic
- Facebook: https://www.facebook.com/OmnivoltaicGlobal
- Instagram: https://www.instagram.com/omnivoltaicglobal
- TikTok: https://www.tiktok.com/@omnivoltaic_global
Contact Details¶
- Email: team_sales@omnivoltaic.com
- Phone: (Not publicly listed)
- Address: Design and R&D in the USA with main distribution centres in China, Philippines, Kenya and Togo
- Partnership Form: https://forms.office.com/r/45vCYswcf4
Default Components¶
Default Header¶
Pattern: Logo + Horizontal Navigation Menu
Structure: - Left: Logo (links to homepage) - Center/Right: Navigation menu (site-specific pages) - Style: Clean, minimal, sticky on scroll - Dark mode: Adaptive colors
Navigation: Each site defines own internal navigation menu
CTA Policy (Mandatory):
- No CTA buttons in the header nav bar. The header must remain clean: logo + navigation links only.
- Partnership/contact CTAs are served exclusively through the footer:
- Footer → Company widget → Contact link → Partnership form (https://forms.office.com/r/45vCYswcf4)
- Footer → Resources widget → Become a Partner link → Same partnership form
- Hero sections on landing pages may include inline CTA buttons (e.g., "Partner with Us") — these are page content, not navigation chrome.
Company Site: Solution Sections (MANDATORY)¶
Purpose: The company site (/) serves as the suite's entry point, showcasing all four solution portfolios with prominent CTAs.
Pattern: Hero + Alternating Feature Sections (TailwindUI "Feature section with screenshot on alternating sides")
Structure:
// In apps/isr/company/src/app/page.tsx
const solutions = [
{
eyebrow: 'E-Mobility',
heading: 'Electric Mobility Solutions',
description: 'Electric mobility solutions for urban transport',
image: 'https://res.cloudinary.com/oves/image/upload/...',
ctaLabel: 'Explore E-Mobility',
ctaLink: '/mobility', // or http://localhost:3101 in dev
},
{
eyebrow: 'Off-Grid Energy',
heading: 'Solar Home Systems and Energy Access',
description: 'Solar home systems and energy access for off-grid communities',
image: 'https://res.cloudinary.com/oves/image/upload/...',
ctaLabel: 'Explore Off-Grid',
ctaLink: '/off-grid', // or http://localhost:3102 in dev
},
{
eyebrow: 'Cross-Grid',
heading: 'Hybrid Solar and Grid Solutions',
description: 'Hybrid solar and grid solutions for reliable power',
image: 'https://res.cloudinary.com/oves/image/upload/...',
ctaLabel: 'Explore Cross-Grid',
ctaLink: '/cross-grid', // or http://localhost:3103 in dev
},
{
eyebrow: 'Productive Use',
heading: 'Solar-Powered Tools for Income Generation',
description: 'Solar-powered tools and equipment for small business empowerment',
image: 'https://res.cloudinary.com/oves/image/upload/...',
ctaLabel: 'Explore Productive Use',
ctaLink: '/productive', // or http://localhost:3104 in dev
},
];
Layout:
- Alternating left/right image placement (even index = image left, odd = image right)
- Large hero images (min 1200px wide)
- CTA button using .cta-button-primary class
Purpose: Drive traffic to each solution site, establish company as multi-portfolio provider.
Default Footer¶
Architecture: 6 independently hydrated zones, props-driven with defaults.
Source of truth: oves-sites/docs/shared/footer-widgets.yaml
Implementation: @dirac/uxi-design-system/components/SiteFooter.tsx
Presets: @dirac/uxi-design-system/lib/footer-widgets.ts
6-Zone Model¶
| Zone | Prop | Type | Default Preset |
|---|---|---|---|
| Logo column | logo? |
FooterLogoProps { src, alt, description } |
Omnivoltaic logo + brand description |
| Widget column 1 | widget1? |
FooterWidget { title, items[] } |
company_sub (includes "Company Home") |
| Widget column 2 | widget2? |
FooterWidget { title, items[] } |
resources |
| Widget column 3 | widget3? |
FooterWidget { title, items[] } |
connect |
| Widget column 4 | widget4? |
FooterWidget { title, items[] } |
solutions |
| Copyright bar | copyright? |
FooterCopyrightProps { holder, tagline } |
Omnivoltaic + "Sustainable Energy for All" |
All props are optional. Omitting a prop uses the built-in default.
Widget Presets¶
company_top -- Company site widget1 (no "Company Home" self-link)
- About Us, Careers, Press, Contact
company_sub -- Solution site widget1 default (includes "Company Home")
- Company Home → /, About Us, Careers, Press, Contact
resources -- widget2 default
- Become a Partner → partnership form, Blog/Articles → /articles, Support, Documentation
connect -- widget3 default
- LinkedIn, Twitter/X, Facebook, Instagram
solutions -- widget4 default (MANDATORY on all sites)
- E-Mobility → /mobility, Off-Grid Energy → /off-grid, Cross-Grid → /cross-grid, Productive Use → /productive
Per-Site Usage¶
Company site -- overrides widget1 only:
// src/config/site.ts
import { companyTopWidget } from '@dirac/uxi-design-system/lib/footer-widgets';
export const footerWidget1 = companyTopWidget;
// In page files:
<SiteFooter widget1={footerWidget1} siteName={SITE_NAME} devLabel="Port 3100" />
Solution sites -- all defaults, zero config:
// In page files:
<SiteFooter siteName={SITE_NAME} devLabel="Port XXXX" />
CICD Properties¶
- Canonical: Widget presets defined once in design system, derived from YAML source of truth
- Idempotent: Same props = same footer
- Commutative: Widget zone order is fixed (columns 1-4), but content is independently swappable
- Decomposable: Each zone is atomic, can be overridden independently without affecting others
Layout¶
- Full Footer: Logo + 4 widget columns + copyright bar (used on: grid pages)
- Minimal Footer: Copyright only (used on: detail pages)
- Custom: Override any subset of zones via props
Copyright & Branding¶
- Trademark notice: "OVES™ · OMNIVOLTAIC® · LUMN™ · OmniTech™ are trademarks of Omnivoltaic Company"
- Copyright: "Omnivoltaic © [YEAR] | Sustainable Energy for All"
- Dev mode indicator: "Development Mode - Port [XXXX]" (development only)
Design Tokens¶
Typography Scale¶
- Display: 6xl (60px)
- Heading 1: 4xl (36px)
- Heading 2: 3xl (30px)
- Heading 3: 2xl (24px)
- Body Large: xl (20px)
- Body: base (16px)
- Small: sm (14px)
- Tiny: xs (12px)
Spacing Scale¶
- Container max-width: 1280px
- Section padding: py-16 (64px) or py-24 (96px)
- Element gap: gap-4 (16px) to gap-8 (32px)
- Card padding: p-6 (24px) or p-8 (32px)
Breakpoints¶
- Mobile: < 768px
- Tablet: 768px - 1024px
- Desktop: > 1024px
- Wide: > 1280px
Content Guidelines¶
Voice & Tone¶
- Professional yet approachable
- Confident but not arrogant
- Africa-focused and context-aware
- Solution-oriented rather than feature-focused
- Impact-driven messaging
Writing Style¶
- Short, clear sentences
- Active voice preferred
- Benefit-focused descriptions
- Avoid jargon when possible
- Provide context for technical terms
Terminology Standards¶
- "Omnivoltaic" - Always capitalized, never abbreviated to "OV" in public-facing content
- "Solutions" - Not "products" at corporate level
- "Clean energy" - Preferred over "renewable energy"
- Regional entities - Use full name on first mention: "Omnivoltaic Kenya (OVK)"
- "Company-solution suite" - Internal development term only
Article Categories¶
Purpose: Provide a stable, multi-dimensional classification system for articles so that each article can be positioned using a small, curated set of category objects.
Model:
- Categories are first-class objects with stable IDs, names, descriptions, and optional media.
- An article may reference zero or more category IDs in a categories array.
- The inverse view ("which articles belong to this category?") is derived at build or query time.
Category Definitions¶
| ID | Name | Description |
|---|---|---|
category:technology-and-innovation |
Technology and Innovation | Technical architectures, engineering trade-offs, system design, and innovation-focused content. |
category:product-features-and-updates |
Product Features and Updates | Articles about specific OVES solutions, feature announcements, and product-oriented deep dives. |
category:sustainability-and-impact |
Sustainability and Impact | Environmental and social impact, SDG alignment, and long-term sustainability narratives. |
category:customer-stories-and-field-insights |
Customer Stories and Field Insights | Stories and insights from customers, field deployments, and on-the-ground learnings. |
category:events-and-activations |
Events and Activations | Conferences, trade shows, campaigns, and key brand activations. |
category:careers-and-culture |
Careers and Culture | Roles, hiring, internal culture, and team-related stories. |
Article front-matter pattern (example):
---
articleKey: ART-2026-0001
slug: omnivoltaic-emobility-solutions-ovego
# ...other fields...
categories:
- category:technology-and-innovation
- category:product-features-and-updates
---
- Editors choose from the approved category IDs above.
- New categories must be added here first, then used in article front-matter.
Collections¶
Purpose: Define reusable, named selections of articles for specific sites or experiences.
Model:
- Collections are first-class objects that live outside individual articles.
- Each collection has an id, name, optional scope/site, description, and an articles list of slugs.
- Articles do not store collection membership; collections point to articles only.
Initial collections (reference YAML):
collections:
- id: emobility
name: e-Mobility
scope: mobility
description: Articles used on the e-Mobility site's /articles view and related pages.
articles:
- omnivoltaic-emobility-solutions-ovego
- omnivoltaic-emobility-paving-the-way-for-sustainable-urban-transportation
- electric-drive-train-heart-and-soul-of-emobility
- path-to-ev-adoption-the-small-is-the-giant
- id: off_grid
name: Off-Grid
scope: off-grid
description: Articles used on off-grid power /articles views and related pages.
articles:
- oasis-series-offgrid-integrated-acdc-power-solutions
- offgrid-power-convergence-technologies
- offgrid-power-basics-omnivoltaics-revolutionary-solar-solutions
- off-grid-world-electrification-is-hapenning
- id: cross_grid
name: Cross-Grid
scope: cross-grid
description: Articles focused on grid-interactive and cross-grid topics.
articles: []
- id: productive_use
name: Productive-Use
scope: off-grid
description: Articles that focus on productive use of energy.
articles:
- solar-productive-use-of-energy-with-omnivoltaic
- id: omnivoltaic_vision
name: Omnivoltaic Vision
scope: omnivoltaic
description: General, technology-focused, and visionary articles for the corporate site.
articles:
- about-omnivoltaic-technologies
- about-omnivoltaic-markets
- off-grid-world-electrification-is-hapenning
- offgrid-power-convergence-technologies
- omnivoltaics-competitive-edge-a-solar-revolution-beyond-the-ordinary
- omnivoltaic-broad-product-range
- omnivoltaic-partnerships
Product Collections¶
Product collections are a first-class product-domain object.
Their definition and retrieval/mutation intent now belongs in:
docs/products/product-collections.md
Site documents should express which collections they use. This shared foundation document should not remain the long-term home of product collection object definitions.
Topic Tags¶
Purpose: Provide lightweight topical hints for search, discovery, and cross-cutting themes, without the strict governance of categories.
Model:
- Tags are defined in a central registry as IDs with human-readable labels and notes.
- Articles reference tags via a tags array in front-matter, e.g. tags: [e_mobility, battery].
- Only tags defined in this registry should be used in production content.
Tag Registry (initial set)¶
| ID | Label | Notes |
|---|---|---|
e_mobility |
e-mobility | Electric mobility topics: motorbikes, scooters, tricycles, boats. |
ev_adoption |
EV adoption | Adoption patterns and drivers for electric vehicles. |
off_grid |
Off-Grid | Off-grid power systems, solutions, and narratives. |
solar |
Solar | Solar products, solar-powered solutions, and solar technology. |
productive_use |
Productive use | Productive use of energy (PUE) applications and stories. |
training |
Training | Training classes, education, and learning content. |
markets |
Markets | Market overviews, regional focus, and go-to-market topics. |
technologies |
Technologies | Technology overviews, architectures, and technical capabilities. |
partnerships |
Partnerships | Partnerships, channels, and global reach. |
battery |
Battery | Battery technology, history, and performance characteristics. |
amptorrent |
AmpTORRENT | AmpTORRENT product and battery content. |
q_and_a |
Q&As | Question-and-answer style articles and FAQs. |
bridgeware |
BridgeWare | BridgeWare™ data and integration topics. |
omni_pay |
Omni-Pay | Omni-Pay™ and related SaaS/payment models. |
saas |
SaaS | SaaS business models and service structures. |
affordability |
Affordability | Affordability, pricing, and access topics. |
data |
Data | Data, telemetry, and analytics themes. |
Image Guidelines¶
Image Hosting¶
- Platform: Cloudinary
- Base URL:
https://res.cloudinary.com/omnivoltaic/image/upload/ - Optimization: Automatic format selection (WebP, AVIF)
- Responsive: Use Cloudinary transformations for different sizes
Image Types¶
- Hero images: 1920x1080 minimum
- Card thumbnails: 600x400 recommended
- Feature images: 800x600 recommended
- Logos: SVG preferred
- Icons: SVG or high-res PNG with transparency
Article Media Aesthetic Requirements¶
Hero Images (Required)
- Dimensions: 1920x1080 minimum (16:9 aspect ratio)
- Format: JPEG or WebP (prefer WebP for smaller file size)
- Content: High-quality photography showing:
- Products in context (e.g., solar lantern illuminating a home)
- Real-world use cases (e.g., customer using e-motorcycle)
- Environmental context (e.g., rural village, urban street)
- Style:
- Natural lighting preferred (avoid overly staged/studio shots)
- Show people when possible (builds connection)
- Avoid stock photos with watermarks or generic corporate imagery
- Cloudinary Transformations:
- Use c_fill,g_auto for intelligent cropping
- Apply q_auto for automatic quality optimization
- Example: .../image/upload/c_fill,g_auto,w_1920,h_1080,q_auto/v1234/hero.jpg
Feature Images (Optional)
- Dimensions: 800x600 (4:3 aspect ratio)
- Purpose:
- Mid-article visual break
- Detail shots of products
- Infographics or diagrams
- Technical close-ups (e.g., battery pack internals)
- Style: Same natural, authentic aesthetic as hero images
- Cloudinary Transformations:
- Example: .../image/upload/c_fill,g_center,w_800,h_600,q_auto/v1234/feature.jpg
Grid Thumbnails (Auto-Generated)
- Articles grid automatically uses hero image with c_fill,g_auto,w_600,h_400 transformation
- No separate thumbnail required
Editorial Guidance: - Prefer: Real customer photos, field deployment shots, authentic product usage - Avoid: Generic stock photos, overly polished marketing shots, studio backdrops - Diversity: Show products serving different markets (urban/rural, different regions) - Brand Consistency: OVES cyan accents in images reinforce brand (but not required)
Alt Text¶
- Descriptive and concise
- Include context when relevant
- Don't start with "Image of..."
SEO Guidelines¶
Page Titles¶
- Format: "[Page Name] | [Site Name] | Omnivoltaic"
- Length: 50-60 characters
- Include primary keyword
Meta Descriptions¶
- Length: 150-160 characters
- Clear value proposition
- Include call-to-action
Heading Structure¶
- One H1 per page (page title)
- Logical H2-H6 hierarchy
- No heading level skipping
Accessibility Standards¶
Minimum Requirements¶
- Color contrast ratio: 4.5:1 (text), 3:1 (large text)
- Focus indicators on interactive elements
- Keyboard navigation support
- Alt text for all images
- Semantic HTML structure
- ARIA labels where appropriate
Dark Mode¶
- All content must support dark mode
- Maintain contrast ratios in dark mode
- Smooth color transitions
- No flash/jarring color switches
Technical Standards¶
Performance¶
- First Contentful Paint: < 1.5s
- Largest Contentful Paint: < 2.5s
- Time to Interactive: < 3.5s
- Images: Lazy loading below fold
Framework¶
- Next.js 15.1.7
- React 19.x
- Tailwind CSS 4.x
- TypeScript 5.7.x
Data Fetching¶
- BFF pattern for CMS content
- ISR (Incremental Static Regeneration) for pages
- Server Components default
- Client Components only when needed
Development Notes¶
Using This Document¶
- This document defines defaults and shared resources
- Site-specific documents reference blocks and assets from here
- If a site overrides a default, it must specify completely (no partial overrides)
- All new block types must be added to Block Library section
- Keep this document updated as standards evolve
Version Control¶
- Update version number on changes
- Document changes in site-specific files that reference this
- Communicate breaking changes to team
Change Log¶
v2.1.0 - 2026-01-21 (Static Build Pattern)¶
- Added Static Build Pattern documentation (CRITICAL for production)
- Problem: BFF
getProductCollectionsreturns inconsistent counts (52 → 229 → 170 → 51) - Solution: Pre-fetch BFF data → Save to
data/products.json→ Build from local file - Implementation:
scripts/fetch-products.js+ file-based data loading - Benefits: Deterministic builds, no BFF calls during SSG, offline-capable, version-controlled data
- Troubleshooting: Orphaned JSON cleanup, data refresh procedures
- BFF Endpoint Analysis:
getProduct(productKey): BROKEN - 100% failure rate due to productKey mismatchgetProductCollections: WORKING but inconsistent - use with static build pattern- Purpose: Ensure reliable static site generation despite BFF instability
v2.0.0 - 2026-01-21 (CICD Refactor)¶
- BREAKING: Refactored all patterns to CICD principles (Canonical, Idempotent, Commutative, Decomposable)
- Added CICD Design Philosophy to document header
- CSS Import Order: Enhanced with intent documentation
- Added CICD compliance notes (NOT commutative, idempotent, decomposable)
- Documented cascade intent: Foundation (layers 1-3) → Accumulative (layer 4) → Corrective (layer 5)
- Each import has purpose comment explaining role in cascade
- Fixed typo:
tailwindcass→tailwindcss - Default Footer: Refactored into atomic widgets
- Created 4 atomic widgets: Company, Resources, Connect, Solutions
- Each widget self-contained with TypeScript export
- Composition example shows Full Footer = sum of atomic widgets
- Added CICD properties documentation (canonical, idempotent, commutative, decomposable)
- Layout flexibility: Full Footer, Minimal Footer, Custom Composition
- Removed monolithic structure, replaced with atomic + composition pattern
- Product Detail Page: Refactored into atomic sections
- Created 3 atomic sections: Product Properties (BoP), Items Included (BoM), Product CTAs
- Each section self-contained with purpose, content, data source, visual treatment
- Composition example shows Full Page = sum of atomic sections
- Added CICD properties documentation
- Sections can be omitted (e.g., no BoM if product has none)
- Section order can be changed (commutative)
- Purpose: Enable atomic component reuse, support partial implementations, clarify cascade/override intent, align with professional design system practices
v1.9.0 - 2026-01-21¶
- Added Solution Site Pattern (Canonical and Idempotent):
- New section documenting the canonical structure for all solution sites (off-grid, cross-grid, mobility, productive)
- Philosophy: Pattern is canonical (not derived from other sites) and idempotent (produces consistent results regardless of modification history)
- Defined 5 required pages: root redirect, products grid, product detail, articles grid, article detail
- Complete
site.tsconfiguration template with all required exports - Products grid specification: collapsible sections, responsive grid, BFF data source
- Product detail specification: BoP/BoM hierarchy, two-column layout, minimal footer
- Articles grid specification: card layout, local markdown source, collection filtering
- Article detail specification: prose typography, minimal header/footer, Lato Hairline body text
- Theme & styling: CSS import order, brand colors, component classes
- Next.js configuration: static export, basePath, trailingSlash
- Build & deploy: dev ports, Cloudflare Pages setup
- Purpose: Eliminate cross-references between site specs ("same as X"), enable idempotent site rebuilds from single source of truth
v1.8.0 - 2026-01-21¶
- Codified cross-site navigation structure:
- Added "Company Site: Solution Sections (MANDATORY)" section documenting homepage solution showcase pattern
- Updated Default Footer specification with mandatory "Solutions" widget (Column 4)
- Added "Company Home" link to Solutions widget — enables navigation back to company homepage from all sub-sites
- Specified exact links for all 5 navigation targets: Company Home (
https://omnivoltaic.com), E-Mobility (/mobility), Off-Grid (/off-grid), Cross-Grid (/cross-grid), Productive Use (/productive) - Added TypeScript implementation example for
footerNavigation.solutions - Documented production vs dev URL patterns (canonical paths vs localhost ports)
- Updated Pre-Deployment Checklist Phase 2 (Cross-Site Consistency):
- Added: "Footer 'Solutions' widget present on ALL sites with links to all 4 solution sites (mandatory)"
- Added: "Company homepage includes 4 solution sections with CTAs to each sub-site (mandatory)"
- Purpose: Ensure suite-wide discoverability — users can navigate between all solution portfolios from any site entry point, including returning to company homepage
v1.7.0 - 2026-01-21¶
- Added collection image requirement:
- Article collections:
imagefield added to the article-collection staging model now represented underdocs/articles/collections/*.yaml - Product collections:
imagefield added to Product Collections reference YAML - Pre-launch requirement: product collection images must be static/local until BFF collections endpoint implemented
- Updated Pre-Deployment Checklist Phase 1:
- Added: "Product collection images uploaded to Cloudinary"
- Added: "Product collection images added to app code as static/local references"
- Added: "Article collection images uploaded to Cloudinary"
- Updated validation script:
validate-articles.jsnow validates collection image fields - Updated TypeScript schema:
ArticleCollectioninterface requiresimage: ImageMeta - Updated BFF GraphQL examples: collection queries include
image { url alt }
v1.6.0 - 2026-01-21¶
- Added Pre-Deployment Checklist (4 phases):
- Phase 1: Data Sources & Content Governance (products, articles)
- Phase 2: Site Implementation & Consistency (per-site + cross-site)
- Phase 3: Content Quality & Editorial (articles, visual assets)
- Phase 4: Technical Readiness (build, deploy, SEO, operational)
- Added Article Development Strategy:
- Local-first workflow with BFF intent
- Article schema as BFF contract (TypeScript interface → GraphQL schema)
- Drop-in replacement migration path (local files → BFF GraphQL)
- ETL workflow: author locally → overhaul → mass-upload → refactor apps
- Added Article Media Aesthetic Requirements:
- Hero images: 1920x1080, natural/authentic photography, Cloudinary transformations
- Feature images: 800x600, technical detail shots
- Editorial guidance: prefer real customer photos over stock imagery
- Created
docs/contracts/article-schema.ts— TypeScript interface as BFF contract reference
v1.5.0 - 2026-01-21¶
- Added Header CTA Policy (Mandatory):
- No CTA buttons in header nav bar — header is logo + nav links only
- Partnership/contact CTAs served through footer (Company → Contact, Resources → Become a Partner)
- Hero section inline CTAs are allowed (page content, not nav chrome)
- Updated Footer: Contact link now points to partnership form URL
- Added Collapsible UI Pattern section:
- Native
<details>/<summary>pattern for zero-JS collapsible sections - Styling rules for chevron rotation and disclosure triangle removal
v1.4.0 - 2026-01-21¶
- Added Product Collections section:
- Defined
featured_productscollection with 8 flagship products (2 per portfolio) - Products: UBP1K Pro, LUMN Sonic (Off-Grid); CIES-6030, CIES-12060 (Cross-Grid); E-3 Pro, CET-1 (Mobility); Solar TV 32", Town™ 10x5 (Productive)
- Established model: collections reference BFF products by slug
v1.3.0 - 2026-01-21¶
- Added Block Theming Pattern section:
- Defined theme prop convention (
'light'|'dark') - Documented implementation rules (default light, explicit opt-in, no CSS cascade)
- Listed themeable blocks: ProductGridSimple, ProductDetailExpandable
- Added usage examples and guidance for new blocks
v1.2.0 - 2026-02-13¶
- Expanded Deployment Architecture into policy-level guidance:
- Added canonical URL governance for path-first architecture
- Added SEO governance requirements (canonical, sitemaps, internal links)
- Added Cloudflare monorepo project-limit note and growth trigger
- Added external references for Cloudflare and Google search behavior
v1.0.0 - 2026-01-19¶
- Initial foundation meta document created
- Defined default header and footer patterns
- Established block library with 9 core block types
- Set brand assets, design tokens, and content guidelines
- Documented technical and accessibility standards
This document serves as the foundation for all company-solution suite sites. Any shared configuration, assets, or patterns should be defined here first, then referenced in site-specific documents.