Skip to content
Merged
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
8 changes: 8 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import Navbar from './components/Navbar'
import Hero from './components/Hero'
import ProblemBar from './components/ProblemBar'
import StatsBar from './components/StatsBar'
import ProductOverview from './components/ProductOverview'
import WorkflowShowcase from './components/WorkflowShowcase'
import MCPDeepDive from './components/MCPDeepDive'
import SkillsShowcase from './components/SkillsShowcase'
import TokenComparison from './components/TokenComparison'
import Dogfooding from './components/Dogfooding'
import FeatureGrid from './components/FeatureGrid'
import PricingPreview from './components/PricingPreview'
Expand All @@ -14,8 +18,12 @@ export default function App() {
<Navbar />
<Hero />
<ProblemBar />
<StatsBar />
<ProductOverview />
<WorkflowShowcase />
<MCPDeepDive />
<SkillsShowcase />
<TokenComparison />
<Dogfooding />
<FeatureGrid />
<PricingPreview />
Expand Down
184 changes: 184 additions & 0 deletions src/components/AppMockup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import { motion } from 'framer-motion'

/* ────────────────────────────────────────────
Stylised app mockup — suggests the DevFlow
workspace without revealing the actual UI.
Pure CSS shapes, no screenshots.
──────────────────────────────────────────── */

const shimmer =
'bg-gradient-to-r from-transparent via-white/[0.03] to-transparent bg-[length:200%_100%] animate-[shimmer_3s_ease-in-out_infinite]'

function Bar({ w, color = 'bg-text-muted/15' }: { w: string; color?: string }) {
return <div className={`h-2 rounded-full ${color} ${w}`} />
}

function KanbanCard({ delay }: { delay: number }) {
return (
<motion.div
className="rounded-md bg-bg/60 border border-white/[0.04] p-2.5 space-y-2"
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay }}
>
<Bar w="w-4/5" />
<Bar w="w-3/5" color="bg-text-muted/10" />
<div className="flex items-center gap-1.5 pt-1">
<div className="w-4 h-4 rounded-full bg-indigo/25" />
<Bar w="w-10" color="bg-text-muted/8" />
</div>
</motion.div>
)
}

function KanbanColumn({
label,
accent,
cards,
delay,
}: {
label: string
accent: string
cards: number
delay: number
}) {
return (
<div className="flex-1 min-w-0 space-y-2.5">
<div className="flex items-center gap-2 px-1 mb-3">
<div className={`w-2 h-2 rounded-full ${accent}`} />
<span className="text-[10px] font-medium text-text-muted/60 uppercase tracking-wider truncate">
{label}
</span>
<span className="text-[9px] text-text-muted/30 ml-auto">{cards}</span>
</div>
{Array.from({ length: cards }).map((_, i) => (
<KanbanCard key={i} delay={delay + i * 0.08} />
))}
</div>
)
}

function TerminalLine({ prompt, text, delay }: { prompt: string; text: string; delay: number }) {
return (
<motion.div
className="flex gap-2 text-[10px] font-mono leading-relaxed"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.4, delay }}
>
<span className="text-indigo/60 shrink-0">{prompt}</span>
<span className="text-text-muted/50">{text}</span>
</motion.div>
)
}

export default function AppMockup() {
return (
<div className="relative rounded-t-xl border border-b-0 border-border bg-bg-raised overflow-hidden shadow-2xl shadow-indigo-glow/20">
{/* Chrome bar */}
<div className="flex items-center gap-2 px-4 py-3 border-b border-border">
<div className="w-3 h-3 rounded-full bg-[#ff5f57]" />
<div className="w-3 h-3 rounded-full bg-[#febc2e]" />
<div className="w-3 h-3 rounded-full bg-[#28c840]" />
<span className="ml-2 text-xs text-text-muted/50 font-mono">DevFlow</span>
</div>

{/* App body */}
<div className="flex h-[340px] sm:h-[400px]">
{/* Sidebar */}
<div className="w-44 shrink-0 border-r border-white/[0.04] bg-bg/40 p-3 hidden sm:flex flex-col gap-1">
{/* Repo selector */}
<div className="flex items-center gap-2 rounded-md bg-white/[0.03] px-2.5 py-2 mb-3">
<div className="w-5 h-5 rounded bg-indigo/20" />
<Bar w="w-20" color="bg-text-muted/20" />
</div>

{/* Nav items */}
{[
{ active: true, label: 'Kanban' },
{ active: false, label: 'Notes' },
{ active: false, label: 'Learning' },
{ active: false, label: 'Ideas' },
{ active: false, label: 'Workflows' },
{ active: false, label: 'PRs' },
].map((item) => (
<div
key={item.label}
className={`flex items-center gap-2.5 rounded-md px-2.5 py-1.5 ${
item.active
? 'bg-indigo/10 border border-indigo/15'
: 'border border-transparent'
}`}
>
<div
className={`w-3.5 h-3.5 rounded ${
item.active ? 'bg-indigo/40' : 'bg-text-muted/10'
}`}
/>
<span
className={`text-[10px] font-medium ${
item.active ? 'text-indigo-light/70' : 'text-text-muted/30'
}`}
>
{item.label}
</span>
</div>
))}

{/* Spacer */}
<div className="flex-1" />

{/* Agent status */}
<div className="rounded-md bg-white/[0.02] border border-white/[0.04] p-2 space-y-1.5">
<div className="flex items-center gap-1.5">
<div className="w-1.5 h-1.5 rounded-full bg-[#28c840] animate-pulse" />
<span className="text-[9px] text-text-muted/40 font-mono">Claude Code</span>
</div>
<Bar w="w-full" color="bg-indigo/10" />
</div>
</div>

{/* Main content area */}
<div className="flex-1 flex flex-col min-w-0">
{/* Kanban area */}
<div className={`flex-1 p-4 overflow-hidden ${shimmer}`}>
<div className="flex gap-3 h-full">
<KanbanColumn label="To Do" accent="bg-text-muted/30" cards={3} delay={0.6} />
<KanbanColumn label="In Progress" accent="bg-indigo" cards={2} delay={0.8} />
<KanbanColumn label="In Review" accent="bg-peach" cards={1} delay={1.0} />
<KanbanColumn
label="Done"
accent="bg-[#28c840]"
cards={2}
delay={1.1}
/>
</div>
</div>

{/* Terminal strip */}
<div className="border-t border-white/[0.04] bg-bg/60 px-4 py-3 space-y-1.5">
<div className="flex items-center gap-3 mb-2">
<div className="flex gap-1">
{['Claude Code', 'Terminal'].map((tab, i) => (
<span
key={tab}
className={`text-[9px] font-mono px-2 py-0.5 rounded ${
i === 0
? 'bg-indigo/15 text-indigo-light/60'
: 'text-text-muted/25'
}`}
>
{tab}
</span>
))}
</div>
</div>
<TerminalLine prompt="$" text="get_project_context()" delay={1.2} />
<TerminalLine prompt="→" text="3 active tasks, 2 blockers, 8 learning entries" delay={1.4} />
<TerminalLine prompt="$" text="get_task_details({ card_id: 142 })" delay={1.6} />
</div>
</div>
</div>
</div>
)
}
2 changes: 1 addition & 1 deletion src/components/Dogfooding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import AnimatedSection from './AnimatedSection'

export default function Dogfooding() {
return (
<AnimatedSection className="py-28">
<AnimatedSection className="py-28 border-t border-border">
<div className="mx-auto max-w-3xl px-6 text-center">
<span className="inline-block rounded-full bg-indigo/10 border border-indigo/20 px-3 py-1 text-xs font-medium text-indigo-light font-mono mb-6">
DOGFOODING
Expand Down
18 changes: 14 additions & 4 deletions src/components/FeatureGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { motion } from 'framer-motion'
import AnimatedSection from './AnimatedSection'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faServer, faArrowRightArrowLeft, faLightbulb, faGraduationCap, faCodePullRequest, faPlay, faMagnifyingGlass, faClipboardList, faMoon, faCircleCheck } from '@fortawesome/pro-regular-svg-icons'
import { faServer, faArrowRightArrowLeft, faLightbulb, faGraduationCap, faCodePullRequest, faPlay, faMagnifyingGlass, faClipboardList, faMoon, faCircleCheck, faRoute, faWandMagicSparkles } from '@fortawesome/pro-regular-svg-icons'
import type { IconDefinition } from '@fortawesome/fontawesome-svg-core'

const features: { title: string; description: string; icon: IconDefinition }[] = [
{
title: 'MCP Server',
description: 'Live repo context for any AI agent',
description: 'Live repo context — zero upfront injection, always current, write access included',
icon: faServer,
},
{
Expand Down Expand Up @@ -55,18 +55,28 @@ const features: { title: string; description: string; icon: IconDefinition }[] =
description: "We use it. That's the proof.",
icon: faCircleCheck,
},
{
title: 'Workflows',
description: 'Goal → AI discussion → phased roadmap',
icon: faRoute,
},
{
title: 'Skills',
description: 'Auto-discovered slash commands for every agent',
icon: faWandMagicSparkles,
},
]

export default function FeatureGrid() {
return (
<AnimatedSection className="py-28 bg-bg-raised border-y border-border">
<AnimatedSection className="py-28 bg-bg-raised border-t border-border">
<div className="mx-auto max-w-6xl px-6">
<div className="text-center mb-16">
<span className="inline-block rounded-full bg-indigo/10 border border-indigo/20 px-3 py-1 text-xs font-medium text-indigo-light font-mono mb-4">
FEATURES
</span>
<h2 className="text-3xl sm:text-4xl font-heading font-bold text-cream tracking-tight">
10 power features
12 power features
</h2>
<p className="mt-4 text-text-muted max-w-lg mx-auto">
Everything technical leads and small teams need to ship with AI agents.
Expand Down
8 changes: 6 additions & 2 deletions src/components/FooterCTA.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,19 @@ export default function FooterCTA() {
<footer className="border-t border-border py-8">
<div className="mx-auto max-w-6xl px-6 flex flex-col sm:flex-row items-center justify-between gap-4 text-sm text-text-muted">
<div className="flex items-center gap-2">
<img src="https://assets.craigcallen.com/media/devflowcode/tertiary-logo-inverse.svg" alt="DevFlow" className="h-10" />
<img
src="https://assets.craigcallen.com/media/devflowcode/tertiary-logo-inverse.svg"
alt="DevFlow"
className="h-10"
/>
</div>
<div className="flex items-center gap-4">
<span>macOS</span>
<span className="text-border">|</span>
<span>Free Beta</span>
<span className="text-border">|</span>
<a
href="https://github.com/craigcallen/devflowcode.com"
href="https://github.com/craigcallen/devflowcode.com/blob/main/README.md"
target="_blank"
rel="noopener noreferrer"
className="hover:text-cream transition-colors"
Expand Down
15 changes: 4 additions & 11 deletions src/components/Hero.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { motion } from 'framer-motion'
import EmailCapture from './EmailCapture'
import AppMockup from './AppMockup'

export default function Hero() {
return (
Expand Down Expand Up @@ -72,22 +73,14 @@ export default function Hero() {
Built inside DevFlow. Every feature you see was designed, tracked, and shipped here.
</motion.p>

{/* App screenshot placeholder */}
{/* Stylised app mockup */}
<motion.div
className="mt-16 mx-auto max-w-3xl rounded-t-xl border border-b-0 border-border bg-bg-raised overflow-hidden shadow-2xl shadow-indigo-glow/20"
className="mt-16 mx-auto max-w-3xl"
initial={{ opacity: 0, y: 40 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.4, ease: [0.25, 0.1, 0.25, 1] }}
>
<div className="flex items-center gap-2 px-4 py-3 border-b border-border">
<div className="w-3 h-3 rounded-full bg-[#ff5f57]" />
<div className="w-3 h-3 rounded-full bg-[#febc2e]" />
<div className="w-3 h-3 rounded-full bg-[#28c840]" />
<span className="ml-2 text-xs text-text-muted font-mono">DevFlow — devflowcode.com</span>
</div>
<div className="aspect-[16/9] bg-bg flex items-center justify-center">
<img src="https://assets.craigcallen.com/media/devflowcode/devflow-screenshot.png"></img>
</div>
<AppMockup />
</motion.div>
</div>
</section>
Expand Down
14 changes: 9 additions & 5 deletions src/components/MCPDeepDive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,28 @@ const codeSnippet = `// claude_desktop_config.json
> get_learning_context()`

const points = [
'Zero upfront injection \u2014 agents fetch exactly what they need, when they need it',
'Every tool call returns live data — not a stale snapshot from session start',
'Agents don\u2019t just read your project — they create tasks, log decisions, and move cards',
'One config copy per agent — paste it, connect, done',
'Context scoped to the active repo automatically',
'Works with Claude Code, Codex, Gemini, and any MCP-compatible agent',
'Drag a card to In Progress — agent launches with full context',
]

export default function MCPDeepDive() {
return (
<AnimatedSection className="py-28 bg-bg-raised border-y border-border" id="mcp">
<AnimatedSection className="py-28 bg-bg-raised border-t border-border" id="mcp">
<div className="mx-auto max-w-6xl px-6">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
<div>
<span className="inline-block rounded-full bg-indigo/10 border border-indigo/20 px-3 py-1 text-xs font-medium text-indigo-light font-mono mb-6">
MCP PROTOCOL
</span>
<h2 className="text-3xl sm:text-4xl font-heading font-bold text-cream tracking-tight mb-6">
Your AI agents finally know what's going on
<h2 className="text-3xl sm:text-4xl font-heading font-bold text-cream tracking-tight mb-4">
Zero upfront context. Always current. Write access included.
</h2>
<p className="text-lg text-cream/80 font-medium mb-4">
Your AI agents finally know what's going on
</p>
<p className="text-text-muted leading-relaxed mb-8">
DevFlow runs a local MCP server that exposes your entire project —
tasks, notes, learning entries, repo context, PR history — to any
Expand Down
8 changes: 6 additions & 2 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ export default function Navbar() {
>
<div className="mx-auto max-w-6xl px-6 flex items-center justify-between h-16">
<a href="#">
<img src="https://assets.craigcallen.com/media/devflowcode/tertiary-logo-inverse.svg" alt="DevFlow" className="h-10" />
<img
src="https://assets.craigcallen.com/media/devflowcode/tertiary-logo-inverse.svg"
alt="DevFlow"
className="h-10"
/>
</a>

<div className="hidden md:flex items-center gap-8 text-sm text-text-muted">
Expand All @@ -35,7 +39,7 @@ export default function Navbar() {
Pricing
</a>
<a
href="https://github.com/craigcallen/devflowcode.com"
href="https://github.com/craigcallen/devflowcode.com/blob/main/README.md"
target="_blank"
rel="noopener noreferrer"
className="hover:text-cream transition-colors"
Expand Down
2 changes: 1 addition & 1 deletion src/components/PricingPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const plans = [

export default function PricingPreview() {
return (
<AnimatedSection className="py-28" id="pricing">
<AnimatedSection className="py-28 border-t border-border" id="pricing">
<div className="mx-auto max-w-4xl px-6">
<div className="text-center mb-16">
<span className="inline-block rounded-full bg-indigo/10 border border-indigo/20 px-3 py-1 text-xs font-medium text-indigo-light font-mono mb-4">
Expand Down
Loading
Loading