+
{article.title}
-
+
@@ -38,7 +40,7 @@ export function BlogPostLayout({ article, references = [], children }) {
{references.length > 0 && (
)}
-
+
Iroh is a dial-any-device networking library that just works. Compose from an ecosystem of ready-made protocols to get the features you need, or go fully custom on a clean abstraction over dumb pipes. Iroh is open source, and already running in production on hundreds of thousands of devices.
To get started, take a look at our docs, dive directly into the code, or chat with us in our discord channel.
diff --git a/src/components/FeatureTabs.jsx b/src/components/FeatureTabs.jsx
new file mode 100644
index 00000000..fd93f2b4
--- /dev/null
+++ b/src/components/FeatureTabs.jsx
@@ -0,0 +1,49 @@
+'use client'
+
+import { useState, useEffect } from 'react'
+
+const INTERVAL = 10000
+
+export function FeatureTabs({ title, tabs }) {
+ const [active, setActive] = useState(0)
+
+ useEffect(() => {
+ const timer = setInterval(() => {
+ setActive((prev) => (prev + 1) % tabs.length)
+ }, INTERVAL)
+ return () => clearInterval(timer)
+ }, [active, tabs.length])
+
+ return (
+
+
+ {title && {title}
}
+
+
+ {tabs.map((tab, i) => (
+
+ ))}
+
+
+ {tabs[active].diagram}
+
+
+
+
+ )
+}
diff --git a/src/components/Header.jsx b/src/components/Header.jsx
index 311b9b4e..c7fec18b 100644
--- a/src/components/Header.jsx
+++ b/src/components/Header.jsx
@@ -25,7 +25,8 @@ export const navItems = [
{content: 'Use Cases', href: '/#solutions', dropdown: [
{label: 'Distributed AI', href: '/solutions/nous'},
{label: 'Video Streaming', href: '/solutions/rave'},
- {label: 'Resilient Apps', href: '/solutions/delta-chat'},
+ {label: 'Real-time Sync', href: '/solutions/delta-chat'},
+ {label: 'Payments & POS', href: '/solutions/pos'},
{label: 'Enterprise', href: '/enterprise'},
]},
{content: 'Docs', href: 'https://docs.iroh.computer/'},
diff --git a/src/components/HomeFeatureTabs.jsx b/src/components/HomeFeatureTabs.jsx
new file mode 100644
index 00000000..e00a89c8
--- /dev/null
+++ b/src/components/HomeFeatureTabs.jsx
@@ -0,0 +1,44 @@
+'use client'
+
+import Link from 'next/link'
+import { FeatureTabs } from '@/components/FeatureTabs'
+import { IrohEverywhere } from '@/components/IrohEverywhere'
+import { OpenSourceIllustration } from '@/components/OpenSourceIllustration'
+import { PaycodePCIDiagram } from '@/components/PaycodePCIDiagram'
+
+const tabs = [
+ {
+ id: 'everywhere',
+ label: 'Works Everywhere',
+ body: (
+
+ Windows, macOS, Linux, Android, iOS, and embedded devices. Connect over Bluetooth, LAN, Wi-Fi, or Tor.
+
+ ),
+ diagram: ,
+ },
+ {
+ id: 'encrypted',
+ label: 'E2E Encrypted, Always',
+ body: (
+
+ Every connection is end-to-end encrypted over QUIC. No certificates to manage.
+
+ ),
+ diagram: ,
+ },
+ {
+ id: 'costs',
+ label: 'Save Cloud Costs',
+ body: (
+
+ Peer-to-peer connections bypass NATs and firewalls. Relays keep data flowing when direct connections can't be made.
+
+ ),
+ diagram: ,
+ },
+]
+
+export function HomeFeatureTabs() {
+ return
+}
diff --git a/src/components/IrohPaymentDiagram.jsx b/src/components/IrohPaymentDiagram.jsx
new file mode 100644
index 00000000..4e58e1e7
--- /dev/null
+++ b/src/components/IrohPaymentDiagram.jsx
@@ -0,0 +1,181 @@
+const palette = [
+ "#7C7CFF", // irohPurple-500 (primary)
+ "#6257F7", // irohPurple-600 (secondary)
+ "#4E3FE0", // irohPurple-700 (tertiary)
+]
+
+const GRAY = "#888"
+
+// Layout — same horizontal positions as MQTT diagram but no broker
+const OP_X = 130
+const OP_Y = 130
+const POS_X = 400
+const POS_Y = 130
+const CLOUD_X = 400
+const CLOUD_Y = 245
+
+// Operator machine — monitor with keyboard
+const OperatorMachine = ({ x, y }) => (
+
+
+
+
+
+
+
+ Point of Sale
+
+)
+
+// Payment Terminal — card reader device
+const POSTerminal = ({ x, y }) => (
+
+
+
+
+
+ {/* Keypad */}
+
+
+
+
+
+
+
+ Payment Terminal
+
+)
+
+// Cloud server
+const CloudServer = ({ x, y }) => (
+
+
+
+
+
+ Payment Backend
+
+)
+
+// Animated bidirectional dot
+const MessageDot = ({ x1, y1, x2, y2, delay, dur, color }) => (
+
+
+
+
+
+)
+
+// Label badge
+const Badge = ({ x, y, text, color = palette[0] }) => {
+ const w = text.length * 4.5 + 16
+ return (
+
+
+
+
+ {text}
+
+
+ )
+}
+
+// iroh channel pill
+const IrohBadge = ({ x, y }) => (
+
+
+
+
+ iroh
+
+
+)
+
+export function IrohPaymentDiagram({ className }) {
+ const opRight = OP_X + 22
+ const posLeft = POS_X - 14
+ const midX = (opRight + posLeft) / 2
+
+ return (
+
+
+
+ )
+}
diff --git a/src/components/MQTTDiagram.jsx b/src/components/MQTTDiagram.jsx
new file mode 100644
index 00000000..cf8fe751
--- /dev/null
+++ b/src/components/MQTTDiagram.jsx
@@ -0,0 +1,247 @@
+const palette = [
+ "#7C7CFF", // irohPurple-500 (primary)
+ "#6257F7", // irohPurple-600 (secondary)
+ "#4E3FE0", // irohPurple-700 (tertiary)
+]
+
+const GRAY = "#888"
+const WARN = "#f59e0b"
+
+// Layout positions — left to right
+const OP_X = 85
+const OP_Y = 130
+const BROKER_X = 260
+const BROKER_Y = 130
+const POS_X = 435
+const POS_Y = 130
+const CLOUD_X = 435
+const CLOUD_Y = 245
+
+// Operator machine — monitor with keyboard
+const OperatorMachine = ({ x, y }) => (
+
+
+
+
+
+
+
+ Point of Sale
+
+)
+
+// MQTT Broker — server with warning indicator
+const BrokerServer = ({ x, y }) => (
+
+
+ {/* Top panel */}
+
+
+
+
+
+
+ {/* Middle panel */}
+
+
+
+
+
+
+ {/* Bottom panel */}
+
+
+
+
+
+ MQTT Broker
+ (local server)
+
+)
+
+// Payment Terminal — card reader device
+const POSTerminal = ({ x, y }) => (
+
+
+
+
+
+ {/* Keypad */}
+
+
+
+
+
+
+
+ Payment Terminal
+
+)
+
+// Cloud server
+const CloudServer = ({ x, y }) => (
+
+ {/* Cloud shape */}
+
+ {/* Server lines inside cloud */}
+
+
+
+ Payment Backend
+
+)
+
+// Animated message dot
+const MessageDot = ({ x1, y1, x2, y2, delay, dur, color }) => (
+
+
+
+
+
+)
+
+// Label badge
+const Badge = ({ x, y, text, color = palette[0] }) => {
+ const w = text.length * 4.5 + 16
+ return (
+
+
+
+
+ {text}
+
+
+ )
+}
+
+export function MQTTDiagram({ className }) {
+ const opRight = OP_X + 22
+ const brokerLeft = BROKER_X - 20
+ const brokerRight = BROKER_X + 20
+ const posLeft = POS_X - 14
+
+ // Midpoints for labels
+ const midLeftX = (opRight + brokerLeft) / 2
+ const midRightX = (brokerRight + posLeft) / 2
+
+ return (
+
+
+
+ )
+}
diff --git a/src/components/POSFeatureTabs.jsx b/src/components/POSFeatureTabs.jsx
new file mode 100644
index 00000000..ed6dbb99
--- /dev/null
+++ b/src/components/POSFeatureTabs.jsx
@@ -0,0 +1,50 @@
+'use client'
+
+import Link from 'next/link'
+import { FeatureTabs } from '@/components/FeatureTabs'
+import { PaycodePCIDiagram } from '@/components/PaycodePCIDiagram'
+import { IrohEverywhere } from '@/components/IrohEverywhere'
+import { OpenSourceIllustration } from '@/components/OpenSourceIllustration'
+
+const tabs = [
+ {
+ id: 'secure',
+ label: 'Secure & Offline',
+ body: (
+
+ All iroh connections are encrypted by default using open standards.
+ Raw card data never leaves the payment terminal. Compliance is maintained by architecture.
+
+ ),
+ diagram: ,
+ },
+ {
+ id: 'cross-platform',
+ label: 'Cross-Platform',
+ body: (
+
+ iroh runs on Android, iOS, Windows, Linux, and embedded devices.
+ Connect any POS device to any terminal regardless of platform—from
+ modern tablets to legacy Windows 7 machines.
+
+ ),
+ diagram: ,
+ },
+ {
+ id: 'resilient',
+ label: 'Resilient by Default',
+ body: (
+
+ Host relays across AWS, GCP, Azure, or your own infrastructure. If one
+ connection path goes down, iroh automatically finds another—direct,
+ local network, or fallback through relays.
+ No single cloud provider is a single point of failure.
+
+ ),
+ diagram: ,
+ },
+]
+
+export function POSFeatureTabs() {
+ return
+}
diff --git a/src/components/PaycodePCIDiagram.jsx b/src/components/PaycodePCIDiagram.jsx
new file mode 100644
index 00000000..8c1c1992
--- /dev/null
+++ b/src/components/PaycodePCIDiagram.jsx
@@ -0,0 +1,434 @@
+const palette = [
+ "#7C7CFF", // irohPurple-500 (primary)
+ "#6257F7", // irohPurple-600 (secondary)
+ "#4E3FE0", // irohPurple-700 (tertiary)
+]
+
+// Monitor icon for the toll booth terminal
+const TerminalIcon = ({ x, y }) => (
+
+ {/* Monitor */}
+
+ {/* Screen content lines */}
+
+
+
+ {/* Stand */}
+
+
+
+)
+
+// POS device icon (card reader terminal)
+const POSIcon = ({ x, y }) => (
+
+ {/* Device body */}
+
+ {/* Screen */}
+
+ {/* Keypad dots */}
+
+
+
+
+
+
+ {/* Card slot indicator */}
+
+
+)
+
+// Credit card icon
+const CardIcon = ({ x, y }) => (
+
+
+ {/* Magnetic stripe */}
+
+ {/* Chip */}
+
+
+)
+
+// Lock icon
+const LockIcon = ({ x, y, size = 12 }) => (
+
+
+
+
+)
+
+// Animated data packet traveling along a path
+const DataPacket = ({ x1, y1, x2, y2, dur, delay, label, color = palette[0] }) => {
+ return (
+
+ {/* Packet dot */}
+
+
+
+
+
+
+ )
+}
+
+export function PaycodePCIDiagram({ className }) {
+ const terminalX = 110
+ const posX = 480
+ const centerY = 140
+
+ // iroh channel endpoints
+ const channelLeft = 185
+ const channelRight = 400
+
+ // PCI boundary box
+ const pciLeft = 370
+ const pciTop = 45
+ const pciWidth = 200
+ const pciHeight = 230
+
+ return (
+
+
+
+ )
+}
diff --git a/src/components/Prose.jsx b/src/components/Prose.jsx
index 5f5bfbe0..1fbbbd30 100644
--- a/src/components/Prose.jsx
+++ b/src/components/Prose.jsx
@@ -3,7 +3,8 @@ import clsx from 'clsx';
export function Prose({as: Component = 'div', className, ...props}) {
return (
);
diff --git a/src/components/QRTicketFlow.jsx b/src/components/QRTicketFlow.jsx
new file mode 100644
index 00000000..175e1cf4
--- /dev/null
+++ b/src/components/QRTicketFlow.jsx
@@ -0,0 +1,233 @@
+const palette = [
+ "#7C7CFF", // irohPurple-500 (primary)
+ "#6257F7", // irohPurple-600 (secondary)
+ "#4E3FE0", // irohPurple-700 (tertiary)
+]
+
+const GRAY = "#888"
+
+// Participant X positions
+const POS_X = 80
+const QR_X = 210
+const TERMINAL_X = 340
+const DISCOVERY_X = 470
+
+// Vertical layout
+const HEAD_Y = 40
+const LIFELINE_START = 62
+const LIFELINE_END = 340
+
+// Message Y positions
+const MSG1_Y = 100
+const MSG2_Y = 150
+const MSG3_Y = 195
+const MSG4_Y = 240
+const MSG5_Y = 285
+const SELF_H = 20
+
+// Participant header box
+const Participant = ({ x, label, sub }) => {
+ const w = sub ? Math.max(label.length, sub.length) * 6.5 + 20 : label.length * 6.5 + 20
+ return (
+
+
+
+
+ {label}
+
+ {sub && (
+
+ {sub}
+
+ )}
+
+ )
+}
+
+// Dashed vertical lifeline
+const Lifeline = ({ x }) => (
+
+)
+
+// Horizontal arrow with label
+const Arrow = ({ x1, x2, y, label, color = palette[0], dashed }) => {
+ const dir = x2 > x1 ? 1 : -1
+ const tipX = x2
+ return (
+
+
+
+
+ {label}
+
+
+
+
+
+
+
+ )
+}
+
+// Self-call arrow
+const SelfArrow = ({ x, y, label, color = palette[0] }) => {
+ const w = 32
+ return (
+
+
+
+
+ {label}
+
+
+ )
+}
+
+// Bidirectional connection
+const BiArrow = ({ x1, x2, y, label, color = palette[0] }) => {
+ const gap = 4
+ return (
+
+
+
+
+
+
+ {label}
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+// Note box
+const Note = ({ x, y, text, sub, color = palette[0] }) => {
+ const w = sub
+ ? Math.max(text.length, sub.length) * 5 + 16
+ : text.length * 5 + 16
+ const h = sub ? 26 : 18
+ return (
+
+
+
+
+ {text}
+
+ {sub && (
+
+ {sub}
+
+ )}
+
+ )
+}
+
+// Small QR icon for the participant header
+const QRIcon = ({ x, y, size }) => {
+ const s = size / 7
+ const ox = x - size / 2
+ const oy = y - size / 2
+ const Finder = ({ gx, gy }) => (
+
+
+
+
+ )
+ return (
+
+
+
+
+
+ {[[3, 0], [4, 1], [3, 3], [5, 4], [3, 5], [4, 6], [6, 3], [6, 6]].map(([c, r], i) => (
+
+ ))}
+
+ )
+}
+
+export function QRTicketFlow({ className }) {
+ return (
+
+
+
+ )
+}
diff --git a/src/components/UsersShowcase.jsx b/src/components/UsersShowcase.jsx
index 53411def..65142ad1 100644
--- a/src/components/UsersShowcase.jsx
+++ b/src/components/UsersShowcase.jsx
@@ -7,7 +7,7 @@ import Link from 'next/link'
const projects = [
{ title: "Delta Chat",
- description: "Iroh powers multi-device backup & live connections for in-chat WebXDC apps",
+ description: "Iroh powers multi-device backup & live connections for apps",
thumbnail: '/img/users/delta_chat.png',
href: 'https://delta.chat',
},
diff --git a/src/components/home/LogoCloud.jsx b/src/components/home/LogoCloud.jsx
index 7a10d72e..51f6b737 100644
--- a/src/components/home/LogoCloud.jsx
+++ b/src/components/home/LogoCloud.jsx
@@ -8,6 +8,7 @@ const companies = [
{ name: "spacedrive", ext: "png" },
{ name: "nous", ext: "png" },
{ name: "shaga", ext: "png" },
+ { name: "paycode", ext: "svg" },
{ name: "rave", ext: "png" },
{ name: "delta_chat", ext: "png" },
{ name: "holochain", ext: "svg" },
diff --git a/src/components/home/UseCases.jsx b/src/components/home/UseCases.jsx
index 7722f0be..6b0f34f6 100644
--- a/src/components/home/UseCases.jsx
+++ b/src/components/home/UseCases.jsx
@@ -16,8 +16,8 @@ const useCases = {
"Data Transfer": [
"Recall uses iroh to replicate massive amounts content-addressed data for validating AI Agents."
],
- "Resilient Apps": [
- "Delta Chat uses iroh to power in-chat apps for hundreds of thousands of devices around the world, even when internet access is precarious."
+ "Real-time Sync for Apps": [
+ "Delta Chat uses iroh to power apps for hundreds of thousands of devices around the world, even when internet access is precarious."
]
}
diff --git a/src/styles/tailwind.css b/src/styles/tailwind.css
index ced56b38..78842fca 100644
--- a/src/styles/tailwind.css
+++ b/src/styles/tailwind.css
@@ -1,5 +1,3 @@
-@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;700&family=Space+Mono&display=swap");
-
@import "tailwindcss";
@import "tw-animate-css";
@@ -146,5 +144,6 @@
}
body {
@apply bg-background text-foreground;
+ font-family: 'Space Grotesk', sans-serif;
}
}
diff --git a/typography.js b/typography.js
index b173f438..0502afe2 100644
--- a/typography.js
+++ b/typography.js
@@ -1,64 +1,58 @@
module.exports = ({ theme }) => ({
DEFAULT: {
css: {
- '--tw-prose-body': theme('colors.zinc.700'),
- '--tw-prose-headings': theme('colors.zinc.900'),
+ '--tw-prose-body': theme('colors.irohGray.700'),
+ '--tw-prose-headings': theme('colors.irohGray.900'),
'--tw-prose-links': theme('colors.irohPurple.500'),
'--tw-prose-links-hover': theme('colors.irohPurple.600'),
'--tw-prose-links-underline': theme('colors.irohPurple.500 / 0.3'),
- '--tw-prose-bold': theme('colors.zinc.900'),
- '--tw-prose-counters': theme('colors.zinc.500'),
- '--tw-prose-bullets': theme('colors.zinc.300'),
- '--tw-prose-hr': theme('colors.zinc.900 / 0.05'),
- '--tw-prose-quotes': theme('colors.zinc.900'),
- '--tw-prose-quote-borders': theme('colors.zinc.200'),
- '--tw-prose-captions': theme('colors.zinc.500'),
- '--tw-prose-code': theme('colors.zinc.900'),
- '--tw-prose-code-bg': theme('colors.zinc.100'),
- '--tw-prose-code-ring': theme('colors.zinc.300'),
- '--tw-prose-th-borders': theme('colors.zinc.300'),
- '--tw-prose-td-borders': theme('colors.zinc.200'),
+ '--tw-prose-bold': theme('colors.irohGray.900'),
+ '--tw-prose-counters': theme('colors.irohGray.500'),
+ '--tw-prose-bullets': theme('colors.irohGray.300'),
+ '--tw-prose-hr': theme('colors.irohGray.900 / 0.05'),
+ '--tw-prose-quotes': theme('colors.irohGray.900'),
+ '--tw-prose-quote-borders': theme('colors.irohGray.200'),
+ '--tw-prose-captions': theme('colors.irohGray.500'),
+ '--tw-prose-code': theme('colors.irohGray.900'),
+ '--tw-prose-code-bg': theme('colors.irohGray.100'),
+ '--tw-prose-code-ring': theme('colors.irohGray.300'),
+ '--tw-prose-th-borders': theme('colors.irohGray.300'),
+ '--tw-prose-td-borders': theme('colors.irohGray.200'),
- '--tw-prose-invert-body': theme('colors.zinc.400'),
+ '--tw-prose-invert-body': theme('colors.irohGray.400'),
'--tw-prose-invert-headings': theme('colors.white'),
'--tw-prose-invert-links': theme('colors.irohPurple.400'),
'--tw-prose-invert-links-hover': theme('colors.irohPurple.500'),
'--tw-prose-invert-links-underline': theme('colors.irohPurple.500 / 0.3'),
'--tw-prose-invert-bold': theme('colors.white'),
- '--tw-prose-invert-counters': theme('colors.zinc.400'),
- '--tw-prose-invert-bullets': theme('colors.zinc.600'),
+ '--tw-prose-invert-counters': theme('colors.irohGray.400'),
+ '--tw-prose-invert-bullets': theme('colors.irohGray.600'),
'--tw-prose-invert-hr': theme('colors.white / 0.05'),
- '--tw-prose-invert-quotes': theme('colors.zinc.100'),
- '--tw-prose-invert-quote-borders': theme('colors.zinc.700'),
- '--tw-prose-invert-captions': theme('colors.zinc.400'),
+ '--tw-prose-invert-quotes': theme('colors.irohGray.100'),
+ '--tw-prose-invert-quote-borders': theme('colors.irohGray.700'),
+ '--tw-prose-invert-captions': theme('colors.irohGray.400'),
'--tw-prose-invert-code': theme('colors.white'),
- '--tw-prose-invert-code-bg': theme('colors.zinc.700 / 0.15'),
+ '--tw-prose-invert-code-bg': theme('colors.irohGray.700 / 0.15'),
'--tw-prose-invert-code-ring': theme('colors.white / 0.1'),
- '--tw-prose-invert-th-borders': theme('colors.zinc.600'),
- '--tw-prose-invert-td-borders': theme('colors.zinc.700'),
+ '--tw-prose-invert-th-borders': theme('colors.irohGray.600'),
+ '--tw-prose-invert-td-borders': theme('colors.irohGray.700'),
// Base
color: 'var(--tw-prose-body)',
- fontSize: theme('fontSize.sm')[0],
- ...theme('fontSize.sm')[1],
+ fontFamily: 'Space Grotesk, sans-serif',
+ fontSize: theme('fontSize.base')[0],
+ ...theme('fontSize.base')[1],
lineHeight: theme('lineHeight.7'),
// Layout
'> *': {
- maxWidth: theme('maxWidth.3xl'),
- // marginLeft: 'auto',
- marginRight: 'auto',
- '@screen lg': {
- maxWidth: theme('maxWidth.3xl'),
- marginLeft: `calc(50% - min(50%, ${theme('maxWidth.lg')}))`,
- marginRight: `calc(50% - min(50%, ${theme('maxWidth.lg')}))`,
- },
+ maxWidth: 'none',
},
// Text
p: {
- fontSize: theme('fontSize.base')[0],
- ...theme('fontSize.base')[1],
+ fontSize: theme('fontSize.lg')[0],
+ ...theme('fontSize.lg')[1],
marginTop: theme('spacing.6'),
marginBottom: theme('spacing.6'),
},
@@ -69,7 +63,7 @@ module.exports = ({ theme }) => ({
// Lists
ol: {
- fontSize: theme('fontSize.base')[0],
+ fontSize: theme('fontSize.lg')[0],
listStyleType: 'decimal',
marginTop: theme('spacing.5'),
marginBottom: theme('spacing.5'),
@@ -104,7 +98,7 @@ module.exports = ({ theme }) => ({
listStyleType: 'decimal',
},
ul: {
- fontSize: theme('fontSize.base')[0],
+ fontSize: theme('fontSize.lg')[0],
listStyleType: 'disc',
marginTop: theme('spacing.5'),
marginBottom: theme('spacing.5'),
@@ -170,47 +164,56 @@ module.exports = ({ theme }) => ({
fontWeight: '500',
fontStyle: 'italic',
color: 'var(--tw-prose-quotes)',
- borderLeftWidth: '0.25rem',
- borderLeftColor: 'var(--tw-prose-quote-borders)',
+ backgroundColor: theme('colors.irohGray.100'),
+ borderRadius: theme('borderRadius.lg'),
+ borderLeftWidth: '3px',
+ borderLeftColor: theme('colors.irohPurple.500'),
quotes: '"\\201C""\\201D""\\2018""\\2019"',
marginTop: theme('spacing.8'),
marginBottom: theme('spacing.8'),
- paddingLeft: theme('spacing.5'),
+ paddingTop: theme('spacing.4'),
+ paddingBottom: theme('spacing.4'),
+ paddingLeft: theme('spacing.6'),
+ paddingRight: theme('spacing.6'),
+ fontSize: theme('fontSize.lg')[0],
+ ...theme('fontSize.lg')[1],
+ },
+ ':is(.dark) blockquote': {
+ backgroundColor: theme('colors.irohGray.800'),
},
'blockquote p:first-of-type::before': {
- content: 'open-quote',
+ content: 'none',
},
'blockquote p:last-of-type::after': {
- content: 'close-quote',
+ content: 'none',
},
// Headings
h1: {
color: 'var(--tw-prose-headings)',
- // TODO(b5): Use theme()
fontFamily: 'Space Grotesk',
fontWeight: '700',
- fontSize: theme('fontSize.2xl')[0],
- ...theme('fontSize.2xl')[1],
- marginBottom: theme('spacing.2'),
+ fontSize: theme('fontSize.3xl')[0],
+ ...theme('fontSize.3xl')[1],
+ marginBottom: theme('spacing.4'),
},
h2: {
color: 'var(--tw-prose-headings)',
fontFamily: 'Space Grotesk',
- fontWeight: '600',
- fontSize: theme('fontSize.lg')[0],
- ...theme('fontSize.lg')[1],
+ fontWeight: '700',
+ fontSize: theme('fontSize.2xl')[0],
+ ...theme('fontSize.2xl')[1],
marginTop: theme('spacing.16'),
- marginBottom: theme('spacing.2'),
+ marginBottom: theme('spacing.4'),
},
h3: {
color: 'var(--tw-prose-headings)',
- fontSize: theme('fontSize.base')[0],
- ...theme('fontSize.base')[1],
+ fontFamily: 'Space Grotesk',
fontWeight: '600',
+ fontSize: theme('fontSize.xl')[0],
+ ...theme('fontSize.xl')[1],
marginTop: theme('spacing.10'),
marginBottom: theme('spacing.2'),
- fontFamily: 'Space Grotesk',
},
// Media
To get started, take a look at our docs, dive directly into the code, or chat with us in our discord channel.
{title}
} ++ Windows, macOS, Linux, Android, iOS, and embedded devices. Connect over Bluetooth, LAN, Wi-Fi, or Tor. +
+ ), + diagram:+ Every connection is end-to-end encrypted over QUIC. No certificates to manage. +
+ ), + diagram:+ Peer-to-peer connections bypass NATs and firewalls. Relays keep data flowing when direct connections can't be made. +
+ ), + diagram:+ All iroh connections are encrypted by default using open standards. + Raw card data never leaves the payment terminal. Compliance is maintained by architecture. +
+ ), + diagram:+ iroh runs on Android, iOS, Windows, Linux, and embedded devices. + Connect any POS device to any terminal regardless of platform—from + modern tablets to legacy Windows 7 machines. +
+ ), + diagram:+ Host relays across AWS, GCP, Azure, or your own infrastructure. If one + connection path goes down, iroh automatically finds another—direct, + local network, or fallback through relays. + No single cloud provider is a single point of failure. +
+ ), + diagram: