| import { useEffect, useState } from "react"; |
| import { ArchitectureSection } from "./components/ArchitectureSection"; |
| import { ContractsSection } from "./components/ContractsSection"; |
| import { DocsPortal } from "./components/DocsPortal"; |
| import { FaqSection } from "./components/FaqSection"; |
| import { FooterCta } from "./components/FooterCta"; |
| import { Hero } from "./components/Hero"; |
| import { OverviewGrid } from "./components/OverviewGrid"; |
| import { RouteMatrix } from "./components/RouteMatrix"; |
| import { Section } from "./components/Section"; |
| import { StudioSection } from "./components/StudioSection"; |
| import { TopNav } from "./components/TopNav"; |
| import { WorkflowShowcase } from "./components/WorkflowShowcase"; |
| import { getConfig, getContent, getContracts } from "./content/api"; |
| import type { AppConfig, ContentResponse, ContractMap } from "./content/types"; |
|
|
| function App() { |
| const [content, setContent] = useState<ContentResponse | null>(null); |
| const [config, setConfig] = useState<AppConfig | null>(null); |
| const [contracts, setContracts] = useState<ContractMap | null>(null); |
| const [error, setError] = useState<string | null>(null); |
|
|
| useEffect(() => { |
| async function bootstrap() { |
| try { |
| const [nextConfig, nextContent, nextContracts] = await Promise.all([ |
| getConfig(), |
| getContent(), |
| getContracts(), |
| ]); |
| setConfig(nextConfig); |
| setContent(nextContent); |
| setContracts(nextContracts); |
| } catch (caughtError) { |
| setError(caughtError instanceof Error ? caughtError.message : "Failed to load app"); |
| } |
| } |
|
|
| void bootstrap(); |
| }, []); |
|
|
| if (error) { |
| return ( |
| <main className="app-shell centered"> |
| <div className="shell-block error-card"> |
| <h1>Unable to load Aether Voice Studio</h1> |
| <p>{error}</p> |
| </div> |
| </main> |
| ); |
| } |
|
|
| if (!content || !config || !contracts) { |
| return ( |
| <main className="app-shell centered"> |
| <div className="shell-block loading-card"> |
| <h1>Loading Aether Voice Studio</h1> |
| <p>Preparing the docs surface, route matrix, and demo contracts.</p> |
| </div> |
| </main> |
| ); |
| } |
|
|
| return ( |
| <main className="app-shell"> |
| <TopNav |
| links={content.site.navigation} |
| secondaryLinks={content.site.secondaryLinks} |
| demoMode={config.demoMode} |
| /> |
| <Hero hero={content.site.hero} demoMode={config.demoMode} /> |
| |
| <Section |
| id="overview" |
| kicker="Product overview" |
| title="Aether Voice Studio spans live, studio, registry, and route-aware product lanes." |
| description="This v1 positions the platform as a premium product surface and technical entrypoint rather than a production inference cluster." |
| > |
| <OverviewGrid features={content.features} /> |
| </Section> |
| |
| <Section |
| id="studio" |
| kicker="Aether Voice Studio" |
| title="Separate immediate TTS from long-form voice production." |
| description="The platform keeps fast preview workflows distinct from studio-grade cloning, design, and dialogue assembly." |
| > |
| <StudioSection narrative={content.site.studioNarrative} seedLibrary={content.seedLibrary} /> |
| </Section> |
| |
| <Section |
| id="routes" |
| kicker="Route / Model Matrix" |
| title="Canonical route intelligence is visible, not hidden." |
| description="Each route is tied to a workflow class, output contract, and UI surface so the system reads as infrastructure rather than generic AI glue." |
| > |
| <RouteMatrix routes={content.routes} /> |
| </Section> |
| |
| <Section |
| id="demos" |
| kicker="Demo workflows" |
| title="Public-safe demos still signal real operational structure." |
| description="The workflow panel is lightweight by design and remains useful with local content only." |
| aside={<span className="route-pill">Port {config.singlePort}</span>} |
| > |
| <WorkflowShowcase |
| demoWorkflows={content.workflows.demo} |
| creatorWorkflows={content.workflows.creator} |
| enterpriseWorkflows={content.workflows.enterprise} |
| demoMode={config.demoMode} |
| /> |
| </Section> |
| |
| <Section |
| id="docs" |
| kicker="Docs entry" |
| title="The Space doubles as a docs-style portal." |
| description="Overview, architecture, routing, registry, and troubleshooting entry points are organized as a clean documentation surface." |
| > |
| <DocsPortal entries={content.docsNav} /> |
| </Section> |
| |
| <Section |
| id="architecture" |
| kicker="Architecture" |
| title="Frontend, routing, registries, and artifacts are deliberately separated." |
| description="That separation makes the Space credible today and extendable into richer docs or interactive flows later." |
| > |
| <ArchitectureSection layers={content.architecture} /> |
| </Section> |
| |
| <Section |
| id="contracts" |
| kicker="Data Contracts" |
| title="Machine-readable shapes are public by design." |
| description="The registry, route matrix, seed library, and provider config are exposed as JSON contracts to signal automation-native architecture." |
| > |
| <ContractsSection contracts={contracts} /> |
| </Section> |
| |
| <Section |
| id="faq" |
| kicker="FAQ" |
| title="Concise answers for route strategy, studio boundaries, and platform vocabulary." |
| description="The v1 Space emphasizes clarity over gimmicks." |
| > |
| <FaqSection faq={content.faq} /> |
| </Section> |
| |
| <FooterCta cta={content.site.cta} /> |
| </main> |
| ); |
| } |
|
|
| export default App; |
|
|