@lastbrain/app 0.1.8 → 0.1.10
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/dist/scripts/init-app.js +7 -10
- package/package.json +3 -2
- package/src/app-shell/(admin)/layout.tsx +13 -0
- package/src/app-shell/(auth)/layout.tsx +13 -0
- package/src/app-shell/(public)/page.tsx +11 -0
- package/src/app-shell/layout.tsx +5 -0
- package/src/app-shell/not-found.tsx +28 -0
- package/src/auth/authHelpers.ts +24 -0
- package/src/auth/useAuthSession.ts +54 -0
- package/src/cli.ts +96 -0
- package/src/index.ts +21 -0
- package/src/layouts/AdminLayout.tsx +7 -0
- package/src/layouts/AppProviders.tsx +61 -0
- package/src/layouts/AuthLayout.tsx +7 -0
- package/src/layouts/PublicLayout.tsx +7 -0
- package/src/layouts/RootLayout.tsx +27 -0
- package/src/modules/module-loader.ts +14 -0
- package/src/scripts/README.md +262 -0
- package/src/scripts/db-init.ts +338 -0
- package/src/scripts/db-migrations-sync.ts +86 -0
- package/src/scripts/dev-sync.ts +218 -0
- package/src/scripts/init-app.ts +1076 -0
- package/src/scripts/module-add.ts +242 -0
- package/src/scripts/module-build.ts +502 -0
- package/src/scripts/module-create.ts +809 -0
- package/src/scripts/module-list.ts +37 -0
- package/src/scripts/module-remove.ts +367 -0
- package/src/scripts/readme-build.ts +60 -0
- package/src/styles.css +3 -0
- package/src/templates/AuthGuidePage.tsx +68 -0
- package/src/templates/DefaultDoc.tsx +462 -0
- package/src/templates/DocPage.tsx +381 -0
- package/src/templates/DocsPageWithModules.tsx +22 -0
- package/src/templates/MigrationsGuidePage.tsx +61 -0
- package/src/templates/ModuleGuidePage.tsx +71 -0
- package/src/templates/SimpleDocPage.tsx +587 -0
- package/src/templates/SimpleHomePage.tsx +385 -0
- package/src/templates/env.example/.env.example +6 -0
- package/src/templates/migrations/20201010100000_app_base.sql +228 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Card, CardBody, CardHeader, Chip, Snippet } from "@lastbrain/ui";
|
|
3
|
+
import {
|
|
4
|
+
Rocket,
|
|
5
|
+
Building2,
|
|
6
|
+
BookOpen,
|
|
7
|
+
Database,
|
|
8
|
+
Palette,
|
|
9
|
+
Link as LinkIcon,
|
|
10
|
+
} from "lucide-react";
|
|
11
|
+
|
|
12
|
+
export function DefaultDocumentation() {
|
|
13
|
+
return (
|
|
14
|
+
<div className="space-y-6">
|
|
15
|
+
<Card id="section-welcome" className="scroll-mt-32">
|
|
16
|
+
<CardHeader>
|
|
17
|
+
<div className="flex items-center justify-between w-full">
|
|
18
|
+
<h1 className="text-3xl font-bold">Documentation LastBrain</h1>
|
|
19
|
+
<Chip color="primary" variant="flat">
|
|
20
|
+
v1.0.0
|
|
21
|
+
</Chip>
|
|
22
|
+
</div>
|
|
23
|
+
</CardHeader>
|
|
24
|
+
<CardBody className="space-y-6">
|
|
25
|
+
<div>
|
|
26
|
+
<p className="text-slate-600 dark:text-slate-400 text-lg">
|
|
27
|
+
LastBrain est un framework modulaire pour créer des applications
|
|
28
|
+
Next.js avec une architecture basée sur des modules réutilisables.
|
|
29
|
+
</p>
|
|
30
|
+
</div>
|
|
31
|
+
</CardBody>
|
|
32
|
+
</Card>
|
|
33
|
+
|
|
34
|
+
<Card id="section-quickstart" className="scroll-mt-32">
|
|
35
|
+
<CardHeader>
|
|
36
|
+
<h2 className="text-2xl font-semibold flex items-center gap-2">
|
|
37
|
+
<Rocket size={24} />
|
|
38
|
+
Démarrage rapide
|
|
39
|
+
</h2>
|
|
40
|
+
</CardHeader>
|
|
41
|
+
<CardBody className="space-y-4">
|
|
42
|
+
<div>
|
|
43
|
+
<h3 className="text-lg font-semibold mb-2">Installation</h3>
|
|
44
|
+
<Snippet symbol="" hideSymbol className="text-sm mb-2">
|
|
45
|
+
pnpm install
|
|
46
|
+
</Snippet>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div>
|
|
50
|
+
<h3 className="text-lg font-semibold mb-2">
|
|
51
|
+
Initialiser la base de données
|
|
52
|
+
</h3>
|
|
53
|
+
<Snippet symbol="" hideSymbol className="text-sm mb-2">
|
|
54
|
+
pnpm db:init
|
|
55
|
+
</Snippet>
|
|
56
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
57
|
+
Démarre Supabase en local et applique les migrations
|
|
58
|
+
</p>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div>
|
|
62
|
+
<h3 className="text-lg font-semibold mb-2">Ajouter des modules</h3>
|
|
63
|
+
<Snippet symbol="" hideSymbol className="text-sm mb-2">
|
|
64
|
+
pnpm lastbrain list-modules
|
|
65
|
+
</Snippet>
|
|
66
|
+
<Snippet symbol="" hideSymbol className="text-sm mb-2">
|
|
67
|
+
pnpm lastbrain add-module auth
|
|
68
|
+
</Snippet>
|
|
69
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
70
|
+
Modules disponibles : <strong>auth</strong> (authentification),{" "}
|
|
71
|
+
<strong>ai</strong> (génération IA)
|
|
72
|
+
</p>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div>
|
|
76
|
+
<h3 className="text-lg font-semibold mb-2">
|
|
77
|
+
Construire les modules
|
|
78
|
+
</h3>
|
|
79
|
+
<Snippet symbol="" hideSymbol className="text-sm mb-2">
|
|
80
|
+
pnpm build:modules
|
|
81
|
+
</Snippet>
|
|
82
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
83
|
+
Génère les pages et routes à partir des modules installés
|
|
84
|
+
</p>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<div>
|
|
88
|
+
<h3 className="text-lg font-semibold mb-2">
|
|
89
|
+
Lancer le serveur de développement
|
|
90
|
+
</h3>
|
|
91
|
+
<Snippet symbol="" hideSymbol className="text-sm mb-2">
|
|
92
|
+
pnpm dev
|
|
93
|
+
</Snippet>
|
|
94
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
95
|
+
Ouvre l'application sur{" "}
|
|
96
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
97
|
+
http://localhost:3000
|
|
98
|
+
</code>
|
|
99
|
+
</p>
|
|
100
|
+
</div>
|
|
101
|
+
</CardBody>
|
|
102
|
+
</Card>
|
|
103
|
+
|
|
104
|
+
<Card id="section-architecture" className="scroll-mt-32">
|
|
105
|
+
<CardHeader>
|
|
106
|
+
<h2 className="text-2xl font-semibold flex items-center gap-2">
|
|
107
|
+
<Building2 size={24} />
|
|
108
|
+
Architecture
|
|
109
|
+
</h2>
|
|
110
|
+
</CardHeader>
|
|
111
|
+
<CardBody className="space-y-4">
|
|
112
|
+
<p className="text-slate-600 dark:text-slate-400">
|
|
113
|
+
Le projet est organisé en monorepo avec pnpm workspaces :
|
|
114
|
+
</p>
|
|
115
|
+
|
|
116
|
+
<div className="space-y-3">
|
|
117
|
+
<div className="border-l-4 border-blue-500 pl-4">
|
|
118
|
+
<h3 className="font-semibold text-lg mb-1">
|
|
119
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
120
|
+
@lastbrain/app
|
|
121
|
+
</code>
|
|
122
|
+
</h3>
|
|
123
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
124
|
+
Framework principal et CLI. Contient les layouts, scripts de
|
|
125
|
+
build, templates et la logique de génération des pages.
|
|
126
|
+
</p>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<div className="border-l-4 border-green-500 pl-4">
|
|
130
|
+
<h3 className="font-semibold text-lg mb-1">
|
|
131
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
132
|
+
@lastbrain/core
|
|
133
|
+
</code>
|
|
134
|
+
</h3>
|
|
135
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
136
|
+
Utilitaires et types partagés. Contient les helpers Supabase,
|
|
137
|
+
fonctions serveur et types TypeScript communs.
|
|
138
|
+
</p>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<div className="border-l-4 border-purple-500 pl-4">
|
|
142
|
+
<h3 className="font-semibold text-lg mb-1">
|
|
143
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
144
|
+
@lastbrain/ui
|
|
145
|
+
</code>
|
|
146
|
+
</h3>
|
|
147
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
148
|
+
Composants UI réutilisables basés sur NextUI et Tailwind CSS.
|
|
149
|
+
Fournit les composants Card, Button, Input, etc.
|
|
150
|
+
</p>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<div className="border-l-4 border-orange-500 pl-4">
|
|
154
|
+
<h3 className="font-semibold text-lg mb-1">
|
|
155
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
156
|
+
@lastbrain/module-*
|
|
157
|
+
</code>
|
|
158
|
+
</h3>
|
|
159
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
160
|
+
Modules fonctionnels (auth, ai, etc.). Chaque module contient
|
|
161
|
+
ses pages, APIs, composants, migrations et documentation.
|
|
162
|
+
</p>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
</CardBody>
|
|
166
|
+
</Card>
|
|
167
|
+
|
|
168
|
+
<Card id="section-create-module" className="scroll-mt-32">
|
|
169
|
+
<CardHeader>
|
|
170
|
+
<h2 className="text-2xl font-semibold flex items-center gap-2">
|
|
171
|
+
<BookOpen size={24} />
|
|
172
|
+
Documentation des modules
|
|
173
|
+
</h2>
|
|
174
|
+
</CardHeader>
|
|
175
|
+
<CardBody className="space-y-4">
|
|
176
|
+
<div>
|
|
177
|
+
<h3 className="text-lg font-semibold mb-2">Commande CLI</h3>
|
|
178
|
+
<Snippet symbol="" hideSymbol className="text-sm mb-2">
|
|
179
|
+
pnpm lastbrain create-module mon-module
|
|
180
|
+
</Snippet>
|
|
181
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-4">
|
|
182
|
+
Crée un nouveau module dans{" "}
|
|
183
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
184
|
+
packages/module-mon-module
|
|
185
|
+
</code>
|
|
186
|
+
</p>
|
|
187
|
+
</div>
|
|
188
|
+
|
|
189
|
+
<div>
|
|
190
|
+
<h3 className="text-lg font-semibold mb-2">
|
|
191
|
+
Structure d'un module
|
|
192
|
+
</h3>
|
|
193
|
+
<div className="bg-slate-50 dark:bg-slate-900 p-4 rounded-lg text-sm font-mono">
|
|
194
|
+
<div className="space-y-1">
|
|
195
|
+
<div>📁 module-mon-module/</div>
|
|
196
|
+
<div className="ml-4">├── 📄 package.json</div>
|
|
197
|
+
<div className="ml-4">├── 📄 mon-module.build.config.ts</div>
|
|
198
|
+
<div className="ml-4">└── 📁 src/</div>
|
|
199
|
+
<div className="ml-8">├── 📄 index.ts</div>
|
|
200
|
+
<div className="ml-8">├── 📄 server.ts</div>
|
|
201
|
+
<div className="ml-8">├── 📁 web/</div>
|
|
202
|
+
<div className="ml-8">├── 📁 api/</div>
|
|
203
|
+
<div className="ml-8">├── 📁 components/</div>
|
|
204
|
+
<div className="ml-8">└── 📁 supabase/</div>
|
|
205
|
+
<div className="ml-12">└── 📁 migrations/</div>
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
<div>
|
|
211
|
+
<h3 className="text-lg font-semibold mb-2">
|
|
212
|
+
Configuration du module
|
|
213
|
+
</h3>
|
|
214
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
215
|
+
Le fichier{" "}
|
|
216
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
217
|
+
{"{slug}"}.build.config.ts
|
|
218
|
+
</code>{" "}
|
|
219
|
+
définit les pages et APIs :
|
|
220
|
+
</p>
|
|
221
|
+
<div className="bg-slate-50 dark:bg-slate-900 p-4 rounded-lg text-sm font-mono overflow-x-auto">
|
|
222
|
+
<pre>{`export default {
|
|
223
|
+
name: "Mon Module",
|
|
224
|
+
description: "Description du module",
|
|
225
|
+
pages: [
|
|
226
|
+
{
|
|
227
|
+
path: "/ma-page",
|
|
228
|
+
component: "./web/MaPage",
|
|
229
|
+
layout: "auth"
|
|
230
|
+
}
|
|
231
|
+
],
|
|
232
|
+
apis: [
|
|
233
|
+
{
|
|
234
|
+
path: "/api/mon-api",
|
|
235
|
+
handler: "./api/mon-api"
|
|
236
|
+
}
|
|
237
|
+
]
|
|
238
|
+
}`}</pre>
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
</CardBody>
|
|
242
|
+
</Card>
|
|
243
|
+
|
|
244
|
+
<Card id="section-database" className="scroll-mt-32">
|
|
245
|
+
<CardHeader>
|
|
246
|
+
<h2 className="text-2xl font-semibold flex items-center gap-2">
|
|
247
|
+
<Database size={24} />
|
|
248
|
+
Base de données
|
|
249
|
+
</h2>
|
|
250
|
+
</CardHeader>
|
|
251
|
+
<CardBody className="space-y-4">
|
|
252
|
+
<div>
|
|
253
|
+
<h3 className="text-lg font-semibold mb-2">Supabase local</h3>
|
|
254
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-3">
|
|
255
|
+
LastBrain utilise Supabase pour la base de données et
|
|
256
|
+
l'authentification.
|
|
257
|
+
</p>
|
|
258
|
+
|
|
259
|
+
<div className="space-y-3">
|
|
260
|
+
<div>
|
|
261
|
+
<p className="text-sm font-medium mb-1">Démarrer Supabase :</p>
|
|
262
|
+
<Snippet symbol="" hideSymbol className="text-sm">
|
|
263
|
+
pnpm db:init
|
|
264
|
+
</Snippet>
|
|
265
|
+
</div>
|
|
266
|
+
|
|
267
|
+
<div>
|
|
268
|
+
<p className="text-sm font-medium mb-1">
|
|
269
|
+
Synchroniser les migrations :
|
|
270
|
+
</p>
|
|
271
|
+
<Snippet symbol="" hideSymbol className="text-sm">
|
|
272
|
+
pnpm db:migrations:sync
|
|
273
|
+
</Snippet>
|
|
274
|
+
</div>
|
|
275
|
+
|
|
276
|
+
<div>
|
|
277
|
+
<p className="text-sm font-medium mb-1">
|
|
278
|
+
Créer une migration :
|
|
279
|
+
</p>
|
|
280
|
+
<Snippet symbol="" hideSymbol className="text-sm">
|
|
281
|
+
supabase migration new ma_migration
|
|
282
|
+
</Snippet>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
</div>
|
|
286
|
+
|
|
287
|
+
<div>
|
|
288
|
+
<h3 className="text-lg font-semibold mb-2">
|
|
289
|
+
Migrations des modules
|
|
290
|
+
</h3>
|
|
291
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
292
|
+
Les modules peuvent avoir leurs propres migrations dans{" "}
|
|
293
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
294
|
+
supabase/migrations/
|
|
295
|
+
</code>
|
|
296
|
+
. Elles sont automatiquement synchronisées lors du build.
|
|
297
|
+
</p>
|
|
298
|
+
</div>
|
|
299
|
+
</CardBody>
|
|
300
|
+
</Card>
|
|
301
|
+
|
|
302
|
+
<Card id="section-ui" className="scroll-mt-32">
|
|
303
|
+
<CardHeader>
|
|
304
|
+
<h2 className="text-2xl font-semibold flex items-center gap-2">
|
|
305
|
+
<Palette size={24} />
|
|
306
|
+
Interface utilisateur
|
|
307
|
+
</h2>
|
|
308
|
+
</CardHeader>
|
|
309
|
+
<CardBody className="space-y-4">
|
|
310
|
+
<div>
|
|
311
|
+
<h3 className="text-lg font-semibold mb-2">Composants NextUI</h3>
|
|
312
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-3">
|
|
313
|
+
Le package{" "}
|
|
314
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
315
|
+
@lastbrain/ui
|
|
316
|
+
</code>
|
|
317
|
+
réexporte les composants NextUI avec une configuration Tailwind
|
|
318
|
+
personnalisée.
|
|
319
|
+
</p>
|
|
320
|
+
</div>
|
|
321
|
+
|
|
322
|
+
<div>
|
|
323
|
+
<h3 className="text-lg font-semibold mb-2">Thèmes</h3>
|
|
324
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
325
|
+
Le mode sombre/clair est géré par{" "}
|
|
326
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
327
|
+
next-themes
|
|
328
|
+
</code>
|
|
329
|
+
. Le switch est disponible dans le header de l'application.
|
|
330
|
+
</p>
|
|
331
|
+
</div>
|
|
332
|
+
|
|
333
|
+
<div>
|
|
334
|
+
<h3 className="text-lg font-semibold mb-2">Tailwind CSS v4</h3>
|
|
335
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
336
|
+
Le projet utilise Tailwind CSS v4 avec un preset personnalisé
|
|
337
|
+
partagé via{" "}
|
|
338
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
339
|
+
@lastbrain/ui/tailwind.preset
|
|
340
|
+
</code>
|
|
341
|
+
.
|
|
342
|
+
</p>
|
|
343
|
+
</div>
|
|
344
|
+
</CardBody>
|
|
345
|
+
</Card>
|
|
346
|
+
|
|
347
|
+
<Card id="section-module-docs" className="scroll-mt-32">
|
|
348
|
+
<CardHeader>
|
|
349
|
+
<h2 className="text-2xl font-semibold flex items-center gap-2">
|
|
350
|
+
<BookOpen size={24} />
|
|
351
|
+
Documenter ses modules
|
|
352
|
+
</h2>
|
|
353
|
+
</CardHeader>
|
|
354
|
+
<CardBody className="space-y-4">
|
|
355
|
+
<p className="text-slate-600 dark:text-slate-400">
|
|
356
|
+
Chaque module peut exporter un composant de documentation qui sera
|
|
357
|
+
automatiquement intégré dans cette page.
|
|
358
|
+
</p>
|
|
359
|
+
|
|
360
|
+
<div>
|
|
361
|
+
<h3 className="text-lg font-semibold mb-2">
|
|
362
|
+
Créer une documentation
|
|
363
|
+
</h3>
|
|
364
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
365
|
+
Dans votre module, créez{" "}
|
|
366
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
367
|
+
src/components/Doc.tsx
|
|
368
|
+
</code>{" "}
|
|
369
|
+
:
|
|
370
|
+
</p>
|
|
371
|
+
<div className="bg-slate-50 dark:bg-slate-900 p-4 rounded-lg text-sm font-mono overflow-x-auto">
|
|
372
|
+
<pre>{`export function MonModuleDoc() {
|
|
373
|
+
return (
|
|
374
|
+
<div>
|
|
375
|
+
<h1>Mon Module</h1>
|
|
376
|
+
<p>Description...</p>
|
|
377
|
+
</div>
|
|
378
|
+
);
|
|
379
|
+
}`}</pre>
|
|
380
|
+
</div>
|
|
381
|
+
</div>
|
|
382
|
+
|
|
383
|
+
<div>
|
|
384
|
+
<h3 className="text-lg font-semibold mb-2">
|
|
385
|
+
Exporter la documentation
|
|
386
|
+
</h3>
|
|
387
|
+
<p className="text-sm text-slate-600 dark:text-slate-400 mb-2">
|
|
388
|
+
Dans{" "}
|
|
389
|
+
<code className="text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded">
|
|
390
|
+
src/index.ts
|
|
391
|
+
</code>{" "}
|
|
392
|
+
:
|
|
393
|
+
</p>
|
|
394
|
+
<div className="bg-slate-50 dark:bg-slate-900 p-4 rounded-lg text-sm font-mono">
|
|
395
|
+
<pre>{`export { MonModuleDoc } from "./components/Doc.js";`}</pre>
|
|
396
|
+
</div>
|
|
397
|
+
</div>
|
|
398
|
+
</CardBody>
|
|
399
|
+
</Card>
|
|
400
|
+
|
|
401
|
+
<Card id="section-links" className="scroll-mt-32">
|
|
402
|
+
<CardHeader>
|
|
403
|
+
<h2 className="text-2xl font-semibold flex items-center gap-2">
|
|
404
|
+
<LinkIcon size={24} />
|
|
405
|
+
Liens utiles
|
|
406
|
+
</h2>
|
|
407
|
+
</CardHeader>
|
|
408
|
+
<CardBody>
|
|
409
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
410
|
+
<a
|
|
411
|
+
href="https://nextjs.org/docs"
|
|
412
|
+
target="_blank"
|
|
413
|
+
rel="noopener noreferrer"
|
|
414
|
+
className="p-4 border border-slate-200 dark:border-slate-700 rounded-lg hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors"
|
|
415
|
+
>
|
|
416
|
+
<h3 className="font-semibold mb-1">Next.js</h3>
|
|
417
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
418
|
+
Documentation officielle
|
|
419
|
+
</p>
|
|
420
|
+
</a>
|
|
421
|
+
|
|
422
|
+
<a
|
|
423
|
+
href="https://supabase.com/docs"
|
|
424
|
+
target="_blank"
|
|
425
|
+
rel="noopener noreferrer"
|
|
426
|
+
className="p-4 border border-slate-200 dark:border-slate-700 rounded-lg hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors"
|
|
427
|
+
>
|
|
428
|
+
<h3 className="font-semibold mb-1">Supabase</h3>
|
|
429
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
430
|
+
Documentation officielle
|
|
431
|
+
</p>
|
|
432
|
+
</a>
|
|
433
|
+
|
|
434
|
+
<a
|
|
435
|
+
href="https://nextui.org/docs"
|
|
436
|
+
target="_blank"
|
|
437
|
+
rel="noopener noreferrer"
|
|
438
|
+
className="p-4 border border-slate-200 dark:border-slate-700 rounded-lg hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors"
|
|
439
|
+
>
|
|
440
|
+
<h3 className="font-semibold mb-1">NextUI</h3>
|
|
441
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
442
|
+
Composants UI
|
|
443
|
+
</p>
|
|
444
|
+
</a>
|
|
445
|
+
|
|
446
|
+
<a
|
|
447
|
+
href="https://tailwindcss.com/docs"
|
|
448
|
+
target="_blank"
|
|
449
|
+
rel="noopener noreferrer"
|
|
450
|
+
className="p-4 border border-slate-200 dark:border-slate-700 rounded-lg hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors"
|
|
451
|
+
>
|
|
452
|
+
<h3 className="font-semibold mb-1">Tailwind CSS</h3>
|
|
453
|
+
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
454
|
+
Framework CSS
|
|
455
|
+
</p>
|
|
456
|
+
</a>
|
|
457
|
+
</div>
|
|
458
|
+
</CardBody>
|
|
459
|
+
</Card>
|
|
460
|
+
</div>
|
|
461
|
+
);
|
|
462
|
+
}
|