@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.
@@ -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
- npm install @riligar/auth-elysia
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.ts](assets/server-snippets.ts).
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-backend
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
- | **Database** | @[.agent/skills/riligar-dev-database] |
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-landing-page
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