miolo 3.0.0-beta.21 → 3.0.0-beta.210
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/build/build.mjs +53 -0
- package/bin/build/build_bin.mjs +17 -0
- package/bin/build/cli/client.mjs +52 -0
- package/bin/build/cli/css.mjs +22 -0
- package/bin/build/cli/index.mjs +40 -0
- package/bin/build/cli/ssr.mjs +21 -0
- package/bin/build/server/aliases.mjs +112 -0
- package/bin/build/server/babel.config.js +24 -0
- package/bin/build/server/banner.mjs +20 -0
- package/bin/build/server/bundle.mjs +111 -0
- package/bin/build/server/fix.mjs +15 -0
- package/bin/build/server/index.mjs +69 -0
- package/bin/build/server/options.mjs +83 -0
- package/bin/create/auth.mjs +23 -0
- package/bin/create/copy.mjs +175 -0
- package/bin/create/docker.mjs +25 -0
- package/bin/create/index.mjs +137 -0
- package/bin/create/pkgjson.mjs +72 -0
- package/bin/create/prepare-template.mjs +158 -0
- package/bin/create/validation.mjs +27 -0
- package/bin/dev/dev.mjs +32 -23
- package/bin/dev/dev_start.mjs +6 -5
- package/bin/index.mjs +94 -52
- package/bin/prod-bin/create-bin.mjs +42 -27
- package/bin/prod-bin/run.mjs +13 -9
- package/bin/{prod-run → run}/pid.mjs +4 -4
- package/bin/run/restart.mjs +13 -0
- package/bin/run/start.mjs +18 -0
- package/bin/run/stop.mjs +20 -0
- package/bin/util.mjs +35 -11
- package/package.json +59 -39
- package/src/config/.env +34 -12
- package/src/config/defaults.mjs +253 -185
- package/src/config/env.mjs +40 -22
- package/src/config/index.mjs +19 -24
- package/src/config/util.mjs +25 -10
- package/src/db-conn.mjs +34 -0
- package/src/engines/cron/emails.mjs +10 -5
- package/src/engines/cron/index.mjs +45 -51
- package/src/engines/cron/init.mjs +16 -17
- package/src/engines/cron/ipsum.mjs +65 -60
- package/src/engines/cron/syscheck.mjs +30 -30
- package/src/engines/emailer/index.mjs +1 -2
- package/src/engines/emailer/queue.mjs +14 -20
- package/src/engines/emailer/transporter.mjs +86 -74
- package/src/engines/geoip/index.mjs +23 -28
- package/src/engines/http/index.mjs +26 -15
- package/src/engines/logger/buildErrorEmailBody.mjs +72 -0
- package/src/engines/logger/index.mjs +114 -122
- package/src/engines/logger/injectStackTrace.mjs +59 -0
- package/src/engines/logger/logger_mail.mjs +47 -61
- package/src/engines/logger/reopenTransportOnHupSignal.mjs +12 -13
- package/src/engines/parser/Parser.mjs +77 -60
- package/src/engines/parser/index.mjs +1 -1
- package/src/engines/schema/diffObjs.mjs +41 -0
- package/src/engines/schema/index.mjs +4 -0
- package/src/engines/schema/input.mjs +54 -0
- package/src/engines/schema/output.mjs +66 -0
- package/src/engines/socket/index.mjs +44 -46
- package/src/index.mjs +15 -10
- package/src/middleware/auth/basic.mjs +41 -40
- package/src/middleware/auth/custom.mjs +10 -13
- package/src/middleware/auth/guest.mjs +27 -27
- package/src/middleware/auth/passport/index.mjs +374 -0
- package/src/middleware/auth/passport/session/index.mjs +43 -0
- package/src/middleware/auth/{credentials → passport}/session/store.mjs +35 -15
- package/src/middleware/auth/passport/session/store_koa_redis.mjs +3 -0
- package/src/middleware/context/cache/index.mjs +78 -33
- package/src/middleware/context/cache/options.mjs +19 -21
- package/src/middleware/context/db.mjs +45 -20
- package/src/middleware/context/index.mjs +12 -12
- package/src/middleware/extra.mjs +4 -5
- package/src/middleware/http/body.mjs +25 -25
- package/src/middleware/http/catcher.mjs +81 -8
- package/src/middleware/http/custom_blacklist.mjs +19 -16
- package/src/middleware/http/headers.mjs +37 -34
- package/src/middleware/http/ratelimit.mjs +16 -23
- package/src/middleware/http/request.mjs +60 -65
- package/src/middleware/routes/catch_js_error.mjs +30 -23
- package/src/middleware/routes/robots.mjs +4 -7
- package/src/middleware/routes/router/crud/attachCrudRoutes.mjs +108 -90
- package/src/middleware/routes/router/crud/getCrudConfig.mjs +31 -55
- package/src/middleware/routes/router/defaults.mjs +6 -19
- package/src/middleware/routes/router/index.mjs +17 -21
- package/src/middleware/routes/router/queries/attachQueriesRoutes.mjs +227 -50
- package/src/middleware/routes/router/queries/getQueriesConfig.mjs +45 -55
- package/src/middleware/routes/router/utils.mjs +41 -26
- package/src/middleware/ssr/context.mjs +5 -7
- package/src/middleware/ssr/html.mjs +66 -43
- package/src/middleware/ssr/loader.mjs +11 -14
- package/src/middleware/ssr/ssr_render.mjs +39 -22
- package/src/middleware/static/index.mjs +33 -14
- package/src/middleware/vite/devserver.mjs +38 -22
- package/src/middleware/vite/watcher.mjs +12 -14
- package/src/server-cron.mjs +13 -8
- package/src/server-dev.mjs +13 -16
- package/src/server.mjs +49 -51
- package/template/.agent/skills/miolo-app-arch/SKILL.md +218 -0
- package/template/.agent/skills/miolo-auth/SKILL.md +450 -0
- package/template/.agent/skills/miolo-cli-router/SKILL.md +394 -0
- package/template/.agent/skills/miolo-database/SKILL.md +358 -0
- package/template/.agent/skills/miolo-react-patterns/SKILL.md +426 -0
- package/template/.agent/skills/miolo-routing/SKILL.md +326 -0
- package/template/.agent/skills/miolo-schemas/SKILL.md +329 -0
- package/template/.agent/skills/miolo-session-context/SKILL.md +397 -0
- package/template/.agent/skills/miolo-ssr/SKILL.md +433 -0
- package/template/.editorconfig +18 -0
- package/template/.env +120 -0
- package/template/biome.json +63 -0
- package/template/components.json +21 -0
- package/template/db/init.sh +89 -0
- package/template/db/sql/00_drop.sql +2 -0
- package/template/db/sql/01_users.sql +31 -0
- package/template/db/sql/02_todos.sql +20 -0
- package/template/docker/Dockerfile +13 -0
- package/template/docker/docker-compose.yaml +79 -0
- package/template/gitignore +42 -0
- package/template/jsconfig.json +18 -0
- package/template/package.json +88 -0
- package/template/postcss.config.js +9 -0
- package/template/src/cli/App.jsx +25 -0
- package/template/src/cli/components/JsonTreeViewer.jsx +128 -0
- package/template/src/cli/components/shadcn-io/spinner/index.jsx +232 -0
- package/template/src/cli/components/stepper.jsx +408 -0
- package/template/src/cli/components/ui/avatar.jsx +36 -0
- package/template/src/cli/components/ui/badge.jsx +31 -0
- package/template/src/cli/components/ui/breadcrumb.jsx +97 -0
- package/template/src/cli/components/ui/card.jsx +73 -0
- package/template/src/cli/components/ui/collapsible.jsx +16 -0
- package/template/src/cli/components/ui/dropdown-menu.jsx +179 -0
- package/template/src/cli/components/ui/field.jsx +217 -0
- package/template/src/cli/components/ui/input.jsx +19 -0
- package/template/src/cli/components/ui/label.jsx +17 -0
- package/template/src/cli/components/ui/pagination.jsx +99 -0
- package/template/src/cli/components/ui/patched/alert.jsx +56 -0
- package/template/src/cli/components/ui/patched/button.jsx +45 -0
- package/template/src/cli/components/ui/patched/dialog.jsx +114 -0
- package/template/src/cli/components/ui/patched/sidebar.jsx +660 -0
- package/template/src/cli/components/ui/select.jsx +141 -0
- package/template/src/cli/components/ui/separator.jsx +21 -0
- package/template/src/cli/components/ui/sheet.jsx +115 -0
- package/template/src/cli/components/ui/skeleton.jsx +13 -0
- package/template/src/cli/components/ui/sonner.jsx +22 -0
- package/template/src/cli/components/ui/switch.jsx +25 -0
- package/template/src/cli/components/ui/table.jsx +88 -0
- package/template/src/cli/components/ui/textarea.jsx +16 -0
- package/template/src/cli/components/ui/tooltip.jsx +45 -0
- package/template/src/cli/config/store_keys.mjs +2 -0
- package/template/src/cli/context/data/DataContext.jsx +5 -0
- package/template/src/cli/context/data/DataProvider.jsx +44 -0
- package/template/src/cli/context/data/useBreads.mjs +15 -0
- package/template/src/cli/context/data/useDataContext.mjs +4 -0
- package/template/src/cli/context/session/SessionContext.mjs +4 -0
- package/template/src/cli/context/session/SessionProvider.jsx +31 -0
- package/template/src/cli/context/session/makePermissioner.mjs +34 -0
- package/template/src/cli/context/session/useSessionContext.mjs +6 -0
- package/template/src/cli/context/theme/ThemeContext.mjs +4 -0
- package/template/src/cli/context/theme/ThemeProvider.jsx +49 -0
- package/template/src/cli/context/theme/useThemeContext.mjs +6 -0
- package/template/src/cli/context/ui/UIContext.jsx +5 -0
- package/template/src/cli/context/ui/UIProvider.jsx +16 -0
- package/template/src/cli/context/ui/useUIContext.mjs +4 -0
- package/template/src/cli/context/util.mjs +17 -0
- package/template/src/cli/entry-cli.jsx +33 -0
- package/template/src/cli/hooks/useIsMobile.mjs +19 -0
- package/template/src/cli/hooks/useStoragedState.mjs +63 -0
- package/template/src/cli/index.html +29 -0
- package/template/src/cli/layout/app-sidebar.jsx +25 -0
- package/template/src/cli/layout/main-layout.jsx +63 -0
- package/template/src/cli/layout/nav-last-todos.jsx +72 -0
- package/template/src/cli/layout/nav-main.jsx +39 -0
- package/template/src/cli/layout/nav-user.jsx +105 -0
- package/template/src/cli/layout/prop-switcher.jsx +93 -0
- package/template/src/cli/lib/utils.mjs +10 -0
- package/template/src/cli/pages/Index.jsx +13 -0
- package/template/src/cli/pages/IndexOffline.jsx +13 -0
- package/template/src/cli/pages/IndexOnline.jsx +18 -0
- package/template/src/cli/pages/dash/Dashboard.jsx +29 -0
- package/template/src/cli/pages/offline/Login.jsx +43 -0
- package/template/src/cli/pages/offline/LoginForm.jsx +115 -0
- package/template/src/cli/pages/security/Security.jsx +39 -0
- package/template/src/cli/pages/security/SecurityForm.jsx +106 -0
- package/template/src/cli/pages/todos/TodoActions.jsx +99 -0
- package/template/src/cli/pages/todos/TodoAdd.jsx +43 -0
- package/template/src/cli/pages/todos/TodoList.jsx +60 -0
- package/template/src/cli/pages/todos/Todos.jsx +23 -0
- package/template/src/cli/pages/todos/context/TodosContext.jsx +5 -0
- package/template/src/cli/pages/todos/context/TodosProvider.jsx +191 -0
- package/template/src/cli/pages/todos/context/useTodosContext.mjs +4 -0
- package/template/src/ns/models/Todo.mjs +29 -0
- package/template/src/ns/models/TodoList.mjs +8 -0
- package/template/src/ns/models/User.mjs +40 -0
- package/template/src/server/bot/check_today.mjs +10 -0
- package/template/src/server/io/cache/base.mjs +21 -0
- package/template/src/server/io/db/filter.mjs +92 -0
- package/template/src/server/io/db/todos/delete.mjs +29 -0
- package/template/src/server/io/db/todos/find.mjs +13 -0
- package/template/src/server/io/db/todos/read.mjs +83 -0
- package/template/src/server/io/db/todos/toggle.mjs +37 -0
- package/template/src/server/io/db/todos/upsave.mjs +32 -0
- package/template/src/server/io/db/triggers/user.mjs +13 -0
- package/template/src/server/io/db/users/auth.mjs +132 -0
- package/template/src/server/io/db/users/pwd.mjs +38 -0
- package/template/src/server/io/db/users/save.mjs +17 -0
- package/template/src/server/miolo/auth/basic.mjs +15 -0
- package/template/src/server/miolo/auth/guest.mjs +3 -0
- package/template/src/server/miolo/auth/passport.mjs +73 -0
- package/template/src/server/miolo/cache.mjs +11 -0
- package/template/src/server/miolo/cron/foo.mjs +7 -0
- package/template/src/server/miolo/cron/index.mjs +28 -0
- package/template/src/server/miolo/cron/invalidate.mjs +21 -0
- package/template/src/server/miolo/db.mjs +36 -0
- package/template/src/server/miolo/http.mjs +14 -0
- package/template/src/server/miolo/index.mjs +43 -0
- package/template/src/server/miolo/routes/crud.mjs +16 -0
- package/template/src/server/miolo/routes/index.mjs +8 -0
- package/template/src/server/miolo/ssr/entry-server.jsx +13 -0
- package/template/src/server/miolo/ssr/loader.mjs +18 -0
- package/template/src/server/routes/index.mjs +66 -0
- package/template/src/server/routes/todos/mod.mjs +52 -0
- package/template/src/server/routes/todos/read.mjs +45 -0
- package/template/src/server/routes/todos/special.mjs +47 -0
- package/template/src/server/routes/users/user.mjs +54 -0
- package/template/src/server/server.mjs +10 -0
- package/template/src/server/utils/crypt.mjs +38 -0
- package/template/src/server/utils/io.mjs +15 -0
- package/template/src/server/utils/pwdfor.mjs +25 -0
- package/template/src/server/utils/schema.mjs +22 -0
- package/template/src/static/img/default/profile.png +0 -0
- package/template/src/static/img/favicon.ico +0 -0
- package/template/src/static/img/miolo_logo.png +0 -0
- package/template/src/static/img/miolo_name.png +0 -0
- package/template/src/static/public/manifest.json +21 -0
- package/template/src/static/public/sw.js +79 -0
- package/template/src/static/style/globals.css +156 -0
- package/template/src/static/style/json-tree.css +54 -0
- package/template/src/static/style/skeleton.css +49 -0
- package/bin/prod-build/build-client.mjs +0 -67
- package/bin/prod-build/build-server.mjs +0 -58
- package/bin/prod-run/restart.mjs +0 -9
- package/bin/prod-run/start.mjs +0 -15
- package/bin/prod-run/stop.mjs +0 -20
- package/src/engines/logger/verify.mjs +0 -22
- package/src/middleware/auth/credentials/index.mjs +0 -151
- package/src/middleware/auth/credentials/session/index.mjs +0 -24
- package/src/middleware/auth/credentials/session/store_koa_redis.mjs +0 -3
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: miolo-cli-router
|
|
3
|
+
description: Client-side routing patterns with react-router v7 for miolo applications. Use when implementing page navigation, route structure, or understanding the client-side routing hierarchy in miolo apps. For page data preloading with SSR, see miolo-ssr skill.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Miolo Client-Side Routing
|
|
7
|
+
|
|
8
|
+
Client-side routing patterns using react-router v7 in miolo applications.
|
|
9
|
+
|
|
10
|
+
## Entry Points (DO NOT MODIFY)
|
|
11
|
+
|
|
12
|
+
Miolo manages routing through react-router v7 with two entry points that **should not be modified** except for very specific needs:
|
|
13
|
+
|
|
14
|
+
### Client Entry (BrowserRouter)
|
|
15
|
+
|
|
16
|
+
**File:** `src/cli/entry-cli.jsx`
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
import React from 'react'
|
|
20
|
+
import { hydrateRoot } from 'react-dom/client'
|
|
21
|
+
import { BrowserRouter } from 'react-router'
|
|
22
|
+
import { AppBrowser } from 'miolo-react'
|
|
23
|
+
import App from './App.jsx'
|
|
24
|
+
|
|
25
|
+
import '../static/style/globals.css'
|
|
26
|
+
|
|
27
|
+
const domNode = document.getElementById('root')
|
|
28
|
+
|
|
29
|
+
hydrateRoot(domNode,
|
|
30
|
+
<AppBrowser>
|
|
31
|
+
<BrowserRouter>
|
|
32
|
+
<App/>
|
|
33
|
+
</BrowserRouter>
|
|
34
|
+
</AppBrowser>
|
|
35
|
+
)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Do not modify** - This is the client-side hydration entry point.
|
|
39
|
+
|
|
40
|
+
### Server Entry (StaticRouter)
|
|
41
|
+
|
|
42
|
+
**File:** `src/server/miolo/ssr/entry-server.jsx`
|
|
43
|
+
|
|
44
|
+
Uses `StaticRouter` for server-side rendering. **Do not modify** except for specific SSR needs.
|
|
45
|
+
|
|
46
|
+
## Developer Starting Points
|
|
47
|
+
|
|
48
|
+
Developers build the application from these two main components:
|
|
49
|
+
|
|
50
|
+
### 1. App.jsx - Context Providers
|
|
51
|
+
|
|
52
|
+
**File:** `src/cli/App.jsx`
|
|
53
|
+
|
|
54
|
+
The root application component that sets up context providers:
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
import React from 'react'
|
|
58
|
+
import { intre_locale_init } from 'intre'
|
|
59
|
+
|
|
60
|
+
import ThemeProvider from '#cli/context/theme/ThemeProvider.jsx'
|
|
61
|
+
import SessionProvider from '#cli/context/session/SessionProvider.jsx'
|
|
62
|
+
import UIProvider from '#cli/context/ui/UIProvider.jsx'
|
|
63
|
+
import DataProvider from '#cli/context/data/DataProvider.jsx'
|
|
64
|
+
|
|
65
|
+
import Index from '#cli/pages/Index.jsx'
|
|
66
|
+
|
|
67
|
+
intre_locale_init('es')
|
|
68
|
+
|
|
69
|
+
const App = () => {
|
|
70
|
+
return (
|
|
71
|
+
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
|
72
|
+
<UIProvider>
|
|
73
|
+
<SessionProvider>
|
|
74
|
+
<DataProvider>
|
|
75
|
+
<Index/>
|
|
76
|
+
</DataProvider>
|
|
77
|
+
</SessionProvider>
|
|
78
|
+
</UIProvider>
|
|
79
|
+
</ThemeProvider>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default App
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Provider hierarchy** (outer to inner):
|
|
87
|
+
1. **ThemeProvider** - Dark/light theme management
|
|
88
|
+
2. **UIProvider** - UI state (sidebar, modals, etc.)
|
|
89
|
+
3. **SessionProvider** - Authentication and user session
|
|
90
|
+
4. **DataProvider** - Application data and API calls
|
|
91
|
+
|
|
92
|
+
**Key points:**
|
|
93
|
+
- Locale initialization with `intre_locale_init()`
|
|
94
|
+
- Predefined providers - can be modified or extended
|
|
95
|
+
- Renders `<Index/>` as the main routing component
|
|
96
|
+
|
|
97
|
+
### 2. Index.jsx - Main Router
|
|
98
|
+
|
|
99
|
+
**File:** `src/cli/pages/Index.jsx`
|
|
100
|
+
|
|
101
|
+
The main routing component that splits between authenticated and unauthenticated states:
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
import React from 'react'
|
|
105
|
+
import useSessionContext from '#cli/context/session/useSessionContext.mjs'
|
|
106
|
+
import IndexOnline from '#cli/pages/IndexOnline.jsx'
|
|
107
|
+
import IndexOffline from '#cli/pages/IndexOffline.jsx'
|
|
108
|
+
|
|
109
|
+
export default function Index() {
|
|
110
|
+
const { authenticated } = useSessionContext()
|
|
111
|
+
|
|
112
|
+
if (!authenticated) {
|
|
113
|
+
return <IndexOffline/>
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return <IndexOnline/>
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Pattern:**
|
|
121
|
+
- Uses `SessionProvider` to check authentication
|
|
122
|
+
- Routes to `IndexOffline` for unauthenticated users
|
|
123
|
+
- Routes to `IndexOnline` for authenticated users
|
|
124
|
+
- Miolo handles session management by default
|
|
125
|
+
|
|
126
|
+
## Authenticated Routes (IndexOnline)
|
|
127
|
+
|
|
128
|
+
**File:** `src/cli/pages/IndexOnline.jsx`
|
|
129
|
+
|
|
130
|
+
Routes for authenticated users using react-router v7 with nested layout:
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
import React from 'react'
|
|
134
|
+
import { Routes, Route } from 'react-router'
|
|
135
|
+
import MainLayout from '#cli/layout/main-layout.jsx'
|
|
136
|
+
import Dashboard from '#cli/pages/dash/Dashboard.jsx'
|
|
137
|
+
import Security from '#cli/pages/security/Security.jsx'
|
|
138
|
+
|
|
139
|
+
export default function IndexOnline() {
|
|
140
|
+
return (
|
|
141
|
+
<Routes>
|
|
142
|
+
<Route path={'/'} element={<MainLayout/>}>
|
|
143
|
+
<Route index element={<Dashboard/>}/>
|
|
144
|
+
<Route path={'security'} element={<Security/>}/>
|
|
145
|
+
<Route path={'*'} element={<Dashboard/>}/>
|
|
146
|
+
</Route>
|
|
147
|
+
</Routes>
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Key patterns:**
|
|
153
|
+
- **Layout route** - `MainLayout` as parent route element
|
|
154
|
+
- **Nested routes** - Child routes render inside layout's `<Outlet/>`
|
|
155
|
+
- **Index route** - Default child route for `/` path
|
|
156
|
+
- **Catch-all route** - `path={'*'}` redirects to Dashboard
|
|
157
|
+
|
|
158
|
+
**Layout component must use `<Outlet/>`:**
|
|
159
|
+
```javascript
|
|
160
|
+
import { Outlet } from 'react-router'
|
|
161
|
+
|
|
162
|
+
function MainLayout() {
|
|
163
|
+
return (
|
|
164
|
+
<div>
|
|
165
|
+
<Sidebar />
|
|
166
|
+
<main>
|
|
167
|
+
<Outlet /> {/* Child routes render here */}
|
|
168
|
+
</main>
|
|
169
|
+
</div>
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Unauthenticated Routes (IndexOffline)
|
|
175
|
+
|
|
176
|
+
**File:** `src/cli/pages/IndexOffline.jsx`
|
|
177
|
+
|
|
178
|
+
Routes for unauthenticated users:
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
import React from 'react'
|
|
182
|
+
import { Routes, Route } from 'react-router'
|
|
183
|
+
import Login from '#cli/pages/offline/Login.jsx'
|
|
184
|
+
|
|
185
|
+
export default function IndexOffline() {
|
|
186
|
+
return (
|
|
187
|
+
<Routes>
|
|
188
|
+
<Route index element={<Login />} />
|
|
189
|
+
<Route path="*" element={<Login />} />
|
|
190
|
+
</Routes>
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Key patterns:**
|
|
196
|
+
- No layout wrapper (full-page login/register)
|
|
197
|
+
- Index route shows Login
|
|
198
|
+
- Catch-all redirects to Login
|
|
199
|
+
- Minimal routes for auth flow
|
|
200
|
+
|
|
201
|
+
## Page Organization
|
|
202
|
+
|
|
203
|
+
Pages are organized in `src/cli/pages/` by feature/section:
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
src/cli/pages/
|
|
207
|
+
├── Index.jsx # Main router (auth split)
|
|
208
|
+
├── IndexOnline.jsx # Authenticated routes
|
|
209
|
+
├── IndexOffline.jsx # Unauthenticated routes
|
|
210
|
+
├── dash/ # Dashboard pages
|
|
211
|
+
│ └── Dashboard.jsx
|
|
212
|
+
├── offline/ # Login/register pages
|
|
213
|
+
│ ├── Login.jsx
|
|
214
|
+
│ └── Register.jsx
|
|
215
|
+
├── security/ # User profile, security
|
|
216
|
+
│ └── Profile.jsx
|
|
217
|
+
└── todos/ # Feature-specific pages
|
|
218
|
+
├── TodosPage.jsx
|
|
219
|
+
└── TodoDetail.jsx
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## React Router v7 Patterns
|
|
223
|
+
|
|
224
|
+
### Basic Route
|
|
225
|
+
|
|
226
|
+
```javascript
|
|
227
|
+
<Route path="/todos" element={<TodosPage />} />
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Route with Parameters
|
|
231
|
+
|
|
232
|
+
```javascript
|
|
233
|
+
<Route path="/todo/:id" element={<TodoDetail />} />
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Access params in component:
|
|
237
|
+
```javascript
|
|
238
|
+
import { useParams } from 'react-router'
|
|
239
|
+
|
|
240
|
+
function TodoDetail() {
|
|
241
|
+
const { id } = useParams()
|
|
242
|
+
return <div>Todo ID: {id}</div>
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Nested Routes
|
|
247
|
+
|
|
248
|
+
```javascript
|
|
249
|
+
<Route path="/todos" element={<TodosLayout />}>
|
|
250
|
+
<Route index element={<TodosList />} />
|
|
251
|
+
<Route path=":id" element={<TodoDetail />} />
|
|
252
|
+
<Route path="new" element={<TodoCreate />} />
|
|
253
|
+
</Route>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Parent component needs `<Outlet>`:
|
|
257
|
+
```javascript
|
|
258
|
+
import { Outlet } from 'react-router'
|
|
259
|
+
|
|
260
|
+
function TodosLayout() {
|
|
261
|
+
return (
|
|
262
|
+
<div>
|
|
263
|
+
<h1>Todos Section</h1>
|
|
264
|
+
<Outlet /> {/* Child routes render here */}
|
|
265
|
+
</div>
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Programmatic Navigation
|
|
271
|
+
|
|
272
|
+
```javascript
|
|
273
|
+
import { useNavigate } from 'react-router'
|
|
274
|
+
|
|
275
|
+
function MyComponent() {
|
|
276
|
+
const navigate = useNavigate()
|
|
277
|
+
|
|
278
|
+
const handleClick = () => {
|
|
279
|
+
navigate('/todos')
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return <button onClick={handleClick}>Go to Todos</button>
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Link Component
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
import { Link } from 'react-router'
|
|
290
|
+
|
|
291
|
+
function Navigation() {
|
|
292
|
+
return (
|
|
293
|
+
<nav>
|
|
294
|
+
<Link to="/dash">Dashboard</Link>
|
|
295
|
+
<Link to="/todos">Todos</Link>
|
|
296
|
+
<Link to="/profile">Profile</Link>
|
|
297
|
+
</nav>
|
|
298
|
+
)
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Adding a New Route
|
|
303
|
+
|
|
304
|
+
1. **Create page component** in `src/cli/pages/[feature]/`:
|
|
305
|
+
```javascript
|
|
306
|
+
// pages/items/ItemsPage.jsx
|
|
307
|
+
export default function ItemsPage() {
|
|
308
|
+
return <div>Items Page</div>
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
2. **Add route** to `IndexOnline.jsx`:
|
|
313
|
+
```javascript
|
|
314
|
+
import ItemsPage from '#cli/pages/items/ItemsPage.jsx'
|
|
315
|
+
|
|
316
|
+
<Route path="/items" element={<ItemsPage />} />
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
3. **Add navigation** in layout/sidebar:
|
|
320
|
+
```javascript
|
|
321
|
+
<Link to="/items">Items</Link>
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Best Practices
|
|
325
|
+
|
|
326
|
+
1. **Don't modify entry points** - `entry-cli.jsx` should remain unchanged
|
|
327
|
+
2. **Use Index.jsx pattern** - Split authenticated/unauthenticated routes
|
|
328
|
+
3. **Organize by feature** - Group related pages in subdirectories
|
|
329
|
+
4. **Use layouts** - Wrap authenticated routes in `MainLayout`
|
|
330
|
+
5. **Handle 404s** - Always include catch-all route with `path="*"`
|
|
331
|
+
6. **Use import aliases** - Always use `#cli/` prefix for imports
|
|
332
|
+
7. **Programmatic navigation** - Use `useNavigate()` for dynamic navigation
|
|
333
|
+
8. **Protected routes** - Let `Index.jsx` handle auth, don't duplicate checks
|
|
334
|
+
|
|
335
|
+
## Common Patterns
|
|
336
|
+
|
|
337
|
+
### Redirect After Action
|
|
338
|
+
|
|
339
|
+
```javascript
|
|
340
|
+
function CreateTodo() {
|
|
341
|
+
const navigate = useNavigate()
|
|
342
|
+
|
|
343
|
+
const handleSubmit = async (data) => {
|
|
344
|
+
await createTodo(data)
|
|
345
|
+
navigate('/todos') // Redirect after creation
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return <form onSubmit={handleSubmit}>...</form>
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Conditional Rendering by Route
|
|
353
|
+
|
|
354
|
+
```javascript
|
|
355
|
+
import { useLocation } from 'react-router'
|
|
356
|
+
|
|
357
|
+
function Header() {
|
|
358
|
+
const location = useLocation()
|
|
359
|
+
const isDashboard = location.pathname === '/dash'
|
|
360
|
+
|
|
361
|
+
return (
|
|
362
|
+
<header>
|
|
363
|
+
{isDashboard && <DashboardActions />}
|
|
364
|
+
</header>
|
|
365
|
+
)
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Query Parameters
|
|
370
|
+
|
|
371
|
+
```javascript
|
|
372
|
+
import { useSearchParams } from 'react-router'
|
|
373
|
+
|
|
374
|
+
function SearchPage() {
|
|
375
|
+
const [searchParams, setSearchParams] = useSearchParams()
|
|
376
|
+
|
|
377
|
+
const query = searchParams.get('q')
|
|
378
|
+
|
|
379
|
+
const handleSearch = (newQuery) => {
|
|
380
|
+
setSearchParams({ q: newQuery })
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return <div>Search: {query}</div>
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
## Examples from miolo-sample
|
|
388
|
+
|
|
389
|
+
See actual implementations:
|
|
390
|
+
- `src/cli/entry-cli.jsx` - BrowserRouter entry point
|
|
391
|
+
- `src/cli/App.jsx` - Context providers hierarchy
|
|
392
|
+
- `src/cli/pages/Index.jsx` - Auth split routing
|
|
393
|
+
- `src/cli/pages/IndexOnline.jsx` - Authenticated routes
|
|
394
|
+
- `src/cli/pages/IndexOffline.jsx` - Unauthenticated routes
|