diff --git a/apps/docs/app/[lang]/page.tsx b/apps/docs/app/[lang]/page.tsx index 5e9ce3d09..864e36453 100644 --- a/apps/docs/app/[lang]/page.tsx +++ b/apps/docs/app/[lang]/page.tsx @@ -1,8 +1,11 @@ -import Link from 'next/link'; import { Database, FileJson, Layers, ShieldCheck, Zap, Globe, Cpu, LayoutTemplate, Bot } from 'lucide-react'; import { HomeLayout } from 'fumadocs-ui/layouts/home'; import { baseOptions } from '@/app/layout.config'; import { getHomepageTranslations } from '@/lib/homepage-i18n'; +import { HeroSection } from '@/components/hero-section'; +import { CodePreview } from '@/components/code-preview'; +import { FeatureCard } from '@/components/feature-card'; +import { PersonaCard } from '@/components/persona-card'; export default async function HomePage({ params, @@ -17,73 +20,21 @@ export default async function HomePage({
{/* Hero Section */} -
-
- - {t.badge.status} {t.badge.version} -
- -

- {t.hero.title.line1}
{t.hero.title.line2} -

- -

- {t.hero.subtitle.line1} -
- {t.hero.subtitle.line2} -

+ -
- - {t.hero.cta.primary} - - - {t.hero.cta.secondary} - -
- - {/* Code Preview Decorator */} -
-
-
-
-
-
-
- {t.codePreview.filename} -
-
-
-
-                  import {'{'} ObjectProtocol {'}'} from '@objectstack/spec';

- export const Issue = ObjectProtocol.define({'{'}
-   code: 'issue_tracker',
-   fields: {'{'}
-     summary: Field.text({'{'} required: true {'}'}),
-     priority: Field.select(['P0', 'P1', 'P2']),
-     assignee: Field.lookup('users')
-   {'}'},
-   policy: {'{'} audit: true, api_access: 'public' {'}'}
- {'}'}); -
-
-
- {/* Glow Effect behind Code */} -
-
-
+ {/* Code Preview */} + {/* Grid Pattern Background */}
{/* Feature Grid */} -
+
} title={t.features.objectql.title} @@ -124,31 +75,31 @@ export default async function HomePage({ {/* Personas Section */}
-

- {t.personas.heading} +

+ {t.personas.heading}

- } - title={t.personas.architect.title} - description={t.personas.architect.description} - href="/docs/concepts/enterprise-patterns" - action={t.personas.architect.action} - /> - } - title={t.personas.aiEngineer.title} - description={t.personas.aiEngineer.description} - href="/docs/concepts/ai-codex" - action={t.personas.aiEngineer.action} - /> - } - title={t.personas.frameworkBuilder.title} - description={t.personas.frameworkBuilder.description} - href="/docs/specifications/data/architecture" - action={t.personas.frameworkBuilder.action} - /> + } + title={t.personas.architect.title} + description={t.personas.architect.description} + href="/docs/concepts/enterprise-patterns" + action={t.personas.architect.action} + /> + } + title={t.personas.aiEngineer.title} + description={t.personas.aiEngineer.description} + href="/docs/concepts/ai-codex" + action={t.personas.aiEngineer.action} + /> + } + title={t.personas.frameworkBuilder.title} + description={t.personas.frameworkBuilder.description} + href="/docs/specifications/data/architecture" + action={t.personas.frameworkBuilder.action} + />
@@ -157,43 +108,3 @@ export default async function HomePage({ ); } -function FeatureCard({ icon, title, description, href }: { icon: React.ReactNode; title: string; description: string; href?: string }) { - const CardContent = ( -
-
- {icon} -
-

- {title} -

-

- {description} -

-
- ); - - if (href) { - return ( - - {CardContent} - - ); - } - - return CardContent; -} - -function PersonaCard({ icon, title, description, href, action }: { icon: React.ReactNode; title: string; description: string; href: string; action: string }) { - return ( - - {icon} -

{title}

-

- {description} -

-
- {action} -
- - ) -} diff --git a/apps/docs/app/global.css b/apps/docs/app/global.css index 1ad97569a..c1d76161a 100644 --- a/apps/docs/app/global.css +++ b/apps/docs/app/global.css @@ -1,2 +1,14 @@ @import "tailwindcss"; @import "fumadocs-ui/style.css"; + +@layer base { + :root { + --radius: 0.5rem; + } +} + +@layer utilities { + .text-balance { + text-wrap: balance; + } +} diff --git a/apps/docs/components/code-preview.tsx b/apps/docs/components/code-preview.tsx new file mode 100644 index 000000000..5dd183249 --- /dev/null +++ b/apps/docs/components/code-preview.tsx @@ -0,0 +1,71 @@ +import { cn } from '@/lib/utils'; + +interface CodePreviewProps { + filename: string; + className?: string; +} + +export function CodePreview({ filename, className }: CodePreviewProps) { + return ( +
+
+ {/* Window Controls */} +
+
+
+
+
+ {filename} +
+
+ + {/* Code Content */} +
+
+            
+              import{' '}
+              {'{'}{' '}
+              ObjectProtocol{' '}
+              {'}'}{' '}
+              from{' '}
+              '@objectstack/spec';
+              

+ export const{' '} + Issue{' '} + ={' '} + ObjectProtocol. + define + ( + {'{'} +
+   code: 'issue_tracker', +
+   fields: {'{'} +
+     summary: Field.text({'{'} required: true {'}'}), +
+     priority: Field.select(['P0', 'P1', 'P2']), +
+     assignee: Field.lookup('users') +
+   {'}'}, +
+   policy: {'{'}{' '} + audit: true, {' '} + api_access: 'public'{' '} + {'}'} +
+ {'}'}); +
+
+
+
+ + {/* Glow Effect */} +
+
+ ); +} diff --git a/apps/docs/components/feature-card.tsx b/apps/docs/components/feature-card.tsx new file mode 100644 index 000000000..a98fb9e49 --- /dev/null +++ b/apps/docs/components/feature-card.tsx @@ -0,0 +1,40 @@ +import Link from 'next/link'; +import { Card, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; +import { cn } from '@/lib/utils'; + +interface FeatureCardProps { + icon: React.ReactNode; + title: string; + description: string; + href?: string; + className?: string; +} + +export function FeatureCard({ icon, title, description, href, className }: FeatureCardProps) { + const CardContent = ( + +
+ {icon} +
+

+ {title} +

+

+ {description} +

+
+ ); + + if (href) { + return ( + + {CardContent} + + ); + } + + return CardContent; +} diff --git a/apps/docs/components/hero-section.tsx b/apps/docs/components/hero-section.tsx new file mode 100644 index 000000000..8133cbc2b --- /dev/null +++ b/apps/docs/components/hero-section.tsx @@ -0,0 +1,69 @@ +import Link from 'next/link'; +import { Badge } from '@/components/ui/badge'; +import { cn } from '@/lib/utils'; + +interface HeroSectionProps { + badge: { + status: string; + version: string; + }; + title: { + line1: string; + line2: string; + }; + subtitle: { + line1: string; + line2: string; + }; + cta: { + primary: string; + secondary: string; + }; + className?: string; +} + +export function HeroSection({ badge, title, subtitle, cta, className }: HeroSectionProps) { + return ( +
+ {/* Badge */} +
+ + {badge.status} + + {badge.version} +
+ + {/* Title */} +

+ {title.line1} +
+ {title.line2} +

+ + {/* Subtitle */} +

+ {subtitle.line1} +
+ + {subtitle.line2} + +

+ + {/* CTA Buttons */} +
+ + {cta.primary} + + + {cta.secondary} + +
+
+ ); +} diff --git a/apps/docs/components/persona-card.tsx b/apps/docs/components/persona-card.tsx new file mode 100644 index 000000000..39e54a0e4 --- /dev/null +++ b/apps/docs/components/persona-card.tsx @@ -0,0 +1,38 @@ +import Link from 'next/link'; +import { ArrowRight } from 'lucide-react'; +import { Card } from '@/components/ui/card'; +import { cn } from '@/lib/utils'; + +interface PersonaCardProps { + icon: React.ReactNode; + title: string; + description: string; + href: string; + action: string; + className?: string; +} + +export function PersonaCard({ icon, title, description, href, action, className }: PersonaCardProps) { + return ( + + +
+ {icon} +
+

+ {title} +

+

+ {description} +

+
+ {action} + +
+
+ + ); +} diff --git a/apps/docs/components/ui/badge.tsx b/apps/docs/components/ui/badge.tsx new file mode 100644 index 000000000..ef315a633 --- /dev/null +++ b/apps/docs/components/ui/badge.tsx @@ -0,0 +1,39 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + outline: "text-foreground border-border", + success: + "border-transparent bg-green-500 text-white hover:bg-green-500/80", + warning: + "border-transparent bg-yellow-500 text-white hover:bg-yellow-500/80", + destructive: + "border-transparent bg-red-500 text-white hover:bg-red-500/80", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ) +} + +export { Badge, badgeVariants } diff --git a/apps/docs/components/ui/button.tsx b/apps/docs/components/ui/button.tsx new file mode 100644 index 000000000..9b9557e20 --- /dev/null +++ b/apps/docs/components/ui/button.tsx @@ -0,0 +1,52 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow-lg shadow-primary/20 hover:bg-primary/90 hover:scale-105 hover:shadow-primary/30", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + outline: + "border border-border bg-card/50 backdrop-blur-sm hover:bg-accent hover:text-accent-foreground hover:scale-105", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-12 px-8 py-3", + sm: "h-9 px-4 py-2", + lg: "h-14 px-10 py-4", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, ...props }, ref) => { + return ( +