deskforge 1.0.0 → 1.0.1

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.
Files changed (84) hide show
  1. package/COMPLETION_REPORT.md +426 -0
  2. package/COMPONENT_API.md +529 -0
  3. package/DELIVERY_SUMMARY.md +455 -0
  4. package/IMPLEMENTATION_GUIDE.md +385 -0
  5. package/IMPORT_GUIDE.md +404 -0
  6. package/QUICK_REFERENCE.md +352 -0
  7. package/README.md +245 -31
  8. package/README_UI_COMPLETE.md +395 -0
  9. package/TYPE_DEFINITIONS.md +671 -0
  10. package/UI_GETTING_STARTED.md +523 -0
  11. package/examples/deskforge-app/App.ts +7 -11
  12. package/examples/deskforge-app/screens/CounterApp.ts +181 -0
  13. package/examples/deskforge-app/screens/GalleryApp.ts +267 -0
  14. package/examples/deskforge-app/screens/NotesApp.ts +376 -0
  15. package/examples/deskforge-app/screens/SettingsApp.ts +226 -0
  16. package/examples/deskforge-app/screens/TodoApp.ts +288 -0
  17. package/examples/deskforge-app/screens/index.ts +50 -0
  18. package/package.json +1 -1
  19. package/packages/cli/dist/commands/start.d.ts +7 -1
  20. package/packages/cli/dist/commands/start.d.ts.map +1 -1
  21. package/packages/cli/dist/commands/start.js +75 -21
  22. package/packages/cli/dist/commands/start.js.map +1 -1
  23. package/packages/cli/src/commands/start.ts +93 -21
  24. package/packages/cli/test/start.test.js +24 -0
  25. package/packages/core/dist/index.d.ts +1 -0
  26. package/packages/core/dist/index.d.ts.map +1 -1
  27. package/packages/core/dist/index.js +1 -0
  28. package/packages/core/dist/index.js.map +1 -1
  29. package/packages/core/dist/style/StyleObject.d.ts +115 -0
  30. package/packages/core/dist/style/StyleObject.d.ts.map +1 -0
  31. package/packages/core/dist/style/StyleObject.js +6 -0
  32. package/packages/core/dist/style/StyleObject.js.map +1 -0
  33. package/packages/core/dist/style/StyleSheet.d.ts +7 -0
  34. package/packages/core/dist/style/StyleSheet.d.ts.map +1 -0
  35. package/packages/core/dist/style/StyleSheet.js +13 -0
  36. package/packages/core/dist/style/StyleSheet.js.map +1 -0
  37. package/packages/core/dist/style/index.d.ts +3 -0
  38. package/packages/core/dist/style/index.d.ts.map +1 -0
  39. package/packages/core/dist/style/index.js +21 -0
  40. package/packages/core/dist/style/index.js.map +1 -0
  41. package/packages/core/src/index.ts +2 -1
  42. package/packages/core/src/style/StyleObject.ts +134 -0
  43. package/packages/core/src/style/StyleSheet.ts +19 -0
  44. package/packages/core/src/style/index.ts +5 -0
  45. package/packages/db/src/db.ts +4 -4
  46. package/packages/deskforge/src/index.ts +95 -0
  47. package/packages/file/dist/file.d.ts +1 -1
  48. package/packages/file/dist/file.d.ts.map +1 -1
  49. package/packages/file/dist/file.js +75 -3
  50. package/packages/file/dist/file.js.map +1 -1
  51. package/packages/file/src/file.ts +96 -4
  52. package/packages/file/test/file.test.js +23 -0
  53. package/packages/router/dist/index.d.ts +1 -0
  54. package/packages/router/dist/index.d.ts.map +1 -1
  55. package/packages/router/dist/index.js +1 -0
  56. package/packages/router/dist/index.js.map +1 -1
  57. package/packages/router/dist/navigation.d.ts +23 -0
  58. package/packages/router/dist/navigation.d.ts.map +1 -0
  59. package/packages/router/dist/navigation.js +61 -0
  60. package/packages/router/dist/navigation.js.map +1 -0
  61. package/packages/router/src/index.ts +2 -1
  62. package/packages/router/src/navigation.ts +86 -0
  63. package/packages/router/test/router.test.js +21 -1
  64. package/packages/theme/src/theme.ts +23 -0
  65. package/packages/ui/src/base/Button.ts +67 -0
  66. package/packages/ui/src/base/Image.ts +59 -0
  67. package/packages/ui/src/base/Pressable.ts +69 -0
  68. package/packages/ui/src/base/Text.ts +42 -0
  69. package/packages/ui/src/base/TextInput.ts +113 -0
  70. package/packages/ui/src/base/TouchableOpacity.ts +52 -0
  71. package/packages/ui/src/base/View.ts +43 -0
  72. package/packages/ui/src/index.ts +40 -25
  73. package/packages/ui/src/input/CheckBox.ts +69 -0
  74. package/packages/ui/src/input/Slider.ts +19 -2
  75. package/packages/ui/src/input/Switch.ts +68 -0
  76. package/packages/ui/src/layout/KeyboardAvoidingView.ts +65 -0
  77. package/packages/ui/src/layout/SafeAreaView.ts +58 -0
  78. package/packages/ui/src/list/FlatList.ts +111 -0
  79. package/packages/ui/src/list/ScrollView.ts +80 -0
  80. package/packages/ui/src/list/SectionList.ts +120 -0
  81. package/packages/ui/src/overlay/ActivityIndicator.ts +70 -0
  82. package/packages/ui/src/overlay/Modal.ts +28 -6
  83. package/packages/ui/src/platform/Platform.ts +119 -0
  84. package/packages/ui/src/platform/StatusBar.ts +63 -0
@@ -0,0 +1,352 @@
1
+ /**
2
+ * DeskForge Components - Quick Reference Card
3
+ *
4
+ * One-page cheat sheet for all components and patterns
5
+ */
6
+
7
+ # DeskForge UI - Quick Reference
8
+
9
+ ## Import
10
+ ```typescript
11
+ import {
12
+ View, Text, Pressable, Button, TouchableOpacity, Image, TextInput,
13
+ ScrollView, FlatList, SectionList,
14
+ SafeAreaView, KeyboardAvoidingView,
15
+ Modal, ActivityIndicator,
16
+ Switch, Slider, CheckBox,
17
+ StatusBar, Platform,
18
+ StyleSheet,
19
+ } from 'deskforge'
20
+
21
+ import { State, Computed, Watch, Effect } from 'deskforge/state'
22
+ ```
23
+
24
+ ---
25
+
26
+ ## Components at a Glance
27
+
28
+ ### Containers
29
+ ```typescript
30
+ // Flex container
31
+ View({ flex: 1 }, [children])
32
+
33
+ // Scroll content
34
+ ScrollView({ flex: 1 }, [children])
35
+
36
+ // Safe areas
37
+ SafeAreaView({ flex: 1 }, [children])
38
+ KeyboardAvoidingView({ flex: 1 }, [children])
39
+
40
+ // Full-screen overlay
41
+ Modal(visible, onClose, style, [children])
42
+ ```
43
+
44
+ ### Text & Input
45
+ ```typescript
46
+ // Static text
47
+ Text('Hello', { fontSize: 16 })
48
+
49
+ // Text input
50
+ TextInput({ flex: 1 }, { placeholder, value, onChangeText })
51
+
52
+ // Password
53
+ TextInput({ flex: 1 }, { secureTextEntry: true })
54
+ ```
55
+
56
+ ### Buttons & Touch
57
+ ```typescript
58
+ // Tappable
59
+ Pressable(style, { onPress, onLongPress, disabled }, [children])
60
+
61
+ // Quick button
62
+ Button('Click', style, { onPress })
63
+
64
+ // With opacity animation
65
+ TouchableOpacity(style, { onPress }, [children])
66
+ ```
67
+
68
+ ### Lists
69
+ ```typescript
70
+ // Simple list
71
+ FlatList(data, (item) => renderItem(item), style)
72
+
73
+ // With config
74
+ FlatList(data, renderItem, style, {
75
+ onEndReached: () => loadMore(),
76
+ ItemSeparatorComponent: () => Separator(),
77
+ })
78
+
79
+ // Grouped
80
+ SectionList(sections, renderItem, renderSectionHeader, style)
81
+ ```
82
+
83
+ ### Media
84
+ ```typescript
85
+ // Images
86
+ Image('/path/file.jpg', { width: 100, height: 100 })
87
+ Image({ uri: 'https://...' }, { width: 100 })
88
+
89
+ // Loading
90
+ ActivityIndicator({ margin: 20 }, { size: 'large' })
91
+ ```
92
+
93
+ ### Inputs
94
+ ```typescript
95
+ // Toggle
96
+ Switch(value, onChange, { onTintColor: '#0077ff' })
97
+
98
+ // Slider
99
+ Slider({ width: 200 }, {
100
+ value: 50,
101
+ minimumValue: 0,
102
+ maximumValue: 100,
103
+ onValueChange: (v) => setState(v),
104
+ })
105
+
106
+ // Checkbox
107
+ CheckBox(checked, onChange)
108
+ ```
109
+
110
+ ### Platform
111
+ ```typescript
112
+ // Detect OS
113
+ Platform.OS // 'ios' | 'android' | 'windows' | 'macos' | 'linux'
114
+
115
+ // Select by platform
116
+ Platform.select({ ios: 'x', android: 'y', default: 'z' })
117
+
118
+ // Conditional render
119
+ Platform.mobile(node) // null on desktop
120
+ Platform.desktop(node) // null on mobile
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Styles
126
+
127
+ ```typescript
128
+ const styles = StyleSheet.create({
129
+ // Layout
130
+ flex: 1,
131
+ flexDirection: 'row' | 'column',
132
+ justifyContent: 'center' | 'flex-start' | 'flex-end' | 'space-between',
133
+ alignItems: 'center',
134
+ gap: 12,
135
+
136
+ // Spacing
137
+ padding: 16,
138
+ margin: 8,
139
+ paddingHorizontal: 12,
140
+ marginVertical: 4,
141
+
142
+ // Size
143
+ width: 100,
144
+ height: 200,
145
+
146
+ // Visual
147
+ backgroundColor: '#fff',
148
+ borderRadius: 8,
149
+ borderWidth: 1,
150
+ borderColor: '#ddd',
151
+
152
+ // Text
153
+ fontSize: 16,
154
+ fontWeight: 'bold' | '600',
155
+ color: '#000',
156
+ textAlign: 'center',
157
+
158
+ // Shadow
159
+ shadowColor: '#000',
160
+ shadowOpacity: 0.1,
161
+ shadowRadius: 4,
162
+ elevation: 2,
163
+ })
164
+ ```
165
+
166
+ ---
167
+
168
+ ## State Management
169
+
170
+ ```typescript
171
+ // Reactive state - mutate directly
172
+ const state = State({ count: 0, items: [] })
173
+ state.count++
174
+ state.items.push(item)
175
+
176
+ // Computed value - auto-updates
177
+ const doubled = Computed(() => state.count * 2)
178
+ Text(`${doubled.value}`)
179
+
180
+ // Side effects
181
+ Effect(() => {
182
+ console.log('count changed')
183
+ return () => console.log('cleanup')
184
+ })
185
+
186
+ // Watch specific value
187
+ Watch(() => state.count, (newVal, oldVal) => {
188
+ console.log(`${oldVal} -> ${newVal}`)
189
+ })
190
+ ```
191
+
192
+ ---
193
+
194
+ ## Common Patterns
195
+
196
+ ### Conditional Rendering
197
+ ```typescript
198
+ View({}, [
199
+ state.loading ? ActivityIndicator() : Content(),
200
+ state.error ? Error(state.error) : null,
201
+ ].filter(Boolean))
202
+ ```
203
+
204
+ ### List with Delete
205
+ ```typescript
206
+ FlatList(state.items, (item) =>
207
+ Pressable({ padding: 12 }, {}, [
208
+ Text(item.name),
209
+ Pressable({ padding: 4 }, {
210
+ onPress: () => {
211
+ const idx = state.items.indexOf(item)
212
+ state.items.splice(idx, 1)
213
+ },
214
+ }, [Text('×')]),
215
+ ])
216
+ )
217
+ ```
218
+
219
+ ### Form Validation
220
+ ```typescript
221
+ const state = State({ email: '', errors: {} })
222
+
223
+ const validate = () => {
224
+ state.errors = {}
225
+ if (!state.email) state.errors.email = 'Required'
226
+ return Object.keys(state.errors).length === 0
227
+ }
228
+
229
+ Pressable({ padding: 12 }, {
230
+ onPress: () => validate() && submit(),
231
+ }, [Text('Submit')])
232
+ ```
233
+
234
+ ### Data Loading
235
+ ```typescript
236
+ Effect(() => {
237
+ state.loading = true
238
+ fetch('/api/items')
239
+ .then(r => r.json())
240
+ .then(data => state.items = data)
241
+ .catch(e => state.error = e.message)
242
+ .finally(() => state.loading = false)
243
+ })
244
+ ```
245
+
246
+ ---
247
+
248
+ ## Common Properties
249
+
250
+ ### Pressable Handlers
251
+ ```typescript
252
+ {
253
+ onPress: () => {}, // Tap/click
254
+ onLongPress: () => {}, // 500ms hold
255
+ onPressIn: () => {}, // Press starts
256
+ onPressOut: () => {}, // Press ends
257
+ disabled: false, // Block handlers
258
+ }
259
+ ```
260
+
261
+ ### TextInput Props
262
+ ```typescript
263
+ {
264
+ value: '',
265
+ placeholder: '',
266
+ onChangeText: (text) => {},
267
+ keyboardType: 'default' | 'numeric' | 'email-address' | 'phone-pad',
268
+ multiline: false,
269
+ maxLength: 100,
270
+ secureTextEntry: false,
271
+ }
272
+ ```
273
+
274
+ ### FlatList Props
275
+ ```typescript
276
+ {
277
+ ItemSeparatorComponent: () => Separator(),
278
+ ListHeaderComponent: Header(),
279
+ ListFooterComponent: Footer(),
280
+ ListEmptyComponent: EmptyState(),
281
+ onEndReached: () => loadMore(),
282
+ onEndReachedThreshold: 0.5,
283
+ horizontal: false,
284
+ numColumns: 1,
285
+ }
286
+ ```
287
+
288
+ ---
289
+
290
+ ## Quick Rules
291
+
292
+ 1. ✅ All components return DFNode
293
+ 2. ✅ All styles use StyleSheet.create()
294
+ 3. ✅ State mutations are direct (no setState)
295
+ 4. ✅ Children always in array
296
+ 5. ✅ Style is always first arg
297
+ 6. ✅ Handlers go in object
298
+ 7. ✅ Platform.OS detects environment
299
+ 8. ✅ Use Computed for derived values
300
+ 9. ✅ Use Effect for side effects
301
+ 10. ✅ Filter booleans with .filter(Boolean)
302
+
303
+ ---
304
+
305
+ ## Anti-Patterns
306
+
307
+ ❌ Don't use JSX
308
+ ❌ Don't use useState/useEffect
309
+ ❌ Don't mutate state with setState
310
+ ❌ Don't use CSS/className
311
+ ❌ Don't return plain JSX elements
312
+ ❌ Don't forget style object
313
+ ❌ Don't forget children array
314
+ ❌ Don't use any type
315
+ ❌ Don't create new state objects
316
+ ❌ Don't use manual renders over FlatList
317
+
318
+ ---
319
+
320
+ ## Getting Help
321
+
322
+ - **Full Guide:** See `IMPLEMENTATION_GUIDE.md`
323
+ - **API Reference:** See `COMPONENT_API.md`
324
+ - **Examples:** See `examples/deskforge-app/screens/`
325
+ - **Getting Started:** See `UI_GETTING_STARTED.md`
326
+
327
+ ---
328
+
329
+ ## Template
330
+
331
+ ```typescript
332
+ import { View, Text, Pressable, StyleSheet } from 'deskforge'
333
+ import { State } from 'deskforge/state'
334
+
335
+ const styles = StyleSheet.create({
336
+ container: { flex: 1, padding: 16 },
337
+ button: { backgroundColor: '#0077ff', padding: 12, borderRadius: 8 },
338
+ })
339
+
340
+ export const MyComponent = () => {
341
+ const state = State({ count: 0 })
342
+
343
+ return View(styles.container, [
344
+ Text(`Count: ${state.count}`, { fontSize: 20 }),
345
+ Pressable(styles.button, {
346
+ onPress: () => state.count++,
347
+ }, [
348
+ Text('Increment'),
349
+ ]),
350
+ ])
351
+ }
352
+ ```
package/README.md CHANGED
@@ -27,7 +27,8 @@ This model is intentionally simple and close to the rendering pipeline used by m
27
27
  ### Core principles
28
28
 
29
29
  - Declarative UI composition using node trees
30
- - Screen-based navigation with route registration
30
+ - Screen-based navigation with automatic route discovery
31
+ - App.ts as the landing entry for the app shell and screen tree
31
32
  - Renderer-driven output for images and visual artifacts
32
33
  - Modular packages that can be used independently
33
34
 
@@ -81,9 +82,233 @@ You can also add the UI package:
81
82
  npm install @deskforge/ui
82
83
  ```
83
84
 
84
- ## 4. Quick start: File-based routing
85
+ To scaffold a new app from the published CLI:
85
86
 
86
- DeskForge now includes a file-based router similar to **Expo Router** and **Next.js**. No need to register routes manually—your file structure becomes your routes:
87
+ ```bash
88
+ npx create-deskforge-app my-app
89
+ cd my-app
90
+ npm install
91
+ npm run start
92
+ ```
93
+
94
+ ## 4. Current authoring syntax
95
+
96
+ The current DeskForge examples use a functional, no-JSX authoring style. Components are written as pure functions that return a DFNode tree created with helpers such as createNode and the built-in UI primitives.
97
+
98
+ ```ts
99
+ import {
100
+ View,
101
+ Text,
102
+ StyleSheet,
103
+ Button,
104
+ } from '@deskforge/ui/src'
105
+ import { State } from '@deskforge/state/src'
106
+
107
+ const styles = StyleSheet.create({
108
+ container: { flex: 1, padding: 24, justifyContent: 'center' },
109
+ title: { fontSize: 24, fontWeight: '600', marginBottom: 12 },
110
+ })
111
+
112
+ export function CounterScreen() {
113
+ const state = State({ count: 0 })
114
+
115
+ return View(styles.container, [
116
+ Text(`Count: ${state.count}`, styles.title),
117
+ Button('Increment', { padding: 12 }, {
118
+ onPress: () => {
119
+ state.count += 1
120
+ },
121
+ }),
122
+ ])
123
+ }
124
+ ```
125
+
126
+ Key patterns in the current codebase:
127
+
128
+ - No JSX or HTML-style tags are used.
129
+ - UI is composed with functional helpers such as View, Text, Pressable, ScrollView, TextInput and Modal.
130
+ - State is created with State(...) and updated directly.
131
+ - Styling is declared with StyleSheet.create(...) using React Native-style objects.
132
+ - Theme usage is imported from @deskforge/theme/src and applied with Theme.apply(...).
133
+
134
+ ## 5. Packages and what they are for
135
+
136
+ DeskForge is organized as a set of focused packages. Each package can be used independently, and they work together through the core node-tree model.
137
+
138
+ ### Core packages
139
+
140
+ - @deskforge/core
141
+ - Core node model, createNode, diff engine, scheduler, and component primitives.
142
+ - Use this when you want to build a UI tree or define custom components.
143
+
144
+ ```ts
145
+ import { createNode } from '@deskforge/core'
146
+
147
+ const node = createNode('view', { style: { padding: 16 } }, [])
148
+ ```
149
+
150
+ - @deskforge/renderer
151
+ - Renders node trees to a canvas-style surface and exports to image/buffer output.
152
+ - Use this to display or export your UI.
153
+
154
+ ```ts
155
+ import { Renderer } from '@deskforge/renderer'
156
+
157
+ const renderer = new Renderer({ width: 800, height: 600, backgroundColor: '#fff' })
158
+ renderer.renderNode(node)
159
+ await renderer.saveAs('./dist/output.png')
160
+ ```
161
+
162
+ - @deskforge/router
163
+ - Screen routing, navigation helpers, and automatic file-based route discovery.
164
+ - Use this when your app needs multiple screens and navigation.
165
+
166
+ ```ts
167
+ import { Router } from '@deskforge/router'
168
+
169
+ // routes are discovered from the file structure automatically
170
+ Router.start()
171
+ ```
172
+
173
+ - @deskforge/ui
174
+ - A modern set of functional UI primitives for layout, text, input, lists, overlays, feedback, and platform-aware controls.
175
+ - The current examples use the monorepo entry point with /src imports, including View, Text, Pressable, Button, TouchableOpacity, Image, TextInput, ScrollView, FlatList, SectionList, SafeAreaView, KeyboardAvoidingView, Modal, ActivityIndicator, Switch, Slider, CheckBox, StatusBar, and Platform.
176
+
177
+ ```ts
178
+ import {
179
+ View,
180
+ Text,
181
+ ScrollView,
182
+ Modal,
183
+ StyleSheet,
184
+ } from '@deskforge/ui/src'
185
+ ```
186
+
187
+ ### State and styling packages
188
+
189
+ - @deskforge/state
190
+ - Reactive state helpers for local app state and component state.
191
+
192
+ ```ts
193
+ import { State } from '@deskforge/state'
194
+
195
+ const state = State({ count: 0 })
196
+ ```
197
+
198
+ - @deskforge/theme
199
+ - Theme tokens, color palettes, spacing, animation helpers, and a simple Theme API for switching modes and applying theme preferences.
200
+
201
+ ```ts
202
+ import { Theme } from '@deskforge/theme/src'
203
+
204
+ Theme.apply({ isDark: true })
205
+ ```
206
+
207
+ ### Device and platform integrations
208
+
209
+ - @deskforge/device
210
+ - Device APIs such as camera, contacts, sensors, and media helpers.
211
+
212
+ ```ts
213
+ import { Camera, Contacts } from '@deskforge/device'
214
+ ```
215
+
216
+ - @deskforge/file
217
+ - File system helpers for reading and writing files.
218
+
219
+ ```ts
220
+ import { readFile, writeFile } from '@deskforge/file'
221
+ ```
222
+
223
+ - @deskforge/network
224
+ - Peer-to-peer networking helpers, mDNS discovery, and TCP transfer utilities.
225
+
226
+ ```ts
227
+ import { discoverPeers } from '@deskforge/network'
228
+ ```
229
+
230
+ - @deskforge/notifications
231
+ - Toasts, push notifications, SMS, email, and notification helpers.
232
+
233
+ ```ts
234
+ import { Notify } from '@deskforge/notifications'
235
+ ```
236
+
237
+ - @deskforge/security
238
+ - Biometric helpers and encryption utilities.
239
+
240
+ ```ts
241
+ import { encrypt } from '@deskforge/security'
242
+ ```
243
+
244
+ ### AI, data, and app platform packages
245
+
246
+ - @deskforge/ai
247
+ - Local AI helpers and brain-style node creation for on-device reasoning.
248
+
249
+ ```ts
250
+ import { createBrain } from '@deskforge/ai'
251
+ ```
252
+
253
+ - @deskforge/db
254
+ - Database adapters for SQLite, Postgres, MySQL, and MongoDB.
255
+
256
+ ```ts
257
+ import { connect } from '@deskforge/db'
258
+ ```
259
+
260
+ - @deskforge/background
261
+ - Background tasks and scheduling helpers.
262
+
263
+ ```ts
264
+ import { BackgroundTask } from '@deskforge/background'
265
+ ```
266
+
267
+ - @deskforge/updater
268
+ - Self-hosted automatic update helpers.
269
+
270
+ ```ts
271
+ import { Updater } from '@deskforge/updater'
272
+ ```
273
+
274
+ - @deskforge/payments
275
+ - Unified payment wrapper with failover support for common providers.
276
+
277
+ ```ts
278
+ import { Pay } from '@deskforge/payments'
279
+ ```
280
+
281
+ - @deskforge/i18n
282
+ - Localization helpers with African language support.
283
+
284
+ ```ts
285
+ import { t } from '@deskforge/i18n'
286
+ ```
287
+
288
+ - @deskforge/logger
289
+ - Structured logging helpers for the framework and app code.
290
+
291
+ ```ts
292
+ import { logger } from '@deskforge/logger'
293
+ ```
294
+
295
+ - @deskforge/bridge
296
+ - Language bridge for calling code written in Python, Go, Rust, PHP, C, Kotlin, or Swift.
297
+
298
+ ```ts
299
+ import { callPython } from '@deskforge/bridge'
300
+ ```
301
+
302
+ - @deskforge/cli
303
+ - Command-line tools for scaffolding and app management.
304
+
305
+ ```bash
306
+ npx create-deskforge-app my-app
307
+ ```
308
+
309
+ ## 5. Quick start: File-based routing
310
+
311
+ DeskForge now includes a file-based router similar to **Expo Router** and **Next.js**. Routes are discovered automatically from your screen files, so you do not manually register them. Your App.ts file acts as the landing page and app shell for the discovered screens:
87
312
 
88
313
  ```ts
89
314
  import { FileRouter, ManifestBuilder, Screen } from '@deskforge/router'
@@ -171,7 +396,7 @@ await renderer.saveAs('./dist/output.png')
171
396
 
172
397
  ### 5.3 Screens and routes
173
398
 
174
- DeskForge uses routes mapping to screen components. A screen is simply a function that returns a node tree, and it can also carry Expo-style metadata such as a title and layout.
399
+ DeskForge uses automatic route discovery from a screen folder structure. A screen is simply a function that returns a node tree, and it can also carry metadata such as a title and layout. The App.ts entry file becomes the landing page that hosts the app shell and initial screen.
175
400
 
176
401
  ```ts
177
402
  import { Screen } from '@deskforge/router'
@@ -185,14 +410,12 @@ function HomeScreen() {
185
410
  const HomeRoute = Screen(HomeScreen, { title: 'Home', layout: 'app' })
186
411
  ```
187
412
 
188
- You register screens with `Router`:
413
+ The router discovers screens automatically from the file structure:
189
414
 
190
415
  ```ts
191
416
  import { Router } from '@deskforge/router'
192
417
 
193
- Router({
194
- home: HomeRoute,
195
- })
418
+ Router.start()
196
419
  ```
197
420
 
198
421
  And navigate with:
@@ -207,8 +430,8 @@ Router.go('home')
207
430
 
208
431
  The simplest app has three parts:
209
432
 
210
- 1. an entry point file, usually `App.ts`
211
- 2. one or more screen files
433
+ 1. an entry point file, usually `App.ts`, which acts as the landing page and app shell
434
+ 2. one or more screen files discovered automatically by the router
212
435
  3. a small UI helper layer for creating views and text blocks
213
436
 
214
437
  The example app in `examples/deskforge-app` follows this pattern.
@@ -223,9 +446,7 @@ import { Renderer } from '@deskforge/renderer'
223
446
  import { Router } from '@deskforge/router'
224
447
  import { HomeScreen } from './src/screens'
225
448
 
226
- Router({
227
- home: HomeScreen,
228
- })
449
+ Router.start()
229
450
 
230
451
  function createRoot() {
231
452
  return createNode('view', {
@@ -269,18 +490,14 @@ export default function HomeScreen(params: ScreenParams = {}) {
269
490
  }
270
491
  ```
271
492
 
272
- ### 6.3 Register screens
493
+ ### 6.3 App entry and automatic screen discovery
273
494
 
274
- In the entry file or a shared bootstrapping module, register all screens:
495
+ The App.ts entry file serves as the landing page and initial app shell. Screen files under the app structure are discovered automatically and exposed by the router.
275
496
 
276
497
  ```ts
277
498
  import { Router } from '@deskforge/router'
278
- import { HomeScreen, DetailsScreen } from './src/screens'
279
499
 
280
- Router({
281
- home: HomeRoute,
282
- details: DetailsRoute,
283
- })
500
+ Router.start()
284
501
  ```
285
502
 
286
503
  ### 6.4 Navigate between screens
@@ -296,6 +513,9 @@ The current router stores navigation history and exposes helpers such as:
296
513
  - `Router.forward()`
297
514
  - `Router.params()`
298
515
  - `Router.currentRoute()`
516
+ - `Router.start()`
517
+
518
+ For a React Navigation-like experience, DeskForge also supports a stack-style navigation model with screen components, route params, and a shared app shell defined in App.ts.
299
519
 
300
520
  ---
301
521
 
@@ -424,10 +644,10 @@ my-app/
424
644
 
425
645
  ### Suggested workflow
426
646
 
427
- 1. Create a main `App.ts` file.
647
+ 1. Create a main `App.ts` file as the landing page and app shell.
428
648
  2. Create one file per screen.
429
649
  3. Create helper modules for common UI primitives.
430
- 4. Register routes in one place.
650
+ 4. Let the router discover screens automatically.
431
651
  5. Render the current screen through the renderer.
432
652
 
433
653
  ---
@@ -460,15 +680,7 @@ import { Renderer } from '@deskforge/renderer'
460
680
  import { Router, Screen } from '@deskforge/router'
461
681
  import { Text, View, Window } from './src/ui/Responsive'
462
682
 
463
- Router({
464
- home: () => Screen({ style: { background: '#f8fafc', padding: 24 } })
465
- .add(
466
- View({ style: { background: '#ffffff', borderRadius: 24, padding: 24 } }),
467
- Text('DeskForge App', { style: { fontSize: 24, fontWeight: '700' } }),
468
- Text('This is a simple DeskForge screen.', { style: { color: '#4b5563', fontSize: 16 } }),
469
- )
470
- .build(),
471
- })
683
+ Router.start()
472
684
 
473
685
  function createRoot() {
474
686
  return Window({ style: { background: '#f7f8fb', padding: 24 } })
@@ -506,6 +718,8 @@ main().catch(console.error)
506
718
  - Use helper functions to hide repetitive node creation.
507
719
  - Keep route names stable and descriptive.
508
720
  - Keep rendering logic separate from navigation logic.
721
+ - Use App.ts as the shared landing page and shell for the app.
722
+ - Let the router discover screens automatically instead of manually registering them.
509
723
  - Use `dist/` for generated assets so your source stays clean.
510
724
 
511
725
  ---