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
10 changes: 5 additions & 5 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
content="Kairo reader, Android RSVP reader, Bionic Reading app, speed reading app, EPUB reader, PDF reader, DOCX reader, local ebook reader"
/>
<meta name="robots" content="index,follow,max-image-preview:large" />
<meta name="theme-color" content="#071011" />
<meta name="theme-color" content="#15191f" />
<script>
(() => {
let theme = "dark";
Expand All @@ -31,7 +31,7 @@
const themeColor = document.querySelector('meta[name="theme-color"]');

if (themeColor) {
themeColor.content = theme === "dark" ? "#071011" : "#f4f6f3";
themeColor.content = theme === "dark" ? "#15191f" : "#f6f3ec";
}
})();
</script>
Expand Down Expand Up @@ -78,9 +78,9 @@
],
"image": "https://kairoreader.com/assets/kairo-logo.png",
"screenshot": [
"https://kairoreader.com/assets/screens/library.webp",
"https://kairoreader.com/assets/screens/reader-controls.webp",
"https://kairoreader.com/assets/screens/rsvp.webp"
"https://kairoreader.com/assets/screens/library-2026.webp",
"https://kairoreader.com/assets/screens/reader-2026.webp",
"https://kairoreader.com/assets/screens/rsvp-2026.webp"
],
"operatingSystem": "Android 7.0 and newer",
"softwareVersion": "1.1.0",
Expand Down
Binary file added public/assets/screens/import-2026.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/screens/library-2026.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/screens/linen-2026.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/screens/reader-2026.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/screens/rsvp-2026.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/screens/speed-2026.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/screens/themes-2026.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/screens/tools-2026.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function App(props: { initialPath?: string } = {}) {
document.documentElement.classList.toggle("dark", nextTheme === "dark");
document.querySelector<HTMLMetaElement>('meta[name="theme-color"]')?.setAttribute(
"content",
nextTheme === "dark" ? "#071011" : "#f4f6f3",
nextTheme === "dark" ? "#15191f" : "#f6f3ec",
);
});

Expand Down
42 changes: 18 additions & 24 deletions src/components/home/GallerySection.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,29 @@
import { For } from "solid-js";
import { For, createSignal } from "solid-js";
import { homeContent } from "../../content/home";

export function GallerySection() {
const [selected, setSelected] = createSignal(0);
const content = homeContent.gallery;

const screens = content.items;
return (
<section class="gallery-section section-pad" aria-labelledby="gallery-title">
<div class="content-wrap">
<div class="gallery-heading">
<div>
<p class="eyebrow">{content.eyebrow}</p>
<h2 id="gallery-title">{content.title}</h2>
<div class="content-wrap gallery-layout">
<div class="gallery-copy">
<p class="eyebrow">{content.eyebrow}</p>
<h2 id="gallery-title">{content.title}</h2>
<p class="gallery-description">{content.body}</p>
<div class="gallery-choices" aria-label="Choose an app preview">
<For each={screens}>{(screen, index) => (
<button type="button" aria-pressed={selected() === index()} aria-controls="gallery-preview" onClick={() => setSelected(index())}>
<span class="gallery-index">0{index() + 1}</span><span>{screen.caption}</span><span aria-hidden="true">↗</span>
</button>
)}</For>
</div>
<p>{content.body}</p>
</div>
<div class="screen-gallery">
<For each={content.items}>
{(item) => (
<figure>
<img
src={item.image.src}
width={item.image.width}
height={item.image.height}
alt={item.image.alt}
loading="lazy"
/>
<figcaption>{item.caption}</figcaption>
</figure>
)}
</For>
</div>
<figure class="gallery-preview" id="gallery-preview" aria-live="polite">
<img src={screens[selected()].image.src} width="810" height="1440" alt={screens[selected()].image.alt} loading="lazy" />
<figcaption>{screens[selected()].description}</figcaption>
</figure>
</div>
</section>
);
Expand Down
26 changes: 2 additions & 24 deletions src/components/home/HeroSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export function HeroSection() {
return (
<>
<section class="hero section-pad" aria-labelledby="hero-title">
<div class="hero-glow" aria-hidden="true" />
<div class="hero-grid content-wrap">
<div class="hero-copy">
<p class="eyebrow">
Expand All @@ -33,15 +32,6 @@ export function HeroSection() {
{content.actions.learnMore.label}
<Icon name={content.actions.learnMore.icon} />
</a>
<a
class="button-secondary hero-support"
href={content.actions.support.href}
target="_blank"
rel="noreferrer"
>
<Icon name={content.actions.support.icon} />
{content.actions.support.label}
</a>
</div>
<div class="hero-proof" aria-label={content.proofAriaLabel}>
<For each={content.proofItems}>
Expand All @@ -55,24 +45,12 @@ export function HeroSection() {
</div>

<div class="hero-visual" aria-label={content.visualAriaLabel}>
<div class="orbit orbit-one" aria-hidden="true" />
<div class="orbit orbit-two" aria-hidden="true" />
<For each={content.screenshots}>
<span class="visual-kicker">A quieter kind of screen time</span>
<For each={content.screenshots.filter((shot) => shot.position !== "back")}>
{(screenshot) => (
<PhoneFrame class={phoneClassByPosition[screenshot.position]} image={screenshot.image} />
)}
</For>
<div class="floating-note note-formats">
<span>{content.formatNote.label}</span>
<strong>{content.formatNote.value}</strong>
</div>
<div class="floating-note note-local">
<Icon name={content.localNote.icon} />
<span>
<strong>{content.localNote.title}</strong>
{content.localNote.body}
</span>
</div>
</div>
</div>
<div class="scroll-cue content-wrap" aria-hidden="true">
Expand Down
142 changes: 83 additions & 59 deletions src/content/home.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export type HomePageContent = {
eyebrow: string;
title: string;
body: string;
items: readonly { caption: string; image: ImageContent }[];
items: readonly { caption: string; description: string; image: ImageContent }[];
};
privacy: {
icon: IconName;
Expand Down Expand Up @@ -113,18 +113,18 @@ export const homeContent = {
hero: {
announcement: `${siteContent.brand.name} ${siteContent.release.badge} · Free on ${siteContent.release.platform}`,
title: {
text: "Read at the speed of",
emphasis: "thought.",
text: "A little more space to",
emphasis: "read.",
},
lede:
"Bring your own books and documents. Read with full context, then shift into adaptive RSVP or Bionic Reading whenever you want more momentum.",
"Your books. Your pace. A thoughtful Android reader that lets you settle into a page, find your focus, and keep the world on pause.",
actions: {
learnMore: { label: "See how it works", href: "#experience", icon: "arrow" },
support: { ...siteContent.actions.support, label: "Buy me a coffee" },
},
proofAriaLabel: "Kairo highlights",
proofItems: [
{ icon: "check", label: "10 format families" },
{ icon: "check", label: "Free to use" },
{ icon: "shield", label: "Local-first" },
{ icon: "github", label: "Open source" },
],
Expand All @@ -133,28 +133,28 @@ export const homeContent = {
{
position: "back",
image: {
src: "/assets/screens/library.webp",
src: "/assets/screens/library-2026.webp",
alt: "Kairo library with imported books, progress and bookmarks",
width: 1080,
height: 1920,
width: 810,
height: 1440,
},
},
{
position: "middle",
image: {
src: "/assets/screens/reader-controls.webp",
alt: "Kairo reader with chapter text and reading controls",
width: 1080,
height: 1920,
src: "/assets/screens/linen-2026.webp",
alt: "Kairo reader in the warm linen theme",
width: 810,
height: 1440,
},
},
{
position: "front",
image: {
src: "/assets/screens/rsvp.webp",
src: "/assets/screens/rsvp-2026.webp",
alt: "Kairo RSVP screen with a focused word and playback controls",
width: 1080,
height: 1920,
width: 810,
height: 1440,
},
},
],
Expand All @@ -174,7 +174,7 @@ export const homeContent = {
experience: {
heading: {
eyebrow: "One continuous reading flow",
title: "Change how you read. Not where you are.",
title: "Find your reading rhythm.",
body:
"Kairo keeps the library, the page and your accelerated reading modes connected. Pick the experience that fits the next passage.",
},
Expand All @@ -188,10 +188,10 @@ export const homeContent = {
visual: {
kind: "phone",
image: {
src: "/assets/screens/reader-rsvp-dock.webp",
alt: "Kairo standard reader with the RSVP launch control",
width: 1080,
height: 1920,
src: "/assets/screens/linen-2026.webp",
alt: "Alice’s Adventures in Wonderland in Kairo’s warm linen reading theme",
width: 810,
height: 1440,
},
},
},
Expand All @@ -204,10 +204,10 @@ export const homeContent = {
visual: {
kind: "phone",
image: {
src: "/assets/screens/rsvp.webp",
alt: "Kairo RSVP mode showing the word seldom at a stable focal point",
width: 1080,
height: 1920,
src: "/assets/screens/rsvp-2026.webp",
alt: "Kairo RSVP mode with a focused word and surrounding sentence context",
width: 810,
height: 1440,
},
},
},
Expand All @@ -229,7 +229,7 @@ export const homeContent = {
formats: {
heading: {
eyebrow: `${siteContent.brand.name} ${siteContent.release.badge} format support`,
title: "Your reading list is bigger than one file type.",
title: "A home for your whole reading list.",
body:
"Choose a supported file from Android storage. Kairo detects it automatically, builds a local library entry and opens the same focused reading toolkit.",
},
Expand All @@ -250,16 +250,16 @@ export const homeContent = {
},
tuning: {
eyebrow: "Power when you want it",
title: "Simple on the surface. Remarkably tuneable underneath.",
title: "Make yourself comfortable.",
body:
"Start with a profile, press play and read. When you want finer control, Kairo exposes the pacing, typography, brightness and focus settings that actually change how a session feels.",
profilesAriaLabel: "Built-in RSVP profiles",
profiles: ["Balanced", "Chill", "Narrative", "Focus", "Flow", "Sprint", "Study"],
image: {
src: `/assets/screens/rsvp-settings.webp?v=${siteContent.release.version}`,
src: "/assets/screens/speed-2026.webp",
alt: "Kairo RSVP settings with profile and timing controls",
width: 1080,
height: 1920,
width: 810,
height: 1440,
},
callouts: [
{ label: "Estimated pace", value: "811 WPM" },
Expand Down Expand Up @@ -314,45 +314,69 @@ export const homeContent = {
gallery: {
eyebrow: "Inside Kairo",
title: "A reading interface that gets out of the way.",
body: "Near-black surfaces, restrained colour and controls that appear when they are useful.",
body: "From your first import to the last page. Explore the little details that make Kairo feel like your own reading space.",
items: [
{
caption: "Library",
image: {
src: "/assets/screens/library.webp",
alt: "Kairo library showing book covers, progress and navigation tabs",
width: 1080,
height: 1920,
},
"caption": "Your library",
"description": "All your books, with a place for every next chapter.",
"image": {
"src": "/assets/screens/library-2026.webp",
"alt": "Kairo: Your library",
"width": 810,
"height": 1440
}
},
{
caption: "Settings",
image: {
src: "/assets/screens/settings.webp",
alt: "Kairo settings home with RSVP, reader, focus and startup settings",
width: 333,
height: 592,
},
"caption": "The reading room",
"description": "Warm linen, comfortable type, and room to lose yourself in a book.",
"image": {
"src": "/assets/screens/linen-2026.webp",
"alt": "Kairo: The reading room",
"width": 810,
"height": 1440
}
},
{
caption: "Reader themes",
image: {
src: "/assets/screens/reader-settings.webp",
alt: "Kairo reader settings with font, theme, brightness and scrolling options",
width: 1080,
height: 1920,
},
"caption": "Find your focus",
"description": "One focal point. Your own pace. The surrounding words, still in reach.",
"image": {
"src": "/assets/screens/rsvp-2026.webp",
"alt": "Kairo: Find your focus",
"width": 810,
"height": 1440
}
},
{
caption: "Reader controls",
image: {
src: "/assets/screens/reader-controls.webp",
alt: "Kairo book reader with bookmarks, focus mode and table of contents controls",
width: 1080,
height: 1920,
},
"caption": "Make it yours",
"description": "Tune the type, colours, and brightness to the way you like to read.",
"image": {
"src": "/assets/screens/themes-2026.webp",
"alt": "Kairo: Make it yours",
"width": 810,
"height": 1440
}
},
],
{
"caption": "Keep your place",
"description": "Bookmarks and reading tools, always close at hand.",
"image": {
"src": "/assets/screens/tools-2026.webp",
"alt": "Kairo: Keep your place",
"width": 810,
"height": 1440
}
},
{
"caption": "Bring your books",
"description": "Start with the ebooks and documents you already own.",
"image": {
"src": "/assets/screens/import-2026.webp",
"alt": "Kairo: Bring your books",
"width": 810,
"height": 1440
}
}
],
},
privacy: {
icon: "shield",
Expand Down
Loading