@riligar/agents-kit 1.15.0 → 1.16.0
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/.agent/skills/riligar-design-system/SKILL.md +1 -0
- package/.agent/skills/riligar-dev-auth-elysia/SKILL.md +2 -2
- package/.agent/skills/riligar-dev-dashboard/SKILL.md +331 -1
- package/.agent/skills/riligar-dev-dashboard/references/dependencies.md +44 -0
- package/.agent/skills/riligar-dev-manager/SKILL.md +13 -9
- package/.agent/skills/riligar-dev-website/SKILL.md +1 -1
- package/.agent/skills/riligar-dev-website-seo/SKILL.md +1 -1
- package/.agent/skills/riligar-infra-cloudfare/SKILL.md +437 -0
- package/.agent/skills/riligar-infra-cloudfare/references/cloudflare-api.md +139 -0
- package/.agent/skills/riligar-infra-cloudfare/references/email-routing.md +262 -0
- package/.agent/skills/riligar-infra-cloudfare/references/r2-storage.md +333 -0
- package/.agent/skills/riligar-infra-fly/SKILL.md +38 -1
- package/.agent/skills/riligar-infra-stripe/SKILL.md +2 -3
- package/package.json +1 -1
- package/.agent/skills/riligar-dev-stack/SKILL.md +0 -110
- package/.agent/skills/riligar-dev-stack/references/tech-stack.md +0 -131
- package/.agent/skills/riligar-infra-cloudfare/.gitkeep +0 -0
- /package/.agent/skills/riligar-dev-auth-elysia/assets/{server-snippets.ts → server-snippets.js} +0 -0
|
@@ -23,6 +23,7 @@ Para atingir a excelência:
|
|
|
23
23
|
- **[Theme Config](assets/theme.js)**: Configuração do tema com suporte a Dark Mode automático.
|
|
24
24
|
- **[Visual references](references/visual-references.md)**: Mapeamento de nuances estéticas.
|
|
25
25
|
- **[Anti-patterns](references/anti-patterns.md)**: O que evitar (especialmente CSS inline).
|
|
26
|
+
- **[Design Guidelines](references/design-system.md)**: Tipografia, cores e hierarquia visual detalhada.
|
|
26
27
|
|
|
27
28
|
## Checklist de Lapidação (RiLiGar Excellence)
|
|
28
29
|
|
|
@@ -14,7 +14,7 @@ This skill provides a backend workflow for integrating authentication and permis
|
|
|
14
14
|
Install the backend SDK:
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
|
|
17
|
+
bun add @riligar/auth-elysia
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
### 2. Environment Variables
|
|
@@ -55,7 +55,7 @@ const app = new Elysia()
|
|
|
55
55
|
.listen(3000)
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
For more patterns, see [server-snippets.
|
|
58
|
+
For more patterns, see [server-snippets.js](assets/server-snippets.js).
|
|
59
59
|
|
|
60
60
|
## Specialized Guides
|
|
61
61
|
|
|
@@ -15,6 +15,7 @@ description: Padrões React específicos do RiLiGar. Zustand, i18n, estrutura de
|
|
|
15
15
|
> Sempre respeite também:
|
|
16
16
|
> - @[.agent/skills/riligar-design-system] — UI exclusivo via Mantine, zero CSS
|
|
17
17
|
> - Rules em `.agent/rules/` — clean-code, naming-conventions, code-style, javascript-only
|
|
18
|
+
> - [references/dependencies.md](references/dependencies.md) — Pacotes e versões do frontend, config Vite
|
|
18
19
|
|
|
19
20
|
---
|
|
20
21
|
|
|
@@ -246,7 +247,336 @@ export const WHATSAPP_SUPPORT_MESSAGE = '...' // ou via i18n se traduzível
|
|
|
246
247
|
|
|
247
248
|
---
|
|
248
249
|
|
|
250
|
+
## 8. Padrões reutilizáveis
|
|
251
|
+
|
|
252
|
+
Estruturas que repetem pela codebase. Copie o esqueleto, ajuste apenas o conteúdo domínio-específico.
|
|
253
|
+
|
|
254
|
+
### 8.1 Page Header
|
|
255
|
+
|
|
256
|
+
Presente em **todas** as pages. Estrutura idêntica sempre:
|
|
257
|
+
|
|
258
|
+
```javascript
|
|
259
|
+
<Box py="xl">
|
|
260
|
+
<Group justify="space-between" align="flex-end" mb="xl">
|
|
261
|
+
<Stack gap={0}>
|
|
262
|
+
<Text size="xs" fw={700} c="dimmed" tt="uppercase" lts="0.1em">
|
|
263
|
+
{t('namespace.subtitle')}
|
|
264
|
+
</Text>
|
|
265
|
+
<Title order={1} style={{ letterSpacing: '-0.04em' }}>
|
|
266
|
+
{t('namespace.title')}
|
|
267
|
+
</Title>
|
|
268
|
+
</Stack>
|
|
269
|
+
{/* CTA opcional — ex: <Button leftSection={<IconPlus size={16} />}> */}
|
|
270
|
+
</Group>
|
|
271
|
+
{/* Conteúdo da página */}
|
|
272
|
+
</Box>
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### 8.2 Empty State
|
|
276
|
+
|
|
277
|
+
Usado quando uma lista está vazia. Card com borda dashed, icone grande, texto e CTA:
|
|
278
|
+
|
|
279
|
+
```javascript
|
|
280
|
+
<Card padding="xl" radius="md" withBorder style={{ borderStyle: 'dashed', textAlign: 'center' }}>
|
|
281
|
+
<Stack align="center" py="xl">
|
|
282
|
+
<IconDominio size={48} stroke={1} color="var(--mantine-color-gray-2)" />
|
|
283
|
+
<Text c="dimmed" size="sm">{t('namespace.emptyMessage')}</Text>
|
|
284
|
+
<Button onClick={handleCreate} leftSection={<IconPlus size={16} />}>
|
|
285
|
+
{t('namespace.createFirst')}
|
|
286
|
+
</Button>
|
|
287
|
+
</Stack>
|
|
288
|
+
</Card>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### 8.3 Loading Guard
|
|
292
|
+
|
|
293
|
+
Loader só aparece quando não há dados ainda (não sobrescreve lista existente):
|
|
294
|
+
|
|
295
|
+
```javascript
|
|
296
|
+
{loading && data.length === 0 ? (
|
|
297
|
+
<Center style={{ height: 300 }}>
|
|
298
|
+
<Loader />
|
|
299
|
+
</Center>
|
|
300
|
+
) : (
|
|
301
|
+
/* conteúdo normal */
|
|
302
|
+
)}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### 8.4 Card Grid
|
|
306
|
+
|
|
307
|
+
Layout responsivo padrão para listas de cards:
|
|
308
|
+
|
|
309
|
+
```javascript
|
|
310
|
+
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }}>
|
|
311
|
+
{items.map((item) => (
|
|
312
|
+
<Card key={item.id} padding="lg" radius="md" withBorder>
|
|
313
|
+
{/* conteúdo do card */}
|
|
314
|
+
</Card>
|
|
315
|
+
))}
|
|
316
|
+
</SimpleGrid>
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Para galerias (mais itens pequenos): `cols={{ base: 1, sm: 2, md: 3, lg: 4 }}`
|
|
320
|
+
|
|
321
|
+
### 8.5 Modal
|
|
322
|
+
|
|
323
|
+
Sempre usa `useDisclosure`. Header com borderBottom específico:
|
|
324
|
+
|
|
325
|
+
```javascript
|
|
326
|
+
const [opened, { open, close }] = useDisclosure(false)
|
|
327
|
+
|
|
328
|
+
<Modal
|
|
329
|
+
opened={opened}
|
|
330
|
+
onClose={close}
|
|
331
|
+
centered
|
|
332
|
+
radius="md"
|
|
333
|
+
padding="xl"
|
|
334
|
+
title={<Text fw={700}>{t('namespace.modalTitle')}</Text>}
|
|
335
|
+
styles={{ header: { borderBottom: '1px solid var(--mantine-color-gray-2)', marginBottom: 20 } }}
|
|
336
|
+
>
|
|
337
|
+
{/* corpo do modal */}
|
|
338
|
+
</Modal>
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Para múltiplos modais na mesma page, renomeia as funções: `{ open: openEdit, close: closeEdit }`
|
|
342
|
+
|
|
343
|
+
### 8.6 Status Badge
|
|
344
|
+
|
|
345
|
+
Mapeia status → configuração visual via função que recebe `t`:
|
|
346
|
+
|
|
347
|
+
```javascript
|
|
348
|
+
const getStatusConfig = (t) => ({
|
|
349
|
+
draft: { color: 'gray', icon: <IconCircleDotted size={16} />, label: t('posts.status.draft') },
|
|
350
|
+
scheduled: { color: 'blue', icon: <IconClock size={16} />, label: t('posts.status.scheduled') },
|
|
351
|
+
published: { color: 'green', icon: <IconCircleCheck size={16} />, label: t('posts.status.published') },
|
|
352
|
+
failed: { color: 'red', icon: <IconCircleX size={16} />, label: t('posts.status.failed') },
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
// Uso
|
|
356
|
+
const config = getStatusConfig(t)[status]
|
|
357
|
+
<Badge variant="dot" color={config.color}>{config.label}</Badge>
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### 8.7 Search / Filter
|
|
361
|
+
|
|
362
|
+
Filtro local sem chamada de API — estado local + filter inline:
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
const [search, setSearch] = useState('')
|
|
366
|
+
|
|
367
|
+
const filtered = items.filter((item) =>
|
|
368
|
+
item.name.toLowerCase().includes(search.toLowerCase())
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
<TextInput
|
|
372
|
+
placeholder={t('common.search')}
|
|
373
|
+
leftSection={<IconSearch size={16} />}
|
|
374
|
+
value={search}
|
|
375
|
+
onChange={(e) => setSearch(e.target.value)}
|
|
376
|
+
/>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## 9. Padrões de dados e lógica
|
|
382
|
+
|
|
383
|
+
### 9.1 Store — async action
|
|
384
|
+
|
|
385
|
+
Template exato que todas as actions seguem. Imports do service como namespace:
|
|
386
|
+
|
|
387
|
+
```javascript
|
|
388
|
+
import { create } from 'zustand'
|
|
389
|
+
import * as feedsService from '../services/feeds.js'
|
|
390
|
+
|
|
391
|
+
export const useFeedStore = create((set) => ({
|
|
392
|
+
feeds: [],
|
|
393
|
+
loading: false,
|
|
394
|
+
error: null,
|
|
395
|
+
|
|
396
|
+
fetchFeeds: async () => {
|
|
397
|
+
set({ loading: true, error: null })
|
|
398
|
+
try {
|
|
399
|
+
const feeds = await feedsService.getAll()
|
|
400
|
+
set({ feeds, loading: false })
|
|
401
|
+
} catch (error) {
|
|
402
|
+
set({ error: error.message, loading: false })
|
|
403
|
+
throw error
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
}))
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Nota: services são importados como `import * as service` (namespace), não como objeto exportado.
|
|
410
|
+
|
|
411
|
+
### 9.2 Store — mutação de listas
|
|
412
|
+
|
|
413
|
+
Atualizações imutáveis via `set(state => ...)` com spread + map/filter:
|
|
414
|
+
|
|
415
|
+
```javascript
|
|
416
|
+
// Atualizar item na lista
|
|
417
|
+
updateFeed: (id, data) => set((state) => ({
|
|
418
|
+
feeds: state.feeds.map((f) => (f.id === id ? { ...f, ...data } : f))
|
|
419
|
+
})),
|
|
420
|
+
|
|
421
|
+
// Remover item
|
|
422
|
+
removeFeed: (id) => set((state) => ({
|
|
423
|
+
feeds: state.feeds.filter((f) => f.id !== id)
|
|
424
|
+
})),
|
|
425
|
+
|
|
426
|
+
// Adicionar item
|
|
427
|
+
addFeed: (feed) => set((state) => ({
|
|
428
|
+
feeds: [...state.feeds, feed]
|
|
429
|
+
})),
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### 9.3 Notifications
|
|
433
|
+
|
|
434
|
+
Shape e convenção de cores consistente em toda a app:
|
|
435
|
+
|
|
436
|
+
```javascript
|
|
437
|
+
import { notifications } from '@mantine/notifications'
|
|
438
|
+
import { IconCheck, IconX, IconAlertCircle } from '@tabler/icons-react'
|
|
439
|
+
|
|
440
|
+
// ✅ Sucesso
|
|
441
|
+
notifications.show({
|
|
442
|
+
title: t('common.success'),
|
|
443
|
+
message: t('namespace.savedMessage'),
|
|
444
|
+
color: 'green',
|
|
445
|
+
icon: <IconCheck size={18} />,
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
// ✅ Erro
|
|
449
|
+
notifications.show({
|
|
450
|
+
title: t('common.error'),
|
|
451
|
+
message: error.message,
|
|
452
|
+
color: 'red',
|
|
453
|
+
icon: <IconX size={18} />,
|
|
454
|
+
})
|
|
455
|
+
|
|
456
|
+
// ✅ Warning
|
|
457
|
+
notifications.show({
|
|
458
|
+
title: t('common.warning'),
|
|
459
|
+
message: t('namespace.warningMessage'),
|
|
460
|
+
color: 'yellow',
|
|
461
|
+
icon: <IconAlertCircle size={18} />,
|
|
462
|
+
})
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Icones de notification: sempre `size={18}`. Mensagens de erro: usa `error.message` diretamente (já vem traduzido do backend).
|
|
466
|
+
|
|
467
|
+
### 9.4 dayjs + i18n
|
|
468
|
+
|
|
469
|
+
Locale do dayjs sincroniza com o idioma do i18n:
|
|
470
|
+
|
|
471
|
+
```javascript
|
|
472
|
+
import dayjs from 'dayjs'
|
|
473
|
+
import relativeTime from 'dayjs/plugin/relativeTime'
|
|
474
|
+
import { useTranslation } from 'react-i18next'
|
|
475
|
+
|
|
476
|
+
dayjs.extend(relativeTime)
|
|
477
|
+
|
|
478
|
+
const MyComponent = () => {
|
|
479
|
+
const { i18n } = useTranslation()
|
|
480
|
+
|
|
481
|
+
useEffect(() => {
|
|
482
|
+
dayjs.locale(i18n.language)
|
|
483
|
+
}, [i18n.language])
|
|
484
|
+
|
|
485
|
+
// Formatos usados no projeto:
|
|
486
|
+
// dayjs(date).format('DD MMM, HH:mm') — compacto com hora
|
|
487
|
+
// dayjs(date).format('DD/MM/YYYY [at] HH:mm') — completo
|
|
488
|
+
// dayjs(date).fromNow() — relativo ("há 2 dias")
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
## 10. Padrões de fluxo
|
|
495
|
+
|
|
496
|
+
### 10.1 Route Guard (wrapper)
|
|
497
|
+
|
|
498
|
+
Componente que protege rotas verificando estado do store:
|
|
499
|
+
|
|
500
|
+
```javascript
|
|
501
|
+
import { Navigate } from 'react-router-dom'
|
|
502
|
+
import { useFeedStore } from '../store/feed-store.js'
|
|
503
|
+
|
|
504
|
+
const RequireFeed = ({ children }) => {
|
|
505
|
+
const activeFeed = useFeedStore((s) => s.activeFeed)
|
|
506
|
+
if (!activeFeed) return <Navigate to="/" />
|
|
507
|
+
return children
|
|
508
|
+
}
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
Usado na definição de rotas: `<RequireFeed><EditorPage /></RequireFeed>`
|
|
512
|
+
|
|
513
|
+
### 10.2 Notificação via URL params
|
|
514
|
+
|
|
515
|
+
Após redirects externos (OAuth, Stripe checkout), status vem via query params:
|
|
516
|
+
|
|
517
|
+
```javascript
|
|
518
|
+
import { useSearchParams } from 'react-router-dom'
|
|
519
|
+
|
|
520
|
+
const SubscriptionPage = () => {
|
|
521
|
+
const [searchParams, setSearchParams] = useSearchParams()
|
|
522
|
+
const { t } = useTranslation()
|
|
523
|
+
|
|
524
|
+
useEffect(() => {
|
|
525
|
+
if (searchParams.get('success')) {
|
|
526
|
+
notifications.show({ title: t('common.success'), message: t('subscription.successMessage'), color: 'green', icon: <IconCheck size={18} /> })
|
|
527
|
+
setSearchParams({})
|
|
528
|
+
} else if (searchParams.get('canceled')) {
|
|
529
|
+
notifications.show({ title: t('common.warning'), message: t('subscription.canceledMessage'), color: 'yellow', icon: <IconAlertCircle size={18} /> })
|
|
530
|
+
setSearchParams({})
|
|
531
|
+
}
|
|
532
|
+
}, [searchParams])
|
|
533
|
+
}
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### 10.3 Autosave
|
|
537
|
+
|
|
538
|
+
Padrão usado no editor — debounce com state machine de status:
|
|
539
|
+
|
|
540
|
+
```javascript
|
|
541
|
+
const [saveStatus, setSaveStatus] = useState('idle') // 'idle' | 'saving' | 'saved'
|
|
542
|
+
|
|
543
|
+
useEffect(() => {
|
|
544
|
+
if (!content) return
|
|
545
|
+
const timeout = setTimeout(async () => {
|
|
546
|
+
setSaveStatus('saving')
|
|
547
|
+
try {
|
|
548
|
+
await postsService.update(postId, { content })
|
|
549
|
+
setSaveStatus('saved')
|
|
550
|
+
// Reset para idle após 3s
|
|
551
|
+
setTimeout(() => setSaveStatus('idle'), 3000)
|
|
552
|
+
} catch {
|
|
553
|
+
setSaveStatus('idle')
|
|
554
|
+
}
|
|
555
|
+
}, 2000) // debounce de 2s
|
|
556
|
+
|
|
557
|
+
return () => clearTimeout(timeout)
|
|
558
|
+
}, [content, postId])
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## 11. Convenção de tamanhos de icones
|
|
564
|
+
|
|
565
|
+
Hierarquia consistente — sempre de `@tabler/icons-react`:
|
|
566
|
+
|
|
567
|
+
| Contexto | Size | Exemplo |
|
|
568
|
+
|---|---|---|
|
|
569
|
+
| Menu items / nav | 14 | Sidebar links |
|
|
570
|
+
| Inline / badges | 16 | Botões, labels, leftSection |
|
|
571
|
+
| Notifications | 18 | Icons nas notifications |
|
|
572
|
+
| Card headers | 20 | Ação principal do card |
|
|
573
|
+
| Feature cards | 24 | Cards de destaque |
|
|
574
|
+
| Empty states | 48 | Icone do empty state (com `stroke={1}`) |
|
|
575
|
+
|
|
576
|
+
Empty states usam `stroke={1}` para parecer mais leve. Icones decorativos genéricos usam `stroke={1.5}`.
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
249
580
|
## Related Skills
|
|
250
581
|
|
|
251
582
|
- @[.agent/skills/riligar-design-system]
|
|
252
|
-
- @[.agent/skills/riligar-dev-stack]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Dependências Frontend
|
|
2
|
+
|
|
3
|
+
## Core
|
|
4
|
+
|
|
5
|
+
| Pacote | Versão | Descrição |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| `react` | ^19.x | Biblioteca UI |
|
|
8
|
+
| `react-dom` | ^19.x | React DOM renderer |
|
|
9
|
+
| `react-router-dom` | ^7.x | Roteamento |
|
|
10
|
+
| `vite` | ^5.x | Build tool |
|
|
11
|
+
| `zustand` | ^5.x | Gerenciamento de estado |
|
|
12
|
+
| `ky` | ^1.x | HTTP client |
|
|
13
|
+
|
|
14
|
+
## UI
|
|
15
|
+
|
|
16
|
+
| Pacote | Versão | Descrição |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `@mantine/core` | ^8.x | Componentes UI |
|
|
19
|
+
| `@mantine/hooks` | ^8.x | Hooks utilitários |
|
|
20
|
+
| `@mantine/form` | ^8.x | Gerenciamento de formulários |
|
|
21
|
+
| `@mantine/notifications` | ^8.x | Sistema de notificações |
|
|
22
|
+
| `@tabler/icons-react` | ^3.x | Iconografia |
|
|
23
|
+
|
|
24
|
+
> Use apenas Mantine para estilização. Sem CSS Modules, Custom CSS ou CSS In-line.
|
|
25
|
+
|
|
26
|
+
## Configuração Vite
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
import { defineConfig } from 'vite'
|
|
30
|
+
import react from '@vitejs/plugin-react'
|
|
31
|
+
|
|
32
|
+
export default defineConfig({
|
|
33
|
+
plugins: [react()],
|
|
34
|
+
build: {
|
|
35
|
+
lib: {
|
|
36
|
+
entry: 'src/index.js',
|
|
37
|
+
formats: ['es', 'cjs'],
|
|
38
|
+
},
|
|
39
|
+
rollupOptions: {
|
|
40
|
+
external: ['react', 'react-dom', '@mantine/core'],
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
```
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: riligar-dev-
|
|
2
|
+
name: riligar-dev-manager
|
|
3
3
|
description: Elysia backend development patterns for Bun. Use when building APIs, routes, plugins, validation, middleware, and error handling with Elysia framework.
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -10,10 +10,7 @@ description: Elysia backend development patterns for Bun. Use when building APIs
|
|
|
10
10
|
## Mandatory Guidelines
|
|
11
11
|
|
|
12
12
|
> [!IMPORTANT]
|
|
13
|
-
> All work in this skill MUST adhere to
|
|
14
|
-
>
|
|
15
|
-
> - @[.agent/skills/riligar-dev-clean-code] (Clean Code Standards)
|
|
16
|
-
> - @[.agent/skills/riligar-tech-stack] (Tech Stack - Bun, Elysia, SQLite, Drizzle)
|
|
13
|
+
> All work in this skill MUST adhere to rules em `.agent/rules/` — clean-code, code-style, javascript-only, naming-conventions.
|
|
17
14
|
|
|
18
15
|
## Quick Reference
|
|
19
16
|
|
|
@@ -62,6 +59,16 @@ src/
|
|
|
62
59
|
└── logger.js # Request logging
|
|
63
60
|
```
|
|
64
61
|
|
|
62
|
+
## Dependencies
|
|
63
|
+
|
|
64
|
+
| Pacote | Versão | Descrição |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `bun` | latest | Runtime |
|
|
67
|
+
| `elysia` | latest | Framework HTTP |
|
|
68
|
+
| `bun:sqlite` | builtin | SQLite driver |
|
|
69
|
+
| `drizzle-orm` | latest | ORM |
|
|
70
|
+
| `bun:s3` | latest | S3/R2 Storage |
|
|
71
|
+
|
|
65
72
|
## Core Patterns
|
|
66
73
|
|
|
67
74
|
### Route Plugin
|
|
@@ -108,10 +115,7 @@ console.log(`Server running at ${app.server?.url}`)
|
|
|
108
115
|
| Need | Skill |
|
|
109
116
|
| --- | --- |
|
|
110
117
|
| **Authentication** | @[.agent/skills/riligar-dev-auth-elysia] |
|
|
111
|
-
| **
|
|
112
|
-
| **Tech Stack** | @[.agent/skills/riligar-tech-stack] |
|
|
113
|
-
| **Clean Code** | @[.agent/skills/riligar-dev-clean-code] |
|
|
114
|
-
| **Infrastructure** | @[.agent/skills/riligar-infrastructure] |
|
|
118
|
+
| **Infrastructure** | @[.agent/skills/riligar-infra-fly] |
|
|
115
119
|
|
|
116
120
|
## Decision Checklist
|
|
117
121
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: riligar-dev-
|
|
2
|
+
name: riligar-dev-website
|
|
3
3
|
description: Specialist in High-Conversion Landing Pages using RiLiGar Design System. Use for: (1) Creating marketing/sales pages, (2) Structuring conversion flows (AIDA/PAS), (3) Implementing high-trust components (Hero, Social Proof, Pricing), (4) Writing persuasive copy.
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: riligar-dev-seo
|
|
2
|
+
name: riligar-dev-website-seo
|
|
3
3
|
description: Implementação de infraestrutura de SEO técnico seguindo a stack RiLiGar (React, Vite, Bun, Elysia). Use para configurar sitemaps, robots.txt, meta tags, OpenGraph, dados estruturados (JSON-LD) e URLs canônicas.
|
|
4
4
|
---
|
|
5
5
|
|