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
14 changes: 13 additions & 1 deletion src/app/page.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Image from 'next/image'
import Link from 'next/link'
import { ArrowRightIcon } from '@heroicons/react/24/outline'
import { Cpu } from 'lucide-react'

import {FooterMarketing} from '@/components/FooterMarketing';
import {HeaderSparse} from '@/components/HeaderSparse';
Expand Down Expand Up @@ -28,7 +29,7 @@ export default function Page() {
<div>
<HeaderSparse />

<div className="bg-irohGray-50 dark:bg-irohGray-900 text-irohGray-700 dark:text-irohGray-100 h-92 justify-between font-space">
<div className="bg-white dark:bg-irohGray-900 text-irohGray-700 dark:text-irohGray-100 h-92 justify-between font-space">
<main className="mb-auto flex flex-col min-h-92">
{/* hero */}
<section className="min-h-92 pt-20 bg-cover" style={{ height: 600 }}>
Expand Down Expand Up @@ -147,6 +148,17 @@ export default function Page() {
</div>
</div>
</Link>
<Link href="/solutions/iot" className="block">
<div className="grid md:grid-cols-3 gap-6 items-center p-6 border border-irohGray-300 dark:border-irohGray-700 rounded-lg hover:border-irohPurple-500 transition-colors">
<div className="md:col-span-2">
<p className="text-xl font-medium text-irohGray-800 dark:text-irohGray-100 mb-2">IoT & Embedded Devices</p>
<p className="text-irohGray-600 dark:text-irohGray-300">Run iroh on ESP32, Raspberry Pi, and Linux with the same API. Devices discover each other automatically — no brokers, no gateways.</p>
</div>
<div className="flex items-center justify-center">
<Cpu className="h-16 w-16 text-irohPurple-500" strokeWidth={1.5} />
</div>
</div>
</Link>
</div>
</section>

Expand Down
2 changes: 1 addition & 1 deletion src/app/providers.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const AppContext = createContext({})

export function Providers({ children }) {
return (
<ThemeProvider attribute="class" disableTransitionOnChange>
<ThemeProvider attribute="class" defaultTheme="light" disableTransitionOnChange>
<ThemeWatcher />
{children}
</ThemeProvider>
Expand Down
130 changes: 130 additions & 0 deletions src/app/solutions/iot/page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { Button } from "@/components/Button"
import { HeaderSparse } from '@/components/HeaderSparse'
import { FooterMarketing } from "@/components/FooterMarketing"
import Link from "next/link"
import { DiscoveryDiagram } from "@/components/DiscoveryDiagram"

export const metadata = {
title: 'Iroh for IoT & Embedded Devices',
description: 'Connect embedded devices directly with iroh. Run on ESP32, Raspberry Pi, and Linux. No brokers, no gateways.',
}

const devices = [
{ name: "Raspberry Pi", note: "Fully supported" },
{ name: "ESP32", note: "4 MiB flash / 2 MiB RAM" },
{ name: "Linux SBCs", note: "x86_64 and ARM" },
{ name: "FreeRTOS", note: "Microcontroller-class" },
]

export default function IoTUseCasePage() {
return (
<div>
<HeaderSparse />

<div className="min-h-screen transition-colors font-space bg-irohGray-50 dark:bg-irohGray-900 text-irohGray-700 dark:text-irohGray-100">
{/* Hero */}
<section className="py-24 px-6 border-b border-irohGray-300 dark:border-irohGray-800">
<div className="container mx-auto max-w-4xl pt-12 text-center">
<p className="text-irohPurple-500 font-medium mb-4 uppercase tracking-wide">IoT & Embedded</p>
<h1 className="text-5xl md:text-6xl mb-6 leading-tight font-bold">
Connect every device, everywhere
</h1>
<p className="text-xl text-irohGray-600 dark:text-irohGray-300 mb-8 leading-relaxed max-w-2xl mx-auto">
Run iroh on ESP32, Raspberry Pi, and Linux with the same API.
No brokers, no gateways.
</p>
<div className="flex gap-4 flex-wrap justify-center">
<Link href="https://docs.iroh.computer/quickstart">
<Button arrow="none" className="bg-irohGray-800 hover:bg-irohGray-700 text-irohPurple-500 px-6 py-2 text-sm font-medium cursor-pointer uppercase">
Get Started
</Button>
</Link>
<Link href="https://cal.com/team/number-0/iroh-services">
<Button arrow="none" variant="outline" className="border-irohGray-300 dark:border-irohGray-600 px-6 py-2 text-sm font-medium cursor-pointer bg-transparent">
Talk to Us
</Button>
</Link>
</div>
</div>
</section>

{/* Discovery */}
<section className="py-20 px-6 border-b border-irohGray-300 dark:border-irohGray-800">
<div className="container mx-auto max-w-6xl">
<div className="grid md:grid-cols-12 gap-12 items-center">
<div className="md:col-span-4">
<p className="text-irohPurple-500 font-medium mb-3 uppercase tracking-wide text-sm">Automatic Discovery</p>
<h2 className="text-4xl font-bold mb-6">Devices find each other</h2>
<p className="text-lg text-irohGray-600 dark:text-irohGray-300 leading-relaxed">
Power on a device and it announces itself on the local network.
Peers connect directly over Wi-Fi, Ethernet, or Bluetooth — no
broker, no manual pairing, no cloud round-trip.
</p>
</div>
<div className="md:col-span-8">
<DiscoveryDiagram className="w-full" />
</div>
</div>
</div>
</section>

{/* Device Support */}
<section className="py-20 px-6 border-b border-irohGray-300 dark:border-irohGray-800">
<div className="container mx-auto max-w-5xl text-center">
<h2 className="text-4xl font-bold mb-4">From microcontroller to cloud</h2>
<p className="text-lg text-irohGray-600 dark:text-irohGray-300 mb-12 max-w-2xl mx-auto">
The same API runs across the full range of hardware a connected product touches.
</p>
<div className="grid grid-cols-2 md:grid-cols-4 gap-6">
{devices.map((device) => (
<div
key={device.name}
className="p-6 border border-irohGray-300 dark:border-irohGray-700 rounded-lg"
>
<h3 className="text-xl font-bold mb-2">{device.name}</h3>
<p className="text-sm text-irohGray-600 dark:text-irohGray-300">{device.note}</p>
</div>
))}
</div>
<p className="text-sm text-irohGray-600 dark:text-irohGray-400 mt-8">
See the full{" "}
<Link href="https://docs.iroh.computer/compatibility" className="text-irohPurple-500 hover:underline">
compatibility matrix
</Link>.
</p>
</div>
</section>

{/* CTA */}
<section className="py-20 px-6">
<div className="container mx-auto max-w-4xl text-center">
<h2 className="text-3xl font-bold mb-6">
Ship devices that just work
</h2>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link href="https://docs.iroh.computer/quickstart">
<Button
arrow="none"
className="bg-irohGray-800 hover:bg-irohGray-700 text-irohPurple-500 px-8 py-3"
>
Read the Docs
</Button>
</Link>
<Link href="https://cal.com/team/number-0/iroh-services">
<Button
arrow="none"
variant="outline"
className="border-irohGray-300 dark:border-irohGray-600 hover:bg-irohGray-100 dark:hover:bg-irohGray-800 px-8 py-3 bg-transparent"
>
Talk to Us
</Button>
</Link>
</div>
</div>
</section>

<FooterMarketing />
</div>
</div>
)
}
7 changes: 7 additions & 0 deletions src/app/solutions/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ const solutions = [
logo: "paycode",
logoExt: "svg",
},
{
category: "IoT & Embedded Devices",
company: "IoT",
headline: "Connect Every Device, Everywhere",
description: "Run iroh on ESP32, Raspberry Pi, and Linux with the same API. No brokers, no gateways, no custom protocols.",
href: "/solutions/iot",
},
]

export default function SolutionsPage() {
Expand Down
129 changes: 129 additions & 0 deletions src/components/DiscoveryDiagram.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
const palette = [
"#7C7CFF", // irohPurple-500
"#6257F7", // irohPurple-600
"#4E3FE0", // irohPurple-700
]

const GRAY = "#888"

// Device positions
const A = { x: 130, y: 110 } // ESP32
const B = { x: 390, y: 110 } // Raspberry Pi
const C = { x: 260, y: 250 } // Phone / controller

const ESP32 = ({ x, y }) => (
<g transform={`translate(${x - 18}, ${y - 14})`}>
<rect x="2" y="2" width="32" height="22" rx="2" fill="none" stroke={palette[0]} strokeWidth="1.5" />
<rect x="6" y="6" width="16" height="10" rx="1" fill={palette[0]} opacity="0.15" />
<line x1="24" y1="7" x2="30" y2="7" stroke={palette[0]} strokeWidth="0.8" opacity="0.5" />
<line x1="24" y1="10" x2="30" y2="10" stroke={palette[0]} strokeWidth="0.8" opacity="0.5" />
<line x1="24" y1="13" x2="30" y2="13" stroke={palette[0]} strokeWidth="0.8" opacity="0.5" />
<circle cx="8" cy="20" r="1" fill={palette[0]} opacity="0.5" />
<circle cx="12" cy="20" r="1" fill={palette[0]} opacity="0.5" />
<circle cx="16" cy="20" r="1" fill={palette[0]} opacity="0.5" />
<text x="18" y="36" textAnchor="middle" fill={GRAY} fontSize="7" fontFamily="sans-serif">ESP32</text>
</g>
)

const RaspberryPi = ({ x, y }) => (
<g transform={`translate(${x - 20}, ${y - 14})`}>
<rect x="2" y="2" width="36" height="22" rx="2" fill="none" stroke={palette[0]} strokeWidth="1.5" />
<rect x="5" y="5" width="10" height="8" rx="1" fill={palette[0]} opacity="0.2" />
<rect x="18" y="5" width="6" height="5" rx="0.5" fill={palette[0]} opacity="0.3" />
<rect x="27" y="5" width="8" height="4" rx="0.5" fill={palette[0]} opacity="0.3" />
{/* pin header */}
<line x1="5" y1="18" x2="35" y2="18" stroke={palette[0]} strokeWidth="0.5" opacity="0.5" />
<line x1="5" y1="21" x2="35" y2="21" stroke={palette[0]} strokeWidth="0.5" opacity="0.5" />
<text x="20" y="36" textAnchor="middle" fill={GRAY} fontSize="7" fontFamily="sans-serif">Raspberry Pi</text>
</g>
)

const Phone = ({ x, y }) => (
<g transform={`translate(${x - 10}, ${y - 18})`}>
<rect x="2" y="2" width="20" height="32" rx="3" fill="none" stroke={palette[0]} strokeWidth="1.5" />
<rect x="4" y="6" width="16" height="22" rx="1" fill={palette[0]} opacity="0.08" />
<circle cx="12" cy="31" r="1.2" fill="none" stroke={palette[0]} strokeWidth="0.8" opacity="0.6" />
<text x="12" y="46" textAnchor="middle" fill={GRAY} fontSize="7" fontFamily="sans-serif">Phone</text>
</g>
)

// Expanding discovery ring
const Ripple = ({ cx, cy, delay, color }) => (
<circle cx={cx} cy={cy} r="0" fill="none" stroke={color} strokeWidth="1.2">
<animate attributeName="r" values="4;70" dur="3s" begin={`${delay}s`} repeatCount="indefinite" />
<animate attributeName="opacity" values="0.6;0" dur="3s" begin={`${delay}s`} repeatCount="indefinite" />
</circle>
)

// Animated connection line that fades in
const Connection = ({ x1, y1, x2, y2, delay, color }) => (
<g>
<line x1={x1} y1={y1} x2={x2} y2={y2} stroke={color} strokeWidth="1.5" strokeDasharray="3 3">
<animate attributeName="opacity" values="0;0.6;0.6;0" dur="6s" begin={`${delay}s`} repeatCount="indefinite" />
</line>
<circle r="2.5" fill={color}>
<animate attributeName="opacity" values="0;1;1;0" dur="6s" begin={`${delay}s`} repeatCount="indefinite" />
<animate attributeName="cx" values={`${x1};${x2}`} dur="6s" begin={`${delay}s`} repeatCount="indefinite" />
<animate attributeName="cy" values={`${y1};${y2}`} dur="6s" begin={`${delay}s`} repeatCount="indefinite" />
</circle>
</g>
)

const IrohBadge = ({ x, y }) => (
<g>
<rect x={x - 22} y={y - 10} width="44" height="20" rx="10" fill={palette[0]} opacity="0.1" />
<rect x={x - 22} y={y - 10} width="44" height="20" rx="10" fill="none" stroke={palette[0]} strokeWidth="1" opacity="0.4" />
<text x={x} y={y + 4} textAnchor="middle" fill={palette[0]} fontSize="9" fontFamily="sans-serif" fontWeight="600" letterSpacing="0.04em">
iroh
</text>
</g>
)

export function DiscoveryDiagram({ className }) {
const centerX = (A.x + B.x + C.x) / 3
const centerY = (A.y + B.y + C.y) / 3

return (
<div className={`flex items-center justify-center bg-irohGray-100 dark:bg-irohGray-900 rounded-lg p-4 ${className || ''}`}>
<svg viewBox="60 60 440 240" className="rounded w-full">

{/* Discovery ripples — each device broadcasts */}
<Ripple cx={A.x} cy={A.y} delay={0} color={palette[0]} />
<Ripple cx={A.x} cy={A.y} delay={1.5} color={palette[0]} />
<Ripple cx={B.x} cy={B.y} delay={0.8} color={palette[1]} />
<Ripple cx={B.x} cy={B.y} delay={2.3} color={palette[1]} />
<Ripple cx={C.x} cy={C.y} delay={0.4} color={palette[2]} />
<Ripple cx={C.x} cy={C.y} delay={1.9} color={palette[2]} />

{/* Peer connections form after discovery */}
<Connection x1={A.x} y1={A.y} x2={B.x} y2={B.y} delay={0} color={palette[0]} />
<Connection x1={B.x} y1={B.y} x2={C.x} y2={C.y} delay={2} color={palette[1]} />
<Connection x1={C.x} y1={C.y} x2={A.x} y2={A.y} delay={4} color={palette[2]} />

{/* Devices */}
<ESP32 x={A.x} y={A.y} />
<RaspberryPi x={B.x} y={B.y} />
<Phone x={C.x} y={C.y} />

{/* Center iroh badge */}
<IrohBadge x={centerX} y={centerY - 10} />

{/* Label */}
<text
x={centerX} y={centerY + 20}
textAnchor="middle" fill={palette[0]} fontSize="6.5" fontFamily="sans-serif"
letterSpacing="0.05em" opacity="0.7" fontWeight="600"
>
LOCAL DISCOVERY
</text>
<text
x={centerX} y={centerY + 32}
textAnchor="middle" fill={GRAY} fontSize="6" fontFamily="sans-serif" opacity="0.6"
>
devices find each other on the network
</text>

</svg>
</div>
)
}
4 changes: 2 additions & 2 deletions src/components/FeatureTabs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ export function FeatureTabs({ title, tabs }) {
className={`text-left py-5 border-l-2 pl-5 transition-all cursor-pointer ${
i === active
? 'border-irohPurple-500 opacity-100'
: 'border-irohGray-200 dark:border-irohGray-700 opacity-40 hover:opacity-60'
: 'border-irohGray-200 dark:border-irohGray-700 opacity-70 hover:opacity-90'
}`}
>
<h3 className={`text-2xl font-bold mb-2 ${
i === active ? 'text-irohPurple-500' : ''
}`}>{tab.label}</h3>
<div className="text-base text-irohGray-600 dark:text-irohGray-300 leading-relaxed">
<div className="text-base text-irohGray-800 dark:text-irohGray-300 leading-relaxed">
{tab.body}
</div>
</button>
Expand Down
3 changes: 2 additions & 1 deletion src/components/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const navItems = [
{label: 'Video Streaming', href: '/solutions/rave'},
{label: 'Real-time Sync', href: '/solutions/delta-chat'},
{label: 'Payments & POS', href: '/solutions/pos'},
{label: 'IoT & Embedded', href: '/solutions/iot'},
]},
{content: 'Docs', href: 'https://docs.iroh.computer/'},
{content: 'Blog', href: '/blog'},
Expand Down Expand Up @@ -77,7 +78,7 @@ function DropdownNavItem({ label, items }) {
<Link
key={item.href}
href={item.href}
className="block px-4 py-2 text-sm text-zinc-600 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-700 hover:text-irohPurple-500"
className="block px-4 py-2 text-sm text-black dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-700 hover:text-irohPurple-500"
>
{item.label}
</Link>
Expand Down
Loading
Loading