Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ const withMDX = createMDX();
const config = {
output: 'export',
reactStrictMode: true,
images: {
unoptimized: true,
},
};

export default withMDX(config);
Binary file added public/assets/hero-demo.mp4
Binary file not shown.
Binary file added public/assets/hero-poster.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
160 changes: 90 additions & 70 deletions src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,73 @@
import Link from 'next/link';
import {
Blocks,
Palette,
ShieldCheck,
Package,
Code,
ArrowRight,
LayoutGrid,
} from 'lucide-react';
import type { Metadata } from 'next';
import { Package, ArrowRight, LayoutGrid } from 'lucide-react';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { CopyCommand } from '@/components/copy-command';
import { FaqAccordion } from '@/components/faq-accordion';
import { InstallTabs } from '@/components/install-tabs';
import { pubDevUrl, showcaseUrl } from '@/lib/shared';

const features = [
export const metadata: Metadata = {
alternates: { canonical: '/' },
openGraph: { images: '/og/home' },
twitter: { images: '/og/home' },
};

const installCommands = [
{ label: 'Flutter', command: 'flutter pub add fossui' },
{
icon: Package,
title: 'One import',
description: 'A full set of components from a single package. No per-widget imports.',
label: 'MCP',
command: 'claude mcp add --transport http fossui https://mcp.fossui.org/mcp',
},
{ label: 'AI Skill', command: 'npx skills add fossui/ai' },
];

const faqs = [
{
icon: Palette,
title: 'Themed',
description: 'A single FossThemeData drives color, type, radius, spacing, and motion.',
question: 'Does fossui lock me into MaterialApp or any app shell?',
answer:
'No wrapper lock-in. FossTheme drops into any app, and context.fossTheme resolves identically under MaterialApp, CupertinoApp, or a bare WidgetsApp.',
},
{
icon: Blocks,
title: 'Framework agnostic',
description: 'Works under MaterialApp, CupertinoApp, or a bare WidgetsApp.',
question: 'How lightweight is fossui?',
answer:
'One runtime dependency, around 314 KB. Pure Dart, no native code, no bundled icon package.',
},
{
icon: ShieldCheck,
title: 'Accessible',
description: 'Semantics, focus, and contrast built in, sized for touch.',
question: 'Does fossui work with AI coding assistants over MCP?',
answer:
'Yes. The fossui MCP server at mcp.fossui.org works with any MCP client over Streamable HTTP, not just Claude Code. It serves the exact component API so an assistant looks up the real API instead of guessing it.',
},
{
icon: Code,
title: 'Pure Dart',
description: 'No native code, one tiny dependency. Nothing else to pull in.',
wide: true,
question: 'Is there an AI coding skill for fossui?',
answer:
'Yes. Install it with npx skills add fossui/ai, not just for Claude Code, it installs across many AI coding agents. It carries the same idioms as the MCP server so AI-written fossui code compiles and stays on-theme on the first try.',
},
];

const faqJsonLd = {
'@context': 'https://schema.org',
'@type': 'FAQPage',
mainEntity: faqs.map((faq) => ({
'@type': 'Question',
name: faq.question,
acceptedAnswer: { '@type': 'Answer', text: faq.answer },
})),
};

export default function HomePage() {
return (
<main className="mx-auto flex min-h-[calc(100svh-3.5rem)] w-full max-w-4xl flex-1 flex-col justify-center gap-6 px-4 py-6 sm:gap-10 sm:py-8">
<section className="flex w-full flex-col items-center gap-4 text-center sm:gap-5">
<div className="flex flex-wrap items-center justify-center gap-2">
<Badge variant="outline">Open source, MIT</Badge>
<Badge variant="outline">v0.1.0</Badge>
</div>
<h1 className="text-5xl font-semibold tracking-tighter sm:text-7xl">fossui</h1>
<p className="max-w-md text-base text-muted-foreground text-balance sm:max-w-xl sm:text-lg">
A Flutter UI kit themed from one source. Framework-agnostic,
accessible, one import.
<main className="mx-auto flex w-full max-w-[1100px] flex-1 flex-col gap-16 px-4 py-10 sm:py-14">
{/* Hero: text-only for v1, no placeholder image */}
<section className="flex w-full flex-col items-center gap-4 text-center">
<Badge variant="outline">Open source, MIT</Badge>
<h1 className="max-w-2xl text-4xl font-semibold tracking-tighter text-balance sm:text-6xl">
A Flutter UI kit with its own identity.
</h1>
<p className="max-w-xl text-base text-muted-foreground text-balance sm:text-lg">
A minimal, lightweight Flutter component set for developers tired of every
app looking like Material. Drops into any Flutter app, no heavy
dependencies.
</p>
<div className="mt-1 flex flex-wrap items-center justify-center gap-3">
<Button size="lg" render={<Link href="/docs" />}>
Expand All @@ -67,50 +80,57 @@ export default function HomePage() {
render={<a href={showcaseUrl} target="_blank" rel="noreferrer" />}
>
<LayoutGrid />
Live gallery
Live playground
</Button>
<Button
size="lg"
variant="ghost"
variant="link"
render={<a href={pubDevUrl} target="_blank" rel="noreferrer" />}
>
<Package />
pub.dev
pub.dev &middot; 160/160
</Button>
</div>
<CopyCommand command="flutter pub add fossui" />
<InstallTabs options={installCommands} />
<p className="max-w-md text-xs text-muted-foreground text-balance">
Design inspired by coss.com/ui, Cal.com&apos;s design system: a clean,
minimal, modern web aesthetic.
</p>
<video
src="/assets/hero-demo.mp4"
poster="/assets/hero-poster.png"
autoPlay
muted
loop
playsInline
className="mt-4 w-full max-w-3xl rounded-2xl border"
/>
</section>

<section className="grid w-full grid-cols-2 gap-3">
{features.map((f) => (
<Card
key={f.title}
className={`transition-colors hover:border-foreground/20 hover:bg-accent/50${f.wide ? ' col-span-2' : ''}`}
>
<CardHeader
className={
f.wide
? 'grid-cols-[auto_1fr] items-center gap-3 p-4'
: 'gap-1.5 p-4'
}
>
<div className="flex size-9 shrink-0 items-center justify-center rounded-lg border bg-muted">
<f.icon className="size-4 text-foreground/80" />
</div>
<div className={f.wide ? 'flex flex-col gap-1' : 'contents'}>
<CardTitle className="text-base font-medium">{f.title}</CardTitle>
<CardDescription className="text-sm leading-relaxed">
{f.description}
</CardDescription>
</div>
</CardHeader>
</Card>
))}
{/* FAQ: answers the queries people actually search or ask a chatbot */}
<section className="flex w-full flex-col gap-6">
<div className="flex flex-col items-center gap-2 text-center">
<h2 className="text-2xl font-semibold tracking-tight">Frequently asked questions</h2>
<p className="text-sm text-muted-foreground">
Build Flutter UI faster. If you don&apos;t find what you need here, reach us at{' '}
<a href="mailto:support@fossui.org" className="font-medium underline underline-offset-2">
support@fossui.org
</a>
.
</p>
</div>
<FaqAccordion items={faqs} />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(faqJsonLd) }}
/>
</section>

<footer className="w-full text-center text-xs text-muted-foreground">
fossui is unofficial and not affiliated with, or endorsed by, Cal.com,
Inc.
<footer className="flex w-full flex-col items-center gap-1.5 border-t pt-8 text-center text-xs text-muted-foreground">
<p>
fossui is unofficial and not affiliated with, or endorsed by, Cal.com, Inc.
</p>
<p>&copy; 2026 fossui. All rights reserved.</p>
</footer>
</main>
);
Expand Down
Loading
Loading