jac-client 0.2.0__py3-none-any.whl → 0.2.3__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.
- jac_client/docs/README.md +50 -20
- jac_client/docs/advanced-state.md +13 -14
- jac_client/docs/asset-serving/intro.md +209 -0
- jac_client/docs/assets/pipe_line-v2.svg +32 -0
- jac_client/docs/file-system/app.jac.md +121 -0
- jac_client/docs/file-system/backend-frontend.md +217 -0
- jac_client/docs/file-system/intro.md +72 -0
- jac_client/docs/file-system/nested-imports.md +348 -0
- jac_client/docs/guide-example/intro.md +11 -13
- jac_client/docs/guide-example/step-01-setup.md +30 -20
- jac_client/docs/guide-example/step-02-components.md +24 -24
- jac_client/docs/guide-example/step-03-styling.md +24 -24
- jac_client/docs/guide-example/step-04-todo-ui.md +17 -17
- jac_client/docs/guide-example/step-05-local-state.md +23 -23
- jac_client/docs/guide-example/step-06-events.md +23 -24
- jac_client/docs/guide-example/step-07-effects.md +27 -28
- jac_client/docs/guide-example/step-08-walkers.md +23 -23
- jac_client/docs/guide-example/step-09-authentication.md +18 -18
- jac_client/docs/guide-example/step-10-routing.md +20 -21
- jac_client/docs/guide-example/step-11-final.md +34 -35
- jac_client/docs/imports.md +4 -5
- jac_client/docs/lifecycle-hooks.md +12 -13
- jac_client/docs/routing.md +21 -22
- jac_client/docs/styling/intro.md +249 -0
- jac_client/docs/styling/js-styling.md +367 -0
- jac_client/docs/styling/material-ui.md +341 -0
- jac_client/docs/styling/pure-css.md +299 -0
- jac_client/docs/styling/sass.md +403 -0
- jac_client/docs/styling/styled-components.md +395 -0
- jac_client/docs/styling/tailwind.md +298 -0
- jac_client/examples/all-in-one/.babelrc +9 -0
- jac_client/examples/all-in-one/README.md +16 -0
- jac_client/examples/all-in-one/app.jac +426 -0
- jac_client/examples/all-in-one/assets/burger.png +0 -0
- jac_client/examples/all-in-one/button.jac +7 -0
- jac_client/examples/all-in-one/components/button.jac +7 -0
- jac_client/examples/all-in-one/package.json +29 -0
- jac_client/examples/all-in-one/styles.css +26 -0
- jac_client/examples/all-in-one/vite.config.js +28 -0
- jac_client/examples/asset-serving/css-with-image/.babelrc +9 -0
- jac_client/examples/asset-serving/css-with-image/README.md +91 -0
- jac_client/examples/asset-serving/css-with-image/app.jac +88 -0
- jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
- jac_client/examples/asset-serving/css-with-image/package.json +28 -0
- jac_client/examples/asset-serving/css-with-image/styles.css +26 -0
- jac_client/examples/asset-serving/css-with-image/vite.config.js +28 -0
- jac_client/examples/asset-serving/image-asset/.babelrc +9 -0
- jac_client/examples/asset-serving/image-asset/README.md +119 -0
- jac_client/examples/asset-serving/image-asset/app.jac +55 -0
- jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
- jac_client/examples/asset-serving/image-asset/package.json +28 -0
- jac_client/examples/asset-serving/image-asset/styles.css +26 -0
- jac_client/examples/asset-serving/image-asset/vite.config.js +28 -0
- jac_client/examples/asset-serving/import-alias/.babelrc +9 -0
- jac_client/examples/asset-serving/import-alias/README.md +83 -0
- jac_client/examples/asset-serving/import-alias/app.jac +111 -0
- jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
- jac_client/examples/asset-serving/import-alias/package.json +28 -0
- jac_client/examples/asset-serving/import-alias/vite.config.js +28 -0
- jac_client/examples/basic/app.jac +14 -9
- jac_client/examples/basic/package.json +1 -1
- jac_client/examples/basic/vite.config.js +0 -1
- jac_client/examples/basic-auth/package.json +1 -1
- jac_client/examples/basic-auth/vite.config.js +0 -1
- jac_client/examples/basic-auth-with-router/package.json +1 -1
- jac_client/examples/basic-auth-with-router/vite.config.js +0 -1
- jac_client/examples/basic-full-stack/package.json +1 -1
- jac_client/examples/basic-full-stack/vite.config.js +0 -1
- jac_client/examples/css-styling/js-styling/.babelrc +9 -0
- jac_client/examples/css-styling/js-styling/README.md +183 -0
- jac_client/examples/css-styling/js-styling/app.jac +84 -0
- jac_client/examples/css-styling/js-styling/package.json +28 -0
- jac_client/examples/css-styling/js-styling/styles.js +100 -0
- jac_client/examples/css-styling/js-styling/vite.config.js +27 -0
- jac_client/examples/css-styling/material-ui/.babelrc +9 -0
- jac_client/examples/css-styling/material-ui/README.md +16 -0
- jac_client/examples/css-styling/material-ui/app.jac +122 -0
- jac_client/examples/css-styling/material-ui/package.json +32 -0
- jac_client/examples/css-styling/material-ui/vite.config.js +27 -0
- jac_client/examples/css-styling/pure-css/.babelrc +9 -0
- jac_client/examples/css-styling/pure-css/README.md +16 -0
- jac_client/examples/css-styling/pure-css/app.jac +64 -0
- jac_client/examples/css-styling/pure-css/package.json +28 -0
- jac_client/examples/css-styling/pure-css/styles.css +111 -0
- jac_client/examples/css-styling/pure-css/vite.config.js +27 -0
- jac_client/examples/css-styling/sass-example/.babelrc +9 -0
- jac_client/examples/css-styling/sass-example/README.md +16 -0
- jac_client/examples/css-styling/sass-example/app.jac +64 -0
- jac_client/examples/css-styling/sass-example/package.json +29 -0
- jac_client/examples/css-styling/sass-example/styles.scss +153 -0
- jac_client/examples/css-styling/sass-example/vite.config.js +27 -0
- jac_client/examples/css-styling/styled-components/.babelrc +9 -0
- jac_client/examples/css-styling/styled-components/README.md +16 -0
- jac_client/examples/css-styling/styled-components/app.jac +71 -0
- jac_client/examples/css-styling/styled-components/package.json +29 -0
- jac_client/examples/css-styling/styled-components/styled.js +90 -0
- jac_client/examples/css-styling/styled-components/vite.config.js +27 -0
- jac_client/examples/css-styling/tailwind-example/.babelrc +9 -0
- jac_client/examples/css-styling/tailwind-example/README.md +16 -0
- jac_client/examples/css-styling/tailwind-example/app.jac +63 -0
- jac_client/examples/css-styling/tailwind-example/global.css +1 -0
- jac_client/examples/css-styling/tailwind-example/package.json +30 -0
- jac_client/examples/css-styling/tailwind-example/vite.config.js +29 -0
- jac_client/examples/full-stack-with-auth/app.jac +20 -33
- jac_client/examples/full-stack-with-auth/package.json +1 -1
- jac_client/examples/full-stack-with-auth/vite.config.js +0 -1
- jac_client/examples/little-x/app.jac +327 -218
- jac_client/examples/little-x/submit-button.jac +1 -1
- jac_client/examples/nested-folders/nested-advance/.babelrc +9 -0
- jac_client/examples/nested-folders/nested-advance/ButtonRoot.jac +11 -0
- jac_client/examples/nested-folders/nested-advance/README.md +77 -0
- jac_client/examples/nested-folders/nested-advance/app.jac +35 -0
- jac_client/examples/nested-folders/nested-advance/level1/ButtonSecondL.jac +19 -0
- jac_client/examples/nested-folders/nested-advance/level1/Card.jac +43 -0
- jac_client/examples/nested-folders/nested-advance/level1/level2/ButtonThirdL.jac +25 -0
- jac_client/examples/nested-folders/nested-advance/package.json +29 -0
- jac_client/examples/nested-folders/nested-advance/vite.config.js +28 -0
- jac_client/examples/nested-folders/nested-basic/.babelrc +9 -0
- jac_client/examples/nested-folders/nested-basic/README.md +183 -0
- jac_client/examples/nested-folders/nested-basic/app.jac +13 -0
- jac_client/examples/nested-folders/nested-basic/app.js +7 -0
- jac_client/examples/nested-folders/nested-basic/button.jac +7 -0
- jac_client/examples/nested-folders/nested-basic/components/button.jac +7 -0
- jac_client/examples/nested-folders/nested-basic/package.json +28 -0
- jac_client/examples/nested-folders/nested-basic/vite.config.js +27 -0
- jac_client/examples/with-router/app.jac +1 -1
- jac_client/examples/with-router/package.json +1 -1
- jac_client/examples/with-router/vite.config.js +0 -1
- jac_client/plugin/cli.py +7 -2
- jac_client/plugin/client.py +68 -5
- jac_client/plugin/client_runtime.jac +1 -1
- jac_client/plugin/vite_client_bundle.py +162 -14
- jac_client/tests/__init__.py +0 -1
- jac_client/tests/fixtures/basic-app/app.jac +7 -2
- jac_client/tests/fixtures/cl_file/app.cl.jac +48 -0
- jac_client/tests/fixtures/cl_file/app.jac +15 -0
- jac_client/tests/fixtures/client_app_with_antd/app.jac +14 -8
- jac_client/tests/fixtures/js_import/app.jac +19 -15
- jac_client/tests/fixtures/js_import/utils.js +0 -1
- jac_client/tests/fixtures/package.json +1 -1
- jac_client/tests/fixtures/relative_import/app.jac +4 -6
- jac_client/tests/fixtures/relative_import/button.jac +7 -6
- jac_client/tests/fixtures/spawn_test/app.jac +1 -5
- jac_client/tests/fixtures/test_fragments_spread/app.jac +24 -10
- jac_client/tests/test_asset_examples.py +322 -0
- jac_client/tests/test_cl.py +480 -426
- jac_client/tests/test_create_jac_app.py +125 -133
- jac_client/tests/test_it.py +329 -0
- jac_client/tests/test_nested_file.py +374 -0
- {jac_client-0.2.0.dist-info → jac_client-0.2.3.dist-info}/METADATA +11 -3
- jac_client-0.2.3.dist-info/RECORD +171 -0
- jac_client-0.2.0.dist-info/RECORD +0 -72
- {jac_client-0.2.0.dist-info → jac_client-0.2.3.dist-info}/WHEEL +0 -0
- {jac_client-0.2.0.dist-info → jac_client-0.2.3.dist-info}/entry_points.txt +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Step 8: Backend with Walkers
|
|
2
2
|
|
|
3
|
-
>
|
|
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 add a **real backend** to your app using walkers - so your todos are stored on a server!
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Part 1: Building the App
|
|
10
10
|
|
|
11
11
|
### Step 8.1: Define the Todo Node
|
|
12
12
|
|
|
@@ -231,15 +231,15 @@ When rendering todos, use `_jac_id` instead of custom id:
|
|
|
231
231
|
1. Add some todos
|
|
232
232
|
2. Check/uncheck them
|
|
233
233
|
3. Delete some
|
|
234
|
-
4. **Refresh the page** - your todos persist!
|
|
234
|
+
4. **Refresh the page** - your todos persist!
|
|
235
235
|
|
|
236
236
|
---
|
|
237
237
|
|
|
238
|
-
|
|
238
|
+
**⏭ Want to skip the theory?** Jump to [Step 9: Authentication](./step-09-authentication.md)
|
|
239
239
|
|
|
240
240
|
---
|
|
241
241
|
|
|
242
|
-
##
|
|
242
|
+
## Part 2: Understanding the Concepts
|
|
243
243
|
|
|
244
244
|
### What Are Walkers?
|
|
245
245
|
|
|
@@ -422,28 +422,28 @@ useEffect(lambda -> None {
|
|
|
422
422
|
|
|
423
423
|
---
|
|
424
424
|
|
|
425
|
-
##
|
|
425
|
+
## What You've Learned
|
|
426
426
|
|
|
427
|
-
-
|
|
428
|
-
-
|
|
429
|
-
-
|
|
430
|
-
-
|
|
431
|
-
-
|
|
432
|
-
-
|
|
433
|
-
-
|
|
434
|
-
-
|
|
435
|
-
-
|
|
427
|
+
- What walkers are (backend functions)
|
|
428
|
+
- How to define data models with nodes
|
|
429
|
+
- Creating walkers for CRUD operations
|
|
430
|
+
- Calling walkers from frontend with `spawn`
|
|
431
|
+
- Graph traversal (`-->`, `` `?Node ``)
|
|
432
|
+
- Creating node connections (`++>`)
|
|
433
|
+
- Reporting data to frontend
|
|
434
|
+
- Using `_jac_id` for node references
|
|
435
|
+
- Data persistence on the server
|
|
436
436
|
|
|
437
437
|
---
|
|
438
438
|
|
|
439
|
-
##
|
|
439
|
+
## Common Issues
|
|
440
440
|
|
|
441
441
|
### Issue: Walker not found
|
|
442
442
|
|
|
443
443
|
**Check:** Is the walker defined OUTSIDE the `cl { }` block?
|
|
444
444
|
|
|
445
445
|
```jac
|
|
446
|
-
#
|
|
446
|
+
# Correct
|
|
447
447
|
walker read_todos {
|
|
448
448
|
# ...
|
|
449
449
|
}
|
|
@@ -452,7 +452,7 @@ cl {
|
|
|
452
452
|
# frontend code
|
|
453
453
|
}
|
|
454
454
|
|
|
455
|
-
#
|
|
455
|
+
# Wrong
|
|
456
456
|
cl {
|
|
457
457
|
walker read_todos { # Can't define walkers in frontend!
|
|
458
458
|
# ...
|
|
@@ -465,12 +465,12 @@ cl {
|
|
|
465
465
|
**Check:** Did you call `report` in your walker?
|
|
466
466
|
|
|
467
467
|
```jac
|
|
468
|
-
#
|
|
468
|
+
# Wrong - no report
|
|
469
469
|
can read with `root entry {
|
|
470
470
|
visit [-->(`?Todo)];
|
|
471
471
|
}
|
|
472
472
|
|
|
473
|
-
#
|
|
473
|
+
# Correct - report in Todo entry
|
|
474
474
|
can report_todos with Todo entry {
|
|
475
475
|
report here;
|
|
476
476
|
}
|
|
@@ -497,7 +497,7 @@ if result.reports and result.reports.length > 0 {
|
|
|
497
497
|
|
|
498
498
|
---
|
|
499
499
|
|
|
500
|
-
##
|
|
500
|
+
## Quick Exercise
|
|
501
501
|
|
|
502
502
|
Try adding a walker to clear all completed todos:
|
|
503
503
|
|
|
@@ -525,10 +525,10 @@ async def clearCompleted() -> None {
|
|
|
525
525
|
|
|
526
526
|
---
|
|
527
527
|
|
|
528
|
-
##
|
|
528
|
+
## Next Step
|
|
529
529
|
|
|
530
530
|
Excellent! Your app now has a real backend. But there's a problem: **everyone can see everyone's todos!**
|
|
531
531
|
|
|
532
532
|
In the next step, we'll add **authentication** to make your app secure and private!
|
|
533
533
|
|
|
534
|
-
|
|
534
|
+
**[Continue to Step 9: Authentication](./step-09-authentication.md)**
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Step 9: Adding Authentication
|
|
2
2
|
|
|
3
|
-
>
|
|
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 add user authentication so each person has their own private todos!
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Part 1: Building the App
|
|
10
10
|
|
|
11
11
|
### Step 9.1: Import Authentication Functions
|
|
12
12
|
|
|
@@ -313,11 +313,11 @@ def TodosPage() -> any {
|
|
|
313
313
|
|
|
314
314
|
---
|
|
315
315
|
|
|
316
|
-
|
|
316
|
+
**⏭ Want to skip the theory?** Jump to [Step 10: Routing](./step-10-routing.md)
|
|
317
317
|
|
|
318
318
|
---
|
|
319
319
|
|
|
320
|
-
##
|
|
320
|
+
## Part 2: Understanding the Concepts
|
|
321
321
|
|
|
322
322
|
### What is Authentication?
|
|
323
323
|
|
|
@@ -506,21 +506,21 @@ await jacLogin("alice", "password123");
|
|
|
506
506
|
|
|
507
507
|
---
|
|
508
508
|
|
|
509
|
-
##
|
|
509
|
+
## What You've Learned
|
|
510
510
|
|
|
511
|
-
-
|
|
512
|
-
-
|
|
513
|
-
-
|
|
514
|
-
-
|
|
515
|
-
-
|
|
516
|
-
-
|
|
517
|
-
-
|
|
518
|
-
-
|
|
519
|
-
-
|
|
511
|
+
- What authentication is and why it's important
|
|
512
|
+
- Using `jacSignup` to create accounts
|
|
513
|
+
- Using `jacLogin` to log users in
|
|
514
|
+
- Using `jacLogout` to log users out
|
|
515
|
+
- Using `jacIsLoggedIn` to check auth status
|
|
516
|
+
- Creating login and signup forms
|
|
517
|
+
- Handling form submission
|
|
518
|
+
- Protecting pages with auth checks
|
|
519
|
+
- User isolation (each user sees only their data)
|
|
520
520
|
|
|
521
521
|
---
|
|
522
522
|
|
|
523
|
-
##
|
|
523
|
+
## Common Issues
|
|
524
524
|
|
|
525
525
|
### Issue: "Signup failed"
|
|
526
526
|
|
|
@@ -552,7 +552,7 @@ await jacLogin("alice", "password123");
|
|
|
552
552
|
|
|
553
553
|
---
|
|
554
554
|
|
|
555
|
-
##
|
|
555
|
+
## Quick Exercise
|
|
556
556
|
|
|
557
557
|
Try adding a "Remember me" message:
|
|
558
558
|
|
|
@@ -577,10 +577,10 @@ def LoginPage() -> any {
|
|
|
577
577
|
|
|
578
578
|
---
|
|
579
579
|
|
|
580
|
-
##
|
|
580
|
+
## Next Step
|
|
581
581
|
|
|
582
582
|
Great! You now have authentication, but you're still showing only one page at a time.
|
|
583
583
|
|
|
584
584
|
In the next step, we'll add **routing** so users can navigate between login, signup, and todos pages!
|
|
585
585
|
|
|
586
|
-
|
|
586
|
+
**[Continue to Step 10: Routing](./step-10-routing.md)**
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Step 10: Adding Routing
|
|
2
2
|
|
|
3
|
-
>
|
|
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 add multiple pages to your app so users can navigate between login, signup, and todos!
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Part 1: Building the App
|
|
10
10
|
|
|
11
11
|
### Step 10.1: Import Routing Components
|
|
12
12
|
|
|
@@ -237,11 +237,11 @@ def app() -> any {
|
|
|
237
237
|
|
|
238
238
|
---
|
|
239
239
|
|
|
240
|
-
|
|
240
|
+
**⏭ Want to skip the theory?** Jump to [Step 11: Final Integration](./step-11-final.md)
|
|
241
241
|
|
|
242
242
|
---
|
|
243
243
|
|
|
244
|
-
##
|
|
244
|
+
## Part 2: Understanding the Concepts
|
|
245
245
|
|
|
246
246
|
### What is Routing?
|
|
247
247
|
|
|
@@ -319,10 +319,10 @@ def login():
|
|
|
319
319
|
**vs regular anchor tag:**
|
|
320
320
|
|
|
321
321
|
```jac
|
|
322
|
-
#
|
|
322
|
+
# Wrong - causes page reload
|
|
323
323
|
<a href="/login">Go to Login</a>
|
|
324
324
|
|
|
325
|
-
#
|
|
325
|
+
# Correct - no page reload
|
|
326
326
|
<Link to="/login">Go to Login</Link>
|
|
327
327
|
```
|
|
328
328
|
|
|
@@ -463,19 +463,19 @@ def handleLogout() -> None {
|
|
|
463
463
|
|
|
464
464
|
---
|
|
465
465
|
|
|
466
|
-
##
|
|
466
|
+
## What You've Learned
|
|
467
467
|
|
|
468
|
-
-
|
|
469
|
-
-
|
|
470
|
-
-
|
|
471
|
-
-
|
|
472
|
-
-
|
|
473
|
-
-
|
|
474
|
-
-
|
|
468
|
+
- What client-side routing is
|
|
469
|
+
- Setting up Router, Routes, and Route
|
|
470
|
+
- Creating navigation with Link
|
|
471
|
+
- Programmatic navigation with Navigate
|
|
472
|
+
- Protected routes with authentication checks
|
|
473
|
+
- Conditional navigation based on auth status
|
|
474
|
+
- Common routing patterns
|
|
475
475
|
|
|
476
476
|
---
|
|
477
477
|
|
|
478
|
-
##
|
|
478
|
+
## Common Issues
|
|
479
479
|
|
|
480
480
|
### Issue: Links don't work
|
|
481
481
|
|
|
@@ -489,10 +489,10 @@ def handleLogout() -> None {
|
|
|
489
489
|
**Cause:** Using `<a href="">` instead of `<Link to="">`
|
|
490
490
|
|
|
491
491
|
```jac
|
|
492
|
-
#
|
|
492
|
+
# Wrong
|
|
493
493
|
<a href="/login">Login</a>
|
|
494
494
|
|
|
495
|
-
#
|
|
495
|
+
# Correct
|
|
496
496
|
<Link to="/login">Login</Link>
|
|
497
497
|
```
|
|
498
498
|
|
|
@@ -511,7 +511,7 @@ def handleLogout() -> None {
|
|
|
511
511
|
|
|
512
512
|
---
|
|
513
513
|
|
|
514
|
-
##
|
|
514
|
+
## Quick Exercise
|
|
515
515
|
|
|
516
516
|
Try adding a 404 page for unknown routes:
|
|
517
517
|
|
|
@@ -532,9 +532,8 @@ def NotFoundPage() -> any {
|
|
|
532
532
|
|
|
533
533
|
---
|
|
534
534
|
|
|
535
|
-
##
|
|
535
|
+
## Next Step
|
|
536
536
|
|
|
537
537
|
Congratulations! You've learned all the key concepts. Now let's put everything together into the **complete, final app**!
|
|
538
538
|
|
|
539
|
-
|
|
540
|
-
|
|
539
|
+
**[Continue to Step 11: Final Integration](./step-11-final.md)**
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Step 11: Final Integration - Complete App
|
|
2
2
|
|
|
3
|
-
>
|
|
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
|
-
Congratulations!
|
|
5
|
+
Congratulations! In this final step, you'll see the complete, production-ready todo application with all features integrated!
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Part 1: The Complete App
|
|
10
10
|
|
|
11
11
|
### Complete `app.jac` File
|
|
12
12
|
|
|
@@ -712,22 +712,22 @@ cl {
|
|
|
712
712
|
|
|
713
713
|
---
|
|
714
714
|
|
|
715
|
-
|
|
715
|
+
** You did it!** You've built a complete full-stack app. The rest of this page explains what you built and what to do next.
|
|
716
716
|
|
|
717
717
|
---
|
|
718
718
|
|
|
719
|
-
##
|
|
719
|
+
## Part 2: What You Built
|
|
720
720
|
|
|
721
721
|
### Features Checklist
|
|
722
722
|
|
|
723
|
-
|
|
723
|
+
**Authentication:**
|
|
724
724
|
- User signup
|
|
725
725
|
- User login
|
|
726
726
|
- Logout
|
|
727
727
|
- Session persistence
|
|
728
728
|
- Protected routes
|
|
729
729
|
|
|
730
|
-
|
|
730
|
+
**Todo Management:**
|
|
731
731
|
- Create todos
|
|
732
732
|
- Mark as complete/incomplete
|
|
733
733
|
- Delete todos
|
|
@@ -735,7 +735,7 @@ cl {
|
|
|
735
735
|
- Item counter
|
|
736
736
|
- Empty state handling
|
|
737
737
|
|
|
738
|
-
|
|
738
|
+
**UI/UX:**
|
|
739
739
|
- Responsive design
|
|
740
740
|
- Modern styling
|
|
741
741
|
- Form validation
|
|
@@ -743,7 +743,7 @@ cl {
|
|
|
743
743
|
- Loading states
|
|
744
744
|
- Smooth navigation
|
|
745
745
|
|
|
746
|
-
|
|
746
|
+
**Backend:**
|
|
747
747
|
- Data persistence with walkers
|
|
748
748
|
- User isolation (each user sees only their data)
|
|
749
749
|
- Graph-based data structure
|
|
@@ -779,7 +779,7 @@ Your entire app:
|
|
|
779
779
|
└── Routes (navigation)
|
|
780
780
|
```
|
|
781
781
|
|
|
782
|
-
That's it! Just one file!
|
|
782
|
+
That's it! Just one file!
|
|
783
783
|
|
|
784
784
|
### Code Organization
|
|
785
785
|
|
|
@@ -800,7 +800,7 @@ app.jac
|
|
|
800
800
|
|
|
801
801
|
---
|
|
802
802
|
|
|
803
|
-
##
|
|
803
|
+
## What's Next?
|
|
804
804
|
|
|
805
805
|
You've completed the tutorial! Here are some ideas to continue learning:
|
|
806
806
|
|
|
@@ -885,7 +885,7 @@ Apply what you learned:
|
|
|
885
885
|
|
|
886
886
|
---
|
|
887
887
|
|
|
888
|
-
##
|
|
888
|
+
## Resources
|
|
889
889
|
|
|
890
890
|
**Official Documentation:**
|
|
891
891
|
- [Jac Documentation](https://www.jac-lang.org)
|
|
@@ -905,21 +905,21 @@ Apply what you learned:
|
|
|
905
905
|
|
|
906
906
|
---
|
|
907
907
|
|
|
908
|
-
##
|
|
908
|
+
## What You Learned
|
|
909
909
|
|
|
910
910
|
Looking back at all 11 steps:
|
|
911
911
|
|
|
912
|
-
1.
|
|
913
|
-
2.
|
|
914
|
-
3.
|
|
915
|
-
4.
|
|
916
|
-
5.
|
|
917
|
-
6.
|
|
918
|
-
7.
|
|
919
|
-
8.
|
|
920
|
-
9.
|
|
921
|
-
10.
|
|
922
|
-
11.
|
|
912
|
+
1. Project setup and structure
|
|
913
|
+
2. Components and props
|
|
914
|
+
3. Styling with inline CSS
|
|
915
|
+
4. Building complex UIs
|
|
916
|
+
5. State management with useState
|
|
917
|
+
6. Event handlers
|
|
918
|
+
7. Side effects with useEffect
|
|
919
|
+
8. Backend with walkers and nodes
|
|
920
|
+
9. User authentication
|
|
921
|
+
10. Client-side routing
|
|
922
|
+
11. Complete full-stack integration
|
|
923
923
|
|
|
924
924
|
**Key concepts mastered:**
|
|
925
925
|
- Full-stack development in one language
|
|
@@ -934,23 +934,23 @@ Looking back at all 11 steps:
|
|
|
934
934
|
|
|
935
935
|
---
|
|
936
936
|
|
|
937
|
-
##
|
|
937
|
+
## Congratulations!
|
|
938
938
|
|
|
939
939
|
You built a **complete, production-ready full-stack application** from scratch!
|
|
940
940
|
|
|
941
941
|
**What makes this special:**
|
|
942
|
-
-
|
|
943
|
-
-
|
|
944
|
-
-
|
|
945
|
-
-
|
|
946
|
-
-
|
|
947
|
-
-
|
|
942
|
+
- **735 lines** of code (compared to 2000+ in traditional stacks)
|
|
943
|
+
- **One language** (compared to 3-4: JavaScript, Python, SQL, HTML/CSS)
|
|
944
|
+
- **One file** (compared to dozens of files)
|
|
945
|
+
- **Zero configuration** (no webpack, babel, etc.)
|
|
946
|
+
- **Built-in auth** (no OAuth setup needed)
|
|
947
|
+
- **Automatic backend** (no Express/Flask setup)
|
|
948
948
|
|
|
949
|
-
You're now ready to build amazing full-stack applications with Jac!
|
|
949
|
+
You're now ready to build amazing full-stack applications with Jac!
|
|
950
950
|
|
|
951
951
|
---
|
|
952
952
|
|
|
953
|
-
##
|
|
953
|
+
## Share Your Success!
|
|
954
954
|
|
|
955
955
|
Built something cool? Share it:
|
|
956
956
|
- Tag #JacLang on social media
|
|
@@ -960,5 +960,4 @@ Built something cool? Share it:
|
|
|
960
960
|
|
|
961
961
|
**Thank you for completing this tutorial!**
|
|
962
962
|
|
|
963
|
-
Happy coding with Jac!
|
|
964
|
-
|
|
963
|
+
Happy coding with Jac!
|
jac_client/docs/imports.md
CHANGED
|
@@ -4,7 +4,7 @@ Learn how to import third-party libraries, other Jac files, and JavaScript modul
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Table of Contents
|
|
8
8
|
|
|
9
9
|
- [Importing Jac-Client Utilities](#importing-jac-client-utilities)
|
|
10
10
|
- [Working with Third-Party Node Modules](#working-with-third-party-node-modules)
|
|
@@ -677,7 +677,7 @@ cl {
|
|
|
677
677
|
return <div>
|
|
678
678
|
<h1>{count} {pluralWord}</h1>
|
|
679
679
|
<Rotate>
|
|
680
|
-
<span style={{"fontSize": "48px"}}
|
|
680
|
+
<span style={{"fontSize": "48px"}}></span>
|
|
681
681
|
</Rotate>
|
|
682
682
|
</div>;
|
|
683
683
|
}
|
|
@@ -983,7 +983,7 @@ cl def ValidationForm() -> any {
|
|
|
983
983
|
### 1. Organize Imports
|
|
984
984
|
|
|
985
985
|
```jac
|
|
986
|
-
#
|
|
986
|
+
# Good: Group imports logically
|
|
987
987
|
# Third-party libraries
|
|
988
988
|
cl import from antd {
|
|
989
989
|
Button,
|
|
@@ -1138,5 +1138,4 @@ Type errors with imported functions
|
|
|
1138
1138
|
- **JavaScript Files**: Import with `cl import from .filename`
|
|
1139
1139
|
- **Best Practices**: Organize imports, import only what you need, document exports
|
|
1140
1140
|
|
|
1141
|
-
Imports in Jac make it easy to use third-party libraries and organize your code!
|
|
1142
|
-
|
|
1141
|
+
Imports in Jac make it easy to use third-party libraries and organize your code!
|
|
@@ -4,7 +4,7 @@ Learn how to use React's `useEffect` and `useState` hooks to manage component st
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Table of Contents
|
|
8
8
|
|
|
9
9
|
- [What are Lifecycle Hooks?](#what-are-lifecycle-hooks)
|
|
10
10
|
- [React Hooks (Recommended)](#react-hooks-recommended)
|
|
@@ -424,7 +424,7 @@ cl {
|
|
|
424
424
|
"padding": "24px",
|
|
425
425
|
"fontFamily": "system-ui, -apple-system, sans-serif"
|
|
426
426
|
}}>
|
|
427
|
-
<h1 style={{"textAlign": "center"}}
|
|
427
|
+
<h1 style={{"textAlign": "center"}}> My Todo App</h1>
|
|
428
428
|
|
|
429
429
|
# Add todo form
|
|
430
430
|
<div style={{"display": "flex", "gap": "8px", "marginBottom": "24px"}}>
|
|
@@ -546,17 +546,17 @@ cl {
|
|
|
546
546
|
Be explicit about what your effect depends on:
|
|
547
547
|
|
|
548
548
|
```jac
|
|
549
|
-
#
|
|
549
|
+
# Good: Empty array for mount-only effects
|
|
550
550
|
useEffect(lambda -> None {
|
|
551
551
|
loadInitialData();
|
|
552
552
|
}, []);
|
|
553
553
|
|
|
554
|
-
#
|
|
554
|
+
# Good: Specify dependencies
|
|
555
555
|
useEffect(lambda -> None {
|
|
556
556
|
console.log("Count changed:", count);
|
|
557
557
|
}, [count]);
|
|
558
558
|
|
|
559
|
-
#
|
|
559
|
+
# Warning: No dependency array runs on every render
|
|
560
560
|
useEffect(lambda -> None {
|
|
561
561
|
console.log("Runs on every render!");
|
|
562
562
|
});
|
|
@@ -567,7 +567,7 @@ useEffect(lambda -> None {
|
|
|
567
567
|
Always handle async operations with proper error handling:
|
|
568
568
|
|
|
569
569
|
```jac
|
|
570
|
-
#
|
|
570
|
+
# Good: Proper async handling
|
|
571
571
|
useEffect(lambda -> None {
|
|
572
572
|
async def loadData() -> None {
|
|
573
573
|
try {
|
|
@@ -587,7 +587,7 @@ useEffect(lambda -> None {
|
|
|
587
587
|
Always clean up event listeners, timers, and subscriptions:
|
|
588
588
|
|
|
589
589
|
```jac
|
|
590
|
-
#
|
|
590
|
+
# Good: Cleanup function removes event listener
|
|
591
591
|
useEffect(lambda -> any {
|
|
592
592
|
def handleResize() -> None {
|
|
593
593
|
setWidth(window.innerWidth);
|
|
@@ -606,7 +606,7 @@ useEffect(lambda -> any {
|
|
|
606
606
|
Show loading indicators while data is being fetched:
|
|
607
607
|
|
|
608
608
|
```jac
|
|
609
|
-
#
|
|
609
|
+
# Good: Clear loading states
|
|
610
610
|
def Component() -> any {
|
|
611
611
|
let [data, setData] = useState(None);
|
|
612
612
|
let [loading, setLoading] = useState(True);
|
|
@@ -638,7 +638,7 @@ def Component() -> any {
|
|
|
638
638
|
Each effect should have a single responsibility:
|
|
639
639
|
|
|
640
640
|
```jac
|
|
641
|
-
#
|
|
641
|
+
# Good: Separate effects for separate concerns
|
|
642
642
|
def Component() -> any {
|
|
643
643
|
useEffect(lambda -> None {
|
|
644
644
|
loadData(); # Data loading
|
|
@@ -661,14 +661,14 @@ def Component() -> any {
|
|
|
661
661
|
Be careful with closures capturing old state values:
|
|
662
662
|
|
|
663
663
|
```jac
|
|
664
|
-
#
|
|
664
|
+
# Avoid: Stale closure problem
|
|
665
665
|
useEffect(lambda -> None {
|
|
666
666
|
setInterval(lambda -> None {
|
|
667
667
|
setCount(count + 1); # count is stale!
|
|
668
668
|
}, 1000);
|
|
669
669
|
}, []);
|
|
670
670
|
|
|
671
|
-
#
|
|
671
|
+
# Good: Use functional update
|
|
672
672
|
useEffect(lambda -> any {
|
|
673
673
|
intervalId = setInterval(lambda -> None {
|
|
674
674
|
setCount(lambda prev: int -> int { return prev + 1; });
|
|
@@ -690,7 +690,7 @@ useEffect(lambda -> any {
|
|
|
690
690
|
- **Cleanup**: Return a cleanup function for subscriptions, timers, and listeners
|
|
691
691
|
- **Best Practices**: Handle errors, use loading states, keep effects focused
|
|
692
692
|
|
|
693
|
-
React hooks provide a powerful and standard way to manage component lifecycle!
|
|
693
|
+
React hooks provide a powerful and standard way to manage component lifecycle!
|
|
694
694
|
|
|
695
695
|
---
|
|
696
696
|
|
|
@@ -771,4 +771,3 @@ useEffect(lambda -> None {
|
|
|
771
771
|
console.log("Count:", count);
|
|
772
772
|
}, [count]);
|
|
773
773
|
```
|
|
774
|
-
|