PageSourceSearch

https://ketoy.dev/

html ketoy.dev collected 2026-10-07 16:53:50 UTC 82,555 bytes, 9 lines download raw bytes

1<!DOCTYPE html><!--gApJWUxpRy7_zBZZe0WQW--><html lang="en" class="__variable_7fd790 __variable_40479c __variable_e896d9"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/558ca1a6aa3cb55e-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/7b0b24f36b1a6d0b-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/a22b1dc24103c00d-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" as="image" href="/assets/ketoy-logo.svg"/><link rel="stylesheet" href="/_next/static/css/a028ffcdacb4e6b9.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/10cce706acc7ff5e.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-b2f0e5b150b12ec0.js"/>
1<script src="/_next/static/chunks/4bd1b696-f785427dddbba9fb.js" async=""></script>
1<script src="/_next/static/chunks/1255-5fe68596fe147850.js" async=""></script>
1<script src="/_next/static/chunks/main-app-5eb0d9c55a395822.js" async=""></script>
1<script src="/_next/static/chunks/5000-250c7c961a3aed60.js" async=""></script>
1<script src="/_next/static/chunks/app/layout-5f049d25b5082e14.js" async=""></script>
1<script src="/_next/static/chunks/app/page-8569f71b469d381c.js" async=""></script>
1<link rel="preconnect" href="https://api.fontshare.com" crossorigin="anonymous"/><meta name="next-size-adjust" content=""/><title>Ketoy - Kotlin Over-The-Air (OTA) Updates for Android</title><meta name="description" content="Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. Write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed bundle, and push changes over-the-air in seconds - no Play Store release, no JSON DSL. Fully within Play Store policies."/><meta name="application-name" content="Ketoy"/><link rel="author" href="https://ketoy.dev"/><meta name="author" content="Ketoy"/><meta name="keywords" content="Kotlin OTA,Android OTA updates,over-the-air updates Android,Kotlin over-the-air updates,Jetpack Compose OTA,Android code push,Kotlin SDUI,Android SDUI,server-driven UI Android,Jetpack Compose SDUI,Kotlin Native SDUI,Compose server-driven UI,OTA vs SDUI,what is OTA in Android,what is server-driven UI,update Android app without Play Store release,update Compose UI over the air,ship ViewModel and business logic over the air,Android instant updates,CodePush for Android Kotlin,Kotlin over-the-air update framework,SDUI framework,Ketoy"/><meta name="creator" content="Ketoy"/><meta name="publisher" content="Ketoy"/><meta name="robots" content="index, follow"/><meta name="googlebot" content="index, follow, max-video-preview:-1, max-image-preview:large, max-snippet:-1"/><meta name="category" content="technology"/><link rel="canonical" href="https://ketoy.dev"/><meta property="og:title" content="Ketoy - Kotlin Over-The-Air (OTA) Updates for Android"/><meta property="og:description" content="Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. Write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed bundle, and push changes over-the-air in seconds - no Play Store release, no JSON DSL. Fully within Play Store policies."/><meta property="og:url" content="https://ketoy.dev"/><meta property="og:image:alt" content="Ketoy - Kotlin over-the-air (OTA) updates for Android, server-driven UI (SDUI) included."/><meta property="og:image:type" content="image/png"/><meta property="og:image" content="https://ketoy.dev/opengraph-image?449440a0bf7f01c9"/><meta property="og:image:width" content="1200"/><meta property="og:image:height" content="630"/><meta property="og:type" content="website"/><meta name="twitter:card" content="summary_large_image"/><meta name="twitter:title" content="Ketoy - Kotlin Over-The-Air (OTA) Updates for Android"/><meta name="twitter:description" content="Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. Write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed bundle, and push changes over-the-air in seconds - no Play Store release, no JSON DSL. Fully within Play Store policies."/><meta name="twitter:image:alt" content="Ketoy - Kotlin over-the-air (OTA) updates for Android, server-driven UI (SDUI) included."/><meta name="twitter:image:type" content="image/png"/><meta name="twitter:image" content="https://ketoy.dev/opengraph-image?449440a0bf7f01c9"/><meta name="twitter:image:width" content="1200"/><meta name="twitter:image:height" content="630"/><link rel="icon" href="/assets/ketoy-logo.svg"/><link rel="stylesheet" href="https://api.fontshare.com/v2/css?f[]=switzer@300,400,500&amp;display=swap"/>
1<script>
2(function () {
3  try {
4    if (localStorage.getItem('ketoy-theme') === 'dark') {
5      document.documentElement.setAttribute('data-theme', 'dark');
6    }
7  } catch (e) {}
8})();
9</script>
9<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://ketoy.dev/#organization","name":"Ketoy","url":"https://ketoy.dev","logo":"https://ketoy.dev/assets/ketoy_logo.png","description":"Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. Write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed bundle, and push changes over-the-air in seconds - no Play Store release, no JSON DSL. Fully within Play Store policies.","sameAs":["https://github.com/developerchunk/ketoy-extended"]},{"@type":"WebSite","@id":"https://ketoy.dev/#website","url":"https://ketoy.dev","name":"Ketoy","description":"Kotlin over-the-air (OTA) updates and server-driven UI (SDUI) for Android","inLanguage":"en","publisher":{"@id":"https://ketoy.dev/#organization"}},{"@type":"SoftwareApplication","@id":"https://ketoy.dev/#software","name":"Ketoy SDK","applicationCategory":"DeveloperApplication","applicationSubCategory":"Over-the-air (OTA) update framework","operatingSystem":"Android","softwareVersion":"0.4.20-alpha","programmingLanguage":"Kotlin","description":"Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. Write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed bundle, and push changes over-the-air in seconds - no Play Store release, no JSON DSL. Fully within Play Store policies.","url":"https://ketoy.dev","downloadUrl":"https://ketoy.dev/get-started","featureList":["Kotlin-native over-the-air (OTA) updates for Android","Ships Compose UI, ViewModels, business logic, and navigation over-the-air","Covers server-driven UI (SDUI) without a JSON schema or DSL","Compiles real Jetpack Compose to a signed .ktx bytecode bundle","Ed25519-signed bundles rendered natively on device","No Play Store release, no parallel component model"],"offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"publisher":{"@id":"https://ketoy.dev/#organization"}}]}</script>
9<script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script>
9</head><body><div hidden=""><!--$--><!--/$--></div><header class="topbar"><div class="topbar-inner"><a class="brand" href="/"><img class="brand-mark" src="/assets/ketoy-logo.svg" alt=""/><span class="brand-name">Ketoy</span></a><nav class="nav"><a href="/get-started">Get started</a><a href="/features">Supported features</a><a href="/architecture">Architecture</a><a href="/docs">Docs</a><a href="/updates">What’s new</a></nav><div class="nav-right"><div class="search-wrap" id="searchWrap"><div class="search"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"></circle><path d="m20 20-3.5-3.5"></path></svg><input id="searchInput" type="text" placeholder="Search docs" autoComplete="off" value=""/><span class="kbd">/</span></div><div class="search-dropdown" id="searchDropdown"><div class="search-results" id="searchResults"></div></div></div><button class="theme-toggle" type="button" aria-label="Toggle theme"><svg class="ic-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"></path></svg><svg class="ic-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg></button><a class="btn btn-primary nav-cta" href="/get-started">Get started</a><button type="button" class="nav-burger" aria-label="Open menu" aria-expanded="false"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 7h16M4 12h16M4 17h16"></path></svg></button></div></div><nav class="mobile-menu" aria-hidden="true"><a href="/get-started">Get started</a><a href="/features">Supported features</a><a href="/architecture">Architecture</a><a href="/docs">Docs</a><a href="/updates">What’s new</a><a class="btn btn-primary mobile-menu-cta" href="/get-started">Get started</a></nav></header><section class="hero"><div class="hero-aurora" aria-hidden="true"><span class="a1"></span><span class="a2"></span><span class="a3"></span></div><div class="container"><div class="hero-grid"><div class="hero-lead"><div class="hero-tag"><span class="pill">v<!-- -->0.4</span><span>Kotlin OTA</span><span class="live-dot" aria-hidden="true"></span></div><h1>Ship <strong>Kotlin</strong> over the air.</h1><p class="lede">Write real Kotlin and Jetpack Compose. Push updates to every device in seconds.</p><div class="hero-actions"><a class="btn btn-primary" href="/get-started">Get started<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M13 5l7 7-7 7"></path></svg></a><a class="btn btn-ghost" href="/architecture">How it works</a></div></div><div class="hero-phone-stage" role="img" aria-label="Over-the-air delivery: the Aurora app updates live from v2.4.1 to v2.4.2 without a Play Store release."><div class="hero-phone-packet p1" aria-hidden="true"><span>ktx</span></div><div class="hero-phone-packet p2" aria-hidden="true"><span>4KB</span></div><div class="hero-phone-frame"><div class="hero-phone-glow" aria-hidden="true"></div><div class="hero-phone-ring" aria-hidden="true"></div><div class="hero-phone-ring delay" aria-hidden="true"></div><div class="hero-phone" aria-hidden="true"><div class="hero-phone-notch"></div><div class="hero-phone-screen"><div class="hero-phone-head"><div class="hero-phone-brand"><span class="hero-phone-mark">A</span><span>Aurora</span></div><div class="hero-phone-version"><span class="v old"><i></i>v2.4.1</span><span class="v new"><i></i>v2.4.2</span></div></div><div class="hero-phone-body"><div class="hero-phone-state before"><div class="hero-card-header"><div class="eyebrow">HOME</div><div class="title">Your orders</div></div><div class="hero-row"><span class="icon">📦</span><span class="meta"><span class="title">Order #4821</span><span class="sub">Delivered · Fri</span></span><span class="price">$42.10</span></div><div class="hero-row"><span class="icon">🚚</span><span class="meta"><span class="title">Order #4820</span><span class="sub">In transit · ETA Tue</span></span><span class="price">$18.00</span></div><div class="hero-row"><span class="icon">📦</span><span class="meta"><span class="title">Order #4818</span><span class="sub">Delivered · Mon</span></span><span class="price">$63.75</span></div></div><div class="hero-phone-state after"><div class="hero-checkout-card"><div class="top"><span class="badge">NEW · OTA</span><span class="cart">2 in cart</span></div><div class="headline">Checkout, redesigned</div><div class="pay"><span>Pay $147</span><span>→</span></div></div><div class="hero-row accent"><span class="icon">👕</span><span class="meta"><span class="title">Nimbus Tee</span><span class="sub">Sage · M · Qty 1</span></span><span class="price">$29</span></div><div class="hero-row accent"><span class="icon">👟</span><span class="meta"><span class="title">Aero Runners</span><span class="sub">White · 10 · Qty 1</span></span><span class="price">$118</span></div></div></div><div class="hero-phone-wipe"></div><div class="hero-phone-patch"><span class="spinner"></span><span>Patching UI…</span></div><div class="hero-phone-toast"><div class="row"><span class="check">✓</span><span class="label">Updated to v2.4.2</span><span class="time">1.2s</span></div><div class="bar-track"><div class="bar-fill"></div></div></div></div></div></div></div></div><div class="hero-stats" data-reveal="true"><div class="hero-stat"><div class="v">&lt; 50<small>ms</small></div><div class="l">Load, verify, and parse</div></div><div class="hero-stat"><div class="v">&lt; 100<small>ms</small></div><div class="l">First frame, cold</div></div><div class="hero-stat"><div class="v">&gt; 100<small>KB</small></div><div class="l">A full app flow</div></div><div class="hero-stat"><div class="v">20<small>×</small></div><div class="l">Smaller than JSON SDUI</div></div></div></div></section><section class="surface"><div class="container"><div class="section-head" data-reveal="true"><span class="eyebrow">Integrate in minutes</span><h2>Command line and AI agents.</h2><p>The Ketoy CLI runs your whole workflow from the terminal. Ketoy Skills give any AI coding agent an accurate map of what Ketoy supp
9orts, before it writes a line.</p></div><div class="integrate-grid" data-reveal="true"><div class="integrate-card"><div class="integrate-head"><span class="integrate-kicker">Command line</span><h3>Ketoy CLI</h3><p>Set up a project, push to the cloud, and roll back — all from the terminal.</p></div><div class="cli-term" aria-hidden="true"><div class="cli-chrome"><span class="cli-dot r"></span><span class="cli-dot y"></span><span class="cli-dot g"></span><span class="cli-title">ketoy</span></div><div class="cli-body"><div class="cli-line"><span class="p">$</span> ketoy init</div><div class="cli-out"><span class="ok">✓</span> Gradle plugin added</div><div class="cli-out"><span class="ok">✓</span> Ed25519 key generated</div><div class="cli-out"><span class="ok">✓</span> HomeScreen.kt created</div><div class="cli-line sp"><span class="p">$</span> ketoy push ktx my-app main.ktx --version 7</div><div class="cli-out"><span class="ok">✓</span> Uploaded. Live in <b>1.2s</b></div><div class="cli-line sp"><span class="p">$</span> ketoy ktx rollback my-app<span class="cli-cur"></span></div></div></div><div class="integrate-cmd"><span class="prompt">$</span><code>npm install -g ketoy-dev</code><button type="button" class="code-copy" aria-label="Copy code" title="Copy code"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="11" height="11" rx="2"></rect><path d="M5 15V5a2 2 0 0 1 2-2h10"></path></svg></button></div><a class="integrate-link" href="/docs/cli">CLI docs<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M13 5l7 7-7 7"></path></svg></a></div><div class="integrate-card"><div class="integrate-head"><span class="integrate-kicker">AI agents</span><h3>Ketoy Skills</h3><p>Install a skill pack that grounds any coding agent in how Ketoy actually works before it writes code.</p></div><div class="skills-panel" aria-hidden="true"><div class="skills-head"><span class="skills-star">✦</span><span>AI agent · ketoy skills</span></div><div class="skills-call"><span class="skills-tool">ketoy skills add</span></div><div class="skills-reply"><span class="ok">✓</span><div>Installed to .claude/skills — catalog, capabilities, and every 
9KetoyBC: fix.</div></div><div class="skills-tools"><span class="skills-chip">catalog<!-- -->.md</span><span class="skills-chip">capabilities<!-- -->.md</span><span class="skills-chip">viewmodel-and-state<!-- -->.md</span><span class="skills-chip">host-integration<!-- -->.md</span><span class="skills-chip">troubleshooting<!-- -->.md</span><span class="skills-chip">build-and-ship<!-- -->.md</span></div></div><div class="agent-row" aria-label="Works with any skills-compatible agent"><span class="agent-chip">Claude Code</span><span class="agent-chip">Codex</span><span class="agent-chip">Cursor</span><span class="agent-chip">Windsurf</span><span class="agent-chip">Gemini CLI</span></div><div class="integrate-cmd"><span class="prompt">$</span><code>ketoy skills add</code><button type="button" class="code-copy" aria-label="Copy code" title="Copy code"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="11" height="11" rx="2"></rect><path d="M5 15V5a2 2 0 0 1 2-2h10"></path></svg></button></div><a class="integrate-link" href="/docs/skills">Skills docs<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M13 5l7 7-7 7"></path></svg></a></div></div></div></section><section class="surface"><div class="container"><div class="section-head" data-reveal="true"><span class="eyebrow">Why Ketoy</span><h2>Update without a release.</h2><p>Add one annotation. Run one Gradle task. Every device gets the change in seconds.</p></div><div class="cards-grid"><div class="card"><div class="num">01</div><div class="icon" aria-hidden="true"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M12 2v6m0 0 3-3m-3 3-3-3M5 13h14l-1 8H6l-1-8z"></path></svg></div><h3>Instant updates</h3><p>Fix a bug at 3pm. Every user has it by 3:01. The app never reinstalls.</p><a class="link" href="/architecture">How it works</a></div><div class="card"><div class="num">02</div><div class="icon" aria-hidden="true"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M12 2 4 6v6c0 5 3.4 9.5 8 10 4.6-.5 8-5 8-10V6l-8-4z"></path><path d="M9 12l2 2 4-4"></path></svg></div><h3>Play Store safe</h3><p>Ketoy generates code on device, the same way ART does. It stays inside Google policy.</p><a class="link" href="#security">Security model</a></div><div class="card"><div class="num">03</div><div class="icon" aria-hidden="true"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 6h16M4 12h10M4 18h16"></path><path d="m16 9 3 3-3 3"></path></svg></div><h3>Just Kotlin</h3><p>It is the Jetpack Compose you already write. Nothing new to learn.</p><a class="link" href="/features">What is supported</a></div></div></div></section><section class="surface"><div class="container"><div class="section-head" data-reveal="true"><span class="eyebrow">What’s supported</span><h2>If it’s Compose, it’s Ketoy.</h2><p>Ketoy supports the full Compose toolkit, not a curated subset. When Compose adds a parameter, one command picks it up.</p></div><div class="support-grid"><div class="support-card"><span class="support-tag">UI</span><h3>Compose and Material 3</h3><p style="font-size:14.5px;color:var(--muted);line-height:1.55">All 35 Material 3 components. Every parameter included.</p><div class="chips"><span class="chip">Scaffold</span><span class="chip">LazyColumn</span><span class="chip">OutlinedTextField</span><span class="chip">Button</span><span class="chip">TopAppBar</span><span class="chip">AlertDialog</span><span class="chip">+29 more</span></div></div><div class="support-card"><span class="support-tag">Language</span><h3>Plain Kotlin</h3><p style="font-size:14.5px;color:var(--muted);line-height:1.55">Data classes, sealed classes, extensions, and lambdas. Real Kotlin, compiled to bytecode.</p><div class="chips"><span class="chip">data class</span><span class="chip">sealed</span><span class="chip">when</span><span class="chip">extensions</span><span class="chip">closures</span></div></div><div class="support-card"><span class="support-tag">Async</span><h3>Coroutines and Flow</h3><p style="font-size:14.5px;color:var(--muted);line-height:1.55">launch, async, withContext, and 9 Flow operators. Structured concurrency included.</p><div class="chips"><span class="chip">launch</span><span class="chip">async</span><span class="chip">StateFlow</span><span class="chip">collectAsState</span><span class="chip">debounce</span></div></div><div class="support-card"><span class="support-tag">State</span><h3>ViewModel</h3><p style="font-size:14.5px;color:var(--muted);line-height:1.55">A real Android ViewModel. It survives config changes and works with Hilt.</p><div class="chips"><span class="chip">viewModelScope</span><span class="chip">SavedStateHandle</span><span class="chip">@HiltViewModel</span><span class="chip">dispatch()</span></div></div><div class="support-card"><span class="support-tag">I/O</span><h3>Networking and storage</h3><p style="font-size:14.5px;color:var(--muted);line-height:1.55">HTTP, DataStore, Room, and navigation. 67 capabilities built in.</p><div class="chips"><span class="chip">HTTP</span><span class="chip">DataStore</span><span class="chip">Room</span><span class="chip">NavController</span><span class="chip">+ your SDKs</span></div></div><div class="support-card"><span class="support-tag">DI</span><h3>Hilt</h3><p style="font-size:14.5px;color:var(--muted);line-height:1.55">Drop it in. @Inject works exactly as before.</p><div class="chips"><span class="chip">@Inject</span><span class="chip">@HiltViewModel</span><span class="chip">@Module</span><span class="chip">dev overlay</span></div></div></div><div class="diff-strip" data-reveal="true"><p class="diff-line"><b style="font-weight:600;color:var(--ink)">One annotation and one Gradle task.</b> That is the whole difference.</p><a class="link" style="font-family:var(--font-ui);font-weight:600;font-size:15px;color:var(--accent-ink);white-space:nowrap" href="/features">
9See everything Ketoy supports</a></div></div></section><section class="ink" id="security"><div class="container"><div class="section-head" data-reveal="true"><span class="eyebrow" style="color:#4AE389">Security</span><h2>Secure and compliant.</h2><p>Ketoy verifies every bundle before it runs. Here is how, in three parts.</p></div><div class="cards-grid"><div class="card dark"><div class="icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M12 2 4 6v6c0 5 3.4 9.5 8 10 4.6-.5 8-5 8-10V6l-8-4z"></path></svg></div><h3>Every bundle is signed</h3><p>An Ed25519 signature is checked before any code runs. Your private key stays on your server. Only you can ship a bundle.</p></div><div class="card dark"><div class="icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="3" width="18" height="18" rx="3"></rect><path d="M9 12l2 2 4-4"></path></svg></div><h3>The sandbox is a build error</h3><p>The compiler rejects file access, reflection, and any unregistered API. Unsafe code never compiles.</p></div><div class="card dark"><div class="icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M3 12h4l3-8 4 16 3-8h4"></path></svg></div><h3>Capabilities are the only door</h3><p>KBC code reaches the platform through registered capabilities. Nothing else is callable.</p></div></div><div class="legal-row legal-row--single"><div class="card dark"><div class="icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M12 2v20M2 12h20"></path></svg></div><div class="legal-quote">Is this allowed on the Play Store?</div><p>Yes. Ketoy generates code on device, exactly like ART does with bytecode. It is the same idea as Lua in a game engine. If your CDN goes down, the last signed bundle keeps running.</p></div></div></div></section><section style="padding-top:56px"><div class="container"><div class="cta-banner"><div><h2>Write Kotlin. Ship the screen.</h2><p>Available now on Maven Central. Hilt, Koin, dev tools, and the full Material 3 catalog are included.</p></div><div class="right"><a class="btn btn-ghost" href="/docs">Read the docs</a><a class="btn btn-primary" href="/get-started">Get started</a></div></div><div class="support-cta" data-reveal="true"><span class="support-cta-icon" aria-hidden="true"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg></span><div class="support-cta-body"><span class="eyebrow">Support</span><h3>Talk to the people who build it.</h3><p>Stuck on something, evaluating Ketoy for your team, or wondering whether your in-house SDK is supported? We answer every email, usually the same day.</p></div><button type="button" class="btn btn-primary">Contact support<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M13 5l7 7-7 7"></path></svg></button></div></div></section><section class="surface" id="faq"><div class="container"><div class="section-head" data-reveal="true"><span class="eyebrow">FAQ</span><h2>Questions, answered.</h2></div><div class="home-faq" data-reveal="true"><details class="faq-item" id="what-is-ketoy"><summary class="faq-q"><span class="faq-q-text">What is Ketoy?</span><svg class="faq-chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg></summary><div class="faq-a"><p>Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. You write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed .ktx bytecode bundle, and push changes over-the-air to installed apps in seconds - no Play Store release and no JSON DSL.</p></div></details>
9<details class="faq-item" id="is-ketoy-ota-or-sdui"><summary class="faq-q"><span class="faq-q-text">Is Ketoy OTA or SDUI?</span><svg class="faq-chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg></summary><div class="faq-a"><p>Ketoy is an OTA framework, and SDUI is one of the things it can do. Because it ships real Kotlin and Compose over the air, a bundle can drive a whole screen from the server - that is SDUI - and it can equally ship a ViewModel, a network call, or a pricing rule that no JSON schema could express.</p></div></details><details class="faq-item" id="what-can-ketoy-update-over-the-air"><summary class="faq-q"><span class="faq-q-text">What can Ketoy update over the air?</span><svg class="faq-chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg></summary><div class="faq-a"><p>Jetpack Compose UI, ViewModels and state, navigation, coroutines and Flow, networking, Room and DataStore access, and ordinary Kotlin such as data classes, objects, and functions. UI-only and logic-only bundles are both fine.</p></div></details><details class="faq-item" id="how-is-ketoy-different-from-json-based-server-driven-ui"><summary class="faq-q"><span class="faq-q-text">How is Ketoy different from JSON-based server-driven UI?</span><svg class="faq-chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg></summary><div class="faq-a"><p>Instead of a JSON schema and a parallel component model, Ketoy uses ordinary Kotlin and Jetpack Compose compiled to Ketoy Bytecode (KBC). Bundles are roughly 20x smaller than equivalent JSON SDUI, Ed25519-signed, and rendered as native Compose on device.</p></div></details><details class="faq-item" id="does-ketoy-allow-over-the-air-ota-updates-on-android-within-play-store-policy"><summary class="faq-q"><span class="faq-q-text">Does Ketoy allow over-the-air (OTA) updates on Android within Play Store policy?</span><svg class="faq-chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"></path></svg></summary><div class="faq-a"><p>Yes. Ketoy delivers UI and logic changes over-the-air without shipping a new APK/AAB. Bundles execute in a sandbox and render native Compose, which keeps updates within Play Store policies.</p></div></details><div class="home-faq-foot"><p>OTA vs SDUI, bundle sizes, Play Store policy, offline behaviour, debugging.</p><a class="btn btn-ghost" href="/docs/faq">More questions<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M13 5l7 7-7 7"></path></svg></a></div></div></div></section>
9<script type="application/ld+json">{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"What is Ketoy?","acceptedAnswer":{"@type":"Answer","text":"Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. You write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed .ktx bytecode bundle, and push changes over-the-air to installed apps in seconds - no Play Store release and no JSON DSL."}},{"@type":"Question","name":"Is Ketoy OTA or SDUI?","acceptedAnswer":{"@type":"Answer","text":"Ketoy is an OTA framework, and SDUI is one of the things it can do. Because it ships real Kotlin and Compose over the air, a bundle can drive a whole screen from the server - that is SDUI - and it can equally ship a ViewModel, a network call, or a pricing rule that no JSON schema could express."}},{"@type":"Question","name":"What can Ketoy update over the air?","acceptedAnswer":{"@type":"Answer","text":"Jetpack Compose UI, ViewModels and state, navigation, coroutines and Flow, networking, Room and DataStore access, and ordinary Kotlin such as data classes, objects, and functions. UI-only and logic-only bundles are both fine."}},{"@type":"Question","name":"How is Ketoy different from JSON-based server-driven UI?","acceptedA
9nswer":{"@type":"Answer","text":"Instead of a JSON schema and a parallel component model, Ketoy uses ordinary Kotlin and Jetpack Compose compiled to Ketoy Bytecode (KBC). Bundles are roughly 20x smaller than equivalent JSON SDUI, Ed25519-signed, and rendered as native Compose on device."}},{"@type":"Question","name":"Does Ketoy allow over-the-air (OTA) updates on Android within Play Store policy?","acceptedAnswer":{"@type":"Answer","text":"Yes. Ketoy delivers UI and logic changes over-the-air without shipping a new APK/AAB. Bundles execute in a sandbox and render native Compose, which keeps updates within Play Store policies."}}]}</script>
9<!--$--><!--/$--><footer class="site-footer"><div class="container"><div class="footer-grid"><div><a class="brand" href="/"><img class="brand-mark" src="/assets/ketoy-logo.svg" alt=""/><span class="brand-name">Ketoy</span></a><p class="footer-brand-blurb">Kotlin-native over-the-air (OTA) updates for Android, server-driven UI (SDUI) included. Write Kotlin and Jetpack Compose, ship a signed bytecode bundle, render real Compose.</p></div><div><h4>Product</h4><ul><li><a href="/get-started">Get started</a></li><li><a href="/features">Supported features</a></li><li><a href="/architecture">Architecture</a></li><li><a href="/updates">Release notes</a></li></ul></div><div><h4>Docs</h4><ul><li><a href="/docs">Documentation</a></li><li><a href="/docs/reference/kbc-opcodes">KBC spec</a></li><li><a href="/docs/reference/capability-registry">Capability registry</a></li><li><a href="/docs/reference/ktx-bundle-format">Bundle format</a></li></ul></div><div><h4>Resources</h4><ul><li><a href="https://central.sonatype.com/namespace/dev.ketoy.vm">Maven Central</a></li><li><a href="https://github.com/KetoyDev/demos">Sample apps</a></li><li><a href="#">Migration guide</a></li><li><a href="/docs/faq">FAQ</a></li></ul></div><div><h4>Community</h4><ul><li><a href="https://github.com/KetoyDev">GitHub</a></li><li><a href="https://discord.gg/jAbcPPyksf">Discord</a></li><li><a href="/issue">Report an issue</a></li><li><button type="button" class="footer-contact-btn" aria-haspopup="dialog" aria-expanded="false">Contact</button></li></ul></div></div><div class="footer-meta"><span>© 2026 Ketoy.<!-- --> <code style="font-family:var(--font-mono);font-size:12px">dev.ketoy.vm</code> <!-- -->· v<!-- -->0.4.20-alpha</span><span>Made for Android · Kotlin 2.0 · Compose</span></div></div></footer>
9<script src="/_next/static/chunks/webpack-b2f0e5b150b12ec0.js" id="_R_" async=""></script>
9<script>(self.__next_f=self.__next_f||[]).push([0])</script>
9<script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n3:I[1341,[\"5000\",\"static/chunks/5000-250c7c961a3aed60.js\",\"7177\",\"static/chunks/app/layout-5f049d25b5082e14.js\"],\"default\"]\n4:I[9766,[],\"\"]\n5:I[8924,[],\"\"]\nb:I[7150,[],\"\"]\n:HL[\"/_next/static/media/558ca1a6aa3cb55e-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/7b0b24f36b1a6d0b-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/a22b1dc24103c00d-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/css/a028ffcdacb4e6b9.css\",\"style\"]\n:HL[\"/_next/static/css/10cce706acc7ff5e.css\",\"style\"]\n2:T7c7,"])</script>
9<script>self.__next_f.push([1,"{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://ketoy.dev/#organization\",\"name\":\"Ketoy\",\"url\":\"https://ketoy.dev\",\"logo\":\"https://ketoy.dev/assets/ketoy_logo.png\",\"description\":\"Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. Write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed bundle, and push changes over-the-air in seconds - no Play Store release, no JSON DSL. Fully within Play Store policies.\",\"sameAs\":[\"https://github.com/developerchunk/ketoy-extended\"]},{\"@type\":\"WebSite\",\"@id\":\"https://ketoy.dev/#website\",\"url\":\"https://ketoy.dev\",\"name\":\"Ketoy\",\"description\":\"Kotlin over-the-air (OTA) updates and server-driven UI (SDUI) for Android\",\"inLanguage\":\"en\",\"publisher\":{\"@id\":\"https://ketoy.dev/#organization\"}},{\"@type\":\"SoftwareApplication\",\"@id\":\"https://ketoy.dev/#software\",\"name\":\"Ketoy SDK\",\"applicationCategory\":\"DeveloperApplication\",\"applicationSubCategory\":\"Over-the-air (OTA) update framework\",\"operatingSystem\":\"Android\",\"softwareVersion\":\"0.4.20-alpha\",\"programmingLanguage\":\"Kotlin\",\"description\":\"Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. Write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed bundle, and push changes over-the-air in seconds - no Play Store release, no JSON DSL. Fully within Play Store policies.\",\"url\":\"https://ketoy.dev\",\"downloadUrl\":\"https://ketoy.dev/get-started\",\"featureList\":[\"Kotlin-native over-the-air (OTA) updates for Android\",\"Ships Compose UI, ViewModels, business logic, and navigation over-the-air\",\"Covers server-driven UI (SDUI) without a JSON schema or DSL\",\"Compiles real Jetpack Compose to a signed .ktx bytecode bundle\",\"Ed25519-signed bundles rendered natively on device\",\"No Play Store release, no parallel component model\"],\"offers\":{\"@type\":\"Offer\",\"price\":\"0\",\"priceCurrency\":\"USD\"},\"publisher\":{\"@id\":\"https://ketoy.dev/#organization\"}}]}"])</script>
9<script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"gApJWUxpRy7_zBZZe0WQW\",\"p\":\"\",\"c\":[\"\",\"\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/a028ffcdacb4e6b9.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"__variable_7fd790 __variable_40479c __variable_e896d9\",\"suppressHydrationWarning\":true,\"children\":[[\"$\",\"head\",null,{\"children\":[[\"$\",\"link\",null,{\"rel\":\"preconnect\",\"href\":\"https://api.fontshare.com\",\"crossOrigin\":\"anonymous\"}],[\"$\",\"link\",null,{\"rel\":\"stylesheet\",\"href\":\"https://api.fontshare.com/v2/css?f[]=switzer@300,400,500\u0026display=swap\"}],[\"$\",\"script\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"\\n(function () {\\n  try {\\n    if (localStorage.getItem('ketoy-theme') === 'dark') {\\n      document.documentElement.setAttribute('data-theme', 'dark');\\n    }\\n  } catch (e) {}\\n})();\\n\"}}],[\"$\",\"script\",null,{\"type\":\"application/ld+json\",\"dangerouslySetInnerHTML\":{\"__html\":\"$2\"}}]]}],[\"$\",\"body\",null,{\"suppressHydrationWarning\":true,\"children\":[[\"$\",\"$L3\",null,{}],[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],\"$L6\",\"$L7\"]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],\"$L8\"]}]]}]]}],{\"children\":[\"__PAGE__\",\"$L9\",{},null,false]},null,false],\"$La\",false]],\"m\":\"$undefined\",\"G\":[\"$b\",[]],\"s\":false,\"S\":true}\n"])</script>
9<script>self.__next_f.push([1,"c:I[953,[\"5000\",\"static/chunks/5000-250c7c961a3aed60.js\",\"7177\",\"static/chunks/app/layout-5f049d25b5082e14.js\"],\"default\"]\nd:I[2619,[\"5000\",\"static/chunks/5000-250c7c961a3aed60.js\",\"8974\",\"static/chunks/app/page-8569f71b469d381c.js\"],\"*\"]\n1f:I[4431,[],\"ViewportBoundary\"]\n21:I[4431,[],\"MetadataBoundary\"]\n22:\"$Sreact.suspense\"\n6:[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}]\n7:[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]\n8:[\"$\",\"$Lc\",null,{}]\n"])</script>
9<script>self.__next_f.push([1,"9:[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"section\",null,{\"className\":\"hero\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-aurora\",\"aria-hidden\":\"true\",\"children\":[[\"$\",\"span\",null,{\"className\":\"a1\"}],[\"$\",\"span\",null,{\"className\":\"a2\"}],[\"$\",\"span\",null,{\"className\":\"a3\"}]]}],[\"$\",\"div\",null,{\"className\":\"container\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-grid\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-lead\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-tag\",\"children\":[[\"$\",\"span\",null,{\"className\":\"pill\",\"children\":[\"v\",\"0.4\"]}],[\"$\",\"span\",null,{\"children\":\"Kotlin OTA\"}],[\"$\",\"span\",null,{\"className\":\"live-dot\",\"aria-hidden\":\"true\"}]]}],[\"$\",\"h1\",null,{\"children\":[\"Ship \",[\"$\",\"strong\",null,{\"children\":\"Kotlin\"}],\" over the air.\"]}],[\"$\",\"p\",null,{\"className\":\"lede\",\"children\":\"Write real Kotlin and Jetpack Compose. Push updates to every device in seconds.\"}],[\"$\",\"div\",null,{\"className\":\"hero-actions\",\"children\":[[\"$\",\"$Ld\",null,{\"className\":\"btn btn-primary\",\"href\":\"/get-started\",\"children\":[\"Get started\",[\"$\",\"svg\",null,{\"width\":\"16\",\"height\":\"16\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"2\",\"children\":[\"$\",\"path\",null,{\"d\":\"M5 12h14M13 5l7 7-7 7\"}]}]]}],[\"$\",\"$Ld\",null,{\"className\":\"btn btn-ghost\",\"href\":\"/architecture\",\"children\":\"How it works\"}]]}]]}],[\"$\",\"div\",null,{\"className\":\"hero-phone-stage\",\"role\":\"img\",\"aria-label\":\"Over-the-air delivery: the Aurora app updates live from v2.4.1 to v2.4.2 without a Play Store release.\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-phone-packet p1\",\"aria-hidden\":\"true\",\"children\":[\"$\",\"span\",null,{\"children\":\"ktx\"}]}],[\"$\",\"div\",null,{\"className\":\"hero-phone-packet p2\",\"aria-hidden\":\"true\",\"children\":[\"$\",\"span\",null,{\"children\":\"4KB\"}]}],[\"$\",\"div\",null,{\"className\":\"hero-phone-frame\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-phone-glow\",\"aria-hidden\":\"true\"}],[\"$\",\"div\",null,{\"className\":\"hero-phone-ring\",\"aria-hidden\":\"true\"}],[\"$\",\"div\",null,{\"className\":\"hero-phone-ring delay\",\"aria-hidden\":\"true\"}],[\"$\",\"div\",null,{\"className\":\"hero-phone\",\"aria-hidden\":\"true\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-phone-notch\"}],[\"$\",\"div\",null,{\"className\":\"hero-phone-screen\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-phone-head\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-phone-brand\",\"children\":[[\"$\",\"span\",null,{\"className\":\"hero-phone-mark\",\"children\":\"A\"}],[\"$\",\"span\",null,{\"children\":\"Aurora\"}]]}],[\"$\",\"div\",null,{\"className\":\"hero-phone-version\",\"children\":[[\"$\",\"span\",null,{\"className\":\"v old\",\"children\":[[\"$\",\"i\",null,{}],\"v2.4.1\"]}],[\"$\",\"span\",null,{\"className\":\"v new\",\"children\":[[\"$\",\"i\",null,{}],\"v2.4.2\"]}]]}]]}],[\"$\",\"div\",null,{\"className\":\"hero-phone-body\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-phone-state before\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-card-header\",\"children\":[[\"$\",\"div\",null,{\"className\":\"eyebrow\",\"children\":\"HOME\"}],[\"$\",\"div\",null,{\"className\":\"title\",\"children\":\"Your orders\"}]]}],[\"$\",\"div\",null,{\"className\":\"hero-row\",\"children\":[[\"$\",\"span\",null,{\"className\":\"icon\",\"children\":\"📦\"}],[\"$\",\"span\",null,{\"className\":\"meta\",\"children\":[[\"$\",\"span\",null,{\"className\":\"title\",\"children\":\"Order #4821\"}],[\"$\",\"span\",null,{\"className\":\"sub\",\"children\":\"Delivered · Fri\"}]]}],[\"$\",\"span\",null,{\"className\":\"price\",\"children\":\"$$42.10\"}]]}],[\"$\",\"div\",null,{\"className\":\"hero-row\",\"children\":[[\"$\",\"span\",null,{\"className\":\"icon\",\"children\":\"🚚\"}],[\"$\",\"span\",null,{\"className\":\"meta\",\"children\":[[\"$\",\"span\",null,{\"className\":\"title\",\"children\":\"Order #4820\"}],[\"$\",\"span\",null,{\"className\":\"sub\",\"children\":\"In transit · ETA Tue\"}]]}],[\"$\",\"span\",null,{\"className\":\"price\",\"children\":\"$$18.00\"}]]}],[\"$\",\"div\",null,{\"className\":\"hero-row\",\"children\":[[\"$\",\"span\",null,{\"className\":\"icon\",\"children\":\"📦\"}],[\"$\",\"span\",null,{\"className\":\"meta\",\"children\":[[\"$\",\"span\",null,{\"className\":\"title\",\"children\":\"Order #4818\"}],[\"$\",\"span\",null,{\"className\":\"sub\",\"children\":\"Delivered · Mon\"}]]}],[\"$\",\"span\",null,{\"className\":\"price\",\"children\":\"$$63.75\"}]]}]]}],[\"$\",\"div\",null,{\"className\":\"hero-phone-state after\",\"children\":[[\"$\",\"div\",null,{\"className\":\"hero-checkout-card\",\"children\":[[\"$\",\"div\",null,{\"className\":\"top\",\"children\":[[\"$\",\"span\",null,{\"className\":\"badge\",\"children\":\"NEW · OTA\"}],[\"$\",\"span\",null,{\"className\":\"cart\",\"children\":\"2 in cart\"}]]}],[\"$\",\"div\",null,{\"className\":\"headline\",\"children\":\"Checkout, redesigned\"}],[\"$\",\"div\",null,{\"className\":\"pay\",\"children\":[[\"$\",\"span\",null,{\"children\":\"Pay $147\"}],[\"$\",\"span\",null,{\"children\":\"→\"}]]}]]}],[\"$\",\"div\",null,{\"className\":\"hero-row accent\",\"children\":[[\"$\",\"span\",null,{\"className\":\"icon\",\"children\":\"👕\"}],[\"$\",\"span\",null,{\"className\":\"meta\",\"children\":[[\"$\",\"span\",null,{\"className\":\"title\",\"children\":\"Nimbus Tee\"}],[\"$\",\"span\",null,{\"className\":\"sub\",\"children\":\"Sage · M · Qty 1\"}]]}],[\"$\",\"span\",null,{\"className\":\"price\",\"children\":\"$$29\"}]]}],[\"$\",\"div\",null,{\"className\":\"hero-row accent\",\"children\":[\"$Le\",\"$Lf\",\"$L10\"]}]]}]]}],\"$L11\",\"$L12\",\"$L13\"]}]]}]]}]]}]]}],\"$L14\"]}]]}],\"$L15\",\"$L16\",\"$L17\",\"$L18\",\"$L19\",\"$L1a\",\"$L1b\",\"$L1c\"],[\"$L1d\"],\"$L1e\"]}]\n"])</script>
9<script>self.__next_f.push([1,"a:[\"$\",\"$1\",\"h\",{\"children\":[null,[[\"$\",\"$L1f\",null,{\"children\":\"$L20\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]],[\"$\",\"$L21\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$22\",null,{\"fallback\":null,\"children\":\"$L23\"}]}]}]]}]\n"])</script>
9<script>self.__next_f.push([1,"24:I[9808,[\"5000\",\"static/chunks/5000-250c7c961a3aed60.js\",\"8974\",\"static/chunks/app/page-8569f71b469d381c.js\"],\"default\"]\n2c:I[9474,[\"5000\",\"static/chunks/5000-250c7c961a3aed60.js\",\"8974\",\"static/chunks/app/page-8569f71b469d381c.js\"],\"default\"]\n31:I[9089,[\"5000\",\"static/chunks/5000-250c7c961a3aed60.js\",\"8974\",\"static/chunks/app/page-8569f71b469d381c.js\"],\"default\"]\n33:I[4431,[],\"OutletBoundary\"]\n35:I[5278,[],\"AsyncMetadataOutlet\"]\ne:[\"$\",\"span\",null,{\"className\":\"icon\",\"children\":\"👟\"}]\nf:[\"$\",\"span\",null,{\"className\":\"meta\",\"children\":[[\"$\",\"span\",null,{\"className\":\"title\",\"children\":\"Aero Runners\"}],[\"$\",\"span\",null,{\"className\":\"sub\",\"children\":\"White · 10 · Qty 1\"}]]}]\n10:[\"$\",\"span\",null,{\"className\":\"price\",\"children\":\"$$118\"}]\n11:[\"$\",\"div\",null,{\"className\":\"hero-phone-wipe\"}]\n12:[\"$\",\"div\",null,{\"className\":\"hero-phone-patch\",\"children\":[[\"$\",\"span\",null,{\"className\":\"spinner\"}],[\"$\",\"span\",null,{\"children\":\"Patching UI…\"}]]}]\n13:[\"$\",\"div\",null,{\"className\":\"hero-phone-toast\",\"children\":[[\"$\",\"div\",null,{\"className\":\"row\",\"children\":[[\"$\",\"span\",null,{\"className\":\"check\",\"children\":\"✓\"}],[\"$\",\"span\",null,{\"className\":\"label\",\"children\":\"Updated to v2.4.2\"}],[\"$\",\"span\",null,{\"className\":\"time\",\"children\":\"1.2s\"}]]}],[\"$\",\"div\",null,{\"className\":\"bar-track\",\"children\":[\"$\",\"div\",null,{\"className\":\"bar-fill\"}]}]]}]\n"])</script>
9<script>self.__next_f.push([1,"14:[\"$\",\"div\",null,{\"className\":\"hero-stats\",\"data-reveal\":true,\"children\":[[\"$\",\"div\",\"0\",{\"className\":\"hero-stat\",\"children\":[[\"$\",\"div\",null,{\"className\":\"v\",\"children\":[\"\u003c 50\",[\"$\",\"small\",null,{\"children\":\"ms\"}]]}],[\"$\",\"div\",null,{\"className\":\"l\",\"children\":\"Load, verify, and parse\"}]]}],[\"$\",\"div\",\"1\",{\"className\":\"hero-stat\",\"children\":[[\"$\",\"div\",null,{\"className\":\"v\",\"children\":[\"\u003c 100\",[\"$\",\"small\",null,{\"children\":\"ms\"}]]}],[\"$\",\"div\",null,{\"className\":\"l\",\"children\":\"First frame, cold\"}]]}],[\"$\",\"div\",\"2\",{\"className\":\"hero-stat\",\"children\":[[\"$\",\"div\",null,{\"className\":\"v\",\"children\":[\"\u003e 100\",[\"$\",\"small\",null,{\"children\":\"KB\"}]]}],[\"$\",\"div\",null,{\"className\":\"l\",\"children\":\"A full app flow\"}]]}],[\"$\",\"div\",\"3\",{\"className\":\"hero-stat\",\"children\":[[\"$\",\"div\",null,{\"className\":\"v\",\"children\":[\"20\",[\"$\",\"small\",null,{\"children\":\"×\"}]]}],[\"$\",\"div\",null,{\"className\":\"l\",\"children\":\"Smaller than JSON SDUI\"}]]}]]}]\n"])</script>
9<script>self.__next_f.push([1,"15:[\"$\",\"section\",null,{\"className\":\"surface\",\"children\":[\"$\",\"div\",null,{\"className\":\"container\",\"children\":[[\"$\",\"div\",null,{\"className\":\"section-head\",\"data-reveal\":true,\"children\":[[\"$\",\"span\",null,{\"className\":\"eyebrow\",\"children\":\"Integrate in minutes\"}],[\"$\",\"h2\",null,{\"children\":\"Command line and AI agents.\"}],[\"$\",\"p\",null,{\"children\":\"The Ketoy CLI runs your whole workflow from the terminal. Ketoy Skills give any AI coding agent an accurate map of what Ketoy supports, before it writes a line.\"}]]}],[\"$\",\"div\",null,{\"className\":\"integrate-grid\",\"data-reveal\":true,\"children\":[[\"$\",\"div\",null,{\"className\":\"integrate-card\",\"children\":[[\"$\",\"div\",null,{\"className\":\"integrate-head\",\"children\":[[\"$\",\"span\",null,{\"className\":\"integrate-kicker\",\"children\":\"Command line\"}],[\"$\",\"h3\",null,{\"children\":\"Ketoy CLI\"}],[\"$\",\"p\",null,{\"children\":\"Set up a project, push to the cloud, and roll back — all from the terminal.\"}]]}],[\"$\",\"div\",null,{\"className\":\"cli-term\",\"aria-hidden\":\"true\",\"children\":[[\"$\",\"div\",null,{\"className\":\"cli-chrome\",\"children\":[[\"$\",\"span\",null,{\"className\":\"cli-dot r\"}],[\"$\",\"span\",null,{\"className\":\"cli-dot y\"}],[\"$\",\"span\",null,{\"className\":\"cli-dot g\"}],[\"$\",\"span\",null,{\"className\":\"cli-title\",\"children\":\"ketoy\"}]]}],[\"$\",\"div\",null,{\"className\":\"cli-body\",\"children\":[[\"$\",\"div\",null,{\"className\":\"cli-line\",\"children\":[[\"$\",\"span\",null,{\"className\":\"p\",\"children\":\"$$\"}],\" ketoy init\"]}],[\"$\",\"div\",null,{\"className\":\"cli-out\",\"children\":[[\"$\",\"span\",null,{\"className\":\"ok\",\"children\":\"✓\"}],\" Gradle plugin added\"]}],[\"$\",\"div\",null,{\"className\":\"cli-out\",\"children\":[[\"$\",\"span\",null,{\"className\":\"ok\",\"children\":\"✓\"}],\" Ed25519 key generated\"]}],[\"$\",\"div\",null,{\"className\":\"cli-out\",\"children\":[[\"$\",\"span\",null,{\"className\":\"ok\",\"children\":\"✓\"}],\" HomeScreen.kt created\"]}],[\"$\",\"div\",null,{\"className\":\"cli-line sp\",\"children\":[[\"$\",\"span\",null,{\"className\":\"p\",\"children\":\"$$\"}],\" ketoy push ktx my-app main.ktx --version 7\"]}],[\"$\",\"div\",null,{\"className\":\"cli-out\",\"children\":[[\"$\",\"span\",null,{\"className\":\"ok\",\"children\":\"✓\"}],\" Uploaded. Live in \",[\"$\",\"b\",null,{\"children\":\"1.2s\"}]]}],[\"$\",\"div\",null,{\"className\":\"cli-line sp\",\"children\":[[\"$\",\"span\",null,{\"className\":\"p\",\"children\":\"$$\"}],\" ketoy ktx rollback my-app\",[\"$\",\"span\",null,{\"className\":\"cli-cur\"}]]}]]}]]}],[\"$\",\"div\",null,{\"className\":\"integrate-cmd\",\"children\":[[\"$\",\"span\",null,{\"className\":\"prompt\",\"children\":\"$$\"}],[\"$\",\"code\",null,{\"children\":\"npm install -g ketoy-dev\"}],[\"$\",\"$L24\",null,{\"text\":\"npm install -g ketoy-dev\"}]]}],[\"$\",\"$Ld\",null,{\"className\":\"integrate-link\",\"href\":\"/docs/cli\",\"children\":[\"CLI docs\",[\"$\",\"svg\",null,{\"width\":\"15\",\"height\":\"15\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"2\",\"children\":[\"$\",\"path\",null,{\"d\":\"M5 12h14M13 5l7 7-7 7\"}]}]]}]]}],[\"$\",\"div\",null,{\"className\":\"integrate-card\",\"children\":[[\"$\",\"div\",null,{\"className\":\"integrate-head\",\"children\":[[\"$\",\"span\",null,{\"className\":\"integrate-kicker\",\"children\":\"AI agents\"}],[\"$\",\"h3\",null,{\"children\":\"Ketoy Skills\"}],[\"$\",\"p\",null,{\"children\":\"Install a skill pack that grounds any coding agent in how Ketoy actually works before it writes code.\"}]]}],[\"$\",\"div\",null,{\"className\":\"skills-panel\",\"aria-hidden\":\"true\",\"children\":[[\"$\",\"div\",null,{\"className\":\"skills-head\",\"children\":[[\"$\",\"span\",null,{\"className\":\"skills-star\",\"children\":\"✦\"}],[\"$\",\"span\",null,{\"children\":\"AI agent · ketoy skills\"}]]}],[\"$\",\"div\",null,{\"className\":\"skills-call\",\"children\":[\"$\",\"span\",null,{\"className\":\"skills-tool\",\"children\":\"ketoy skills add\"}]}],[\"$\",\"div\",null,{\"className\":\"skills-reply\",\"children\":[[\"$\",\"span\",null,{\"className\":\"ok\",\"children\":\"✓\"}],[\"$\",\"div\",null,{\"children\":\"Installed to .claude/skills — catalog, capabilities, and every 
9KetoyBC: fix.\"}]]}],[\"$\",\"div\",null,{\"className\":\"skills-tools\",\"children\":[[\"$\",\"span\",\"catalog\",{\"className\":\"skills-chip\",\"children\":[\"catalog\",\".md\"]}],[\"$\",\"span\",\"capabilities\",{\"className\":\"skills-chip\",\"children\":[\"capabilities\",\".md\"]}],[\"$\",\"span\",\"viewmodel-and-state\",{\"className\":\"skills-chip\",\"children\":[\"viewmodel-and-state\",\".md\"]}],[\"$\",\"span\",\"host-integration\",{\"className\":\"skills-chip\",\"children\":[\"host-integration\",\".md\"]}],[\"$\",\"span\",\"troubleshooting\",{\"className\":\"skills-chip\",\"children\":[\"troubleshooting\",\".md\"]}],[\"$\",\"span\",\"build-and-ship\",{\"className\":\"skills-chip\",\"children\":[\"build-and-ship\",\".md\"]}]]}]]}],[\"$\",\"div\",null,{\"className\":\"agent-row\",\"aria-label\":\"Works with any skills-compatible agent\",\"children\":[[\"$\",\"span\",\"Claude Code\",{\"className\":\"agent-chip\",\"children\":\"Claude Code\"}],[\"$\",\"span\",\"Codex\",{\"className\":\"agent-chip\",\"children\":\"Codex\"}],\"$L25\",\"$L26\",\"$L27\"]}],\"$L28\",\"$L29\"]}]]}]]}]}]\n"])</script>
9<script>self.__next_f.push([1,"16:[\"$\",\"section\",null,{\"className\":\"surface\",\"children\":[\"$\",\"div\",null,{\"className\":\"container\",\"children\":[[\"$\",\"div\",null,{\"className\":\"section-head\",\"data-reveal\":true,\"children\":[[\"$\",\"span\",null,{\"className\":\"eyebrow\",\"children\":\"Why Ketoy\"}],[\"$\",\"h2\",null,{\"children\":\"Update without a release.\"}],[\"$\",\"p\",null,{\"children\":\"Add one annotation. Run one Gradle task. Every device gets the change in seconds.\"}]]}],[\"$\",\"div\",null,{\"className\":\"cards-grid\",\"children\":[[\"$\",\"div\",\"01\",{\"className\":\"card\",\"children\":[[\"$\",\"div\",null,{\"className\":\"num\",\"children\":\"01\"}],[\"$\",\"div\",null,{\"className\":\"icon\",\"aria-hidden\":\"true\",\"children\":[\"$\",\"svg\",null,{\"width\":\"22\",\"height\":\"22\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"1.8\",\"children\":[\"$\",\"path\",null,{\"d\":\"M12 2v6m0 0 3-3m-3 3-3-3M5 13h14l-1 8H6l-1-8z\"}]}]}],[\"$\",\"h3\",null,{\"children\":\"Instant updates\"}],[\"$\",\"p\",null,{\"children\":\"Fix a bug at 3pm. Every user has it by 3:01. The app never reinstalls.\"}],[\"$\",\"a\",null,{\"className\":\"link\",\"href\":\"/architecture\",\"children\":\"How it works\"}]]}],[\"$\",\"div\",\"02\",{\"className\":\"card\",\"children\":[[\"$\",\"div\",null,{\"className\":\"num\",\"children\":\"02\"}],[\"$\",\"div\",null,{\"className\":\"icon\",\"aria-hidden\":\"true\",\"children\":[\"$\",\"svg\",null,{\"width\":\"22\",\"height\":\"22\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"1.8\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12 2 4 6v6c0 5 3.4 9.5 8 10 4.6-.5 8-5 8-10V6l-8-4z\"}],[\"$\",\"path\",null,{\"d\":\"M9 12l2 2 4-4\"}]]}]}],[\"$\",\"h3\",null,{\"children\":\"Play Store safe\"}],[\"$\",\"p\",null,{\"children\":\"Ketoy generates code on device, the same way ART does. It stays inside Google policy.\"}],[\"$\",\"a\",null,{\"className\":\"link\",\"href\":\"#security\",\"children\":\"Security model\"}]]}],[\"$\",\"div\",\"03\",{\"className\":\"card\",\"children\":[[\"$\",\"div\",null,{\"className\":\"num\",\"children\":\"03\"}],[\"$\",\"div\",null,{\"className\":\"icon\",\"aria-hidden\":\"true\",\"children\":[\"$\",\"svg\",null,{\"width\":\"22\",\"height\":\"22\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"1.8\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M4 6h16M4 12h10M4 18h16\"}],[\"$\",\"path\",null,{\"d\":\"m16 9 3 3-3 3\"}]]}]}],[\"$\",\"h3\",null,{\"children\":\"Just Kotlin\"}],[\"$\",\"p\",null,{\"children\":\"It is the Jetpack Compose you already write. Nothing new to learn.\"}],[\"$\",\"a\",null,{\"className\":\"link\",\"href\":\"/features\",\"children\":\"What is supported\"}]]}]]}]]}]}]\n"])</script>
9<script>self.__next_f.push([1,"17:[\"$\",\"section\",null,{\"className\":\"surface\",\"children\":[\"$\",\"div\",null,{\"className\":\"container\",\"children\":[[\"$\",\"div\",null,{\"className\":\"section-head\",\"data-reveal\":true,\"children\":[[\"$\",\"span\",null,{\"className\":\"eyebrow\",\"children\":\"What’s supported\"}],[\"$\",\"h2\",null,{\"children\":\"If it’s Compose, it’s Ketoy.\"}],[\"$\",\"p\",null,{\"children\":\"Ketoy supports the full Compose toolkit, not a curated subset. When Compose adds a parameter, one command picks it up.\"}]]}],[\"$\",\"div\",null,{\"className\":\"support-grid\",\"children\":[[\"$\",\"div\",\"Compose and Material 3\",{\"className\":\"support-card\",\"children\":[[\"$\",\"span\",null,{\"className\":\"support-tag\",\"children\":\"UI\"}],[\"$\",\"h3\",null,{\"children\":\"Compose and Material 3\"}],[\"$\",\"p\",null,{\"style\":{\"fontSize\":14.5,\"color\":\"var(--muted)\",\"lineHeight\":1.55},\"children\":\"All 35 Material 3 components. Every parameter included.\"}],[\"$\",\"div\",null,{\"className\":\"chips\",\"children\":[[\"$\",\"span\",\"Scaffold\",{\"className\":\"chip\",\"children\":\"Scaffold\"}],[\"$\",\"span\",\"LazyColumn\",{\"className\":\"chip\",\"children\":\"LazyColumn\"}],[\"$\",\"span\",\"OutlinedTextField\",{\"className\":\"chip\",\"children\":\"OutlinedTextField\"}],[\"$\",\"span\",\"Button\",{\"className\":\"chip\",\"children\":\"Button\"}],[\"$\",\"span\",\"TopAppBar\",{\"className\":\"chip\",\"children\":\"TopAppBar\"}],[\"$\",\"span\",\"AlertDialog\",{\"className\":\"chip\",\"children\":\"AlertDialog\"}],[\"$\",\"span\",\"+29 more\",{\"className\":\"chip\",\"children\":\"+29 more\"}]]}]]}],[\"$\",\"div\",\"Plain Kotlin\",{\"className\":\"support-card\",\"children\":[[\"$\",\"span\",null,{\"className\":\"support-tag\",\"children\":\"Language\"}],[\"$\",\"h3\",null,{\"children\":\"Plain Kotlin\"}],[\"$\",\"p\",null,{\"style\":{\"fontSize\":14.5,\"color\":\"var(--muted)\",\"lineHeight\":1.55},\"children\":\"Data classes, sealed classes, extensions, and lambdas. Real Kotlin, compiled to bytecode.\"}],[\"$\",\"div\",null,{\"className\":\"chips\",\"children\":[[\"$\",\"span\",\"data class\",{\"className\":\"chip\",\"children\":\"data class\"}],[\"$\",\"span\",\"sealed\",{\"className\":\"chip\",\"children\":\"sealed\"}],[\"$\",\"span\",\"when\",{\"className\":\"chip\",\"children\":\"when\"}],[\"$\",\"span\",\"extensions\",{\"className\":\"chip\",\"children\":\"extensions\"}],[\"$\",\"span\",\"closures\",{\"className\":\"chip\",\"children\":\"closures\"}]]}]]}],[\"$\",\"div\",\"Coroutines and Flow\",{\"className\":\"support-card\",\"children\":[[\"$\",\"span\",null,{\"className\":\"support-tag\",\"children\":\"Async\"}],[\"$\",\"h3\",null,{\"children\":\"Coroutines and Flow\"}],[\"$\",\"p\",null,{\"style\":{\"fontSize\":14.5,\"color\":\"var(--muted)\",\"lineHeight\":1.55},\"children\":\"launch, async, withContext, and 9 Flow operators. Structured concurrency included.\"}],[\"$\",\"div\",null,{\"className\":\"chips\",\"children\":[[\"$\",\"span\",\"launch\",{\"className\":\"chip\",\"children\":\"launch\"}],[\"$\",\"span\",\"async\",{\"className\":\"chip\",\"children\":\"async\"}],[\"$\",\"span\",\"StateFlow\",{\"className\":\"chip\",\"children\":\"StateFlow\"}],[\"$\",\"span\",\"collectAsState\",{\"className\":\"chip\",\"children\":\"collectAsState\"}],[\"$\",\"span\",\"debounce\",{\"className\":\"chip\",\"children\":\"debounce\"}]]}]]}],[\"$\",\"div\",\"ViewModel\",{\"className\":\"support-card\",\"children\":[[\"$\",\"span\",null,{\"className\":\"support-tag\",\"children\":\"State\"}],[\"$\",\"h3\",null,{\"children\":\"ViewModel\"}],[\"$\",\"p\",null,{\"style\":{\"fontSize\":14.5,\"color\":\"var(--muted)\",\"lineHeight\":1.55},\"children\":\"A real Android ViewModel. It survives config changes and works with Hilt.\"}],[\"$\",\"div\",null,{\"className\":\"chips\",\"children\":[[\"$\",\"span\",\"viewModelScope\",{\"className\":\"chip\",\"children\":\"viewModelScope\"}],[\"$\",\"span\",\"SavedStateHandle\",{\"className\":\"chip\",\"children\":\"SavedStateHandle\"}],[\"$\",\"span\",\"@HiltViewModel\",{\"className\":\"chip\",\"children\":\"@HiltViewModel\"}],[\"$\",\"span\",\"dispatch()\",{\"className\":\"chip\",\"children\":\"dispatch()\"}]]}]]}],[\"$\",\"div\",\"Networking and storage\",{\"className\":\"support-card\",\"children\":[[\"$\",\"span\",null,{\"className\":\"support-tag\",\"children\":\"I/O\"}],[\"$\",\"h3\",null,{\"children\":\"Networking and storage\"}],[\"$\",\"p\",null,{\"style\":{\"fontSize\":14.5,\"color\":\"var(--muted)\",\"lineHeight\"
9:1.55},\"children\":\"HTTP, DataStore, Room, and navigation. 67 capabilities built in.\"}],[\"$\",\"div\",null,{\"className\":\"chips\",\"children\":[[\"$\",\"span\",\"HTTP\",{\"className\":\"chip\",\"children\":\"HTTP\"}],[\"$\",\"span\",\"DataStore\",{\"className\":\"chip\",\"children\":\"DataStore\"}],[\"$\",\"span\",\"Room\",{\"className\":\"chip\",\"children\":\"Room\"}],[\"$\",\"span\",\"NavController\",{\"className\":\"chip\",\"children\":\"NavController\"}],[\"$\",\"span\",\"+ your SDKs\",{\"className\":\"chip\",\"children\":\"+ your SDKs\"}]]}]]}],[\"$\",\"div\",\"Hilt\",{\"className\":\"support-card\",\"children\":[[\"$\",\"span\",null,{\"className\":\"support-tag\",\"children\":\"DI\"}],[\"$\",\"h3\",null,{\"children\":\"Hilt\"}],[\"$\",\"p\",null,{\"style\":{\"fontSize\":14.5,\"color\":\"var(--muted)\",\"lineHeight\":1.55},\"children\":\"Drop it in. @Inject works exactly as before.\"}],\"$L2a\"]}]]}],\"$L2b\"]}]}]\n"])</script>
9<script>self.__next_f.push([1,"18:[\"$\",\"section\",null,{\"className\":\"ink\",\"id\":\"security\",\"children\":[\"$\",\"div\",null,{\"className\":\"container\",\"children\":[[\"$\",\"div\",null,{\"className\":\"section-head\",\"data-reveal\":true,\"children\":[[\"$\",\"span\",null,{\"className\":\"eyebrow\",\"style\":{\"color\":\"#4AE389\"},\"children\":\"Security\"}],[\"$\",\"h2\",null,{\"children\":\"Secure and compliant.\"}],[\"$\",\"p\",null,{\"children\":\"Ketoy verifies every bundle before it runs. Here is how, in three parts.\"}]]}],[\"$\",\"div\",null,{\"className\":\"cards-grid\",\"children\":[[\"$\",\"div\",\"Every bundle is signed\",{\"className\":\"card dark\",\"children\":[[\"$\",\"div\",null,{\"className\":\"icon\",\"children\":[\"$\",\"svg\",null,{\"width\":\"22\",\"height\":\"22\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"1.8\",\"children\":[\"$\",\"path\",null,{\"d\":\"M12 2 4 6v6c0 5 3.4 9.5 8 10 4.6-.5 8-5 8-10V6l-8-4z\"}]}]}],[\"$\",\"h3\",null,{\"children\":\"Every bundle is signed\"}],[\"$\",\"p\",null,{\"children\":\"An Ed25519 signature is checked before any code runs. Your private key stays on your server. Only you can ship a bundle.\"}]]}],[\"$\",\"div\",\"The sandbox is a build error\",{\"className\":\"card dark\",\"children\":[[\"$\",\"div\",null,{\"className\":\"icon\",\"children\":[\"$\",\"svg\",null,{\"width\":\"22\",\"height\":\"22\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"1.8\",\"children\":[[\"$\",\"rect\",null,{\"x\":\"3\",\"y\":\"3\",\"width\":\"18\",\"height\":\"18\",\"rx\":\"3\"}],[\"$\",\"path\",null,{\"d\":\"M9 12l2 2 4-4\"}]]}]}],[\"$\",\"h3\",null,{\"children\":\"The sandbox is a build error\"}],[\"$\",\"p\",null,{\"children\":\"The compiler rejects file access, reflection, and any unregistered API. Unsafe code never compiles.\"}]]}],[\"$\",\"div\",\"Capabilities are the only door\",{\"className\":\"card dark\",\"children\":[[\"$\",\"div\",null,{\"className\":\"icon\",\"children\":[\"$\",\"svg\",null,{\"width\":\"22\",\"height\":\"22\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"1.8\",\"children\":[\"$\",\"path\",null,{\"d\":\"M3 12h4l3-8 4 16 3-8h4\"}]}]}],[\"$\",\"h3\",null,{\"children\":\"Capabilities are the only door\"}],[\"$\",\"p\",null,{\"children\":\"KBC code reaches the platform through registered capabilities. Nothing else is callable.\"}]]}]]}],[\"$\",\"div\",null,{\"className\":\"legal-row legal-row--single\",\"children\":[[\"$\",\"div\",\"Is this allowed on the Play Store?\",{\"className\":\"card dark\",\"children\":[[\"$\",\"div\",null,{\"className\":\"icon\",\"children\":[\"$\",\"svg\",null,{\"width\":\"22\",\"height\":\"22\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"1.8\",\"children\":[\"$\",\"path\",null,{\"d\":\"M12 2v20M2 12h20\"}]}]}],[\"$\",\"div\",null,{\"className\":\"legal-quote\",\"children\":\"Is this allowed on the Play Store?\"}],[\"$\",\"p\",null,{\"children\":\"Yes. Ketoy generates code on device, exactly like ART does with bytecode. It is the same idea as Lua in a game engine. If your CDN goes down, the last signed bundle keeps running.\"}]]}]]}]]}]}]\n"])</script>
9<script>self.__next_f.push([1,"19:[\"$\",\"section\",null,{\"style\":{\"paddingTop\":56},\"children\":[\"$\",\"div\",null,{\"className\":\"container\",\"children\":[[\"$\",\"div\",null,{\"className\":\"cta-banner\",\"children\":[[\"$\",\"div\",null,{\"children\":[[\"$\",\"h2\",null,{\"children\":\"Write Kotlin. Ship the screen.\"}],[\"$\",\"p\",null,{\"children\":\"Available now on Maven Central. Hilt, Koin, dev tools, and the full Material 3 catalog are included.\"}]]}],[\"$\",\"div\",null,{\"className\":\"right\",\"children\":[[\"$\",\"$Ld\",null,{\"className\":\"btn btn-ghost\",\"href\":\"/docs\",\"prefetch\":false,\"children\":\"Read the docs\"}],[\"$\",\"$Ld\",null,{\"className\":\"btn btn-primary\",\"href\":\"/get-started\",\"children\":\"Get started\"}]]}]]}],[\"$\",\"$L2c\",null,{}]]}]}]\n"])</script>
9<script>self.__next_f.push([1,"1a:[\"$\",\"section\",null,{\"className\":\"surface\",\"id\":\"faq\",\"children\":[\"$\",\"div\",null,{\"className\":\"container\",\"children\":[[\"$\",\"div\",null,{\"className\":\"section-head\",\"data-reveal\":true,\"children\":[[\"$\",\"span\",null,{\"className\":\"eyebrow\",\"children\":\"FAQ\"}],[\"$\",\"h2\",null,{\"children\":\"Questions, answered.\"}]]}],[\"$\",\"div\",null,{\"className\":\"home-faq\",\"data-reveal\":true,\"children\":[[[\"$\",\"details\",\"What is Ketoy?\",{\"className\":\"faq-item\",\"id\":\"what-is-ketoy\",\"children\":[[\"$\",\"summary\",null,{\"className\":\"faq-q\",\"children\":[[\"$\",\"span\",null,{\"className\":\"faq-q-text\",\"children\":\"What is Ketoy?\"}],[\"$\",\"svg\",null,{\"className\":\"faq-chevron\",\"width\":\"16\",\"height\":\"16\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"2\",\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"aria-hidden\":\"true\",\"children\":[\"$\",\"path\",null,{\"d\":\"m6 9 6 6 6-6\"}]}]]}],[\"$\",\"div\",null,{\"className\":\"faq-a\",\"children\":[\"$\",\"p\",null,{\"children\":\"Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. You write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed .ktx bytecode bundle, and push changes over-the-air to installed apps in seconds - no Play Store release and no JSON DSL.\"}]}]]}],[\"$\",\"details\",\"Is Ketoy OTA or SDUI?\",{\"className\":\"faq-item\",\"id\":\"is-ketoy-ota-or-sdui\",\"children\":[[\"$\",\"summary\",null,{\"className\":\"faq-q\",\"children\":[[\"$\",\"span\",null,{\"className\":\"faq-q-text\",\"children\":\"Is Ketoy OTA or SDUI?\"}],[\"$\",\"svg\",null,{\"className\":\"faq-chevron\",\"width\":\"16\",\"height\":\"16\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"2\",\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"aria-hidden\":\"true\",\"children\":[\"$\",\"path\",null,{\"d\":\"m6 9 6 6 6-6\"}]}]]}],[\"$\",\"div\",null,{\"className\":\"faq-a\",\"children\":[\"$\",\"p\",null,{\"children\":\"Ketoy is an OTA framework, and SDUI is one of the things it can do. Because it ships real Kotlin and Compose over the air, a bundle can drive a whole screen from the server - that is SDUI - and it can equally ship a ViewModel, a network call, or a pricing rule that no JSON schema could express.\"}]}]]}],[\"$\",\"details\",\"What can Ketoy update over the air?\",{\"className\":\"faq-item\",\"id\":\"what-can-ketoy-update-over-the-air\",\"children\":[[\"$\",\"summary\",null,{\"className\":\"faq-q\",\"children\":[[\"$\",\"span\",null,{\"className\":\"faq-q-text\",\"children\":\"What can Ketoy update over the air?\"}],[\"$\",\"svg\",null,{\"className\":\"faq-chevron\",\"width\":\"16\",\"height\":\"16\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"2\",\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"aria-hidden\":\"true\",\"children\":[\"$\",\"path\",null,{\"d\":\"m6 9 6 6 6-6\"}]}]]}],[\"$\",\"div\",null,{\"className\":\"faq-a\",\"children\":[\"$\",\"p\",null,{\"children\":\"Jetpack Compose UI, ViewModels and state, navigation, coroutines and Flow, networking, Room and DataStore access, and ordinary Kotlin such as data classes, objects, and functions. UI-only and logic-only bundles are both fine.\"}]}]]}],[\"$\",\"details\",\"How is Ketoy different from JSON-based server-driven UI?\",{\"className\":\"faq-item\",\"id\":\"how-is-ketoy-different-from-json-based-server-driven-ui\",\"children\":[[\"$\",\"summary\",null,{\"className\":\"faq-q\",\"children\":[[\"$\",\"span\",null,{\"className\":\"faq-q-text\",\"children\":\"How is Ketoy different from JSON-based server-driven UI?\"}],[\"$\",\"svg\",null,{\"className\":\"faq-chevron\",\"width\":\"16\",\"height\":\"16\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"2\",\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"aria-hidden\":\"true\",\"children\":[\"$\",\"path\",null,{\"d\":\"m6 9 6 6 6-6\"}]}]]}],[\"$\",\"div\",null,{\"className\":\"faq-a\",\"children\":[\"$\",\"p\",null,{\"children\":\"Instead of a JSON sc
9hema and a parallel component model, Ketoy uses ordinary Kotlin and Jetpack Compose compiled to Ketoy Bytecode (KBC). Bundles are roughly 20x smaller than equivalent JSON SDUI, Ed25519-signed, and rendered as native Compose on device.\"}]}]]}],[\"$\",\"details\",\"Does Ketoy allow over-the-air (OTA) updates on Android within Play Store policy?\",{\"className\":\"faq-item\",\"id\":\"does-ketoy-allow-over-the-air-ota-updates-on-android-within-play-store-policy\",\"children\":[[\"$\",\"summary\",null,{\"className\":\"faq-q\",\"children\":[\"$L2d\",\"$L2e\"]}],\"$L2f\"]}]],\"$L30\"]}]]}]}]\n"])</script>
9<script>self.__next_f.push([1,"1b:[\"$\",\"$L31\",null,{}]\n32:T77d,"])</script>
9<script>self.__next_f.push([1,"{\"@context\":\"https://schema.org\",\"@type\":\"FAQPage\",\"mainEntity\":[{\"@type\":\"Question\",\"name\":\"What is Ketoy?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. You write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed .ktx bytecode bundle, and push changes over-the-air to installed apps in seconds - no Play Store release and no JSON DSL.\"}},{\"@type\":\"Question\",\"name\":\"Is Ketoy OTA or SDUI?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Ketoy is an OTA framework, and SDUI is one of the things it can do. Because it ships real Kotlin and Compose over the air, a bundle can drive a whole screen from the server - that is SDUI - and it can equally ship a ViewModel, a network call, or a pricing rule that no JSON schema could express.\"}},{\"@type\":\"Question\",\"name\":\"What can Ketoy update over the air?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Jetpack Compose UI, ViewModels and state, navigation, coroutines and Flow, networking, Room and DataStore access, and ordinary Kotlin such as data classes, objects, and functions. UI-only and logic-only bundles are both fine.\"}},{\"@type\":\"Question\",\"name\":\"How is Ketoy different from JSON-based server-driven UI?\",\"acceptedA
9nswer\":{\"@type\":\"Answer\",\"text\":\"Instead of a JSON schema and a parallel component model, Ketoy uses ordinary Kotlin and Jetpack Compose compiled to Ketoy Bytecode (KBC). Bundles are roughly 20x smaller than equivalent JSON SDUI, Ed25519-signed, and rendered as native Compose on device.\"}},{\"@type\":\"Question\",\"name\":\"Does Ketoy allow over-the-air (OTA) updates on Android within Play Store policy?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Yes. Ketoy delivers UI and logic changes over-the-air without shipping a new APK/AAB. Bundles execute in a sandbox and render native Compose, which keeps updates within Play Store policies.\"}}]}"])</script>
9<script>self.__next_f.push([1,"1c:[\"$\",\"script\",null,{\"type\":\"application/ld+json\",\"dangerouslySetInnerHTML\":{\"__html\":\"$32\"}}]\n1d:[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/10cce706acc7ff5e.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]\n1e:[\"$\",\"$L33\",null,{\"children\":[\"$L34\",[\"$\",\"$L35\",null,{\"promise\":\"$@36\"}]]}]\n"])</script>
9<script>self.__next_f.push([1,"25:[\"$\",\"span\",\"Cursor\",{\"className\":\"agent-chip\",\"children\":\"Cursor\"}]\n26:[\"$\",\"span\",\"Windsurf\",{\"className\":\"agent-chip\",\"children\":\"Windsurf\"}]\n27:[\"$\",\"span\",\"Gemini CLI\",{\"className\":\"agent-chip\",\"children\":\"Gemini CLI\"}]\n28:[\"$\",\"div\",null,{\"className\":\"integrate-cmd\",\"children\":[[\"$\",\"span\",null,{\"className\":\"prompt\",\"children\":\"$$\"}],[\"$\",\"code\",null,{\"children\":\"ketoy skills add\"}],[\"$\",\"$L24\",null,{\"text\":\"ketoy skills add\"}]]}]\n29:[\"$\",\"$Ld\",null,{\"className\":\"integrate-link\",\"href\":\"/docs/skills\",\"children\":[\"Skills docs\",[\"$\",\"svg\",null,{\"width\":\"15\",\"height\":\"15\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"2\",\"children\":[\"$\",\"path\",null,{\"d\":\"M5 12h14M13 5l7 7-7 7\"}]}]]}]\n2a:[\"$\",\"div\",null,{\"className\":\"chips\",\"children\":[[\"$\",\"span\",\"@Inject\",{\"className\":\"chip\",\"children\":\"@Inject\"}],[\"$\",\"span\",\"@HiltViewModel\",{\"className\":\"chip\",\"children\":\"@HiltViewModel\"}],[\"$\",\"span\",\"@Module\",{\"className\":\"chip\",\"children\":\"@Module\"}],[\"$\",\"span\",\"dev overlay\",{\"className\":\"chip\",\"children\":\"dev overlay\"}]]}]\n2b:[\"$\",\"div\",null,{\"className\":\"diff-strip\",\"data-reveal\":true,\"children\":[[\"$\",\"p\",null,{\"className\":\"diff-line\",\"children\":[[\"$\",\"b\",null,{\"style\":{\"fontWeight\":600,\"color\":\"var(--ink)\"},\"children\":\"One annotation and one Gradle task.\"}],\" That is the whole difference.\"]}],[\"$\",\"$Ld\",null,{\"className\":\"link\",\"href\":\"/features\",\"style\":{\"fontFamily\":\"var(--font-ui)\",\"fontWeight\":600,\"fontSize\":15,\"color\":\"var(--accent-ink)\",\"whiteSpace\":\"nowrap\"},\"children\":\"See everything Ketoy supports\"}]]}]\n2d:[\"$\",\"span\",null,{\"className\":\"faq-q-text\",\"children\":\"Does Ketoy allow over-the-air (OTA) updates on Android within Play Store policy?\"}]\n2e:[\"$\",\"svg\",null,{\"className\":\"faq-chevron\",\"width\":\"16\",\"height\":\"16\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"2\",\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"aria-hidden\":\"true\",\"children\":[\"$\",\"path\",null,{\"d\":\"m6 9 6 6 6-6\"}]}]\n2f:[\"$\",\"div\",null,{\"className\":\"faq-a\",\"children\":[\"$\",\"p\",null,{\"c"])</script>
9<script>self.__next_f.push([1,"hildren\":\"Yes. Ketoy delivers UI and logic changes over-the-air without shipping a new APK/AAB. Bundles execute in a sandbox and render native Compose, which keeps updates within Play Store policies.\"}]}]\n30:[\"$\",\"div\",null,{\"className\":\"home-faq-foot\",\"children\":[[\"$\",\"p\",null,{\"children\":\"OTA vs SDUI, bundle sizes, Play Store policy, offline behaviour, debugging.\"}],[\"$\",\"$Ld\",null,{\"className\":\"btn btn-ghost\",\"href\":\"/docs/faq\",\"prefetch\":false,\"children\":[\"More questions\",[\"$\",\"svg\",null,{\"width\":\"16\",\"height\":\"16\",\"viewBox\":\"0 0 24 24\",\"fill\":\"none\",\"stroke\":\"currentColor\",\"strokeWidth\":\"2\",\"children\":[\"$\",\"path\",null,{\"d\":\"M5 12h14M13 5l7 7-7 7\"}]}]]}]]}]\n"])</script>
9<script>self.__next_f.push([1,"20:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script>
9<script>self.__next_f.push([1,"34:null\n"])</script>
9<script>self.__next_f.push([1,"37:I[622,[],\"IconMark\"]\n"])</script>
9<script>self.__next_f.push([1,"36:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Ketoy - Kotlin Over-The-Air (OTA) Updates for Android\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. Write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed bundle, and push changes over-the-air in seconds - no Play Store release, no JSON DSL. Fully within Play Store policies.\"}],[\"$\",\"meta\",\"2\",{\"name\":\"application-name\",\"content\":\"Ketoy\"}],[\"$\",\"link\",\"3\",{\"rel\":\"author\",\"href\":\"https://ketoy.dev\"}],[\"$\",\"meta\",\"4\",{\"name\":\"author\",\"content\":\"Ketoy\"}],[\"$\",\"meta\",\"5\",{\"name\":\"keywords\",\"content\":\"Kotlin OTA,Android OTA updates,over-the-air updates Android,Kotlin over-the-air updates,Jetpack Compose OTA,Android code push,Kotlin SDUI,Android SDUI,server-driven UI Android,Jetpack Compose SDUI,Kotlin Native SDUI,Compose server-driven UI,OTA vs SDUI,what is OTA in Android,what is server-driven UI,update Android app without Play Store release,update Compose UI over the air,ship ViewModel and business logic over the air,Android instant updates,CodePush for Android Kotlin,Kotlin over-the-air update framework,SDUI framework,Ketoy\"}],[\"$\",\"meta\",\"6\",{\"name\":\"creator\",\"content\":\"Ketoy\"}],[\"$\",\"meta\",\"7\",{\"name\":\"publisher\",\"content\":\"Ketoy\"}],[\"$\",\"meta\",\"8\",{\"name\":\"robots\",\"content\":\"index, follow\"}],[\"$\",\"meta\",\"9\",{\"name\":\"googlebot\",\"content\":\"index, follow, max-video-preview:-1, max-image-preview:large, max-snippet:-1\"}],[\"$\",\"meta\",\"10\",{\"name\":\"category\",\"content\":\"technology\"}],[\"$\",\"link\",\"11\",{\"rel\":\"canonical\",\"href\":\"https://ketoy.dev\"}],[\"$\",\"meta\",\"12\",{\"property\":\"og:title\",\"content\":\"Ketoy - Kotlin Over-The-Air (OTA) Updates for Android\"}],[\"$\",\"meta\",\"13\",{\"property\":\"og:description\",\"content\":\"Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. Write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed bundle, and push changes over-the-air in seconds - no Play Store release, no JSON DSL. Fully within Play Store policies.\"}],[\"$\",\"meta\",\"14\",{\"property\":\"og:url\",\"content\":\"https://ketoy.dev\"}],[\"$\",\"meta\",\"15\",{\"property\":\"og:image:alt\",\"content\":\"Ketoy - Kotlin over-the-air (OTA) updates for Android, server-driven UI (SDUI) included.\"}],[\"$\",\"meta\",\"16\",{\"property\":\"og:image:type\",\"content\":\"image/png\"}],[\"$\",\"meta\",\"17\",{\"property\":\"og:image\",\"content\":\"https://ketoy.dev/opengraph-image?449440a0bf7f01c9\"}],[\"$\",\"meta\",\"18\",{\"property\":\"og:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"19\",{\"property\":\"og:image:height\",\"content\":\"630\"}],[\"$\",\"meta\",\"20\",{\"property\":\"og:type\",\"content\":\"website\"}],[\"$\",\"meta\",\"21\",{\"name\":\"twitter:card\",\"content\":\"summary_large_image\"}],[\"$\",\"meta\",\"22\",{\"name\":\"twitter:title\",\"content\":\"Ketoy - Kotlin Over-The-Air (OTA) Updates for Android\"}],[\"$\",\"meta\",\"23\",{\"name\":\"twitter:description\",\"content\":\"Ketoy is a Kotlin-native over-the-air (OTA) update framework for Android. Write real Jetpack Compose, ViewModels, and business logic in Kotlin, compile it to a tiny signed bundle, and push changes over-the-air in seconds - no Play Store release, no JSON DSL. Fully within Play Store policies.\"}],[\"$\",\"meta\",\"24\",{\"name\":\"twitter:image:alt\",\"content\":\"Ketoy - Kotlin over-the-air (OTA) updates for Android, server-driven UI (SDUI) included.\"}],[\"$\",\"meta\",\"25\",{\"name\":\"twitter:image:type\",\"content\":\"image/png\"}],[\"$\",\"meta\",\"26\",{\"name\":\"twitter:image\",\"content\":\"https://ketoy.dev/opengraph-image?449440a0bf7f01c9\"}],[\"$\",\"meta\",\"27\",{\"name\":\"twitter:image:width\",\"content\":\"1200\"}],[\"$\",\"meta\",\"28\",{\"name\":\"twitter:image:height\",\"content\":\"630\"}],[\"$\",\"link\",\"29\",{\"rel\":\"icon\",\"href\":\"/assets/ketoy-logo.svg\"}],[\"$\",\"$L37\",\"30\",{}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script>
9<script>self.__next_f.push([1,"23:\"$36:metadata\"\n"])</script>
9</body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.