create-aziz-app 3.1.1 → 3.1.3

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 (33) hide show
  1. package/README.md +658 -207
  2. package/bin/create-aziz-app.js +302 -351
  3. package/package.json +1 -1
  4. package/template/README.md +14 -279
  5. package/template/_framework/api.js +219 -219
  6. package/template/_framework/boot.js +33 -33
  7. package/template/_framework/hooks.js +367 -291
  8. package/template/_framework/next-response.js +128 -128
  9. package/template/_framework/route-match.js +145 -145
  10. package/template/_framework/router.js +465 -259
  11. package/template/_framework/runtime.js +264 -264
  12. package/template/app/layout.js +3 -5
  13. package/template/app/page.js +9 -32
  14. package/template/docs/01-getting-started.md +151 -151
  15. package/template/docs/02-project-structure.md +109 -109
  16. package/template/docs/03-pages-and-layouts.md +140 -140
  17. package/template/docs/04-routing.md +120 -120
  18. package/template/docs/05-hooks.md +169 -169
  19. package/template/docs/06-api-routes.md +210 -210
  20. package/template/docs/07-api-client.md +151 -151
  21. package/template/docs/08-styling.md +94 -94
  22. package/template/docs/09-imports-and-modules.md +97 -97
  23. package/template/docs/10-database-and-models.md +154 -154
  24. package/template/docs/11-authentication.md +171 -171
  25. package/template/docs/12-production-and-deployment.md +121 -121
  26. package/template/docs/13-internals.md +179 -179
  27. package/template/docs/README.md +67 -67
  28. package/template/index.html +20 -20
  29. package/template/package.json +16 -16
  30. package/template/scripts/dev-server.js +493 -381
  31. package/template/scripts/lib/api-router.js +525 -525
  32. package/template/scripts/lib/js-transform.js +213 -141
  33. package/template/scripts/lib/module-resolver.js +132 -132
@@ -1,140 +1,140 @@
1
- # 03 · Pages & Layouts
2
-
3
- Pages are screens. Layouts wrap screens in shared chrome (nav, footer, providers).
4
-
5
- ## Pages
6
-
7
- A page is a file named `page.js` (or `page.jsx`) that **exports a default component**.
8
-
9
- ```js
10
- // app/about/page.js → /about
11
- export default function About() {
12
- return (
13
- <div>
14
- <h1>About</h1>
15
- <p>We build lightweight frameworks.</p>
16
- </div>
17
- );
18
- }
19
- ```
20
-
21
- Rules:
22
-
23
- - The file must be named **`page.js`** inside a folder under `app/`.
24
- - It must have a **default export**.
25
- - **JSX works out of the box** — no imports needed.
26
-
27
- ### Pages can use state and hooks
28
-
29
- ```js
30
- // app/clock/page.js
31
- export default function Clock() {
32
- const [now, setNow] = useState(new Date());
33
-
34
- useEffect(() => {
35
- const id = setInterval(() => setNow(new Date()), 1000);
36
- return () => clearInterval(id); // cleanup runs on unmount
37
- }, []);
38
-
39
- return <p>{now.toLocaleTimeString()}</p>;
40
- }
41
- ```
42
-
43
- Hooks are global: `useState`, `useEffect`, `useMemo`, `useRef`, `useReducer`, `useContext`, `useLocalStorage`, `useFetch`, `useApi`, `useRouter`, `useParams`, `useSearchParams`. Full list in [Hooks](./05-hooks.md).
44
-
45
- ### Page metadata
46
-
47
- Export a `metadata` object to set the document title / description per page:
48
-
49
- ```js
50
- // app/about/page.js
51
- export default function About() { /* … */ }
52
-
53
- export const metadata = {
54
- title: 'About us',
55
- description: 'Who we are',
56
- };
57
- ```
58
-
59
- Layout metadata is merged outermost → innermost, and **page metadata wins** for `title`.
60
-
61
- ## Layouts
62
-
63
- A layout is a file named `layout.js` that **exports a default component receiving `{ children }`**:
64
-
65
- ```js
66
- // app/layout.js → wraps EVERY page
67
- import Navbar from '/components/Navbar.js';
68
- import Footer from '/components/Footer.js';
69
-
70
- export default function Layout({ children }) {
71
- return (
72
- <div style={{ display: 'flex', flexDirection: 'column', minHeight: '100vh' }}>
73
- <Navbar />
74
- <main style={{ flex: 1 }}>{children}</main>
75
- <Footer />
76
- </div>
77
- );
78
- }
79
-
80
- export const metadata = {
81
- title: 'My App',
82
- description: 'Built with Aziz.js',
83
- };
84
- ```
85
-
86
- `children` is whatever page (or nested layout) the router mounted. Always render it — otherwise nothing below the layout appears.
87
-
88
- ### Nested layouts
89
-
90
- A `layout.js` inside a folder applies to **that folder and everything under it**, outermost-first:
91
-
92
- ```
93
- app/layout.js → wraps / (root)
94
- app/about/layout.js → wraps /about (and children)
95
- app/blog/layout.js → wraps /blog/*
96
- ```
97
-
98
- For a request to `/blog/hello`, the chain is:
99
-
100
- ```
101
- app/layout.js → app/blog/layout.js → app/blog/[slug]/page.js
102
- ```
103
-
104
- Layouts do **not** re-mount when you navigate between sibling routes (their state persists); only the page below them changes.
105
-
106
- ## The 404 page
107
-
108
- `app/not-found.js` renders when no route matches (or a page exports nothing usable):
109
-
110
- ```js
111
- // app/not-found.js
112
- export default function NotFound() {
113
- return (
114
- <div style={{ padding: '60px 24px', textAlign: 'center' }}>
115
- <h1 style={{ fontSize: '72px' }}>404</h1>
116
- <p>This page could not be found.</p>
117
- <button onClick={() => navigate('/')}>Go Home</button>
118
- </div>
119
- );
120
- }
121
- ```
122
-
123
- If you don't ship one, a built-in default 404 is used.
124
-
125
- ## Root entry
126
-
127
- `index.html` is the only real HTML file. It defines `<div id="root">`, loads `/_framework/boot.js`, and the client router renders the matching page into `#root`. You normally **don't touch `index.html`** except to add global `<link>`/`<script>` (the CSS-framework flags inject these for you).
128
-
129
- ## Programmatic navigation from a page
130
-
131
- ```js
132
- navigate('/about'); // global function
133
- window.__rerenderPage?.(); // force re-render (advanced)
134
- ```
135
-
136
- See [Routing](./04-routing.md) for links, params, and search strings.
137
-
138
- ## Continue
139
-
140
- → [Routing](./04-routing.md)
1
+ # 03 · Pages & Layouts
2
+
3
+ Pages are screens. Layouts wrap screens in shared chrome (nav, footer, providers).
4
+
5
+ ## Pages
6
+
7
+ A page is a file named `page.js` (or `page.jsx`) that **exports a default component**.
8
+
9
+ ```js
10
+ // app/about/page.js → /about
11
+ export default function About() {
12
+ return (
13
+ <div>
14
+ <h1>About</h1>
15
+ <p>We build lightweight frameworks.</p>
16
+ </div>
17
+ );
18
+ }
19
+ ```
20
+
21
+ Rules:
22
+
23
+ - The file must be named **`page.js`** inside a folder under `app/`.
24
+ - It must have a **default export**.
25
+ - **JSX works out of the box** — no imports needed.
26
+
27
+ ### Pages can use state and hooks
28
+
29
+ ```js
30
+ // app/clock/page.js
31
+ export default function Clock() {
32
+ const [now, setNow] = useState(new Date());
33
+
34
+ useEffect(() => {
35
+ const id = setInterval(() => setNow(new Date()), 1000);
36
+ return () => clearInterval(id); // cleanup runs on unmount
37
+ }, []);
38
+
39
+ return <p>{now.toLocaleTimeString()}</p>;
40
+ }
41
+ ```
42
+
43
+ Hooks are global: `useState`, `useEffect`, `useMemo`, `useRef`, `useReducer`, `useContext`, `useLocalStorage`, `useFetch`, `useApi`, `useRouter`, `useParams`, `useSearchParams`. Full list in [Hooks](./05-hooks.md).
44
+
45
+ ### Page metadata
46
+
47
+ Export a `metadata` object to set the document title / description per page:
48
+
49
+ ```js
50
+ // app/about/page.js
51
+ export default function About() { /* … */ }
52
+
53
+ export const metadata = {
54
+ title: 'About us',
55
+ description: 'Who we are',
56
+ };
57
+ ```
58
+
59
+ Layout metadata is merged outermost → innermost, and **page metadata wins** for `title`.
60
+
61
+ ## Layouts
62
+
63
+ A layout is a file named `layout.js` that **exports a default component receiving `{ children }`**:
64
+
65
+ ```js
66
+ // app/layout.js → wraps EVERY page
67
+ import Navbar from '/components/Navbar.js';
68
+ import Footer from '/components/Footer.js';
69
+
70
+ export default function Layout({ children }) {
71
+ return (
72
+ <div style={{ display: 'flex', flexDirection: 'column', minHeight: '100vh' }}>
73
+ <Navbar />
74
+ <main style={{ flex: 1 }}>{children}</main>
75
+ <Footer />
76
+ </div>
77
+ );
78
+ }
79
+
80
+ export const metadata = {
81
+ title: 'My App',
82
+ description: 'Built with Aziz.js',
83
+ };
84
+ ```
85
+
86
+ `children` is whatever page (or nested layout) the router mounted. Always render it — otherwise nothing below the layout appears.
87
+
88
+ ### Nested layouts
89
+
90
+ A `layout.js` inside a folder applies to **that folder and everything under it**, outermost-first:
91
+
92
+ ```
93
+ app/layout.js → wraps / (root)
94
+ app/about/layout.js → wraps /about (and children)
95
+ app/blog/layout.js → wraps /blog/*
96
+ ```
97
+
98
+ For a request to `/blog/hello`, the chain is:
99
+
100
+ ```
101
+ app/layout.js → app/blog/layout.js → app/blog/[slug]/page.js
102
+ ```
103
+
104
+ Layouts do **not** re-mount when you navigate between sibling routes (their state persists); only the page below them changes.
105
+
106
+ ## The 404 page
107
+
108
+ `app/not-found.js` renders when no route matches (or a page exports nothing usable):
109
+
110
+ ```js
111
+ // app/not-found.js
112
+ export default function NotFound() {
113
+ return (
114
+ <div style={{ padding: '60px 24px', textAlign: 'center' }}>
115
+ <h1 style={{ fontSize: '72px' }}>404</h1>
116
+ <p>This page could not be found.</p>
117
+ <button onClick={() => navigate('/')}>Go Home</button>
118
+ </div>
119
+ );
120
+ }
121
+ ```
122
+
123
+ If you don't ship one, a built-in default 404 is used.
124
+
125
+ ## Root entry
126
+
127
+ `index.html` is the only real HTML file. It defines `<div id="root">`, loads `/_framework/boot.js`, and the client router renders the matching page into `#root`. You normally **don't touch `index.html`** except to add global `<link>`/`<script>` (the CSS-framework flags inject these for you).
128
+
129
+ ## Programmatic navigation from a page
130
+
131
+ ```js
132
+ navigate('/about'); // global function
133
+ window.__rerenderPage?.(); // force re-render (advanced)
134
+ ```
135
+
136
+ See [Routing](./04-routing.md) for links, params, and search strings.
137
+
138
+ ## Continue
139
+
140
+ → [Routing](./04-routing.md)
@@ -1,120 +1,120 @@
1
- # 04 · Routing
2
-
3
- Aziz.js maps files under `app/` to URLs, the same way the Next.js App Router does.
4
-
5
- ## File → URL table
6
-
7
- | File | URL |
8
- |------|-----|
9
- | `app/page.js` | `/` |
10
- | `app/about/page.js` | `/about` |
11
- | `app/blog/page.js` | `/blog` |
12
- | `app/blog/[slug]/page.js` | `/blog/:slug` |
13
- | `app/docs/[...path]/page.js` | `/docs/*` (catch-all) |
14
- | `app/not-found.js` | (renders 404) |
15
-
16
- The file must be named **`page.js`** — that's what registers a route.
17
-
18
- ## Dynamic segments
19
-
20
- Create `app/blog/[slug]/page.js`. Brackets become a **parameter**:
21
-
22
- ```js
23
- // app/blog/[slug]/page.js → /blog/:slug
24
- export default function Post() {
25
- const { slug } = useParams();
26
- return <article>Post: {slug}</article>;
27
- }
28
- ```
29
-
30
- Visiting `/blog/hello-world` renders `Post: hello-world`.
31
-
32
- Multiple dynamic segments are fine: `app/shop/[category]/[id]/page.js` → `useParams()` gives `{ category, id }`.
33
-
34
- ## Catch-all segments
35
-
36
- `[...name]` captures **the rest of the path** as an array:
37
-
38
- ```js
39
- // app/docs/[...path]/page.js → /docs/*
40
- export default function Docs() {
41
- const { path } = useParams();
42
- // /docs/a/b → path === ['a', 'b']
43
- // /docs/one → path === ['one']
44
- return <pre>{JSON.stringify(path, null, 2)}</pre>;
45
- }
46
- ```
47
-
48
- The literal prefix is validated — `/docs/[...path]` will **not** match `/other/a`.
49
-
50
- ## Route specificity
51
-
52
- When several routes could match, the most specific wins:
53
-
54
- 1. **Static** (`/blog/new`) beats
55
- 2. **Dynamic** (`/blog/[slug]`) beats
56
- 3. **Catch-all** (`/[...all]`)
57
-
58
- So with all three present:
59
-
60
- - `/blog/new` → static route
61
- - `/blog/hello` → dynamic route
62
- - `/other/x` → catch-all route
63
-
64
- Trailing slashes are normalized: `/about/` matches `/about`.
65
-
66
- ## Navigation
67
-
68
- ### `<Link>` (client-side, no full reload)
69
-
70
- ```js
71
- <Link href="/about">About</Link>
72
- <Link href="/blog/hello" class="nav-link">Post</Link>
73
- ```
74
-
75
- `<Link>` intercepts ordinary left-clicks and calls `navigate()`, but **respects** modifier/middle clicks (⌘/Ctrl/Shift/Alt, middle-click) and external/hash/mailto URLs, so the browser behaves normally.
76
-
77
- ### `navigate()`
78
-
79
- ```js
80
- navigate('/about'); // pushState + render
81
- ```
82
-
83
- ### `useRouter()`
84
-
85
- ```js
86
- const { pathname, push, replace, back, forward, refresh, params } = useRouter();
87
-
88
- push('/about');
89
- replace('/search?q=aziz');
90
- refresh(); // re-render current route
91
- ```
92
-
93
- ### `useParams()` / `useSearchParams()`
94
-
95
- ```js
96
- const { slug } = useParams();
97
-
98
- const search = useSearchParams();
99
- const q = search.get('q'); // ?q=aziz → "aziz"
100
- ```
101
-
102
- ### Browser history
103
-
104
- The router listens for `popstate`, so Back/Forward work as expected, and scroll position / focus are restored on same-route re-renders.
105
-
106
- ## Custom 404
107
-
108
- See [Pages & Layouts](./03-pages-and-layouts.md#the-404-page) — export a default component from `app/not-found.js`.
109
-
110
- ## How the router finds pages
111
-
112
- 1. The dev server scans `app/` and emits `/_framework/routes.json` (the **manifest**).
113
- 2. On boot, the client imports that manifest and `import()`s each `page.js` / `layout.js`.
114
- 3. On every navigation it normalizes the path, resolves the most specific route, collects the layout chain, and mounts it into `#root`.
115
-
116
- You can inspect the manifest live at **<http://localhost:3000/_framework/routes.json>**.
117
-
118
- ## Continue
119
-
120
- → [Hooks](./05-hooks.md)
1
+ # 04 · Routing
2
+
3
+ Aziz.js maps files under `app/` to URLs, the same way the Next.js App Router does.
4
+
5
+ ## File → URL table
6
+
7
+ | File | URL |
8
+ |------|-----|
9
+ | `app/page.js` | `/` |
10
+ | `app/about/page.js` | `/about` |
11
+ | `app/blog/page.js` | `/blog` |
12
+ | `app/blog/[slug]/page.js` | `/blog/:slug` |
13
+ | `app/docs/[...path]/page.js` | `/docs/*` (catch-all) |
14
+ | `app/not-found.js` | (renders 404) |
15
+
16
+ The file must be named **`page.js`** — that's what registers a route.
17
+
18
+ ## Dynamic segments
19
+
20
+ Create `app/blog/[slug]/page.js`. Brackets become a **parameter**:
21
+
22
+ ```js
23
+ // app/blog/[slug]/page.js → /blog/:slug
24
+ export default function Post() {
25
+ const { slug } = useParams();
26
+ return <article>Post: {slug}</article>;
27
+ }
28
+ ```
29
+
30
+ Visiting `/blog/hello-world` renders `Post: hello-world`.
31
+
32
+ Multiple dynamic segments are fine: `app/shop/[category]/[id]/page.js` → `useParams()` gives `{ category, id }`.
33
+
34
+ ## Catch-all segments
35
+
36
+ `[...name]` captures **the rest of the path** as an array:
37
+
38
+ ```js
39
+ // app/docs/[...path]/page.js → /docs/*
40
+ export default function Docs() {
41
+ const { path } = useParams();
42
+ // /docs/a/b → path === ['a', 'b']
43
+ // /docs/one → path === ['one']
44
+ return <pre>{JSON.stringify(path, null, 2)}</pre>;
45
+ }
46
+ ```
47
+
48
+ The literal prefix is validated — `/docs/[...path]` will **not** match `/other/a`.
49
+
50
+ ## Route specificity
51
+
52
+ When several routes could match, the most specific wins:
53
+
54
+ 1. **Static** (`/blog/new`) beats
55
+ 2. **Dynamic** (`/blog/[slug]`) beats
56
+ 3. **Catch-all** (`/[...all]`)
57
+
58
+ So with all three present:
59
+
60
+ - `/blog/new` → static route
61
+ - `/blog/hello` → dynamic route
62
+ - `/other/x` → catch-all route
63
+
64
+ Trailing slashes are normalized: `/about/` matches `/about`.
65
+
66
+ ## Navigation
67
+
68
+ ### `<Link>` (client-side, no full reload)
69
+
70
+ ```js
71
+ <Link href="/about">About</Link>
72
+ <Link href="/blog/hello" class="nav-link">Post</Link>
73
+ ```
74
+
75
+ `<Link>` intercepts ordinary left-clicks and calls `navigate()`, but **respects** modifier/middle clicks (⌘/Ctrl/Shift/Alt, middle-click) and external/hash/mailto URLs, so the browser behaves normally.
76
+
77
+ ### `navigate()`
78
+
79
+ ```js
80
+ navigate('/about'); // pushState + render
81
+ ```
82
+
83
+ ### `useRouter()`
84
+
85
+ ```js
86
+ const { pathname, push, replace, back, forward, refresh, params } = useRouter();
87
+
88
+ push('/about');
89
+ replace('/search?q=aziz');
90
+ refresh(); // re-render current route
91
+ ```
92
+
93
+ ### `useParams()` / `useSearchParams()`
94
+
95
+ ```js
96
+ const { slug } = useParams();
97
+
98
+ const search = useSearchParams();
99
+ const q = search.get('q'); // ?q=aziz → "aziz"
100
+ ```
101
+
102
+ ### Browser history
103
+
104
+ The router listens for `popstate`, so Back/Forward work as expected, and scroll position / focus are restored on same-route re-renders.
105
+
106
+ ## Custom 404
107
+
108
+ See [Pages & Layouts](./03-pages-and-layouts.md#the-404-page) — export a default component from `app/not-found.js`.
109
+
110
+ ## How the router finds pages
111
+
112
+ 1. The dev server scans `app/` and emits `/_framework/routes.json` (the **manifest**).
113
+ 2. On boot, the client imports that manifest and `import()`s each `page.js` / `layout.js`.
114
+ 3. On every navigation it normalizes the path, resolves the most specific route, collects the layout chain, and mounts it into `#root`.
115
+
116
+ You can inspect the manifest live at **<http://localhost:3000/_framework/routes.json>**.
117
+
118
+ ## Continue
119
+
120
+ → [Hooks](./05-hooks.md)