jac-client 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl

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 (154) hide show
  1. jac_client/docs/README.md +50 -20
  2. jac_client/docs/advanced-state.md +13 -14
  3. jac_client/docs/asset-serving/intro.md +209 -0
  4. jac_client/docs/assets/pipe_line-v2.svg +32 -0
  5. jac_client/docs/file-system/app.jac.md +121 -0
  6. jac_client/docs/file-system/backend-frontend.md +217 -0
  7. jac_client/docs/file-system/intro.md +72 -0
  8. jac_client/docs/file-system/nested-imports.md +348 -0
  9. jac_client/docs/guide-example/intro.md +11 -13
  10. jac_client/docs/guide-example/step-01-setup.md +30 -20
  11. jac_client/docs/guide-example/step-02-components.md +24 -24
  12. jac_client/docs/guide-example/step-03-styling.md +24 -24
  13. jac_client/docs/guide-example/step-04-todo-ui.md +17 -17
  14. jac_client/docs/guide-example/step-05-local-state.md +23 -23
  15. jac_client/docs/guide-example/step-06-events.md +23 -24
  16. jac_client/docs/guide-example/step-07-effects.md +27 -28
  17. jac_client/docs/guide-example/step-08-walkers.md +23 -23
  18. jac_client/docs/guide-example/step-09-authentication.md +18 -18
  19. jac_client/docs/guide-example/step-10-routing.md +20 -21
  20. jac_client/docs/guide-example/step-11-final.md +34 -35
  21. jac_client/docs/imports.md +4 -5
  22. jac_client/docs/lifecycle-hooks.md +12 -13
  23. jac_client/docs/routing.md +21 -22
  24. jac_client/docs/styling/intro.md +249 -0
  25. jac_client/docs/styling/js-styling.md +367 -0
  26. jac_client/docs/styling/material-ui.md +341 -0
  27. jac_client/docs/styling/pure-css.md +299 -0
  28. jac_client/docs/styling/sass.md +403 -0
  29. jac_client/docs/styling/styled-components.md +395 -0
  30. jac_client/docs/styling/tailwind.md +298 -0
  31. jac_client/examples/all-in-one/.babelrc +9 -0
  32. jac_client/examples/all-in-one/README.md +16 -0
  33. jac_client/examples/all-in-one/app.jac +426 -0
  34. jac_client/examples/all-in-one/assets/burger.png +0 -0
  35. jac_client/examples/all-in-one/button.jac +7 -0
  36. jac_client/examples/all-in-one/components/button.jac +7 -0
  37. jac_client/examples/all-in-one/package.json +29 -0
  38. jac_client/examples/all-in-one/styles.css +26 -0
  39. jac_client/examples/all-in-one/vite.config.js +28 -0
  40. jac_client/examples/asset-serving/css-with-image/.babelrc +9 -0
  41. jac_client/examples/asset-serving/css-with-image/README.md +91 -0
  42. jac_client/examples/asset-serving/css-with-image/app.jac +88 -0
  43. jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
  44. jac_client/examples/asset-serving/css-with-image/package.json +28 -0
  45. jac_client/examples/asset-serving/css-with-image/styles.css +26 -0
  46. jac_client/examples/asset-serving/css-with-image/vite.config.js +28 -0
  47. jac_client/examples/asset-serving/image-asset/.babelrc +9 -0
  48. jac_client/examples/asset-serving/image-asset/README.md +119 -0
  49. jac_client/examples/asset-serving/image-asset/app.jac +55 -0
  50. jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
  51. jac_client/examples/asset-serving/image-asset/package.json +28 -0
  52. jac_client/examples/asset-serving/image-asset/styles.css +26 -0
  53. jac_client/examples/asset-serving/image-asset/vite.config.js +28 -0
  54. jac_client/examples/asset-serving/import-alias/.babelrc +9 -0
  55. jac_client/examples/asset-serving/import-alias/README.md +83 -0
  56. jac_client/examples/asset-serving/import-alias/app.jac +111 -0
  57. jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
  58. jac_client/examples/asset-serving/import-alias/package.json +28 -0
  59. jac_client/examples/asset-serving/import-alias/vite.config.js +28 -0
  60. jac_client/examples/basic/app.jac +14 -9
  61. jac_client/examples/basic/package.json +1 -1
  62. jac_client/examples/basic/vite.config.js +0 -1
  63. jac_client/examples/basic-auth/package.json +1 -1
  64. jac_client/examples/basic-auth/vite.config.js +0 -1
  65. jac_client/examples/basic-auth-with-router/package.json +1 -1
  66. jac_client/examples/basic-auth-with-router/vite.config.js +0 -1
  67. jac_client/examples/basic-full-stack/package.json +1 -1
  68. jac_client/examples/basic-full-stack/vite.config.js +0 -1
  69. jac_client/examples/css-styling/js-styling/.babelrc +9 -0
  70. jac_client/examples/css-styling/js-styling/README.md +183 -0
  71. jac_client/examples/css-styling/js-styling/app.jac +84 -0
  72. jac_client/examples/css-styling/js-styling/package.json +28 -0
  73. jac_client/examples/css-styling/js-styling/styles.js +100 -0
  74. jac_client/examples/css-styling/js-styling/vite.config.js +27 -0
  75. jac_client/examples/css-styling/material-ui/.babelrc +9 -0
  76. jac_client/examples/css-styling/material-ui/README.md +16 -0
  77. jac_client/examples/css-styling/material-ui/app.jac +122 -0
  78. jac_client/examples/css-styling/material-ui/package.json +32 -0
  79. jac_client/examples/css-styling/material-ui/vite.config.js +27 -0
  80. jac_client/examples/css-styling/pure-css/.babelrc +9 -0
  81. jac_client/examples/css-styling/pure-css/README.md +16 -0
  82. jac_client/examples/css-styling/pure-css/app.jac +64 -0
  83. jac_client/examples/css-styling/pure-css/package.json +28 -0
  84. jac_client/examples/css-styling/pure-css/styles.css +111 -0
  85. jac_client/examples/css-styling/pure-css/vite.config.js +27 -0
  86. jac_client/examples/css-styling/sass-example/.babelrc +9 -0
  87. jac_client/examples/css-styling/sass-example/README.md +16 -0
  88. jac_client/examples/css-styling/sass-example/app.jac +64 -0
  89. jac_client/examples/css-styling/sass-example/package.json +29 -0
  90. jac_client/examples/css-styling/sass-example/styles.scss +153 -0
  91. jac_client/examples/css-styling/sass-example/vite.config.js +27 -0
  92. jac_client/examples/css-styling/styled-components/.babelrc +9 -0
  93. jac_client/examples/css-styling/styled-components/README.md +16 -0
  94. jac_client/examples/css-styling/styled-components/app.jac +71 -0
  95. jac_client/examples/css-styling/styled-components/package.json +29 -0
  96. jac_client/examples/css-styling/styled-components/styled.js +90 -0
  97. jac_client/examples/css-styling/styled-components/vite.config.js +27 -0
  98. jac_client/examples/css-styling/tailwind-example/.babelrc +9 -0
  99. jac_client/examples/css-styling/tailwind-example/README.md +16 -0
  100. jac_client/examples/css-styling/tailwind-example/app.jac +63 -0
  101. jac_client/examples/css-styling/tailwind-example/global.css +1 -0
  102. jac_client/examples/css-styling/tailwind-example/package.json +30 -0
  103. jac_client/examples/css-styling/tailwind-example/vite.config.js +29 -0
  104. jac_client/examples/full-stack-with-auth/app.jac +20 -33
  105. jac_client/examples/full-stack-with-auth/package.json +1 -1
  106. jac_client/examples/full-stack-with-auth/vite.config.js +0 -1
  107. jac_client/examples/little-x/app.jac +327 -218
  108. jac_client/examples/little-x/submit-button.jac +1 -1
  109. jac_client/examples/nested-folders/nested-advance/.babelrc +9 -0
  110. jac_client/examples/nested-folders/nested-advance/ButtonRoot.jac +11 -0
  111. jac_client/examples/nested-folders/nested-advance/README.md +77 -0
  112. jac_client/examples/nested-folders/nested-advance/app.jac +35 -0
  113. jac_client/examples/nested-folders/nested-advance/level1/ButtonSecondL.jac +19 -0
  114. jac_client/examples/nested-folders/nested-advance/level1/Card.jac +43 -0
  115. jac_client/examples/nested-folders/nested-advance/level1/level2/ButtonThirdL.jac +25 -0
  116. jac_client/examples/nested-folders/nested-advance/package.json +29 -0
  117. jac_client/examples/nested-folders/nested-advance/vite.config.js +28 -0
  118. jac_client/examples/nested-folders/nested-basic/.babelrc +9 -0
  119. jac_client/examples/nested-folders/nested-basic/README.md +183 -0
  120. jac_client/examples/nested-folders/nested-basic/app.jac +13 -0
  121. jac_client/examples/nested-folders/nested-basic/app.js +7 -0
  122. jac_client/examples/nested-folders/nested-basic/button.jac +7 -0
  123. jac_client/examples/nested-folders/nested-basic/components/button.jac +7 -0
  124. jac_client/examples/nested-folders/nested-basic/package.json +28 -0
  125. jac_client/examples/nested-folders/nested-basic/vite.config.js +27 -0
  126. jac_client/examples/with-router/app.jac +1 -1
  127. jac_client/examples/with-router/package.json +1 -1
  128. jac_client/examples/with-router/vite.config.js +0 -1
  129. jac_client/plugin/cli.py +7 -2
  130. jac_client/plugin/client.py +68 -5
  131. jac_client/plugin/client_runtime.jac +1 -1
  132. jac_client/plugin/vite_client_bundle.py +162 -14
  133. jac_client/tests/__init__.py +0 -1
  134. jac_client/tests/fixtures/basic-app/app.jac +7 -2
  135. jac_client/tests/fixtures/cl_file/app.cl.jac +48 -0
  136. jac_client/tests/fixtures/cl_file/app.jac +15 -0
  137. jac_client/tests/fixtures/client_app_with_antd/app.jac +14 -8
  138. jac_client/tests/fixtures/js_import/app.jac +19 -15
  139. jac_client/tests/fixtures/js_import/utils.js +0 -1
  140. jac_client/tests/fixtures/package.json +1 -1
  141. jac_client/tests/fixtures/relative_import/app.jac +4 -6
  142. jac_client/tests/fixtures/relative_import/button.jac +7 -6
  143. jac_client/tests/fixtures/spawn_test/app.jac +1 -5
  144. jac_client/tests/fixtures/test_fragments_spread/app.jac +24 -10
  145. jac_client/tests/test_asset_examples.py +322 -0
  146. jac_client/tests/test_cl.py +480 -426
  147. jac_client/tests/test_create_jac_app.py +125 -133
  148. jac_client/tests/test_it.py +329 -0
  149. jac_client/tests/test_nested_file.py +374 -0
  150. {jac_client-0.2.0.dist-info → jac_client-0.2.2.dist-info}/METADATA +2 -2
  151. jac_client-0.2.2.dist-info/RECORD +171 -0
  152. jac_client-0.2.0.dist-info/RECORD +0 -72
  153. {jac_client-0.2.0.dist-info → jac_client-0.2.2.dist-info}/WHEEL +0 -0
  154. {jac_client-0.2.0.dist-info → jac_client-0.2.2.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,348 @@
1
+ # Nested Folder Imports
2
+
3
+ Jac preserves folder structure during compilation, similar to TypeScript transpilation. This allows you to organize code in nested folders and use relative imports across multiple directory levels.
4
+
5
+ ## Folder Structure Preservation
6
+
7
+ When Jac compiles your files, it preserves the folder structure in the `src/` directory:
8
+
9
+ ```
10
+ Source Structure: Compiled Structure:
11
+ my-app/ src/
12
+ ├── app.jac → ├── app.js
13
+ ├── ButtonRoot.jac → ├── ButtonRoot.js
14
+ └── level1/ └── level1/
15
+ ├── ButtonSecondL.jac → ├── ButtonSecondL.js
16
+ ├── Card.jac → ├── Card.js
17
+ └── level2/ └── level2/
18
+ └── ButtonThirdL.jac → └── ButtonThirdL.js
19
+ ```
20
+
21
+ ## Relative Import Syntax
22
+
23
+ Jac uses dot notation for relative imports:
24
+
25
+ - **Single dot (`.`)** - Current directory
26
+ - **Double dot (`..`)** - Parent directory (one level up)
27
+ - **Triple dot (`...`)** - Two levels up
28
+ - **Multiple dots** - Continue going up the directory tree
29
+ - **Dot notation after dots** - Go down into subdirectories (e.g., `.level2`)
30
+
31
+ ## Import Patterns by Directory Level
32
+
33
+ ### Root Level Imports
34
+
35
+ From the root directory, you can import from nested folders:
36
+
37
+ ```jac
38
+ # app.jac (root level)
39
+
40
+ # Import from root
41
+ cl import from .ButtonRoot {
42
+ ButtonRoot
43
+ }
44
+
45
+ # Import from level1
46
+ cl import from .level1.ButtonSecondL {
47
+ ButtonSecondL
48
+ }
49
+
50
+ # Import from level1/level2
51
+ cl import from .level1.level2.ButtonThirdL {
52
+ ButtonThirdL
53
+ }
54
+
55
+ # Import from level1
56
+ cl import from .level1.Card {
57
+ Card
58
+ }
59
+ ```
60
+
61
+ ### Second Level Imports
62
+
63
+ From `level1/`, you can import from root (up) or level2 (down):
64
+
65
+ ```jac
66
+ # level1/ButtonSecondL.jac
67
+
68
+ # Import from root (go up one level with ..)
69
+ cl import from ..ButtonRoot {
70
+ ButtonRoot
71
+ }
72
+ ```
73
+
74
+ ```jac
75
+ # level1/Card.jac
76
+
77
+ # Import from root (go up two levels with ..)
78
+ cl import from ..ButtonRoot {
79
+ ButtonRoot
80
+ }
81
+
82
+ # Import from level2 (go down one level with .level2)
83
+ cl import from .level2.ButtonThirdL {
84
+ ButtonThirdL
85
+ }
86
+ ```
87
+
88
+ ### Third Level Imports
89
+
90
+ From `level1/level2/`, you can import from root or parent levels:
91
+
92
+ ```jac
93
+ # level1/level2/ButtonThirdL.jac
94
+
95
+ # Import from root (go up three levels with ...)
96
+ cl import from ...ButtonRoot {
97
+ ButtonRoot
98
+ }
99
+
100
+ # Import from second level (go up one level with ..)
101
+ cl import from ..ButtonSecondL {
102
+ ButtonSecondL
103
+ }
104
+ ```
105
+
106
+ ## Complete Example
107
+
108
+ Here's a complete example demonstrating nested folder imports:
109
+
110
+ **Project Structure:**
111
+ ```
112
+ nested-advance/
113
+ ├── app.jac # Root entry point
114
+ ├── ButtonRoot.jac # Root level button
115
+ └── level1/
116
+ ├── ButtonSecondL.jac # Second level button
117
+ ├── Card.jac # Card component (imports from root and level2)
118
+ └── level2/
119
+ └── ButtonThirdL.jac # Third level button
120
+ ```
121
+
122
+ **app.jac:**
123
+ ```jac
124
+ cl import from .ButtonRoot {
125
+ ButtonRoot
126
+ }
127
+ cl import from .level1.ButtonSecondL {
128
+ ButtonSecondL
129
+ }
130
+ cl import from .level1.level2.ButtonThirdL {
131
+ ButtonThirdL
132
+ }
133
+ cl import from .level1.Card {
134
+ Card
135
+ }
136
+
137
+ cl def app() -> any {
138
+ return <div>
139
+ <ButtonRoot />
140
+ <ButtonSecondL />
141
+ <ButtonThirdL />
142
+ <Card />
143
+ </div>;
144
+ }
145
+ ```
146
+
147
+ **level1/ButtonSecondL.jac:**
148
+ ```jac
149
+ cl import from ..ButtonRoot {
150
+ ButtonRoot
151
+ }
152
+
153
+ cl def ButtonSecondL() -> any {
154
+ return <div>
155
+ <Button>Second Level</Button>
156
+ <ButtonRoot />
157
+ </div>;
158
+ }
159
+ ```
160
+
161
+ **level1/Card.jac:**
162
+ ```jac
163
+ # Imports from both above (root) and below (level2)
164
+ cl import from ..ButtonRoot {
165
+ ButtonRoot
166
+ }
167
+ cl import from .level2.ButtonThirdL {
168
+ ButtonThirdL
169
+ }
170
+
171
+ cl def Card() -> any {
172
+ return <div>
173
+ <ButtonRoot />
174
+ <ButtonThirdL />
175
+ </div>;
176
+ }
177
+ ```
178
+
179
+ **level1/level2/ButtonThirdL.jac:**
180
+ ```jac
181
+ cl import from ...ButtonRoot {
182
+ ButtonRoot
183
+ }
184
+ cl import from ..ButtonSecondL {
185
+ ButtonSecondL
186
+ }
187
+
188
+ cl def ButtonThirdL() -> any {
189
+ return <div>
190
+ <Button>Third Level</Button>
191
+ <ButtonRoot />
192
+ <ButtonSecondL />
193
+ </div>;
194
+ }
195
+ ```
196
+
197
+ ## Import Path Reference
198
+
199
+ | Your Location | Target Location | Import Path |
200
+ |--------------|----------------|-------------|
201
+ | `app.jac` (root) | `ButtonRoot.jac` (root) | `.ButtonRoot` |
202
+ | `app.jac` (root) | `level1/ButtonSecondL.jac` | `.level1.ButtonSecondL` |
203
+ | `app.jac` (root) | `level1/level2/ButtonThirdL.jac` | `.level1.level2.ButtonThirdL` |
204
+ | `level1/ButtonSecondL.jac` | `ButtonRoot.jac` (root) | `..ButtonRoot` |
205
+ | `level1/Card.jac` | `ButtonRoot.jac` (root) | `..ButtonRoot` |
206
+ | `level1/Card.jac` | `level2/ButtonThirdL.jac` | `.level2.ButtonThirdL` |
207
+ | `level1/level2/ButtonThirdL.jac` | `ButtonRoot.jac` (root) | `...ButtonRoot` |
208
+ | `level1/level2/ButtonThirdL.jac` | `level1/ButtonSecondL.jac` | `..ButtonSecondL` |
209
+
210
+ ## Benefits of Nested Folder Structure
211
+
212
+ 1. **Relative imports work correctly**: Folder structure is preserved, so imports resolve properly
213
+ 2. **No file name conflicts**: Files with the same name in different folders don't overwrite each other
214
+ 3. **Familiar structure**: Organize code in nested folders just like in TypeScript/JavaScript projects
215
+ 4. **Consistent with modern tooling**: Matches the behavior of TypeScript, Babel, and other transpilers
216
+ 5. **Scalable organization**: Organize large applications into logical folder hierarchies
217
+
218
+ ## Best Practices for Nested Folders
219
+
220
+ 1. **Organize by feature or component type**: Group related files together
221
+ ```
222
+ components/
223
+ ├── ui/
224
+ │ ├── Button.jac
225
+ │ └── Card.jac
226
+ ├── layout/
227
+ │ ├── Header.jac
228
+ │ └── Footer.jac
229
+ └── features/
230
+ ├── TodoList.jac
231
+ └── TodoItem.jac
232
+ ```
233
+
234
+ 2. **Use consistent naming**: Keep file names descriptive and consistent
235
+ 3. **Limit nesting depth**: Avoid going too deep (3-4 levels is usually sufficient)
236
+ 4. **Document import patterns**: Comment complex import relationships
237
+
238
+ ## Common Patterns
239
+
240
+ ### Pattern 1: Component Library Structure
241
+ ```
242
+ components/
243
+ ├── ui/
244
+ │ ├── Button.jac
245
+ │ └── Input.jac
246
+ ├── forms/
247
+ │ ├── LoginForm.jac
248
+ │ └── SignupForm.jac
249
+ └── layout/
250
+ ├── Header.jac
251
+ └── Sidebar.jac
252
+ ```
253
+
254
+ **Usage:**
255
+ ```jac
256
+ # From root
257
+ cl import from .components.ui.Button { Button }
258
+ cl import from .components.forms.LoginForm { LoginForm }
259
+
260
+ # From components/ui/Button.jac importing from forms
261
+ cl import from ..forms.LoginForm { LoginForm }
262
+ ```
263
+
264
+ ### Pattern 2: Feature-Based Structure
265
+ ```
266
+ features/
267
+ ├── auth/
268
+ │ ├── Login.jac
269
+ │ └── Signup.jac
270
+ ├── todos/
271
+ │ ├── TodoList.jac
272
+ │ └── TodoItem.jac
273
+ └── dashboard/
274
+ ├── Dashboard.jac
275
+ └── Stats.jac
276
+ ```
277
+
278
+ **Usage:**
279
+ ```jac
280
+ # From root
281
+ cl import from .features.auth.Login { Login }
282
+ cl import from .features.todos.TodoList { TodoList }
283
+
284
+ # From features/auth/Login.jac importing from todos
285
+ cl import from ..todos.TodoList { TodoList }
286
+ ```
287
+
288
+ ### Pattern 3: Mixed Structure
289
+ ```
290
+ app.jac # Root entry
291
+ components/
292
+ ├── ui/
293
+ │ └── Button.jac
294
+ utils/
295
+ ├── helpers/
296
+ │ └── format.jac
297
+ hooks/
298
+ └── useCounter.jac
299
+ ```
300
+
301
+ **Usage:**
302
+ ```jac
303
+ # From app.jac
304
+ cl import from .components.ui.Button { Button }
305
+ cl import from .utils.helpers.format { capitalize }
306
+ cl import from .hooks.useCounter { useCounter }
307
+
308
+ # From components/ui/Button.jac
309
+ cl import from ...utils.helpers.format { capitalize }
310
+ ```
311
+
312
+ ## Troubleshooting
313
+
314
+ ### Import Not Found
315
+ - Verify the file exists at the expected path
316
+ - Check that the relative path matches the folder structure
317
+ - Ensure file extension is `.jac` (not `.cl.jac` for imports)
318
+
319
+ ### Wrong Import Path
320
+ - Count the directory levels between source and target
321
+ - Use `..` for each level up, `.folder` for each level down
322
+ - Start with `.` for current directory imports
323
+
324
+ ### File Name Conflicts
325
+ - Use nested folders to avoid conflicts
326
+ - Files with the same name in different folders won't conflict
327
+ - Folder structure is preserved in compiled output
328
+
329
+ ## Examples
330
+
331
+ Complete working examples demonstrating nested folder imports:
332
+
333
+ - [`nested-basic/`](../../examples/nested-folders/nested-basic/) - Simple nested folder structure
334
+ - [`nested-advance/`](../../examples/nested-folders/nested-advance/) - Advanced multi-level nesting
335
+
336
+ Run any example:
337
+
338
+ ```bash
339
+ cd jac-client/jac_client/examples/nested-folders/<example-name>
340
+ npm install
341
+ jac serve app.jac
342
+ ```
343
+
344
+ ## Related Documentation
345
+
346
+ - [Backend/Frontend Separation](backend-frontend.md)
347
+ - [Import System](../imports.md)
348
+ - [File System Organization](intro.md)
@@ -15,19 +15,19 @@ Traditionally, you'd need:
15
15
  - **SQL** for database
16
16
  - **REST APIs** to connect them
17
17
 
18
- With **Jac**, you write **everything in one language**, in **one file**! 🚀
18
+ With **Jac**, you write **everything in one language**, in **one file**!
19
19
 
20
20
  ## What You'll Build
21
21
 
22
22
  By the end of this guide, you'll have a fully functional Todo app with:
23
23
 
24
- -**Beautiful UI** - Modern, responsive interface
25
- -**User Authentication** - Signup and login
26
- -**Protected Routes** - Private pages only for logged-in users
27
- -**Full CRUD** - Create, Read, Update, Delete todos
28
- -**Real Backend** - Data persists even after refresh
29
- -**Filtering** - View all, active, or completed todos
30
- -**Multiple Pages** - Routing without page reloads
24
+ - **Beautiful UI** - Modern, responsive interface
25
+ - **User Authentication** - Signup and login
26
+ - **Protected Routes** - Private pages only for logged-in users
27
+ - **Full CRUD** - Create, Read, Update, Delete todos
28
+ - **Real Backend** - Data persists even after refresh
29
+ - **Filtering** - View all, active, or completed todos
30
+ - **Multiple Pages** - Routing without page reloads
31
31
 
32
32
  All of this in approximately **735 lines of Jac code**!
33
33
 
@@ -67,8 +67,8 @@ pip install jac-client
67
67
 
68
68
  Each step builds on the previous one, gradually creating the complete app. Every step has **two parts**:
69
69
 
70
- 1. **🏗️ Part 1: Building the App** - Hands-on coding, building the actual app
71
- 2. **💡 Part 2: Understanding the Concepts** - Optional deeper knowledge
70
+ 1. ** Part 1: Building the App** - Hands-on coding, building the actual app
71
+ 2. ** Part 2: Understanding the Concepts** - Optional deeper knowledge
72
72
 
73
73
  **Want to just build?** Follow only Part 1 of each step and skip all Part 2 sections. You'll still have a working app!
74
74
 
@@ -112,6 +112,4 @@ We'll build the app in 11 progressive steps:
112
112
 
113
113
  Let's build your first full-stack app!
114
114
 
115
- 👉 **[Continue to Step 1: Project Setup](./step-01-setup.md)**
116
-
117
-
115
+ **[Continue to Step 1: Project Setup](./step-01-setup.md)**
@@ -1,12 +1,12 @@
1
1
  # Step 1: Project Setup
2
2
 
3
- > **💡 Quick Tip:** Each step has two parts. **Part 1** shows you what to build. **Part 2** explains why it works. Want to just build? Skip all Part 2 sections!
3
+ > ** Quick Tip:** Each step has two parts. **Part 1** shows you what to build. **Part 2** explains why it works. Want to just build? Skip all Part 2 sections!
4
4
 
5
5
  In this first step, you'll create your Jac project and understand the basic file structure.
6
6
 
7
7
  ---
8
8
 
9
- ## 🏗️ Part 1: Building the App
9
+ ## Part 1: Building the App
10
10
 
11
11
  ### Step 1.1: Create Your Project
12
12
 
@@ -78,15 +78,15 @@ Open your browser and go to:
78
78
  http://localhost:8000/page/app
79
79
  ```
80
80
 
81
- You should see "Hello, Jac!" and "My first full-stack app" 🎉
81
+ You should see "Hello, Jac!" and "My first full-stack app"
82
82
 
83
83
  ---
84
84
 
85
- **⏭️ Want to skip the theory?** Jump to [Step 2: First Component](./step-02-components.md)
85
+ **⏭ Want to skip the theory?** Jump to [Step 2: First Component](./step-02-components.md)
86
86
 
87
87
  ---
88
88
 
89
- ## 💡 Part 2: Understanding the Concepts
89
+ ## Part 2: Understanding the Concepts
90
90
 
91
91
  ### What is `cl { ... }`?
92
92
 
@@ -99,6 +99,7 @@ cl {
99
99
  ```
100
100
 
101
101
  Think of it like this:
102
+
102
103
  - Code **inside** `cl { }` → Runs in the browser (frontend)
103
104
  - Code **outside** `cl { }` → Runs on the server (backend)
104
105
 
@@ -113,6 +114,7 @@ def app() -> any {
113
114
  ```
114
115
 
115
116
  **Requirements:**
117
+
116
118
  - Must be named `app` (by convention)
117
119
  - Must return JSX (HTML-like syntax)
118
120
  - Located inside `cl { }` block
@@ -142,19 +144,22 @@ return <div>
142
144
  ```
143
145
 
144
146
  **Key rules:**
147
+
145
148
  1. Must have **one root element**
149
+
146
150
  ```jac
147
- #Correct
151
+ # Correct
148
152
  return <div><h1>Title</h1><p>Text</p></div>;
149
153
 
150
- #Wrong (two root elements)
154
+ # Wrong (two root elements)
151
155
  return <h1>Title</h1><p>Text</p>;
152
156
  ```
153
157
 
154
158
  2. Self-closing tags need `/`
159
+
155
160
  ```jac
156
- <img src="photo.jpg" /> #Correct
157
- <img src="photo.jpg"> #Wrong
161
+ <img src="photo.jpg" /> # Correct
162
+ <img src="photo.jpg"> # Wrong
158
163
  ```
159
164
 
160
165
  3. Use `{}` to insert Jac code
@@ -190,22 +195,23 @@ But for this tutorial, we'll keep everything in one file for simplicity.
190
195
 
191
196
  ---
192
197
 
193
- ## What You've Learned
198
+ ## What You've Learned
194
199
 
195
- - How to create a Jac project
196
- - Project structure basics
197
- - What `cl { }` means (client-side code)
198
- - The `def app()` entry point
199
- - JSX basics (HTML in code)
200
- - Running your app with `jac serve`
200
+ - How to create a Jac project
201
+ - Project structure basics
202
+ - What `cl { }` means (client-side code)
203
+ - The `def app()` entry point
204
+ - JSX basics (HTML in code)
205
+ - Running your app with `jac serve`
201
206
 
202
207
  ---
203
208
 
204
- ## 🐛 Common Issues
209
+ ## Common Issues
205
210
 
206
211
  ### Issue: `jac: command not found`
207
212
 
208
213
  **Solution**: Install jac-client:
214
+
209
215
  ```bash
210
216
  pip install jac-client
211
217
  ```
@@ -213,14 +219,17 @@ pip install jac-client
213
219
  ### Issue: Port 8000 already in use
214
220
 
215
221
  **Solution**: Use a different port:
222
+
216
223
  ```bash
217
224
  jac serve app.jac --port 8080
218
225
  ```
226
+
219
227
  Then visit `http://localhost:8080/page/app`
220
228
 
221
229
  ### Issue: Blank page in browser
222
230
 
223
231
  **Check:**
232
+
224
233
  - Did you visit `/page/app` (not just `/`)?
225
234
  - Check terminal for errors
226
235
  - Make sure `app()` has a `return` statement
@@ -228,13 +237,14 @@ Then visit `http://localhost:8080/page/app`
228
237
  ### Issue: Changes not showing
229
238
 
230
239
  **Solution**:
240
+
231
241
  - Stop the server (Ctrl+C)
232
242
  - Restart: `jac serve app.jac`
233
243
  - Refresh browser
234
244
 
235
245
  ---
236
246
 
237
- ## 🎯 Quick Exercise
247
+ ## Quick Exercise
238
248
 
239
249
  Before moving on, try changing the text:
240
250
 
@@ -253,8 +263,8 @@ Save, refresh your browser, and see the changes!
253
263
 
254
264
  ---
255
265
 
256
- ## ➡️ Next Step
266
+ ## Next Step
257
267
 
258
268
  Great! You have a running Jac app. Now let's learn about **components** - the building blocks of any UI.
259
269
 
260
- 👉 **[Continue to Step 2: First Component](./step-02-components.md)**
270
+ **[Continue to Step 2: First Component](./step-02-components.md)**
@@ -1,12 +1,12 @@
1
1
  # Step 2: First Component
2
2
 
3
- > **💡 Quick Tip:** Each step has two parts. **Part 1** shows you what to build. **Part 2** explains why it works. Want to just build? Skip all Part 2 sections!
3
+ > ** Quick Tip:** Each step has two parts. **Part 1** shows you what to build. **Part 2** explains why it works. Want to just build? Skip all Part 2 sections!
4
4
 
5
5
  In this step, you'll create your first reusable component - a **TodoItem** that displays a single todo.
6
6
 
7
7
  ---
8
8
 
9
- ## 🏗️ Part 1: Building the App
9
+ ## Part 1: Building the App
10
10
 
11
11
  ### Step 2.1: Create a TodoItem Component
12
12
 
@@ -119,11 +119,11 @@ cl {
119
119
 
120
120
  ---
121
121
 
122
- **⏭️ Want to skip the theory?** Jump to [Step 3: Styling](./step-03-styling.md)
122
+ **⏭ Want to skip the theory?** Jump to [Step 3: Styling](./step-03-styling.md)
123
123
 
124
124
  ---
125
125
 
126
- ## 💡 Part 2: Understanding the Concepts
126
+ ## Part 2: Understanding the Concepts
127
127
 
128
128
  ### What is a Component?
129
129
 
@@ -182,12 +182,12 @@ If there's a bug in how todos display, you know to check `TodoItem`.
182
182
  **1. Use PascalCase** (first letter capitalized)
183
183
 
184
184
  ```jac
185
- #Correct
185
+ # Correct
186
186
  def TodoItem() -> any { ... }
187
187
  def UserProfile() -> any { ... }
188
188
  def NavigationBar() -> any { ... }
189
189
 
190
- #Wrong
190
+ # Wrong
191
191
  def todoItem() -> any { ... } # camelCase
192
192
  def user_profile() -> any { ... } # snake_case
193
193
  def navigation-bar() -> any { ... } # kebab-case
@@ -196,12 +196,12 @@ def navigation-bar() -> any { ... } # kebab-case
196
196
  **2. Name describes what it does**
197
197
 
198
198
  ```jac
199
- #Good names
199
+ # Good names
200
200
  def TodoItem() -> any { ... }
201
201
  def LoginForm() -> any { ... }
202
202
  def ProductCard() -> any { ... }
203
203
 
204
- #Bad names
204
+ # Bad names
205
205
  def Component1() -> any { ... }
206
206
  def Thing() -> any { ... }
207
207
  def X() -> any { ... }
@@ -226,14 +226,14 @@ def TodoItem(props: any) -> any {
226
226
  **Important**: In React (which Jac uses), components receive props as a **single object**, not individual parameters.
227
227
 
228
228
  ```jac
229
- #Correct way
229
+ # Correct way
230
230
  def TodoItem(props: any) -> any {
231
231
  let text = props.text;
232
232
  let done = props.done;
233
233
  # ...
234
234
  }
235
235
 
236
- #Wrong way (won't work)
236
+ # Wrong way (won't work)
237
237
  def TodoItem(text: str, done: bool) -> any {
238
238
  # This doesn't work in React!
239
239
  }
@@ -328,19 +328,19 @@ let myText = "Learn Jac";
328
328
 
329
329
  ---
330
330
 
331
- ##What You've Learned
331
+ ## What You've Learned
332
332
 
333
- -Components are functions that return UI
334
- -How to create a component
335
- -PascalCase naming convention
336
- -Passing data to components with props
337
- -Receiving props as a single object
338
- -Composing components (nesting)
339
- -Organizing app into multiple components
333
+ - Components are functions that return UI
334
+ - How to create a component
335
+ - PascalCase naming convention
336
+ - Passing data to components with props
337
+ - Receiving props as a single object
338
+ - Composing components (nesting)
339
+ - Organizing app into multiple components
340
340
 
341
341
  ---
342
342
 
343
- ## 🐛 Common Issues
343
+ ## Common Issues
344
344
 
345
345
  ### Issue: Component not showing up
346
346
 
@@ -354,12 +354,12 @@ let myText = "Learn Jac";
354
354
  **Cause**: Using individual parameters instead of props object
355
355
 
356
356
  ```jac
357
- #Wrong
357
+ # Wrong
358
358
  def TodoItem(text: str, done: bool) -> any {
359
359
  # ...
360
360
  }
361
361
 
362
- #Correct
362
+ # Correct
363
363
  def TodoItem(props: any) -> any {
364
364
  let text = props.text;
365
365
  # ...
@@ -385,7 +385,7 @@ def TodoItem(props: any) -> any {
385
385
 
386
386
  ---
387
387
 
388
- ## 🎯 Quick Exercise
388
+ ## Quick Exercise
389
389
 
390
390
  Try adding a new component:
391
391
 
@@ -409,8 +409,8 @@ def app() -> any {
409
409
 
410
410
  ---
411
411
 
412
- ## ➡️ Next Step
412
+ ## Next Step
413
413
 
414
414
  Great! You can now create and organize components. But they look plain. Let's make them beautiful with **styling**!
415
415
 
416
- 👉 **[Continue to Step 3: Styling](./step-03-styling.md)**
416
+ **[Continue to Step 3: Styling](./step-03-styling.md)**