@take-out/docs 0.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/hot-updater.md ADDED
@@ -0,0 +1,223 @@
1
+ ---
2
+ name: hot-updater
3
+ description: Guide for implementing OTA updates and hot updates in React Native apps. INVOKE WHEN: hot updater, OTA updates, over-the-air updates, app updates, code push, deploy updates, @hot-updater/react-native, HotUpdaterProvider, useHotUpdater, update deployment.
4
+ ---
5
+
6
+ # Hot Updater Guide
7
+
8
+ This guide covers the hot update system for delivering over-the-air (OTA)
9
+ updates to React Native applications.
10
+
11
+ ## Overview
12
+
13
+ The hot updater system allows you to push JavaScript bundle updates to deployed
14
+ React Native apps without going through the app store review process. This
15
+ enables rapid bug fixes and feature deployments.
16
+
17
+ ## Architecture
18
+
19
+ ### Components
20
+
21
+ 1. **@hot-updater/react-native** - React Native client library
22
+ 2. **HotUpdaterProvider** - React context provider for update management
23
+ 3. **Feature Flags** - Remote configuration via PostHog
24
+ 4. **Update Server** - Hosts update bundles (configurable via feature flag)
25
+
26
+ ## Setup
27
+
28
+ ### Installation
29
+
30
+ The hot-updater package is already installed:
31
+
32
+ ```bash
33
+ bun add @hot-updater/react-native
34
+ ```
35
+
36
+ ### Configuration
37
+
38
+ In `app.config.ts`:
39
+
40
+ ```typescript
41
+ {
42
+ expo: {
43
+ version: "0.0.6",
44
+ runtimeVersion: version, // Required for appVersion strategy
45
+ plugins: [
46
+ [
47
+ "@hot-updater/react-native",
48
+ {
49
+ channel: APP_VARIANT, // development, preview, or production
50
+ }
51
+ ]
52
+ ]
53
+ }
54
+ }
55
+ ```
56
+
57
+ ### Feature Flags
58
+
59
+ Two feature flags control hot updates:
60
+
61
+ 1. **ENABLE_HOT_UPDATES** - Boolean flag to enable/disable hot updates
62
+ 2. **HOT_UPDATE_SERVER_URL** - Dynamic config for update server URL
63
+
64
+ Configure these in PostHog or your feature flag service.
65
+
66
+ ## Implementation
67
+
68
+ ### Provider Setup
69
+
70
+ Wrap your app with the HotUpdaterProvider:
71
+
72
+ ```tsx
73
+ import { HotUpdaterProvider } from '~/features/hot-updater'
74
+
75
+ function App() {
76
+ return <HotUpdaterProvider>{/* Your app components */}</HotUpdaterProvider>
77
+ }
78
+ ```
79
+
80
+ ### Update Notification UI
81
+
82
+ Add the notification component to show update prompts:
83
+
84
+ ```tsx
85
+ import { HotUpdaterNotification } from '~/features/hot-updater'
86
+
87
+ function AppLayout() {
88
+ return (
89
+ <>
90
+ {/* Your app content */}
91
+ <HotUpdaterNotification />
92
+ </>
93
+ )
94
+ }
95
+ ```
96
+
97
+ ### Using the Hook
98
+
99
+ Access hot updater functionality in components:
100
+
101
+ ```tsx
102
+ import { useHotUpdater } from '~/features/hot-updater'
103
+
104
+ function SettingsScreen() {
105
+ const {
106
+ isUpdateAvailable,
107
+ isDownloading,
108
+ downloadProgress,
109
+ checkForUpdate,
110
+ applyUpdate,
111
+ lastCheckTime,
112
+ } = useHotUpdater()
113
+
114
+ return (
115
+ <View>
116
+ {isUpdateAvailable && <Button onPress={applyUpdate}>Apply Update</Button>}
117
+
118
+ <Button onPress={checkForUpdate}>Check for Updates</Button>
119
+
120
+ {lastCheckTime && (
121
+ <Text>Last checked: {lastCheckTime.toLocaleString()}</Text>
122
+ )}
123
+ </View>
124
+ )
125
+ }
126
+ ```
127
+
128
+ ## Update Strategy
129
+
130
+ ### Version Management
131
+
132
+ The app uses the "appVersion" strategy:
133
+
134
+ - Runtime version matches app version (e.g., "0.0.6")
135
+ - Updates are compatible within the same runtime version
136
+ - Native changes require a new app store release
137
+
138
+ ### Channels
139
+
140
+ Updates are distributed through channels based on APP_VARIANT:
141
+
142
+ - **development** - For development builds
143
+ - **preview** - For staging/preview builds
144
+ - **production** - For production releases
145
+
146
+ ### Update Check Frequency
147
+
148
+ - On app launch
149
+ - When app returns to foreground
150
+ - Every 30 minutes while app is active
151
+ - Manual check via UI
152
+
153
+ ## Deployment
154
+
155
+ ### Creating an Update
156
+
157
+ 1. Make JavaScript/asset changes (no native code changes)
158
+ 2. Build the update bundle:
159
+
160
+ ```bash
161
+ eas update --branch [branch-name] --message "[update message]"
162
+ ```
163
+
164
+ 3. The update is automatically distributed to devices
165
+
166
+ ### Update Server
167
+
168
+ Configure the update server URL via the HOT_UPDATE_SERVER_URL feature flag. The
169
+ default server handles:
170
+
171
+ - Bundle hosting
172
+ - Version compatibility checks
173
+ - Channel-based distribution
174
+ - Download progress tracking
175
+
176
+ ## Monitoring
177
+
178
+ ### Analytics Events
179
+
180
+ The system tracks these events via PostHog:
181
+
182
+ - `hot_update_available` - Update detected
183
+ - `hot_update_downloaded` - Update downloaded successfully
184
+ - `hot_update_check_error` - Error checking for updates
185
+ - `hot_update_apply_error` - Error applying update
186
+
187
+ ### Debugging
188
+
189
+ Enable verbose logging:
190
+
191
+ ```tsx
192
+ // In development
193
+ console.info('Hot updates enabled:', isEnabled)
194
+ console.info('Server URL:', serverUrl)
195
+ console.info('Current version:', Updates.currentVersion)
196
+ ```
197
+
198
+ ## Best Practices
199
+
200
+ ### Do's
201
+
202
+ 1. **Test updates thoroughly** in development/preview channels first
203
+ 2. **Use feature flags** to control rollout
204
+ 3. **Monitor analytics** after deploying updates
205
+ 4. **Keep updates small** - large bundles take longer to download
206
+ 5. **Version native changes** properly with runtime version bumps
207
+
208
+ ### Don'ts
209
+
210
+ 1. **Don't include native changes** in hot updates
211
+ 2. **Don't skip testing** in preview environments
212
+ 3. **Don't force updates** without user consent
213
+ 4. **Don't update during critical user operations**
214
+ 5. **Don't ignore error tracking**
215
+
216
+ ## Rollback Strategy
217
+
218
+ If an update causes issues:
219
+
220
+ 1. **Disable via feature flag** - Turn off ENABLE_HOT_UPDATES
221
+ 2. **Deploy fix** - Create and test a fix
222
+ 3. **Roll forward** - Deploy the fix as a new update
223
+ 4. **Monitor** - Track analytics to ensure issues are resolved
@@ -0,0 +1,252 @@
1
+ ---
2
+ name: native-hot-update
3
+ description: Native hot update (OTA/over-the-air) system guide for @take-out/native-hot-update. Use for HotUpdaterSplash, splash screen, deploy-hot-update scripts, update issues, or troubleshooting OTA updates.
4
+ ---
5
+
6
+ # Native Hot Update System
7
+
8
+ ## Overview
9
+
10
+ The app uses hot updates to deploy code changes to production without requiring
11
+ app store submissions. Updates are checked on app start and applied
12
+ automatically or after user confirmation.
13
+
14
+ ## Architecture
15
+
16
+ ### Package
17
+
18
+ Located at packages/native-hot-update, this is a reusable package that provides:
19
+
20
+ - Instance-based API via createHotUpdater()
21
+ - Pluggable storage interface (get/set/delete)
22
+ - Timeout protection (5s soft, 20s hard)
23
+ - Progress tracking during downloads
24
+ - Alert handling for critical updates
25
+
26
+ ### Integration
27
+
28
+ Located at src/features/hot-updater, this integrates the package with the app:
29
+
30
+ - useHotUpdater hook with PostHog feature flags
31
+ - HotUpdaterSplash component for app initialization
32
+ - Analytics tracking for update events
33
+
34
+ ## Update Flow
35
+
36
+ ### On App Start
37
+
38
+ 1. HotUpdaterSplash component renders
39
+ 2. useHotUpdater hook checks PostHog feature flags
40
+ 3. If enabled, queries update server for available updates
41
+ 4. Shows splash screen during download with progress indicator
42
+ 5. After timeout or completion, displays app content
43
+
44
+ ### Update Types
45
+
46
+ Critical updates reload immediately if user hasn't accessed the app yet. If the
47
+ user is already in the app, an alert prompts them to reload now or later.
48
+
49
+ Non-critical updates download silently and apply on the next app restart.
50
+
51
+ Rollback updates check if a pre-release bundle is active and skip if the current
52
+ version is newer.
53
+
54
+ ## Configuration
55
+
56
+ ### Feature Flags
57
+
58
+ Controlled via PostHog:
59
+
60
+ - ENABLE_HOT_UPDATES: Master on/off switch
61
+ - HOT_UPDATE_SERVER_URL: Server endpoint for updates
62
+
63
+ ### Environment
64
+
65
+ Required variables in .env:
66
+
67
+ - HOT_UPDATER_SUPABASE_URL
68
+ - HOT_UPDATER_SUPABASE_ANON_KEY
69
+ - HOT_UPDATER_SUPABASE_BUCKET_NAME
70
+
71
+ ### Update Strategy
72
+
73
+ Uses appVersion strategy, which requires runtimeVersion set in app.config.ts to
74
+ match the version field.
75
+
76
+ ## Deployment
77
+
78
+ ### Manual
79
+
80
+ Run deployment scripts for specific platforms:
81
+
82
+ ```
83
+ bun deploy-hot-update:ios
84
+ bun deploy-hot-update:android
85
+ bun deploy-hot-update
86
+ ```
87
+
88
+ ### Automated
89
+
90
+ Two GitHub Actions workflows handle deployments.
91
+
92
+ Manual deployment via Actions tab:
93
+ - Workflow: deploy-hot-update.yml
94
+ - Choose platform, channel, and critical flag
95
+ - Triggered manually from GitHub Actions UI
96
+
97
+ Automatic deployment after CI success:
98
+ - Workflow: auto-deploy-hot-update.yml
99
+ - Runs when CI completes on main branch
100
+ - Deploys to production-pre channel
101
+ - Non-critical updates only
102
+
103
+ Required GitHub secrets:
104
+ - HOT_UPDATER_SUPABASE_URL
105
+ - HOT_UPDATER_SUPABASE_ANON_KEY
106
+ - HOT_UPDATER_SUPABASE_BUCKET_NAME
107
+
108
+ ### Channels
109
+
110
+ - production-pre: Pre-release testing channel
111
+ - production: Stable release channel
112
+
113
+ ## Usage
114
+
115
+ ### Basic Integration
116
+
117
+ ```ts
118
+ import { HotUpdaterSplash } from '~/features/hot-updater/HotUpdaterSplash'
119
+
120
+ export function Layout() {
121
+ return (
122
+ <HotUpdaterSplash>
123
+ <App />
124
+ </HotUpdaterSplash>
125
+ )
126
+ }
127
+ ```
128
+
129
+ The component handles update checks automatically and shows a splash screen
130
+ during downloads.
131
+
132
+ ### Custom Behavior
133
+
134
+ ```ts
135
+ import { useHotUpdater } from '~/features/hot-updater/useHotUpdater'
136
+
137
+ export function CustomUpdater() {
138
+ const { userClearedForAccess, progress } = useHotUpdater()
139
+
140
+ if (!userClearedForAccess) {
141
+ return <CustomSplash progress={progress} />
142
+ }
143
+
144
+ return <App />
145
+ }
146
+ ```
147
+
148
+ ### Debugging
149
+
150
+ ```ts
151
+ import { hotUpdater } from '@take-out/native-hot-update'
152
+
153
+ console.info('Applied OTA:', hotUpdater.getAppliedOta())
154
+ console.info('Short ID:', hotUpdater.getShortOtaId())
155
+ console.info('Channel:', hotUpdater.getChannel())
156
+ console.info('Pending:', hotUpdater.getIsUpdatePending())
157
+ ```
158
+
159
+ ## Alert Behavior
160
+
161
+ ### Critical Updates
162
+
163
+ Before user accesses app: Reloads automatically After user accesses app: Shows
164
+ alert with "Later" and "Reload Now" options
165
+
166
+ ### Non-Critical Updates
167
+
168
+ No alerts shown. Updates apply silently on next app restart.
169
+
170
+ ### Rollback Protection
171
+
172
+ If using a pre-release bundle and a rollback is detected, shows alert: "Update
173
+ Skipped - Skipped rollback because you are using a newer pre-release bundle."
174
+
175
+ ## Storage
176
+
177
+ The package uses a pluggable storage interface. The app provides MMKV storage:
178
+
179
+ ```ts
180
+ import { MMKV } from 'react-native-mmkv'
181
+ import { createMMKVStorage } from '@take-out/native-hot-update/mmkv'
182
+
183
+ const mmkv = new MMKV({ id: 'hot-updater' })
184
+ const storage = createMMKVStorage(mmkv)
185
+ ```
186
+
187
+ Storage persists:
188
+
189
+ - Bundle IDs per app version
190
+ - Pre-release bundle markers
191
+ - Update state across app restarts
192
+
193
+ ## Analytics
194
+
195
+ Update events are automatically tracked via PostHog:
196
+
197
+ - ota_update_downloaded: When update completes
198
+ - ota_update_error: When update fails
199
+
200
+ Event properties include bundle ID, critical flag, file URL, and error details.
201
+
202
+ ## Timeout Protection
203
+
204
+ Soft timeout at 5 seconds: Shows app if no update is downloading Hard timeout at
205
+ 20 seconds: Always shows app regardless of update state
206
+
207
+ This prevents slow servers or network issues from blocking user access.
208
+
209
+ ## Build Configuration
210
+
211
+ The hot-updater.config.ts file at the project root configures:
212
+
213
+ - Build adapter: bare (with Hermes enabled)
214
+ - Storage: Supabase
215
+ - Database: Supabase
216
+ - Update strategy: appVersion
217
+
218
+ ## Platform Support
219
+
220
+ iOS and Android both supported. Web is a no-op (splash component renders
221
+ children immediately).
222
+
223
+ Updates are deployed per platform and can be triggered independently.
224
+
225
+ ## Security
226
+
227
+ Updates are served via Supabase with configured access controls. The anon key is
228
+ used for read access to the update bundles.
229
+
230
+ Pre-release updates use a separate channel and are marked in storage to prevent
231
+ accidental rollbacks.
232
+
233
+ ## Troubleshooting
234
+
235
+ ### Updates not applying
236
+
237
+ Check feature flags in PostHog, verify server URL is configured, confirm
238
+ .env.hotupdater has correct credentials.
239
+
240
+ ### Splash screen stuck
241
+
242
+ Check network connectivity, verify server is responding, review timeout logs.
243
+
244
+ ### Wrong version shown
245
+
246
+ Use hotUpdater.getAppliedOta() to check current bundle, compare with server to
247
+ verify latest version is available.
248
+
249
+ ## References
250
+
251
+ - Package README: packages/native-hot-update/README.md
252
+ - Integration guide: packages/native-hot-update/INTEGRATION.md
@@ -0,0 +1,234 @@
1
+ ---
2
+ name: one-components
3
+ description: One framework components guide for navigation, layouts, and UI elements. INVOKE WHEN: Link, Redirect, navigation, Head, meta tags, SEO, SafeAreaView, StatusBar, device safe areas, Stack, Tabs, Slot, layout components, LoadProgressBar, ScrollBehavior.
4
+ ---
5
+
6
+ # one framework: components
7
+
8
+ comprehensive guide to built-in components in one framework for navigation,
9
+ layouts, and ui enhancements.
10
+
11
+ ## navigation components
12
+
13
+ ### Link
14
+
15
+ type-safe navigation component for both web and native.
16
+
17
+ ```tsx
18
+ import { Link } from 'one'
19
+
20
+ <Link href="/blog">go to blog</Link>
21
+ <Link href="/blog/post" replace>replace history</Link>
22
+ <Link href="https://example.com" target="_blank">external</Link>
23
+ ```
24
+
25
+ **props:**
26
+
27
+ - `href` (required): typed route path
28
+ - `asChild`: forward props to child component
29
+ - `replace`: replace history instead of push
30
+ - `push`: explicitly push to history
31
+ - `className`: web class, native css interop
32
+ - `target`: web-only (\_blank, \_self, \_top, \_parent)
33
+ - `rel`: web-only (nofollow, noopener, noreferrer, etc.)
34
+ - `download`: web-only download attribute
35
+
36
+ **examples:**
37
+
38
+ ```tsx
39
+ // basic navigation
40
+ <Link href="/home/profile">view profile</Link>
41
+
42
+ // dynamic routes (type-safe)
43
+ <Link href={`/user/${userId}`}>user page</Link>
44
+
45
+ // replace history
46
+ <Link href="/login" replace>login</Link>
47
+
48
+ // external link
49
+ <Link href="https://github.com" target="_blank" rel="noopener">
50
+ github
51
+ </Link>
52
+
53
+ // as child (forward to custom component)
54
+ <Link href="/about" asChild>
55
+ <CustomButton>about us</CustomButton>
56
+ </Link>
57
+ ```
58
+
59
+ ### Redirect
60
+
61
+ redirects when route is focused. uses `useFocusEffect` internally.
62
+
63
+ ```tsx
64
+ import { Redirect } from 'one'
65
+
66
+ export default function Page() {
67
+ const { isAuthenticated } = useAuth()
68
+
69
+ if (!isAuthenticated) {
70
+ return <Redirect href="/login" />
71
+ }
72
+
73
+ return <Content />
74
+ }
75
+ ```
76
+
77
+ **props:**
78
+
79
+ - `href`: destination route
80
+
81
+ **note:** prefer using `~/interface/Link` over One's Link component in this project.
82
+
83
+ ## ui components
84
+
85
+ ### Head
86
+
87
+ control `<head>` on web and app meta on native.
88
+
89
+ ```tsx
90
+ import { Head } from 'one'
91
+
92
+ export default function Page() {
93
+ return (
94
+ <>
95
+ <Head>
96
+ <title>my page title</title>
97
+ <meta name="description" content="page description" />
98
+ <meta property="og:image" content="/og-image.png" />
99
+ </Head>
100
+ <Content />
101
+ </>
102
+ )
103
+ }
104
+ ```
105
+
106
+ can be used in any route or component. web: renders into `<head>`, native:
107
+ controls app metadata.
108
+
109
+ ### SafeAreaView
110
+
111
+ re-exports from `react-native-safe-area-context`. respects device safe areas
112
+ (notches, status bars).
113
+
114
+ ```tsx
115
+ import { SafeAreaView } from 'one'
116
+
117
+ export default function Page() {
118
+ return (
119
+ <SafeAreaView edges={['top', 'left', 'right']}>
120
+ <Content />
121
+ </SafeAreaView>
122
+ )
123
+ }
124
+ ```
125
+
126
+ **props:**
127
+
128
+ - `edges`: array of edges to apply safe area ('top' | 'bottom' | 'left' |
129
+ 'right')
130
+
131
+ one uses `SafeAreaProvider` from react navigation automatically.
132
+
133
+ ### LoadProgressBar
134
+
135
+ web-only loading bar during page transitions.
136
+
137
+ ```tsx
138
+ // app/_layout.tsx
139
+ import { LoadProgressBar, Slot } from 'one'
140
+
141
+ export default function Layout() {
142
+ return (
143
+ <>
144
+ <LoadProgressBar
145
+ startDelay={100}
146
+ finishDelay={100}
147
+ initialPercent={20}
148
+ updateInterval={100}
149
+ sporadicness={0.3}
150
+ />
151
+ <Slot />
152
+ </>
153
+ )
154
+ }
155
+ ```
156
+
157
+ **props:**
158
+
159
+ - `startDelay`: delay before showing (ms)
160
+ - `finishDelay`: delay before hiding (ms)
161
+ - `initialPercent`: starting percentage (0-100)
162
+ - `updateInterval`: update frequency (ms)
163
+ - `sporadicness`: randomness factor (0-1)
164
+
165
+ ### ScrollBehavior
166
+
167
+ automatic scroll restoration for web. resets to top on new page, restores
168
+ position on back/forward.
169
+
170
+ ```tsx
171
+ // app/_layout.tsx
172
+ import { ScrollBehavior, Slot } from 'one'
173
+
174
+ export default function Layout() {
175
+ return (
176
+ <>
177
+ <ScrollBehavior />
178
+ <Slot />
179
+ </>
180
+ )
181
+ }
182
+ ```
183
+
184
+ **props:**
185
+
186
+ - `disabled`: boolean | 'restore' - disable completely or only restoration
187
+
188
+ ```tsx
189
+ // disable restoration, keep reset behavior
190
+ <ScrollBehavior disabled="restore" />
191
+
192
+ // disable completely
193
+ <ScrollBehavior disabled={true} />
194
+ ```
195
+
196
+ ## practical patterns
197
+
198
+ ### safe area with scroll
199
+
200
+ ```tsx
201
+ import { SafeAreaView, ScrollView } from 'one'
202
+
203
+ export default function Page() {
204
+ return (
205
+ <SafeAreaView edges={['top']} style={{ flex: 1 }}>
206
+ <ScrollView>
207
+ <Content />
208
+ </ScrollView>
209
+ </SafeAreaView>
210
+ )
211
+ }
212
+ ```
213
+
214
+ ### progressive loading indicator
215
+
216
+ ```tsx
217
+ // app/_layout.tsx
218
+ import { LoadProgressBar, Slot } from 'one'
219
+
220
+ export default function Layout() {
221
+ return (
222
+ <>
223
+ <LoadProgressBar
224
+ startDelay={200} // wait 200ms before showing
225
+ finishDelay={300} // wait 300ms before hiding
226
+ initialPercent={30} // start at 30%
227
+ updateInterval={80} // update every 80ms
228
+ sporadicness={0.4} // moderate randomness
229
+ />
230
+ <Slot />
231
+ </>
232
+ )
233
+ }
234
+ ```