{"id":"repo/cms-v2-roadmap","source":"repo","sourceLabel":"repository root","sourcePath":"CMS_V2_ROADMAP.md","routePath":"/fastapp/public-docs/page/repo/cms-v2-roadmap","rawPath":"/fastapp/public-docs/raw/repo/cms-v2-roadmap","slug":["repo","cms-v2-roadmap"],"slugPath":"repo/cms-v2-roadmap","title":"CMS V2 Implementacao Atual e Guia Tecnico","description":"Atualizado em: 2026 02 26","headings":["CMS V2 Implementacao Atual e Guia Tecnico","Objetivo","Escopo Entregue (Sprint 1 + 1.5)","Mapa de Arquivos (Implementacao CMS)","Contratos e utilitarios","Core CMS components","Integracao nas paginas","Validacao de API","Contrato de Dados (PageSchemaV2)","Exemplo de Pagina CMS V2","Fluxo de Runtime e Persistencia","Runtime em pagina custom","Payload salvo no localStorage","Binding com Objetos (Query Mapping)","Grid 12 Colunas + Rows (Sprint 1.5)","Pontos Fortes Atuais","Gaps para ficar \"CMS real\" (mais faceis agora)","Diferencial FastApp (Abstracao + IA)","Guia Rapido para Adicionar Novo Tipo de Secao","Checklist de Validacao","Conclusao"],"wordCount":980,"markdown":"# CMS V2 - Implementacao Atual e Guia Tecnico\r\n\r\nAtualizado em: 2026-02-26\r\n\r\n## Objetivo\r\nEste documento consolida o estado real do CMS V2 no FastApp apos Sprint 1 e Sprint 1.5, com foco em:\r\n\r\n- implementacoes entregues\r\n- mapa de arquivos\r\n- contratos de dados\r\n- fluxo de edicao e runtime\r\n- integracao com objetos do app\r\n- limites atuais e proximos passos\r\n\r\n## Escopo Entregue (Sprint 1 + 1.5)\r\n\r\nStatus geral:\r\n\r\n- [x] Secoes verticais com reorder via drag and drop\r\n- [x] Fallback de reorder por botoes (up/down)\r\n- [x] Renderer CMS generico por registro de componentes\r\n- [x] Grid 12 colunas + rows (modelo compativel com Tailwind/Bootstrap)\r\n- [x] Binding de dados para objetos via `/api/v1/data/:object`\r\n- [x] Rich text editavel com toolbar + tokens de dados\r\n- [x] Secoes `object_list` e `object_cards`\r\n- [x] Persistencia de draft no `localStorage` com versao v2\r\n- [x] Migracao automatica de chave legacy de `localStorage`\r\n- [x] Validacao/sanitizacao server-side no `PATCH /api/app/:id`\r\n- [x] Integracao do CMS no Schema Manager (`schema-v3`) e no runtime de paginas custom\r\n\r\nAinda nao entregue (ja mapeado no contrato):\r\n\r\n- [x] renderer para `object_table`\r\n- [x] renderer para `kpi_strip`\r\n- [ ] drag and drop espacial de grid (hoje e reorder vertical)\r\n- [ ] fluxo publish com versao/historico de pagina\r\n- [ ] permissao/auditoria por usuario no nivel de secao\r\n\r\n## Mapa de Arquivos (Implementacao CMS)\r\n\r\n### Contratos e utilitarios\r\n\r\n- `app/types/schema.ts`\r\n  - Define `PageSchemaV2`, `CmsSection`, `CmsSectionLayout`, `CmsSectionBinding`.\r\n  - `CmsSectionType` inclui: `rich_text`, `object_list`, `object_cards`, `object_table`, `kpi_strip`.\r\n  - Layout com grid: `col_span`, `row_span`, `col_start`, `row_start`, `min_height`.\r\n\r\n- `app/utils/cms-page.ts`\r\n  - Fabrica e normaliza secoes (`createCmsSection`, `normalizeCmsSections`).\r\n  - Migra pagina legacy html para secao `rich_text`.\r\n  - Forca defaults de `layout_mode`, `theme_preset`, `sections` (`ensurePageSchemaV2`).\r\n  - Templates rapidos de secao (`createCmsTemplateSection`) para `rich_text`, `object_list`, `object_cards`.\r\n\r\n- `app/composables/useCmsBinding.ts`\r\n  - Resolve binding de dados de secao.\r\n  - Converte `filters`, `sort`, `limit`, `projection` para query string.\r\n  - Interpola contexto em filtros (`{{route.params.*}}`, `{{route.query.*}}`, etc).\r\n  - Faz fetch generico em `/api/v1/data/:object`.\r\n\r\n### Core CMS components\r\n\r\n- `app/components/core/cms/CoreCmsRenderer.vue`\r\n  - Runtime principal de renderizacao.\r\n  - Registry atual:\r\n    - `rich_text` -> `CoreCmsSectionRichText`\r\n    - `object_list` -> `CoreCmsSectionObjectList`\r\n    - `object_cards` -> `CoreCmsSectionObjectCards`\r\n  - Usa grid de 12 colunas com `gridColumn`/`gridRow`.\r\n  - Fallback visual para tipo de secao nao suportado.\r\n\r\n- `app/components/core/cms/CoreCmsSectionPalette.vue`\r\n  - Catalogo de templates de secao.\r\n  - Adiciona secao nova com defaults de binding e props.\r\n\r\n- `app/components/core/cms/CoreCmsSectionStack.vue`\r\n  - Lista vertical de secoes com drag and drop (`vuedraggable`).\r\n  - Exibe metadados de cada secao (tipo, grid, objeto).\r\n  - Fallback de reorder por botoes.\r\n\r\n- `app/components/core/cms/CoreCmsSectionInspector.vue`\r\n  - Editor da secao selecionada.\r\n  - Edita:\r\n    - base: label, type, enabled\r\n    - grid: span/start/min height\r\n    - binding: source, object, limit\r\n    - props especificas por tipo (`rich_text`, `object_list`, `object_cards`)\r\n\r\n- `app/components/core/cms/CoreCmsSectionRichText.vue`\r\n  - Bloco editavel (contenteditable) com toolbar.\r\n  - Suporte a tokens em modo leitura:\r\n    - `{{record.campo}}`\r\n    - `{{object.count}}`\r\n    - `{{object.name}}`\r\n    - `{{image:https://...}}`\r\n\r\n- `app/components/core/cms/CoreCmsSectionObjectList.vue`\r\n  - Lista de registros conectada ao objeto.\r\n  - Usa `CoreDynamicList`.\r\n  - Suporte a layout `list`/`grid` e `columns`.\r\n\r\n- `app/components/core/cms/CoreCmsSectionObjectCards.vue`\r\n  - Cards visuais conectados ao objeto.\r\n  - Props: `image_field`, `title_field`, `description_field`, `cta_label`, `columns`.\r\n  - Heuristica para inferir campos quando nao configurados.\r\n\r\n### Integracao nas paginas\r\n\r\n- `app/pages/fastapp/schema-v3.vue`\r\n  - Editor de pagina no Architect com:\r\n    - `CoreCmsSectionPalette`\r\n    - `CoreCmsSectionStack`\r\n    - `CoreCmsSectionInspector`\r\n    - `CoreCmsRenderer` (preview)\r\n  - `pageFields` inclui `layout_mode` e `theme_preset`.\r\n  - Garante pagina em formato V2 via `ensurePageSchemaV2`.\r\n\r\n- `app/pages/[app]/[module]/index.vue`\r\n  - Runtime de pagina custom com edicao local.\r\n  - Persistencia de draft em `localStorage`:\r\n    - v2: `fastapp:cms:v2:draft:{appSlug}:{pageToken}`\r\n    - legacy: `fastapp:cms:{appSlug}:{pageToken}`\r\n  - Migracao automatica do legado para V2.\r\n\r\n### Validacao de API\r\n\r\n- `server/api/app/[id].patch.ts`\r\n  - Sanitiza `pages`, `sections`, `layout`, `binding`.\r\n  - Valida `layout_mode` permitido.\r\n  - Valida tipo/shape de `filters`, `sort`, `projection`, `limit`.\r\n  - Se payload CMS for invalido, retorna `400` antes da tentativa SQL fallback.\r\n\r\n## Contrato de Dados (PageSchemaV2)\r\n\r\n```ts\r\ntype CmsLayoutMode = 'flow_vertical' | 'split' | 'dashboard'\r\n\r\ntype CmsSectionType =\r\n  | 'rich_text'\r\n  | 'object_list'\r\n  | 'object_cards'\r\n  | 'object_table'\r\n  | 'kpi_strip'\r\n\r\ninterface CmsSectionLayout {\r\n  col_span?: number // 1..12\r\n  row_span?: number // 1..12\r\n  col_start?: number // 1..12\r\n  row_start?: number // 1..12\r\n  min_height?: string\r\n  gap?: string | number\r\n  width?: string\r\n  align?: 'left' | 'center' | 'right' | 'stretch'\r\n}\r\n\r\ninterface CmsSectionBinding {\r\n  source_type?: 'none' | 'object' | 'static'\r\n  object_name?: string\r\n  filters?: Record<string, any>\r\n  sort?: Record<string, 1 | -1>\r\n  limit?: number\r\n  projection?: string[]\r\n}\r\n\r\ninterface CmsSection {\r\n  id: string\r\n  type: CmsSectionType\r\n  label: string\r\n  order: number\r\n  enabled: boolean\r\n  layout?: CmsSectionLayout\r\n  style?: Record<string, any>\r\n  binding?: CmsSectionBinding\r\n  props?: Record<string, any>\r\n  actions?: Record<string, any>\r\n}\r\n\r\ninterface PageSchemaV2 {\r\n  slug: string\r\n  layout_mode?: CmsLayoutMode\r\n  theme_preset?: string\r\n  sections?: CmsSection[]\r\n}\r\n```\r\n\r\n## Exemplo de Pagina CMS V2\r\n\r\n```json\r\n{\r\n  \"slug\": \"landing\",\r\n  \"layout_mode\": \"flow_vertical\",\r\n  \"theme_preset\": \"industrial_zen\",\r\n  \"sections\": [\r\n    {\r\n      \"id\": \"sec_intro\",\r\n      \"type\": \"rich_text\",\r\n      \"label\": \"Hero\",\r\n      \"order\": 1,\r\n      \"enabled\": true,\r\n      \"layout\": { \"col_span\": 12, \"row_span\": 1, \"min_height\": \"280px\" },\r\n      \"binding\": { \"source_type\": \"object\", \"object_name\": \"lead\", \"limit\": 1, \"sort\": { \"id\": -1 } },\r\n      \"props\": {\r\n        \"html\": \"<h1>Leads ativos: {{object.count}}</h1><p>Ultimo lead: {{record.name}}</p><p>{{image:https://cdn.site/banner.jpg}}</p>\"\r\n      }\r\n    },\r\n    {\r\n      \"id\": \"sec_cards\",\r\n      \"type\": \"object_cards\",\r\n      \"label\": \"Leads em destaque\",\r\n      \"order\": 2,\r\n      \"enabled\": true,\r\n      \"layout\": { \"col_span\": 12, \"row_span\": 1 },\r\n      \"binding\": { \"source_type\": \"object\", \"object_name\": \"lead\", \"limit\": 6, \"sort\": { \"id\": -1 } },\r\n      \"props\": {\r\n        \"title\": \"Top leads\",\r\n        \"columns\": 3,\r\n        \"image_field\": \"image\",\r\n        \"title_field\": \"name\",\r\n        \"description_field\": \"description\",\r\n        \"cta_label\": \"Abrir\"\r\n      }\r\n    }\r\n  ]\r\n}\r\n```\r\n\r\n## Fluxo de Runtime e Persistencia\r\n\r\n### Runtime em pagina custom\r\n\r\n1. Normaliza pagina base para V2 (`ensurePageSchemaV2`).\r\n2. Carrega draft do `localStorage` (chave v2).\r\n3. Se v2 nao existir, tenta chave legacy.\r\n4. Concatena base + draft para `cmsRuntimePage`.\r\n5. Renderiza com `CoreCmsRenderer`.\r\n6. Ao salvar draft:\r\n   - grava payload com `version: 2`\r\n   - remove chave legacy\r\n\r\n### Payload salvo no localStorage\r\n\r\n```json\r\n{\r\n  \"version\": 2,\r\n  \"updated_at\": \"2026-02-26T12:34:56.000Z\",\r\n  \"page\": {\r\n    \"layout_mode\": \"flow_vertical\",\r\n    \"theme_preset\": \"industrial_zen\",\r\n    \"sections\": []\r\n  }\r\n}\r\n```\r\n\r\n## Binding com Objetos (Query Mapping)\r\n\r\nContrato de binding para `source_type: object`:\r\n\r\n- `object_name` define endpoint base.\r\n- `filters` vira query plana.\r\n- `sort` vira `$sort[field]=1|-1`.\r\n- `limit` vira `$limit`.\r\n- `projection` vira `$select=campo1,campo2`.\r\n\r\nExemplo:\r\n\r\n```ts\r\nbinding = {\r\n  source_type: 'object',\r\n  object_name: 'lead',\r\n  filters: { status: 'open', owner_id: '{{route.params.id}}' },\r\n  sort: { created_at: -1 },\r\n  limit: 10,\r\n  projection: ['id', 'name', 'status']\r\n}\r\n```\r\n\r\nRequest gerada:\r\n\r\n`/api/v1/data/lead?status=open&owner_id=123&$sort[created_at]=-1&$limit=10&$select=id,name,status`\r\n\r\n## Grid 12 Colunas + Rows (Sprint 1.5)\r\n\r\nImplementacao atual:\r\n\r\n- `CoreCmsRenderer` usa grid `grid-cols-12`.\r\n- Cada secao aplica:\r\n  - `gridColumn: span X / span X` ou `start / span X`\r\n  - `gridRow: span Y / span Y` ou `start / span Y`\r\n- Inspector controla:\r\n  - `col_span`, `row_span`\r\n  - `col_start`, `row_start`\r\n  - `min_height`\r\n- Presets rapidos no inspector: `12/1`, `6/1`, `4/1`, `8/2`.\r\n\r\nObservacao:\r\n\r\n- O posicionamento na grade ainda e configurado por formulario (nao por drag espacial).\r\n- O reorder de secoes continua vertical.\r\n\r\n## Pontos Fortes Atuais\r\n\r\n- Abstracao generica: a pagina e schema-driven, sem branch por app.\r\n- Reuso de objetos: secoes conectam em qualquer objeto via metadados.\r\n- Composicao visual: palette + stack + inspector + preview no mesmo fluxo.\r\n- Migrao suave: legado html e convertido para secao `rich_text`.\r\n- Seguranca de contrato: API valida shape de pages/secoes antes de persistir.\r\n\r\n## Gaps para ficar \"CMS real\" (mais faceis agora)\r\n\r\nPrioridade P0/P1 de baixo custo tecnico:\r\n\r\n1. Sanitizacao de HTML no `rich_text` antes de render (`v-html` hoje aceita html bruto).\r\n2. Blocos mistos em rich text:\r\n   - insercao visual de \"chips de objeto\" (campo dinamico)\r\n   - seletor de imagem do app/asset object (alem de URL)\r\n3. `object_table` renderer reaproveitando tabela dinamica.\r\n4. `kpi_strip` renderer com agregacoes simples (`count`, `sum`, `avg`).\r\n5. Toolbar de rich text moderna (evitar dependencia total de `document.execCommand`).\r\n\r\n## Diferencial FastApp (Abstracao + IA)\r\n\r\nDirecao recomendada para agentes IA no CMS:\r\n\r\n1. \"Pilot mode\":\r\n   - agente cria/reordena secoes por prompt\r\n   - gera bindings com base em objetos e relacoes existentes\r\n2. \"Data-aware content\":\r\n   - agente sugere tokens (`{{record.*}}`, `{{object.count}}`) conforme schema\r\n   - propoe card/list/table mais aderente ao tipo de objeto\r\n3. \"Layout copilot\":\r\n   - agente ajusta `col_span/row_span` para responsividade\r\n   - aplica presets visuais por intencao (landing, dashboard, catalogo)\r\n4. \"Safe patch\":\r\n   - agente escreve patch em `sections[]` validado por contrato server-side\r\n\r\n## Guia Rapido para Adicionar Novo Tipo de Secao\r\n\r\nExemplo: `object_table`\r\n\r\n1. Garantir o tipo em `app/types/schema.ts` (ja existe).\r\n2. Criar componente `app/components/core/cms/CoreCmsSectionObjectTable.vue`.\r\n3. Registrar no `SECTION_REGISTRY` de `CoreCmsRenderer.vue`.\r\n4. Adicionar template em `CoreCmsSectionPalette.vue`.\r\n5. Expor props no `CoreCmsSectionInspector.vue`.\r\n6. Definir template default em `createCmsTemplateSection` (`app/utils/cms-page.ts`).\r\n7. Validar comportamento com binding via `useCmsBinding`.\r\n\r\n## Checklist de Validacao\r\n\r\n- Criar pagina nova no Architect e confirmar defaults `layout_mode/theme_preset/sections`.\r\n- Adicionar secoes `rich_text`, `object_list`, `object_cards`.\r\n- Reordenar por drag e por botoes.\r\n- Alterar grid no inspector e validar preview.\r\n- Conectar secao a objeto real e validar fetch.\r\n- Salvar draft em pagina custom e recarregar browser.\r\n- Testar migracao da chave legacy `fastapp:cms:*`.\r\n- Enviar `PATCH /api/app/:id` com payload invalido e validar erro `400`.\r\n\r\n## Conclusao\r\n\r\nO CMS V2 ja saiu do modo \"html editavel simples\" e entrou em um modelo composavel, orientado a schema, com binding de objetos, grid de 12 colunas e persistencia local versionada. A base para evolucao com IA ja esta pronta, especialmente no eixo de geracao/edicao automatica de `sections[]`.\r\n"}