[{"data":1,"prerenderedAt":885},["ShallowReactive",2],{"docs-page:en:\u002Fdocs\u002Fquick-start\u002Fcapacitor":3,"docs-navigation:en":786},{"id":4,"title":5,"body":6,"description":779,"extension":780,"meta":781,"navigation":196,"path":782,"seo":783,"stem":784,"__hash__":785},"docs_en\u002Fen\u002Fdocs\u002Fquick-start\u002Fcapacitor.md","Capacitor quick start",{"type":7,"value":8,"toc":771},"minimark",[9,19,22,27,30,42,101,105,108,141,148,592,599,641,650,654,657,660,664,669,687,691,720,724,767],[10,11,12,13,18],"p",{},"Use this page to wire the installed Capacitor app. Publishing is a separate release step covered by ",[14,15,17],"a",{"href":16},"\u002Fdocs\u002Fquick-start\u002Fquick-start","Publish in 5 minutes",".",[10,20,21],{},"For Otalan Cloud, Otalan handles bundle validation for you.",[23,24,26],"h2",{"id":25},"install-the-runtime-packages","Install the runtime packages",[10,28,29],{},"Run these commands in your Capacitor app repository:",[10,31,32,33,18],{},"NPM package: ",[14,34,38],{"href":35,"rel":36},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@otalan\u002Fcapacitor",[37],"nofollow",[39,40,41],"code",{},"@otalan\u002Fcapacitor",[43,44,49],"pre",{"className":45,"code":46,"language":47,"meta":48,"style":48},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Install the Otalan client and required Capacitor runtime packages with Bun.\nbun add @otalan\u002Fcapacitor @capawesome\u002Fcapacitor-live-update @capacitor\u002Fapp @capacitor\u002Fcore\n# Sync native projects after changing Capacitor plugins.\nbunx cap sync\n","bash","",[39,50,51,60,83,89],{"__ignoreMap":48},[52,53,56],"span",{"class":54,"line":55},"line",1,[52,57,59],{"class":58},"sHwdD","# Install the Otalan client and required Capacitor runtime packages with Bun.\n",[52,61,63,67,71,74,77,80],{"class":54,"line":62},2,[52,64,66],{"class":65},"sBMFI","bun",[52,68,70],{"class":69},"sfazB"," add",[52,72,73],{"class":69}," @otalan\u002Fcapacitor",[52,75,76],{"class":69}," @capawesome\u002Fcapacitor-live-update",[52,78,79],{"class":69}," @capacitor\u002Fapp",[52,81,82],{"class":69}," @capacitor\u002Fcore\n",[52,84,86],{"class":54,"line":85},3,[52,87,88],{"class":58},"# Sync native projects after changing Capacitor plugins.\n",[52,90,92,95,98],{"class":54,"line":91},4,[52,93,94],{"class":65},"bunx",[52,96,97],{"class":69}," cap",[52,99,100],{"class":69}," sync\n",[23,102,104],{"id":103},"initialize-otalan-on-startup","Initialize Otalan on startup",[10,106,107],{},"Create the app-side environment values. Use an OTA App Key here, never an OTA Publish Key.",[43,109,113],{"className":110,"code":111,"language":112,"meta":48,"style":48},"language-dotenv shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","VITE_OTALAN_API_URL=https:\u002F\u002Fapi.otalan.com\nVITE_OTALAN_APP_KEY=otalan_ota_xxx\nVITE_OTALAN_APP_ID=com.example.app\nVITE_OTALAN_CHANNEL=production\nVITE_OTALAN_RUNTIME_VERSION=1.0\n","dotenv",[39,114,115,120,125,130,135],{"__ignoreMap":48},[52,116,117],{"class":54,"line":55},[52,118,119],{},"VITE_OTALAN_API_URL=https:\u002F\u002Fapi.otalan.com\n",[52,121,122],{"class":54,"line":62},[52,123,124],{},"VITE_OTALAN_APP_KEY=otalan_ota_xxx\n",[52,126,127],{"class":54,"line":85},[52,128,129],{},"VITE_OTALAN_APP_ID=com.example.app\n",[52,131,132],{"class":54,"line":91},[52,133,134],{},"VITE_OTALAN_CHANNEL=production\n",[52,136,138],{"class":54,"line":137},5,[52,139,140],{},"VITE_OTALAN_RUNTIME_VERSION=1.0\n",[10,142,143,144,147],{},"Create ",[39,145,146],{},"src\u002Fota-update.ts",":",[43,149,153],{"className":150,"code":151,"language":152,"meta":48,"style":48},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { initializeUpdater, type InitializedCapacitorUpdater } from '@otalan\u002Fcapacitor'\n\nlet updater: InitializedCapacitorUpdater | undefined\n\nexport async function syncOtalanUpdates() {\n  if (!updater) {\n    updater = await initializeUpdater({\n      apiUrl: import.meta.env.VITE_OTALAN_API_URL,\n      apiKey: import.meta.env.VITE_OTALAN_APP_KEY,\n      appId: import.meta.env.VITE_OTALAN_APP_ID,\n      channel: import.meta.env.VITE_OTALAN_CHANNEL,\n      runtimeVersion: import.meta.env.VITE_OTALAN_RUNTIME_VERSION || undefined,\n      onResume: true,\n      onDownloadProgress: (event) => {\n        console.log(\n          event.bundleId,\n          event.progress,\n          event.downloadedBytes,\n          event.totalBytes,\n        )\n      },\n    })\n  }\n\n  \u002F\u002F If you only want to check availability without updating yet, call check() and inspect updateAvailable.\n  \u002F\u002F const { updateAvailable } = await updater.check()\n\n  \u002F\u002F sync() checks too, then downloads and installs when an update is available.\n  return updater.sync()\n}\n","ts",[39,154,155,192,198,217,221,242,264,283,312,337,362,387,416,430,452,466,479,491,503,515,521,527,536,542,547,553,559,564,570,586],{"__ignoreMap":48},[52,156,157,161,165,169,172,175,178,181,184,187,189],{"class":54,"line":55},[52,158,160],{"class":159},"s7zQu","import",[52,162,164],{"class":163},"sMK4o"," {",[52,166,168],{"class":167},"sTEyZ"," initializeUpdater",[52,170,171],{"class":163},",",[52,173,174],{"class":159}," type",[52,176,177],{"class":167}," InitializedCapacitorUpdater",[52,179,180],{"class":163}," }",[52,182,183],{"class":159}," from",[52,185,186],{"class":163}," '",[52,188,41],{"class":69},[52,190,191],{"class":163},"'\n",[52,193,194],{"class":54,"line":62},[52,195,197],{"emptyLinePlaceholder":196},true,"\n",[52,199,200,204,207,209,211,214],{"class":54,"line":85},[52,201,203],{"class":202},"spNyl","let",[52,205,206],{"class":167}," updater",[52,208,147],{"class":163},[52,210,177],{"class":65},[52,212,213],{"class":163}," |",[52,215,216],{"class":65}," undefined\n",[52,218,219],{"class":54,"line":91},[52,220,197],{"emptyLinePlaceholder":196},[52,222,223,226,229,232,236,239],{"class":54,"line":137},[52,224,225],{"class":159},"export",[52,227,228],{"class":202}," async",[52,230,231],{"class":202}," function",[52,233,235],{"class":234},"s2Zo4"," syncOtalanUpdates",[52,237,238],{"class":163},"()",[52,240,241],{"class":163}," {\n",[52,243,245,248,252,255,258,261],{"class":54,"line":244},6,[52,246,247],{"class":159},"  if",[52,249,251],{"class":250},"swJcz"," (",[52,253,254],{"class":163},"!",[52,256,257],{"class":167},"updater",[52,259,260],{"class":250},") ",[52,262,263],{"class":163},"{\n",[52,265,267,270,273,276,278,281],{"class":54,"line":266},7,[52,268,269],{"class":167},"    updater",[52,271,272],{"class":163}," =",[52,274,275],{"class":159}," await",[52,277,168],{"class":234},[52,279,280],{"class":250},"(",[52,282,263],{"class":163},[52,284,286,289,291,294,296,299,301,304,306,309],{"class":54,"line":285},8,[52,287,288],{"class":250},"      apiUrl",[52,290,147],{"class":163},[52,292,293],{"class":159}," import",[52,295,18],{"class":163},[52,297,298],{"class":167},"meta",[52,300,18],{"class":163},[52,302,303],{"class":167},"env",[52,305,18],{"class":163},[52,307,308],{"class":167},"VITE_OTALAN_API_URL",[52,310,311],{"class":163},",\n",[52,313,315,318,320,322,324,326,328,330,332,335],{"class":54,"line":314},9,[52,316,317],{"class":250},"      apiKey",[52,319,147],{"class":163},[52,321,293],{"class":159},[52,323,18],{"class":163},[52,325,298],{"class":167},[52,327,18],{"class":163},[52,329,303],{"class":167},[52,331,18],{"class":163},[52,333,334],{"class":167},"VITE_OTALAN_APP_KEY",[52,336,311],{"class":163},[52,338,340,343,345,347,349,351,353,355,357,360],{"class":54,"line":339},10,[52,341,342],{"class":250},"      appId",[52,344,147],{"class":163},[52,346,293],{"class":159},[52,348,18],{"class":163},[52,350,298],{"class":167},[52,352,18],{"class":163},[52,354,303],{"class":167},[52,356,18],{"class":163},[52,358,359],{"class":167},"VITE_OTALAN_APP_ID",[52,361,311],{"class":163},[52,363,365,368,370,372,374,376,378,380,382,385],{"class":54,"line":364},11,[52,366,367],{"class":250},"      channel",[52,369,147],{"class":163},[52,371,293],{"class":159},[52,373,18],{"class":163},[52,375,298],{"class":167},[52,377,18],{"class":163},[52,379,303],{"class":167},[52,381,18],{"class":163},[52,383,384],{"class":167},"VITE_OTALAN_CHANNEL",[52,386,311],{"class":163},[52,388,390,393,395,397,399,401,403,405,407,410,413],{"class":54,"line":389},12,[52,391,392],{"class":250},"      runtimeVersion",[52,394,147],{"class":163},[52,396,293],{"class":159},[52,398,18],{"class":163},[52,400,298],{"class":167},[52,402,18],{"class":163},[52,404,303],{"class":167},[52,406,18],{"class":163},[52,408,409],{"class":167},"VITE_OTALAN_RUNTIME_VERSION",[52,411,412],{"class":163}," ||",[52,414,415],{"class":163}," undefined,\n",[52,417,419,422,424,428],{"class":54,"line":418},13,[52,420,421],{"class":250},"      onResume",[52,423,147],{"class":163},[52,425,427],{"class":426},"sfNiH"," true",[52,429,311],{"class":163},[52,431,433,436,438,440,444,447,450],{"class":54,"line":432},14,[52,434,435],{"class":234},"      onDownloadProgress",[52,437,147],{"class":163},[52,439,251],{"class":163},[52,441,443],{"class":442},"sHdIc","event",[52,445,446],{"class":163},")",[52,448,449],{"class":202}," =>",[52,451,241],{"class":163},[52,453,455,458,460,463],{"class":54,"line":454},15,[52,456,457],{"class":167},"        console",[52,459,18],{"class":163},[52,461,462],{"class":234},"log",[52,464,465],{"class":250},"(\n",[52,467,469,472,474,477],{"class":54,"line":468},16,[52,470,471],{"class":167},"          event",[52,473,18],{"class":163},[52,475,476],{"class":167},"bundleId",[52,478,311],{"class":163},[52,480,482,484,486,489],{"class":54,"line":481},17,[52,483,471],{"class":167},[52,485,18],{"class":163},[52,487,488],{"class":167},"progress",[52,490,311],{"class":163},[52,492,494,496,498,501],{"class":54,"line":493},18,[52,495,471],{"class":167},[52,497,18],{"class":163},[52,499,500],{"class":167},"downloadedBytes",[52,502,311],{"class":163},[52,504,506,508,510,513],{"class":54,"line":505},19,[52,507,471],{"class":167},[52,509,18],{"class":163},[52,511,512],{"class":167},"totalBytes",[52,514,311],{"class":163},[52,516,518],{"class":54,"line":517},20,[52,519,520],{"class":250},"        )\n",[52,522,524],{"class":54,"line":523},21,[52,525,526],{"class":163},"      },\n",[52,528,530,533],{"class":54,"line":529},22,[52,531,532],{"class":163},"    }",[52,534,535],{"class":250},")\n",[52,537,539],{"class":54,"line":538},23,[52,540,541],{"class":163},"  }\n",[52,543,545],{"class":54,"line":544},24,[52,546,197],{"emptyLinePlaceholder":196},[52,548,550],{"class":54,"line":549},25,[52,551,552],{"class":58},"  \u002F\u002F If you only want to check availability without updating yet, call check() and inspect updateAvailable.\n",[52,554,556],{"class":54,"line":555},26,[52,557,558],{"class":58},"  \u002F\u002F const { updateAvailable } = await updater.check()\n",[52,560,562],{"class":54,"line":561},27,[52,563,197],{"emptyLinePlaceholder":196},[52,565,567],{"class":54,"line":566},28,[52,568,569],{"class":58},"  \u002F\u002F sync() checks too, then downloads and installs when an update is available.\n",[52,571,573,576,578,580,583],{"class":54,"line":572},29,[52,574,575],{"class":159},"  return",[52,577,206],{"class":167},[52,579,18],{"class":163},[52,581,582],{"class":234},"sync",[52,584,585],{"class":250},"()\n",[52,587,589],{"class":54,"line":588},30,[52,590,591],{"class":163},"}\n",[10,593,594,595,598],{},"Call ",[39,596,597],{},"syncOtalanUpdates()"," from app boot, a settings screen, or any user interaction that should check for updates:",[43,600,602],{"className":150,"code":601,"language":152,"meta":48,"style":48},"\u002F\u002F src\u002Fmain.ts\nimport { syncOtalanUpdates } from '.\u002Fota-update'\n\nvoid syncOtalanUpdates()\n",[39,603,604,609,628,632],{"__ignoreMap":48},[52,605,606],{"class":54,"line":55},[52,607,608],{"class":58},"\u002F\u002F src\u002Fmain.ts\n",[52,610,611,613,615,617,619,621,623,626],{"class":54,"line":62},[52,612,160],{"class":159},[52,614,164],{"class":163},[52,616,235],{"class":167},[52,618,180],{"class":163},[52,620,183],{"class":159},[52,622,186],{"class":163},[52,624,625],{"class":69},".\u002Fota-update",[52,627,191],{"class":163},[52,629,630],{"class":54,"line":85},[52,631,197],{"emptyLinePlaceholder":196},[52,633,634,637,639],{"class":54,"line":91},[52,635,636],{"class":163},"void",[52,638,235],{"class":234},[52,640,585],{"class":167},[10,642,643,646,647,649],{},[39,644,645],{},"initializeUpdater()"," does not check for updates immediately. It prepares install confirmation and the optional resume listener. Call ",[39,648,597],{}," when you want update work to run.",[23,651,653],{"id":652},"keep-the-ota-bundle-lean","Keep the OTA bundle lean",[10,655,656],{},"Capacitor clients download the selected archive when Otalan serves a new bundle. Keep that archive focused on the web shell: HTML, CSS, JavaScript, and small runtime-critical assets.",[10,658,659],{},"Do not bundle product images, videos, large fonts, PDFs, marketing media, or other content-heavy files into the OTA ZIP. Put those files behind your own external hosting and reference them by URL from the app.",[23,661,663],{"id":662},"publish-the-first-bundle","Publish the first bundle",[10,665,666,667,18],{},"After the native build contains this runtime initialization, publish a baseline bundle from the app repository with ",[14,668,17],{"href":16},[10,670,671,672,675,676,675,679,682,683,686],{},"Use the same ",[39,673,674],{},"appId",", ",[39,677,678],{},"platform",[39,680,681],{},"channel",", and ",[39,684,685],{},"runtimeVersion"," values that the installed app reports.",[23,688,690],{"id":689},"verify-update-and-rollback","Verify update and rollback",[692,693,694,698,708,711,714,717],"ol",{},[695,696,697],"li",{},"Install a native build that contains the updater initialization above.",[695,699,700,701,704,705,18],{},"Publish a visible text or style change through ",[39,702,703],{},"otalan bundle"," and ",[39,706,707],{},"otalan publish",[695,709,710],{},"Fully close and reopen the app, or trigger the app path that calls the updater sync.",[695,712,713],{},"Confirm the app loads the new web assets.",[695,715,716],{},"Roll back to the first bundle from the dashboard.",[695,718,719],{},"Restart or sync again and confirm the app returns to the known-good bundle.",[23,721,723],{"id":722},"troubleshooting","Troubleshooting",[725,726,727,739,754,764],"ul",{},[695,728,729,730,675,732,675,734,675,736,738],{},"If no update is returned, check the selected project, ",[39,731,674],{},[39,733,678],{},[39,735,681],{},[39,737,685],{},", OTA App Key, and rollout percentage.",[695,740,741,742,745,746,749,750,753],{},"If a local API or bundle URL fails on device, make sure the native runtime can reach it. Physical devices usually need your machine's LAN IP, Android emulators often need ",[39,743,744],{},"10.0.2.2",", Android HTTP testing may require ",[39,747,748],{},"android:usesCleartextTraffic=\"true\""," in the development manifest, and plain HTTP bundle URLs also require ",[39,751,752],{},"allowInsecureBundleUrls: true"," only in local development.",[695,755,756,757,760,761,18],{},"If the native app does not change, run ",[39,758,759],{},"bunx cap sync"," after plugin changes and install a fresh native build that imports ",[39,762,763],{},"ota-update.ts",[695,765,766],{},"If rollback is not visible, confirm the rolled-back bundle targets the same tuple and restart or trigger another updater sync.",[768,769,770],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":48,"searchDepth":85,"depth":85,"links":772},[773,774,775,776,777,778],{"id":25,"depth":62,"text":26},{"id":103,"depth":62,"text":104},{"id":652,"depth":62,"text":653},{"id":662,"depth":62,"text":663},{"id":689,"depth":62,"text":690},{"id":722,"depth":62,"text":723},"Wire the Otalan Capacitor runtime into an installed app so it can check for OTA updates, install compatible bundles, and confirm successful launches.","md",{},"\u002Fen\u002Fdocs\u002Fquick-start\u002Fcapacitor",{"title":5,"description":779},"en\u002Fdocs\u002Fquick-start\u002Fcapacitor","1qIdOowiu3ihojlheoX18CNFmYZ0wmEr3ANdFh_4irw",[787],{"title":788,"path":789,"stem":790,"children":791,"page":809},"En","\u002Fen","en",[792],{"title":793,"path":794,"stem":795,"children":796,"page":-1,"description":798},"Introduction","\u002Fen\u002Fdocs","en\u002Fdocs\u002Findex",[797,799,810,820,830,840,855,875],{"title":793,"path":794,"stem":795,"description":798},"Understand what Otalan is, when to use it, and how the first safe OTA release flow works for Capacitor and Expo apps.",{"title":800,"path":801,"stem":802,"children":803,"page":809},"About","\u002Fen\u002Fdocs\u002Fabout","en\u002Fdocs\u002Fabout",[804],{"title":805,"path":806,"stem":807,"description":808},"Security and trust","\u002Fen\u002Fdocs\u002Fabout\u002Fsecurity-trust","en\u002Fdocs\u002Fabout\u002Fsecurity-trust","How Otalan keeps OTA releases controlled: scoped keys, bundle validation, exact matching, rollout controls, rollback, deletion behavior, and support contact.",false,{"title":811,"path":812,"stem":813,"children":814,"page":809},"Build","\u002Fen\u002Fdocs\u002Fbuild","en\u002Fdocs\u002Fbuild",[815],{"title":816,"path":817,"stem":818,"description":819},"Generate a bundle","\u002Fen\u002Fdocs\u002Fbuild\u002Fgenerate-bundle","en\u002Fdocs\u002Fbuild\u002Fgenerate-bundle","Prepare a release artifact that will pass Otalan's validation pipeline, including the extra considerations required for Expo-based publish flows.",{"title":821,"path":822,"stem":823,"children":824,"page":809},"Deploy","\u002Fen\u002Fdocs\u002Fdeploy","en\u002Fdocs\u002Fdeploy",[825],{"title":826,"path":827,"stem":828,"description":829},"Publish a release","\u002Fen\u002Fdocs\u002Fdeploy\u002Fpublish-release","en\u002Fdocs\u002Fdeploy\u002Fpublish-release","Submit a release through the dashboard, understand each field in the publish form, and operate the validation lifecycle with confidence.",{"title":831,"path":832,"stem":833,"children":834,"page":809},"Integration","\u002Fen\u002Fdocs\u002Fintegration","en\u002Fdocs\u002Fintegration",[835],{"title":836,"path":837,"stem":838,"description":839},"Migrate from App Center CodePush","\u002Fen\u002Fdocs\u002Fintegration\u002Fapp-center-codepush","en\u002Fdocs\u002Fintegration\u002Fapp-center-codepush","Plan a migration from Microsoft App Center CodePush to Otalan, with mapping notes, rollout guidance, and common failure modes.",{"title":841,"path":842,"stem":843,"children":844,"page":809},"Quick Start","\u002Fen\u002Fdocs\u002Fquick-start","en\u002Fdocs\u002Fquick-start",[845,846,851],{"title":5,"path":782,"stem":784,"description":779},{"title":847,"path":848,"stem":849,"description":850},"Expo quick start","\u002Fen\u002Fdocs\u002Fquick-start\u002Fexpo","en\u002Fdocs\u002Fquick-start\u002Fexpo","Configure expo-updates with Otalan, add the Otalan Expo helper, and make the installed app ready to receive compatible OTA bundles.",{"title":17,"path":852,"stem":853,"description":854},"\u002Fen\u002Fdocs\u002Fquick-start\u002Fquick-start","en\u002Fdocs\u002Fquick-start\u002Fquick-start","Create the first Otalan release path, publish a baseline bundle, verify one update, and prove rollback before widening rollout.",{"title":856,"path":857,"stem":858,"children":859,"page":809},"Tooling","\u002Fen\u002Fdocs\u002Ftooling","en\u002Fdocs\u002Ftooling",[860,865,870],{"title":861,"path":862,"stem":863,"description":864},"AI skill","\u002Fen\u002Fdocs\u002Ftooling\u002Fai-skill","en\u002Fdocs\u002Ftooling\u002Fai-skill","Copy a compact assistant skill for Otalan SDK setup, CLI publishing, and safe credential boundaries.",{"title":866,"path":867,"stem":868,"description":869},"CLI","\u002Fen\u002Fdocs\u002Ftooling\u002Fcli","en\u002Fdocs\u002Ftooling\u002Fcli","Learn when to use the Otalan CLI, what workflows it covers, and how it complements the dashboard instead of replacing the platform model.",{"title":871,"path":872,"stem":873,"description":874},"SDKs","\u002Fen\u002Fdocs\u002Ftooling\u002Fsdk","en\u002Fdocs\u002Ftooling\u002Fsdk","Understand the difference between the Capacitor and Expo integrations, and choose the runtime package that matches the way your mobile app actually updates.",{"title":876,"path":877,"stem":878,"children":879,"page":809},"Versions","\u002Fen\u002Fdocs\u002Fversions","en\u002Fdocs\u002Fversions",[880],{"title":881,"path":882,"stem":883,"description":884},"v1","\u002Fen\u002Fdocs\u002Fversions\u002Fv1","en\u002Fdocs\u002Fversions\u002Fv1","Supported runtimes, public limits, and post-v1 candidates for Otalan v1.",1780287525123]