This tutorial is the first installment of a comprehensive guide to creating an-driven system for automatically generating web pages using React 19 and Next.js 15. Our focus is not just on speed, but on architectural elegance and consistent, on-brand design.

Open source: (https://github.com/aifa-agi/aifa)

Here’s the roadmap:

This step-by-step blueprint walks you through building your own enterprise-ready v0 clone, complete with authentication and payment flows. A real-world AI product from concept to launch—full source code available at . Subscribe to follow the full series—this is only the beginning!

Technology Stack: React 19 · Next.js 15 · Vercel · Prisma · Stripe · AI SDK · ChatGPT

Our platform blends enterprise-grade stability with bleedingedge innovation:

How It Works

  1. Prompt: Send a single natural-language request to ChatGPT.
  2. Generate: Receive a JSON-based PageConfig that defines your page’s sections, metadata, and layout.
  3. Build: Drop the config file into your Next.js app and run npm run build. Instantly you have a fully styled, SEO-ready page, complete with auth and AI-powered chat.

Need enterprise integration? Simply switch on our “v0 Corporate Mode” in the [upcoming aifa.dev(https://aifa.dev) for advanced automation, role-based access, and scalable microservices architecture.

Who Wins with an AI-Powered Site Generator? Studios, Enterprises, Startups, and Freelancers

The Next-Generation Design Agency: From Mockup to Mass Production in Minutes

Imagine an agency that architects scalable tech ecosystems, not just static mockups. A single upfront investment in a proprietary component library unlocks the ability to generate and deploy 50+ production-grade websites per hour.

This isn't science fiction. It's a new operational paradigm where creative capital meets automated execution. And with Stripe integration built-in, you can monetize this new velocity from day one. We'll explore this further in a later post.

Enterprise Deployments: Brand Consistency and Radical Scalability

A classic enterprise use case: a turnkey QR menu solution for a national restaurant franchise. You build a master design system for the core user experience—like product cards or menus—just once. This becomes a white-label solution you can deploy to hundreds of franchisees or locations.

Each location customizes its branding and content via a simple interface, while the core UX, performance, and design integrity remain locked down and consistent. This is the trifecta the enterprise market demands in 2025: radical scalability, bulletproof brand consistency, and unmatched speed-to-market.

The Core Engine: Our JSON-to-React Transformer Architecture

This entire system is powered by two critical components:

  1. Intelligent Prompt Engineering

    We use highly-tuned instructions that command the AI to pull battle-tested section templates from a vector database and tailor them to your specific request.

  2. The Component Transformer Architecture

    Our React components are engineered to interpret these JSON configs, instantly transforming them into fully-rendered, interactive pages.

While external models like ChatGPT and Claude handle the content generation, our proprietary transformer components are the system's core engine—the part we built to guarantee performance and design fidelity.

AI-Native Documentation: Use This Tutorial as a Live Knowledge Base

Stop reading documentation. Start commanding it.

The real power of this guide isn't in reading it cover-to-cover. It's designed to be your project's private, expert knowledge base.

How it Works:

  1. Feed this entire document into ChatGPT.
  2. Ask specific, contextual questions: "How do I implement a custom section?", "What's the purpose of the FullScreenWrapper?", "Show me the code for the DoublePresentation component."
  3. Receive precise, production-ready answers with complete code snippets.

This isn’t just documentation; it's an actionable playbook. Try this approach, and you’ll understand why all technical documentation in 2025 needs to be AI-native.

1. Introduction: Our Philosophy—Consistency Trumps Raw Speed

This guide is not about creating the fastest possible AI page generator. While AI tools like v0 prioritize raw generation speed, our methodology focuses on a more critical business metric: Total Cost of Ownership (TCO). Our primary goal is to deliver bulletproof design consistency and architectural harmony across your entire digital footprint.

While the initial generation of a single page might take slightly longer, the downstream savings in development, maintenance, and brand management are exponential. Here’s why this trade-off delivers superior ROI:

The result isn't just a collection of pages; it's a cohesive, professional-grade digital asset that scales gracefully with minimal maintenance overhead.


Beyond the Basics: Handling Real-World Complexity

This initial tutorial focuses on building standard pages with our core Header, Body, and Footer components. However, the open-source codebase provides advanced, out-of-the-box solutions for more complex requirements:

Our architecture is designed for extensibility. For unique, highly interactive features—like animated presentations, real-time data dashboards, or components with complex state management—you can inject Custom Components directly into the rendering pipeline. This gives you the flexibility to implement bespoke functionality without ever compromising the system's core integrity.

Your Next Step: Hands-On with Custom Components

To truly master this system, your practical assignment is to explore the process of creating and integrating a new Custom Component. This will solidify your understanding of the architecture's power and flexibility.

1.1. The Concept: AI as Your Brand Steward, Not Just a Content Engine

Modern digital operations demand velocity, brand integrity, and market agility. Our architecture achieves this by treating your design system as a structured, intelligent knowledge base. Formalized, pre-approved definitions for every brand-critical section (Hero, CTA, FAQ, Features, etc.) are ingested by the AI.

By feeding the AI your exact UI/UX standards, it becomes more than a content generator—it becomes the ultimate steward of your brand identity, enforcing consistency at every stage of the page creation lifecycle.

1.2. The 5-Step Workflow: From Design System to SEO-Optimized Build

  1. Ingest Your Design System: We load the AI's knowledge base with your component templates and explicit instructions on how to implement them visually and structurally, ensuring 100% brand alignment.
  2. Define the Goal with a Prompt: A user, project manager, or developer submits a simple text prompt describing the desired page or its elements.
  3. AI Interpretation & Structuring: The AI agent parses the request, generates the semantic content, and intelligently maps it to the appropriate, pre-approved templates from the knowledge base.
  4. Generate a Declarative PageConfig: Based on the selected templates, the system outputs a strongly-typed PageConfig—a declarative JSON description of the final page. This guarantees brand compliance and simplifies downstream development.
  5. Automated Build & Deployment: The config is consumed by our render components during the build process. The output is a production-ready, SEO-optimized page that is visually and technically compliant with your corporate standards.

1.3. The Business Impact: Drive Conversions and Slash TCO

1.4. Your Roadmap Through This Series

In this comprehensive tutorial, we will guide you through:

2. The Anatomy of Our AI-Powered Architecture

Our project is organized to maximize scalability, maintainability, and development velocity. We use Next.js 15 App Router conventions, including parallel routes (@right) and private folders (_folder), to create a clean and powerful structure.

Project Directory Tree

app/@right/
├── public/
│   ├── (_routing)/
│   │   └── [[...slug]]/
│   │       └── page.tsx                   # 1. Dynamic Catch-All Route Handler
│   └── (_service)/
│       ├── (_config)/
│       │   └── public-pages-config.ts     # 6. AI-Generated Page Configurations
│       └── (_libs)/
│           └── utils.ts                   # 7. Configuration Utilities
└── (_service)/
    ├── (_types)
    │   └── page-wrapper-types.ts          # 5. The TypeScript Data Contract (AI <-> UI)
    └── (_components)/
        └── page-transformer-components/
            ├── page-html-transformer.tsx    # 2. The Core Page Transformer Engine
            ├── custom-sections/             # Directory for complex, interactive components
            ├── wrappers/
            │   ├── full-screen-wrapper.tsx  # 3. Immersive Full-Screen Wrapper
            │   └── wrapper.tsx              # 4. Standard Content Section Wrapper
            ├── header-sections-components/
            │   ├── header-section.tsx       # 8. Standardized Header Component
            │   ├── page-header-elements.tsx # 9. Atomic Header Elements (H1/H2)
            │   └── announcement.tsx         # 10. Announcement Banner Component
            ├── body-sections-components/
            │   └── body-section.tsx         # 12. Flexible Body Content Container
            └── footer-sections-components/
                └── footer-section.tsx       # 11. Standardized Footer Component

Enter fullscreen mode Exit fullscreen mode

Key Component Paths

1. @/app/@right/public/(_routing)/[[...slug]]/page.tsx
2. @/app/@right/(_service)/(_components)/page-transformer-components/page-html-transformer.tsx
3. @/app/@right/(_service)/(_components)/page-transformer-components/wrappers/full-screen-wrapper.tsx
4. @/app/@right/(_service)/(_components)/page-transformer-components/wrappers/wrapper.tsx
5. @/app/@right/(_service)/(_types)/page-wrapper-types.ts
6. @/app/@right/public/(_service)/(_config)/public-pages-config.ts
7. @/app/@right/public/(_service)/(_libs)/utils.ts
8. @/app/@right/(_service)/(_components)/page-transformer-components/header-sections-components/header-section.tsx
9. @/app/@right/(_service)/(_components)/page-transformer-components/header-sections-components/page-header-elements.tsx
10. @/app/@right/(_service)/(_components)/page-transformer-components/header-sections-components/announcement.tsx
11. @/app/@right/(_service)/(_components)/page-transformer-components/footer-sections-components/footer-section.tsx
12. @/app/@right/(_service)/(_components)/page-transformer-components/body-sections-components/body-section.tsx

Enter fullscreen mode Exit fullscreen mode

2.1. The Core Component Toolkit: Production-Ready Pages Out of the Box

Purpose

Our standard component library provides the engineered foundation for creating strongly-typed, brand-aligned pages at scale. This collection comprises the architectural pillars of our system: dynamic routing, a central transformer engine, versatile content wrappers, unified header and footer sections, and the configuration files and data contracts that drive them.

Core Architectural Principles:

Together, these components form the bedrock of the system, guaranteeing that every AI-generated page is not only visually cohesive but also technically robust and enterprise-ready.

2.1.1. The [[...slug]]/page.tsx Component: Universal Catch-All Route for Dynamic URLs

2.1.1.1. The Strategic Value of Catch-All Routes: Agility and Deployment Speed

A catch-all route is a dynamic routing pattern in Next.js that allows a single page component to handle an infinite number of URL segments. By using the [[...slug]] convention, the slug parameter becomes an array containing every part of the URL path, no matter how deeply nested it is.

From a business perspective, this architectural choice is a massive competitive advantage. Here’s why:

2.1.1.2. The Value of Dynamic URLs for AI Assistants: Infinite Content Scalability

In today's competitive landscape, modern SaaS and AI platforms demand the agility to generate new pages on the fly. Whether initiated by a user, an administrator, or an autonomous AI agent, content must be architected for instant creation and deployment. Our catch-all routing architecture is the engine that drives this capability.

Strategic Business Advantages:

2.1.1.3. Real-World Use Cases at Scale

This architecture isn't theoretical; it's a battle-tested model for deploying high-value, deeply-nested content structures that drive business growth:

At its core, the process is elegantly simple yet powerful: it dynamically translates any URL path into a corresponding page configuration, which is then rendered on the fly. This is the technical foundation that unlocks the business agility described earlier.

The component's primary tasks are:

  1. Receive the URL: It captures the incoming URL path as an array of segments (e.g., ["category", "nike", "sneakers"]).

  2. Generate Static Paths: The generateStaticParams function proactively reads your public-pages-config.ts file. It informs Next.js of all valid page routes defined in your configuration. For the business, this translates to comprehensive Static Site Generation (SSG), ensuring every page is pre-built for lightning-fast load times and optimal SEO.

    export async function generateStaticParams() { const pages: PageConfig[] = getAllPublicPages(); return pages.map((page: PageConfig) => ({ slug: page.metadata.slug ? page.metadata.slug.slice(1) : [], })); }

  3. Fetch and Render: When a user requests a URL, the component receives the slug array. It then uses the getPageBySlug utility to perform a high-speed lookup against the configuration array (prepending "public" for an accurate match). If a match is found, the configuration is passed to our universal PageHtmlTransformer component for rendering.

    export default async function PublicDynamicSlugPage({ params }: Props) { const resolvedParams = await params; const slugArr = resolvedParams.slug ?? []; const pageConfig = getPageBySlug(["public", ...slugArr]); if (!pageConfig) { return Page not found; } return ; }

Because the slugArr can be of any length and the lookup is a direct match, this system provides infinite nesting depth with zero risk of route collisions.

2.1.1.5. Key Functions and Their Business Impact

2.1.1.7. The Component: The Execution Engine

This component is the engine that brings our AI-powered architecture to life. It's a single, powerful Next.js Server Component that acts as a universal handler for every dynamically generated public page. It is responsible for fetching the correct page configuration based on the URL and orchestrating the final render, ensuring both maximum performance and out-of-the-box SEO compliance.

// @/app/@right/public/(_routing)/[[...slug]]/page.tsx


import { PageHtmlTransformer } from "@/app/@right/(_service)/(_components)/page-transformer-components/page-html-transformer";
import { getPageBySlug } from "@/app/@right/(_service)/(_config)/pages-config";
import { constructMetadata } from "@/lib/construct-metadata";
import type { PageConfig } from "@/app/@right/(_service)/(_types)/page-wrapper-types";
import { getAllPublicPages } from "../../(_servise)/(_libs)/get-all-public-pages";


interface Props {
  params: Promise<{ slug?: string[] }>;
}


export async function generateStaticParams() {
  const pages: PageConfig[] = getAllPublicPages();


  return pages.map((page: PageConfig) => ({
    slug: page.metadata.slug || [],
  }));
}


export async function generateMetadata({ params }: Props) {
  const resolvedParams = await params;
  const slugArr = resolvedParams.slug ?? [];
  const pageConfig = getPageBySlug(["public", ...slugArr]);


  if (!pageConfig) return {};
  return constructMetadata(pageConfig.metadata);
}


export default async function PublicDynamicSlugPage({ params }: Props) {
  const resolvedParams = await params;
  const slugArr = resolvedParams.slug ?? [];
  const publicPageConfig = getPageBySlug(["public", ...slugArr]);


  if (!publicPageConfig) {
    return <div>Page not found</div>;
  }


  return <PageHtmlTransformer data={publicPageConfig} />;
}

Enter fullscreen mode Exit fullscreen mode

2.1.1.7. The Bottom Line: Catch-All Routes as Your AI Content Engine

Combining catch-all routes with a centralized page configuration creates an architecture that is maximally flexible, extensible, and purpose-built for AI-driven content orchestration. This approach is friendly to both developers and AI agents, creating a seamless workflow from concept to deployment.

The core principle is simple but transformative: A new page is just a new entry in a configuration file. No new code files, no complex folder structures. The navigation and rendering systems adapt automatically, making this the cornerstone of a truly agile and scalable AI-powered platform.

2.1.3. FullScreenWrapper vs. Wrapper: Crafting Immersive Full-Screen Experiences

2.1.3.1. Core Purpose

The FullScreenWrapper is specifically engineered for sections that require an immersive, full-screen presentation with background video or image support. It serves as the foundational container for "hero" sections, where content is elegantly overlaid on top of rich media elements.

2.1.3.2. Layered Architecture

The component uses a sophisticated layered structure to ensure content remains legible and visually distinct from the background.

Technical Highlights:

Enter fullscreen mode Exit fullscreen mode

2.1.3.3. Customization and Extensibility

The FullScreenWrapper is designed for easy customization. You can add complex visual effects directly via the className prop.

<FullScreenWrapper className="bg-gradient-to-br from-blue-900 to-purple-900">

Enter fullscreen mode Exit fullscreen mode

2.1.3.4. Advanced Styling and Reusable Templates

When you need section dividers, borders, glow effects, or background blurs, the FullScreenWrapper provides the ideal foundation for implementing these styles. This makes it perfect for creating highly stylized, reusable templates.

typescript

<FullScreenWrapper className="border-t-4 border-gradient bg-blur-effect">

Enter fullscreen mode Exit fullscreen mode

2.1.3.5. The Component

// @/app/@right/(_service)/(_components)/page-transformer-components/wrappers/full-screen-wrapper.tsx


import React, { HTMLAttributes } from "react";
import { cn } from "@/lib/utils";


interface FullScreenWrapperProps extends HTMLAttributes<HTMLDivElement> {
  videoUrl?: string;
  imageUrl?: string;
  className?: string;
  children: React.ReactNode;
}


export function FullScreenWrapper({
  videoUrl,
  imageUrl,
  className,
  children,
  ...props
}: FullScreenWrapperProps) {
  let backgroundElement: React.ReactNode = null;


  if (videoUrl) {
    backgroundElement = (
      <video
        className="absolute inset-0 size-full object-cover z-0 opacity-40 transition-all duration-500"
        autoPlay
        loop
        muted
        playsInline
        src={videoUrl}
      />
    );
  } else if (imageUrl) {
    backgroundElement = (
      <img
        className="absolute inset-0 size-full object-cover z-0"
        src={imageUrl || "/placeholder.svg"}
        alt="Background"
      />
    );
  }


  return (
    <section
      className={cn(
        "relative flex min-h-screen flex-col py-10 lg:py-14 bg-background",
        className
      )}
      {...props}
    >
      {backgroundElement}
      <div className="relative z-10 flex flex-col flex-1">{children}</div>
    </section>
  );
}

Enter fullscreen mode Exit fullscreen mode

2.1.4. Wrapper: The Standard Sectional Container

2.1.4.1. Primary Use Case

The Wrapper is the default, go-to container for the majority of content sections. It's designed to provide standard padding, content centering, and a consistent, predictable layout for informational blocks.

2.1.4.2. Structure and Styling

typescript
<section className="py-10 lg:py-14 bg-background">
  <div className="container mx-auto px-4">
    {children}  // Header → Body → Footer
  </div>
</section>

Enter fullscreen mode Exit fullscreen mode

The component's structure is simple and optimized for performance, relying on a few key Tailwind CSS classes:

2.1.4.3. Customization Points

While minimalist by design, the Wrapper is a flexible foundation for custom styling via the className prop. It's the perfect base for adding:

2.1.4.4. Building Reusable Templates

typescript
// Пример для pricing-секций
<Wrapper className="bg-gradient-to-br from-green-50 to-green-100 border-2 border-green-200">
  <HeaderSection />
  <PricingTable />
  <FooterSection />
</Wrapper>

Enter fullscreen mode Exit fullscreen mode

When your design calls for a template with unique styling but a standard, centered content structure, Wrapper is the ideal choice. It provides the structural backbone, allowing you to focus on the specific styles of the template.

2.1.4.5. The Component

// app/@right/(_service)/(_components)/page-transformer-components/wrappers/wrapper.tsx


import React, { HTMLAttributes } from "react";
import { cn } from "@/lib/utils";


interface WrapperProps extends HTMLAttributes<HTMLDivElement> {
  className?: string;
  children: React.ReactNode;
}


export function Wrapper({ className, children, ...props }: WrapperProps) {
  return (
    <section
      className={cn("py-10 lg:py-14 bg-background", className)}
      {...props}
    >
      <div className="container mx-auto px-4">{children}</div>
    </section>
  );
}

Enter fullscreen mode Exit fullscreen mode

2.1.5. page-wrapper-types.ts: The AI-to-UI TypeScript Contract

2.1.5.1. The Core Contract: Bridging AI Generation and UI Rendering

The page-wrapper-types.ts file establishes a formal, strictly-typed contract between our AI content generator and the UI rendering system. This contract is fundamental to our architecture, defining the structure of all possible page components and the rules governing their interactions to ensure seamless integration and predictability.

2.1.5.2. SectionType Categories and AI-Driven Generation

The AI's operational model is centered around the SectionType enum. First, the AI analyzes the available section types defined within this enum. Then, based on the user's request, it strategically selects which sections to assemble for a given page. To facilitate fully autonomous and high-quality content generation, the AI's knowledge base must be populated with comprehensive instructions and diverse examples for each of the 25+ section types.

typescript
export type SectionType =
  | "hero-section" | "cta-section" | "faq-section"
  | "features-section" | "testimonials-section" | "pricing-section"

Enter fullscreen mode Exit fullscreen mode

2.1.5.3. SEO Optimization and Metadata

The PageMetadata interface ensures the standards-compliant generation of meta tags, which is critical for search engine optimization (SEO). Meta tags are generated automatically via the generateMetadata() function. This function retrieves data from the page configuration and passes it to the constructMetadata() utility, which in turn constructs well-formed HTML headers.

typescript
export interface PageMetadata {
  id: string;           // Уникальный идентификатор
  title: string;        // <title> тег для SEO
  description: string;  // <meta description> для сниппетов
  image?: string;       // Open Graph изображение
  slug?: string[];      // URL-структура страницы
  type: SectionType;    // Тип основной секции
}

Enter fullscreen mode Exit fullscreen mode

2.1.5.4. HeaderContentConfig: Managing SEO Hierarchy

Managing the heading hierarchy is critical for on-page SEO.

A note of caution: The Header section is optional. This is an intentional design choice because certain section types may embed H1/H2 tags directly within their bodyContent. While this provides flexibility, it introduces a potential risk to UI consistency, which is a primary objective of this architecture. Careful implementation is required to maintain a logical and SEO-friendly document structure.

typescript
interface HeaderContentConfig {
  heading: string;
  headingLevel?: 1 | 2;  // H1/H2 для поисковой иерархии
  description?: string;
  showBorder?: boolean;
}

Enter fullscreen mode Exit fullscreen mode

2.1.5.5. BodySection: Enabling Maximum Design Freedom

typescript
bodyContent?: React.ReactNode;

Enter fullscreen mode Exit fullscreen mode

By design, the body of a section is granted complete freedom to implement any layout or design. This architectural choice allows for maximum creative flexibility, enabling the AI to generate rich and varied content. This approach deliberately contrasts with the Header and Footer, which are standardized to maintain a consistent look and feel across the entire application.

typescript
interface FooterContentConfig {
  actions?: {
    label: string;
    href: string;
    variant?: "default" | "secondary" | "outline" | "ghost" | "link";
  }[];
}

Enter fullscreen mode Exit fullscreen mode

The current implementation of the footer is intentionally minimalist. It supports only optional call-to-action buttons. No additional elements are included, a decision made to prioritize simplicity, speed, and uniformity across all generated pages.

2.1.5.7. Principles for Extending Type Definitions

To introduce a new SectionType, the following steps must be taken:

  1. Update AI Knowledge: The AI's knowledge base must be updated with comprehensive instructions and examples for the new section type.
  2. Extend Enum: The new type must be added to the SectionType enum.
  3. Expand Interfaces: If the new section requires unique configuration parameters, the corresponding configuration interface must be extended.

This process strikes a crucial architectural balance: the Header and Footer are strictly typed to enforce SEO best practices and UI consistency, while the Body offers maximum flexibility for innovative, AI-driven design solutions.

2.1.5.8. Component

// app/@right/(_service)/(_types)/page-wrapper-types.ts




export interface MetadataConfig {
  title?: string;
  description?: string;
}


export interface PageMetadata {
  id: string;
  title: string;
  description: string;
  image?: string;
  slug?: string[];
  type: SectionType;
}


export type SectionType =
  | "hero-section"
  | "cta-section"
  | "faq-section"
  | "features-section"
  | "testimonials-section"
  | "pricing-section"
  | "contact-section"
  | "blog-posts-section"
  | "product-grid-section"
  | "image-gallery-section"
  | "text-block-section"
  | "video-section"
  | "team-section"
  | "about-us-section"
  | "newsletter-section"
  | "social-proof-section"
  | "comparison-table-section"
  | "map-section"
  | "custom-html-section"
  | "changelog-section"
  | "comparison-two-column-section"
  | "comparison-three-column-section"
  | "feature-showcase-section";


export interface BaseSection {
  id: string;
  type: SectionType;
  className?: string;
}


export interface HeaderContentConfig {
  announcement?: {
    badgeText?: string;
    descriptionText?: string;
    href?: string;
  };
  heading: string;
  headingLevel?: 1 | 2;
  description?: string;
  showBorder?: boolean;
}


export interface FooterContentConfig {
  actions?: {
    label: string;
    href: string;
    variant?:
      | "default"
      | "secondary"
      | "destructive"
      | "outline"
      | "ghost"
      | "link";
  }[];
}
export interface SectionConfig extends BaseSection {
  type: SectionType;
  headerContent: HeaderContentConfig;
  bodyContent?: React.ReactNode;
  footerContent?: FooterContentConfig;
  videoUrl?: string;
  imageUrl?: string;
  sectionClassName?: string;
  contentWrapperClassName?: string;
  customComponentsAnyTypeData?: any;
}


export type Section = SectionConfig;


export interface PageConfig {
  metadata: PageMetadata;
  sections: Section[];
}


export type SlugType = string[];

Enter fullscreen mode Exit fullscreen mode

2.1.5.9. customComponentsAnyTypeData: Supporting Arbitrary Custom Components

The customComponentsAnyTypeData?: any; field within SectionConfig serves as a powerful "escape hatch." It is designed for passing unstructured data to sections that leverage complex or unique custom components that do not conform to our standard interfaces.

To maintain architectural integrity, the type and structure of this data must be rigorously defined and documented within the custom component itself. This design choice provides the necessary flexibility to integrate highly interactive, dynamic, and advanced user-facing sections without compromising the core typing contract of the main page architecture.

2.1.6. public-pages-config.ts: The Public Page and Slug Route Registry

2.1.6.1. Role in System Architecture

The public-pages-config.ts file is an AI-generated registry of all public-facing pages within the application. This configuration is automatically generated by our AI based on system instructions and user prompts. Its structure is directly influenced by the available components in our knowledge base examples and the enumerations within the SectionType definitions.

The resulting configuration acts as a bridge, translating the AI's analysis of user requirements into a structure that our page rendering system can interpret and display.

2.1.6.2. When to Use This File-Based Configuration

This approach is ideal for:

When to Transition to a Database:

For large-scale production applications, a file-based approach is only practical for a small set of pages. Most scenarios will benefit from storing this information in a database to enable dynamic content management and scalability.

2.1.6.3. Configuration Structure

typescript
export const PublicPagesConfig = {
  pages: [
    {
      metadata: {
        id: "public",
        title: "Enterprise-Grade AI Next.js starter",
        description: "Free Open-Source starter kit...",
        slug: ["public", "test"],
        type: "hero-section",
      },
      sections: [
        {
          id: "test-block",
          type: "hero-section",
          headerContent: { /* SEO-заголовки */ },
          bodyContent: {},
          footerContent: { /* Кнопки действий */ },
          videoUrl: "/_static/video/ai-loop.mp4",
          contentWrapperClassName: "text-white",
        } as SectionConfig,
      ],
    },
  ] as PageConfig[],
};

Enter fullscreen mode Exit fullscreen mode

2.1.6.4. Configuration Categorization Principle

Key Architectural Decision: Placing the configuration file in the public/(_service)/(_config)/ directory signifies its role in managing public-facing pages.

Scaling by Category:

Our architecture supports scaling by categorizing configurations, ensuring a clean and organized structure:

Each category is designed to have its own:

2.1.6.5. Interaction with the AI Generation System

For our AI system, this configuration file serves as:

The workflow is as follows:

  1. The AI analyzes the existing configuration file.
  2. It generates a new PageConfig object based on the user's prompt.
  3. A developer then adds the new configuration to the pages array.
  4. The system automatically recognizes and registers the new routes.

2.1.6.6. Advantages and Limitations

Advantages of the File-Based Approach:

Limitations:

2.1.6.7. Component

// @/app/@right/public/(_servise)/(_config)/public-pages-config.ts


import {
  PageConfig,
  SectionConfig,
} from "@/app/@right/(_service)/(_types)/page-wrapper-types";


export const PublicPagesConfig = {
  pages: [
    {
      metadata: {
        id: "public",
        title: "Enterprise-Grade AI Next.js starter",
        description: "Free Open-Source starter kit...",
        slug: ["public", "test"],
        type: "hero-section",
      },
      sections: [
        {
          id: "test-block",
          type: "hero-section",
          headerContent: {
            announcement: {
              badgeText: "Thanks",
              descriptionText: "AI-SDK V5 & Vercel AI",
              href: "https://github.com/aifa-agi/aifa",
            },
            heading: "Enterprise-Grade AI Next.js starter",
            description:
              "Free Open-Source starter kit to build, deploy, and scale intelligent AI applications. Artifacts Feature, features secure multi-provider auth, Stripe payments, vector knowledge bases, deep-research agents, and a unique fractal architecture designed for the future of AI.",
            showBorder: false,
            headingLevel: 1,
          },
          bodyContent: {},
          footerContent: {
            actions: [
              {
                label: "Get Started",
                href: "/https://github.com/aifa-agi/aifa",
                variant: "default",
              },
              { label: "Browse Docs", href: "/docs", variant: "ghost" },
            ],
          },
          videoUrl: "/_static/video/ai-loop.mp4",
          contentWrapperClassName: "text-white",
        } as SectionConfig,
      ],
    },
  ] as PageConfig[],
};

Enter fullscreen mode Exit fullscreen mode

2.1.6.8. Conclusion

public-pages-config.ts is a practical solution for small to medium-sized projects, offering a balance between ease of management and functionality. For larger-scale applications, it serves as an excellent starting point before transitioning to a more robust, database-driven architecture.

2.1.7. utils.ts: Configuration Utility Functions

This module provides utility functions for managing page configurations. It includes two primary functions: getAllPublicPages(), which filters all pages with the "public" prefix for static generation, and getPageBySlug(), which locates a specific page by an exact, case-sensitive match of its slug array.

// @app/@right/public/(_servise)/(_libs)/utils.ts


import {
  PageConfig,
  SlugType,
} from "@/app/@right/(_service)/(_types)/page-wrapper-types";
import { PublicPagesConfig } from "../(_config)/public-pages-config";


export function getAllPublicPages(): PageConfig[] {
  return PublicPagesConfig.pages.filter(
    (page: PageConfig) => page.metadata.slug?.[0] === "public"
  );
}


export function getPageBySlug(slug: SlugType): PageConfig | undefined {
  return PublicPagesConfig.pages.find(
    (page: PageConfig) =>
      JSON.stringify(
        page.metadata.slug?.map((s: string) => s.toLowerCase())
      ) === JSON.stringify(slug.map((s: string) => s.toLowerCase()))
  );
}

Enter fullscreen mode Exit fullscreen mode

2.1.8. header-section.tsx: Unified Section Header

This standardized component serves as a universal header for all section types, ensuring consistency across the application. It offers optional elements such as an announcement, an H1/H2 heading, and a description. This component plays a crucial role in SEO optimization and maintaining visual consistency for AI-generated pages.

// @/app/@right/(_service)/(_components)/page-transformer-components/header-sections-components/header-section.tsx


import React from "react";
import { cn } from "@/lib/utils";
import {
  PageHeaderDescription,
  PageHeaderHeading,
} from "./page-header-elements";


import { Announcement } from "./announcement";
import { HeaderContentConfig } from "../../../(_types)/page-wrapper-types";


export type HeaderSectionProps = {
  headerContent: HeaderContentConfig;
} & React.HTMLAttributes<HTMLDivElement>;


export function HeaderSection({
  headerContent,
  className,
  ...props
}: HeaderSectionProps) {
  if (!headerContent) return null;


  const {
    announcement,
    heading,
    headingLevel = 1,
    description,
    showBorder = false,
  } = headerContent;


  return (
    <section
      className={cn(
        showBorder && "border-t-4 border-b-4 border-primary",
        className
      )}
      {...props}
    >
      <div className="container mx-auto px-4">
        <div className="flex flex-col items-center gap-1 py-8 md:py-10 lg:py-12">
          {announcement && (
            <Announcement
              badgeText={announcement.badgeText}
              descriptionText={announcement.descriptionText}
              href={announcement.href}
            />
          )}
          <PageHeaderHeading level={headingLevel}>{heading}</PageHeaderHeading>
          {description && (
            <PageHeaderDescription>{description}</PageHeaderDescription>
          )}
        </div>
      </div>
    </section>
  );
}

Enter fullscreen mode Exit fullscreen mode

2.1.9. header-section.tsx: Unified Section Header (Atomic Components)

This section details the atomic components used to construct headers: PageHeaderHeading (supporting H1/H2), PageHeaderDescription for subheadings, and PageActions for placing buttons. These components leverage createElement for dynamic HTML tag generation, ensuring correct SEO hierarchy.

// @app/@right/(_service)/(_components)/page-transformer-components/header-sections-components/page-header-elements.tsx


import { HTMLAttributes, createElement } from "react";
import { cn } from "@/lib/utils";


type HeadingTag = "h1" | "h2";


interface PageHeaderHeadingProps extends HTMLAttributes<HTMLHeadingElement> {
  level?: 1 | 2;
}


function PageHeaderHeading({
  className,
  level = 1,
  ...props
}: PageHeaderHeadingProps) {

  const Heading: HeadingTag = level === 1 ? "h1" : "h2";
  const h1Classes = "text-2xl sm:text-3xl  md:text-6xl lg:text-7xl";
  const h2Classes = "text-lg sm:text-xl  md:text-3xl lg:text-4xl";



  return createElement(Heading, {
    className: cn(
      "text-center font-bold leading-tight tracking-tighter font-serif",
      level === 1 ? h1Classes : h2Classes,
      className
    ),
    ...props,
  });
}


function PageHeaderDescription({
  className,
  ...props
}: HTMLAttributes<HTMLParagraphElement>) {
  return (
    <p
      className={cn(
        "max-w-2xl text-balance text-center text-base font-light text-muted-foreground sm:text-lg",
        className
      )}
      {...props}
    />
  );
}


function PageActions({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
  return (
    <div
      className={cn(
        "flex w-full items-center justify-center gap-2 pt-2",
        className
      )}
      {...props}
    />
  );
}



export { PageActions, PageHeaderDescription, PageHeaderHeading };

Enter fullscreen mode Exit fullscreen mode

2.1.10. announcement.tsx: Announcement Component

This interactive badge component is designed for announcements and notifications. It supports navigation, keyboard control, and conditional rendering, automatically hiding when no content is present. It is used to draw attention to important updates or links.

// @app/@right/(_service)/(_components)/page-transformer-components/header-sections-components/announcement.tsx


"use client";


import { useRouter } from "next/navigation";
import { Badge } from "@/components/ui/badge";
import { ArrowRight } from "lucide-react";
import { cn } from "@/lib/utils";


interface AnnouncementProps {
  badgeText?: string; 
  descriptionText?: string; 
  href?: string; 
  className?: string;
}


export function Announcement({
  badgeText,
  descriptionText,
  href,
  className,
}: AnnouncementProps) {
  const router = useRouter();


  const handleOnClick = () => {
    if (href) {
      router.push(href);
    }
  };


  // Если нет текста для бейджа, описания или ссылки, возвращаем null
  if (!badgeText && !descriptionText && !href) {
    return null;
  }


  return (
    <div
      className={cn(
        "flex cursor-pointer items-center gap-2 rounded-full border border-primary bg-muted px-3 py-1 text-sm transition-colors hover:bg-muted/80",
        className
      )}
      onClick={handleOnClick}
      role="link"
      tabIndex={0}
      onKeyDown={(e) => {
        if (e.key === "Enter" || e.key === " ") {
          handleOnClick();
        }
      }}
    >
      {badgeText && (
        <Badge variant="secondary" className="text-xs">
          {badgeText}
        </Badge>
      )}
      {descriptionText && (
        <span className="text-muted-foreground">{descriptionText}</span>
      )}
      {href && <ArrowRight className=" h-3 w-3 text-muted-foreground" />}
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

This standardized footer component includes action buttons. It supports multiple buttons with various styling options, ensuring uniformity of Call-to-Action (CTA) elements across all sections. It automatically hides when no actions are defined.

// @app/@right/(_service)/(_components)/page-transformer-components/footer-sections-components/footer-section.tsx


"use client";


import { useRouter } from "next/navigation";
import type { HTMLAttributes } from "react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { PageActions } from "../header-sections-components/page-header-elements";


interface FooterAction {
  label: string;
  href: string;
  variant?:
    | "default"
    | "secondary"
    | "destructive"
    | "outline"
    | "ghost"
    | "link";
}


interface FooterSectionProps extends HTMLAttributes<HTMLDivElement> {
  actions?: FooterAction[];
}


export function FooterSection({
  actions,
  className,
  ...props
}: FooterSectionProps) {
  const router = useRouter();


  if (!actions || actions.length === 0) {
    return null;
  }


  return (
    <section className={cn("py-4 md:py-6 lg:py-8", className)} {...props}>
      <div className="container mx-auto px-4">
        <PageActions>
          {actions.map((action) => (
            <Button
              key={action.href} // href должен быть уникальным!
              size="sm"
              variant={action.variant || "default"}
              onClick={() => router.push(action.href)}
            >
              {action.label}
            </Button>
          ))}
        </PageActions>
      </div>
    </section>
  );
}

Enter fullscreen mode Exit fullscreen mode

2.1.12. body-section.tsx: Arbitrary Content Container

2.1.12.1. Purpose and Philosophy

BodySection serves as a highly flexible container for the main content within sections. Unlike the strictly standardized Header and Footer components, BodySection provides complete freedom for placing any React content.

2.1.12.2. Content Generation Principles

Crucially: Content for bodyContent must be generated as plain TSX without using .map() elements, where all elements are presented in an expanded format.

typescript
// ✅ 
bodyContent: (
  <>
    <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
      <div className="feature-card">
        <h3>Feature 1</h3>
        <p>Description 1</p>
      </div>
      <div className="feature-card">
        <h3>Feature 2</h3>
        <p>Description 2</p>
      </div>
      <div className="feature-card">
        <h3>Feature 3</h3>
        <p>Description 3</p>
      </div>
    </div>
  </>
)

Enter fullscreen mode Exit fullscreen mode

// ❌ 
bodyContent: (
  <div className="grid">
    {features.map(feature => <FeatureCard key={feature.id} {...feature} />)}
  </div>
)

Enter fullscreen mode Exit fullscreen mode

2.1.12.3. When to Use Custom Components

If a section requires complex logic (state, effects, interactivity), create an independent component and add it to PageHtmlTransformer as a separate entity.

typescript
// @/app/@right/(_service)/(_components)/page-transformer-components/body-sections-components/body-section.tsx
export function BodySection({ children, className, ...props }: BodySectionProps) {
  const hasChildren = children !== null && children !== undefined && 
    !(Array.isArray(children) && children.length === 0) &&
    !(typeof children === "string" && children === "");

  if (!hasChildren) return null;

  return (
    <div className={cn(className)} {...props}>
      {children}
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

2.1.12.4. Component

// @app/@right/(_service)/(_components)/page-transformer-components/body-sections-components/body-section.tsx


import type { HTMLAttributes, ReactNode } from "react";
import { cn } from "@/lib/utils";
import { SectionType } from "../../../(_types)/page-wrapper-types";


interface BodySectionProps extends HTMLAttributes<HTMLDivElement> {
  children?: ReactNode | null;
  type: SectionType;
}



export function BodySection({
  children,
  className,
  ...props
}: BodySectionProps) {
  const defaultHeightRem = 0;
  const hasChildren =
    children !== null &&
    children !== undefined &&
    // Covers case when children = [] or ""
    !(Array.isArray(children) && children.length === 0) &&
    !(typeof children === "string" && children === "");


  if (!hasChildren && defaultHeightRem) {
    return (
      <div
        className={cn(className)}
        style={{ height: `${defaultHeightRem}rem` }}
        {...props}
      >
        {/* Empty section with default height */}
      </div>
    );
  }


  if (!hasChildren) {
    return null;
  }


  return (
    <div className={cn(className)} {...props}>
      {children}
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

2.1.12.5. Conclusion

BodySection acts as a bridge between the system's standardized architecture and the creative freedom of AI generation, striking a balance between control and flexibility.

2.2. Advanced Custom Components

Advanced Custom Components are engineered to deliver complex, interactive functionality that extends beyond the capabilities of our standard architectural patterns. These components are reserved for scenarios requiring state management, sophisticated animations, real-time data handling, or unique business logic.

When to Use Custom Components:

Architectural Integration:

Custom components are integrated into the PageHtmlTransformer as distinct case statements within a switch block. This approach allows them to access system-wide context, such as theme and device information, while maintaining a consistent look and feel through shared CSS classes and design tokens. Although they adhere to the system's visual language, they retain complete freedom in their internal logic and implementation. This strategy provides a balance between standardizing the majority of content and allowing for creative freedom in implementing complex interactive elements.

2.2.1. Guidelines for Implementing Custom Components

2.2.1.1. Wrapper Policy

No External Wrappers: Custom components must be returned directly without being enclosed in Wrapper or FullScreenWrapper. They are responsible for managing their own layout, padding, and layering to ensure full control over their presentation.

2.2.1.2. Component-Scoped Typing

Local Prop Interfaces: The prop interfaces for a custom component should be declared at the top of the component file itself. All data is passed from the page configuration into the component via the customComponentsAnyTypeData field in the section config.

2.2.1.3. Extending SectionType

Add a New Section Type: Each custom component requires a unique type to be added to the SectionType enum in page-wrapper-types.ts. This ensures proper type-checking and enables the switch statement in the transformer to correctly identify and render the component.

typescript
// @/app/@right/(_service)/(_types)/page-wrapper-types.ts
// ...
export type SectionType ="hero-section" | “new-custom-section”;

Enter fullscreen mode Exit fullscreen mode

2.2.1.4. Update cases in the ageHtmlTransformer

Custom case processingA new case is added to the PageHtmlTransformer to handle a custom section type with a direct

// В PageHtmlTransformer:
case "new-custom-section":
  return (
    <NewCustomSection
      key={config.id}
      customData={section.customComponentsAnyTypeData.customData}
    />
  );

Enter fullscreen mode Exit fullscreen mode

2.2.1.5. Custom Config Structure

Configuration Structure: The following is an example of a page configuration that includes a custom section. All component-specific data is placed within the customComponentsAnyTypeData object, which can have any structure required by the component.

export const PublicPagesConfig = {
    pages: [
{
      metadata: {
        id: "CIUD",
        title: "1",
        description: "2",
        slug: ["public", "name"],
        type: "new-custom-section",
      },
      sections: [
        {
          id: "new-custom-section",
          type: "new-custom-section",
          customComponentsAnyTypeData: {
            metaData: {
              metaTitle: "1",
              metaDescription: "2",
            },
            customData: {
              mediaUrl: "/_static/illustrations/3.png",
              title: "4",
              description:
                "5",
            },
          },
        } as SectionConfig,
      ],
    },


             ] as PageConfig[],

Enter fullscreen mode Exit fullscreen mode

2.2.2. Custom Component Example

2.2.2.1. DoublePresentation

2.2.2.1.1. Update Core Types

First, add the new section type to the SectionType enum.

typescript
// @/app/@right/(_service)/(_types)/page-wrapper-types.ts


export type SectionType =
  | "hero-section"
  | "cta-section"
  | "double-presentation-section" 

Enter fullscreen mode Exit fullscreen mode

2.2.2.1.2. Add New Case to PageHtmlTransformer

Next, add the corresponding case to the PageHtmlTransformer to render the component.

case "double-presentation-section":
            return (
              <DoublePresentation
                key={section.id}
                metaData={section.customComponentsAnyTypeData.metaData}
                leftItem={section.customComponentsAnyTypeData.leftItem}
                rightItem={section.customComponentsAnyTypeData.rightItem}
              />
            );

Enter fullscreen mode Exit fullscreen mode

2.2.2.1.4. Config Example

Here is an example of how to configure the DoublePresentation component in public-pages-config.ts.

// app/@right/(_service)/(_types)/page-wrapper-types.ts


export interface MetadataConfig {
  title?: string;
  description?: string;
}


export type CuidString = string;


export interface PageMetadata {
  id: CuidString;
  title: string;
  description: string;
  image?: string;
  slug?: string[];
  type: SectionType;
}


export type SectionType =
  | "hero-section"
  | "cta-section"
  | "faq-section"
  | "features-section"
  | "testimonials-section"
  | "pricing-section"
  | "contact-section"
  | "blog-posts-section"
  | "product-grid-section"
  | "image-gallery-section"
  | "text-block-section"
  | "video-section"
  | "team-section"
  | "about-us-section"
  | "newsletter-section"
  | "social-proof-section"
  | "comparison-table-section"
  | "map-section"
  | "custom-html-section"
  | "changelog-section"
  | "comparison-two-column-section"
  | "comparison-three-column-section"
  | "feature-showcase-section"
  | "double-presentation-section";


export interface BaseSection {
  id: string;
  type: SectionType;
  className?: string;
}


export interface HeaderContentConfig {
  announcement?: {
    badgeText?: string;
    descriptionText?: string;
    href?: string;
  };
  heading: string;
  headingLevel?: 1 | 2;
  description?: string;
  showBorder?: boolean;
}


export interface FooterContentConfig {
  actions?: {
    label: string;
    href: string;
    variant?:
      | "default"
      | "secondary"
      | "destructive"
      | "outline"
      | "ghost"
      | "link";
  }[];
}
export interface SectionConfig extends BaseSection {
  type: SectionType;
  headerContent: HeaderContentConfig;
  bodyContent?: React.ReactNode;
  footerContent?: FooterContentConfig;
  videoUrl?: string;
  imageUrl?: string;
  sectionClassName?: string;
  contentWrapperClassName?: string;
  customComponentsAnyTypeData?: any;
}


export type Section = SectionConfig;


export interface PageConfig {
  metadata: PageMetadata;
  sections: Section[];
}


export type SlugType = string[];

Enter fullscreen mode Exit fullscreen mode

2.2.2.1.5. Component

The complete code for the DoublePresentation component.

// @/app/@right/public/(_servise)/(_config)/public-pages-config.ts


import {
  PageConfig,
  SectionConfig,
} from "@/app/@right/(_service)/(_types)/page-wrapper-types";


export const PublicPagesConfig = {
  pages: [
    {
      metadata: {
        id: "public",
        title: "Enterprise-Grade AI Next.js starter",
        description: "Free Open-Source starter kit...",
        slug: ["public", "test"],
        type: "hero-section",
      },
      sections: [
        {
          id: "test-block",
          type: "hero-section",
          headerContent: {
            announcement: {
              badgeText: "Thanks",
              descriptionText: "AI-SDK V5 & Vercel AI",
              href: "https://github.com/aifa-agi/aifa",
            },
            heading: "Enterprise-Grade AI Next.js starter",
            description:
              "Free Open-Source starter kit to build, deploy, and scale intelligent AI applications. Artifacts Feature, features secure multi-provider auth, Stripe payments, vector knowledge bases, deep-research agents, and a unique fractal architecture designed for the future of AI.",
            showBorder: false,
            headingLevel: 1,
          },
          bodyContent: {},
          footerContent: {
            actions: [
              {
                label: "Get Started",
                href: "/https://github.com/aifa-agi/aifa",
                variant: "default",
              },
              { label: "Browse Docs", href: "/docs", variant: "ghost" },
            ],
          },
          videoUrl: "/_static/video/ai-loop.mp4",
          contentWrapperClassName: "text-white",
        } as SectionConfig,
      ],
    },
    {
      metadata: {
        id: "interactive-ai",
        title: "Interactive AI Demo",
        description: "Demo: DoublePresentation custom case",
        slug: ["public", "example"],
        type: "double-presentation-section",
      },


      sections: [
        {
          id: "double-presentation-demo",
          type: "double-presentation-section",
          customComponentsAnyTypeData: {
            metaData: {
              metaTitle: "Interactive AI: Where Conversation Builds the UI",
              metaDescription: "Discover what makes AIFA revolutionary...",
            },
            leftItem: {
              mediaUrl: "/_static/illustrations/ai-chat.png",
              title: "Ai Artifacts Chatbot",
              description:
                "As the AI chatbot speaks, it highlights elements...",
            },
            rightItem: {
              mediaUrl: "/_static/illustrations/ai-web.png",
              title: "Related Pages",
              description:
                "Click any UI element, and the AI provides instant context...",
            },
          },
        } as SectionConfig,
      ],
    },
  ] as PageConfig[],
};

Enter fullscreen mode Exit fullscreen mode

2.2.2.1.3. page-wrapper-types.ts

Here is the complete page-wrapper-types.ts file with the new type included.

// @/app/@right/(_service)/(_components)/page-transformer-components/custom-sections/custom-double-prsentation.tsx


"use client";


import React, { useState, useEffect } from "react";
import { motion } from "framer-motion";
import Image from "next/image";
import { cn } from "@/lib/utils";
import { useMediaQuery } from "@/hooks/use-media-query";


interface PresentationMeta {
  metaTitle: string;
  metaDescription: string;
}


interface PresentationItem {
  mediaUrl: string;
  title: string;
  description: string;
}


interface DoublePresentationProps {
  metaData: PresentationMeta;
  leftItem: PresentationItem;
  rightItem: PresentationItem;
}


export default function DoublePresentation({
  metaData,
  leftItem,
  rightItem,
}: DoublePresentationProps) {
  const { isMobile } = useMediaQuery();


  // Desktop animation state
  const [activeContainer, setActiveContainer] = useState<"left" | "right">(
    "left"
  );
  const [sliderKey, setSliderKey] = useState(0);


  // Desktop auto-switching effect
  useEffect(() => {
    // Only run animation cycle on desktop
    if (isMobile) return;


    let sliderTimer: NodeJS.Timeout;
    let transitionTimer: NodeJS.Timeout;


    const startAnimationCycle = () => {
      setSliderKey((prev) => prev + 1);
      sliderTimer = setTimeout(() => {
        setActiveContainer((prev) => (prev === "left" ? "right" : "left"));
        transitionTimer = setTimeout(() => {
          startAnimationCycle();
        }, 500);
      }, 9000);
    };


    startAnimationCycle();


    return () => {
      clearTimeout(sliderTimer);
      clearTimeout(transitionTimer);
    };
  }, [isMobile]);


  // Return null while determining screen size
  if (isMobile === null) {
    return null;
  }


  // Common CSS classes
  const metaBlockClass = "text-center max-w-3xl flex flex-col items-center";
  const descriptionClass =
    "mb-12 max-w-xl text-base text-muted-foreground text-center";
  const desktopTitleClass =
    "mb-6 max-w-3xl font-serif font-bold leading-tight md:text-2xl lg:text-4xl";
  const desktopDescriptionClass =
    "mb-12 max-w-xl text-lg text-muted-foreground md:text-xl text-center";


  // Mobile card renderer
  const renderMobileCard = (item: PresentationItem) => (
    <div className="relative flex flex-col rounded-xl bg-gray-900 text-white shadow-lg mb-6 overflow-hidden">
      <div className="w-full relative" style={{ paddingTop: "56.25%" }}>
        <Image
          src={item.mediaUrl}
          alt={item.title}
          fill
          className="object-cover rounded-t-xl"
          sizes="100vw"
          priority
        />
      </div>
      <div className="flex flex-col p-4">
        <h2 className="text-xl font-bold mb-2">{item.title}</h2>
        <p className="text-gray-300 mb-2 text-base min-h-16">
          {item.description}
        </p>
      </div>
    </div>
  );


  // Desktop card renderer
  const renderDesktopCard = (item: PresentationItem, isActive: boolean) => (
    <motion.div
      layout
      animate={{ flex: isActive ? "7 1 0%" : "3 1 0%" }}
      transition={{ duration: 0.5 }}
      className="relative flex flex-col rounded-lg overflow-hidden bg-transparent text-white p-0 shadow-lg h-[30rem] flex-shrink-0"
    >
      <div className="relative w-full h-60 mb-4 rounded-xl overflow-hidden border-4 border-gray-700">
        <Image
          src={item.mediaUrl}
          alt={item.title}
          fill
          className="object-cover"
          priority
          sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
        />
      </div>
      <div className="flex flex-col pt-6">
        <h2 className="text-2xl font-bold mb-2 whitespace-nowrap overflow-hidden text-ellipsis">
          {item.title}
        </h2>
        <div className="relative w-full h-px bg-gray-700 mb-4">
          <motion.div
            key={`slider-${item.title}-${sliderKey}`}
            className={cn(
              "absolute top-0 left-0 h-full",
              isActive ? "bg-primary" : "bg-gray-700"
            )}
            initial={{ width: 0 }}
            animate={{ width: isActive ? "100%" : "0%" }}
            transition={
              isActive ? { duration: 9, ease: "linear" } : { duration: 0 }
            }
          />
        </div>
        <p className="text-gray-300 mb-4 text-sm line-clamp-4 min-h-[4rem]">
          {item.description}
        </p>
      </div>
    </motion.div>
  );


  // Mobile layout
  if (isMobile) {
    return (
      <section className="w-full pt-20">
        <div className="container mx-auto px-4 flex flex-col items-center">
          <div className={metaBlockClass}>
            <h2 className="text-xl font-bold mb-4">{metaData.metaTitle}</h2>
            <p className={descriptionClass}>{metaData.metaDescription}</p>
          </div>


          <div className="w-full flex flex-col">
            {renderMobileCard(leftItem)}
            {renderMobileCard(rightItem)}
          </div>
        </div>
      </section>
    );
  }


  // Desktop layout
  return (
    <section className="w-full pt-28">
      <div className="container mx-auto px-4 flex flex-col items-center gap-12">
        <div className={metaBlockClass}>
          <h2 className={desktopTitleClass}>{metaData.metaTitle}</h2>
          <p className={desktopDescriptionClass}>{metaData.metaDescription}</p>
        </div>


        <div className="flex gap-6 w-full max-w-6xl">
          {renderDesktopCard(leftItem, activeContainer === "left")}
          {renderDesktopCard(rightItem, activeContainer === "right")}
        </div>
      </div>
    </section>
  );
}

Enter fullscreen mode Exit fullscreen mode

Conclusion: How to Get the Most Out of This Documentation

We understand that the instructions and components presented here might seem extensive for a single post. You might even feel that this isn't the most exciting read, and you'd be right. This isn't entertainment; it's a detailed technical guide designed to give you complete control over a powerful system.

To transform the study of this complex system into an interactive and productive process, we recommend the following approach.

Use AI for Accelerated Learning

Instead of passively reading, use this documentation as the "brain" for your AI assistant.

Your Action Plan:

  1. Copy the entire content of this article, from the introduction to this section.
  2. Use it as a system prompt for ChatGPT. This will provide the AI with the full context of the architecture we're discussing.
  3. Ask questions about the source code. You can now have a dialogue with an AI that "understands" our rules and conventions. For example:
    • "Based on the provided documentation, explain how to create a new custom component to display customer testimonials."
    • "Show me a configuration example for a page that uses both DoublePresentation and HeroSection."

This method will help you understand the application's principles much faster. You can find the full source code for this project on our GitHub repository.

What's Next?

In this article, we've built one of the two critical pieces of our site generation system: a tool that transforms a Config file into ready-to-use React components. This paves the way for automated page creation, where an AI can generate the configuration, and our Transformer turns it into a beautiful interface.

To see our project in action, visit the live demo at aifa.dev.

A Glimpse into Future Posts:

In the next tutorial, we'll start by answering a key question: Why was Markdown chosen for content management? Stay tuned!