Um CMS Laravel modular, extensível e orientado a blocos de conteúdo
- Visão Geral
- Setup Inicial do Projeto
- Makefile e Automação
- Arquitetura e Padrões
- CLI — Criando Blocos e Variações (Guia)
- Renderização de Páginas
- Configuração do CMS
- Persistência de Dados
- Rotas do CMS
- Estado Atual do Projeto
Este projeto implementa um CMS modular baseado em blocos, construído em Laravel, com foco em:
- reutilização de componentes de conteúdo
- extensibilidade por convenção
- separação clara entre domínio, infraestrutura e UI
- uso como módulo interno, plugin ou pacote
Todo o código relacionado a domínio e negócio fica em app-modules/. O núcleo do CMS reside em app-modules/cms.
- Instale as dependências:
composer install- Configure o ambiente:
cp .env.example .env
php artisan key:generate- Execute as migrations:
php artisan migrate --seed- Inicie o ambiente de desenvolvimento:
composer run devO projeto possui um Makefile para tarefas comuns:
make build– build do projetomake pint– formatação com Laravel Pintmake rector– refatoração automática
Esta seção descreve a arquitetura esperada pelos blocos e os padrões que o CMS usa para descobrir e renderizar componentes.
Um Block é a menor unidade de conteúdo renderizável de uma página. Exemplos: Hero, Text, CTA, Features, Footer. Uma página é composta por uma sequência ordenada de blocks.
Cada block vive em:
app-modules/cms/src/Blocks/<NomeDoBloco>/
Cada bloco tem três responsabilidades principais:
-
Block (Definição)
- Classe principal do bloco (ex.:
TextBlock). - Identifica o tipo do bloco, fornece label amigável, expõe schema do admin e define como renderizar variações.
- Implementa o contrato
BlockDefinition.
- Classe principal do bloco (ex.:
-
Data (DTO)
- DTO imutável que representa os dados do bloco (ex.:
TextData). - Normaliza defaults e fornece helpers para a view.
- Implementa
BlockData.
- DTO imutável que representa os dados do bloco (ex.:
-
Schema (Admin / Filament)
- Schema usado no painel administrativo para editar o
datado bloco. - Deve escrever/ler campos dentro de
data.*(o conteúdo do bloco é persistido em JSON).
- Schema usado no painel administrativo para editar o
As variações visuais são definidas exclusivamente por arquivos Blade:
resources/views/components/blocks/<slug-do-bloco>/<variant>.blade.php
- Cada arquivo representa uma variação.
- Não existe registro manual; a existência do arquivo é a fonte da verdade.
BlockCatalogfaz listagem de blocos e variantes para selects e admin.BlockFactoryinstancia e fornece instâncias deBlockDefinition(estateless, cacheadas por request).- Esses componentes vivem em
app-modules/cms/src/Infrastructure/.
Separação clara entre domínio e infraestrutura facilita evolução e teste.
Esta seção reúne o uso dos comandos CLI do CMS, exemplos práticos e o comportamento esperado (detecção e outputs).
- Criar um bloco com variantes (option arrays):
php artisan cms:make-block Text --variants=default --variants=rich- Criar um bloco e seguir prompts interativos:
php artisan cms:make-block Text- Criar uma nova variação para um bloco existente:
php artisan cms:make-variant text gridObservações:
cms:make-blockaceita--variants=*(ex.:--variants=default --variants=rich).- Se faltarem argumentos obrigatórios, o Laravel fará prompts automáticos (Prompts for Missing Input).
-
cms:make-block <Name>gera:BlockDefinition(ex.:TextBlockemapp-modules/cms/src/Blocks/Text/TextBlock.php)BlockData(ex.:TextDataemapp-modules/cms/src/Blocks/Text/TextData.php)BlockSchema(ex.:TextSchemaemapp-modules/cms/src/Blocks/Text/TextSchema.php)- Views Blade para cada variação em
app-modules/cms/resources/views/components/blocks/<slug>/<variant>.blade.php
-
cms:make-variant <block> <variant>gera:- Apenas o arquivo Blade da variação desejada.
- As views são a "fonte da verdade". Ao criar um novo arquivo Blade em
resources/views/components/blocks/<slug>/<variant>.blade.php, o CMS passa a detectar automaticamente:- Novos blocos (quando surge uma nova pasta em
resources/views/components/blocks). - Novas variações (quando surge um novo arquivo dentro da pasta do bloco).
- Novos blocos (quando surge uma nova pasta em
- O
BlockCataloge a infra do CMS atualizarão as opções do admin para incluir a nova variação — nada mais é necessário.
Após executar o comando, o CLI exibe um resumo organizado:
Arquivos criados— lista de novos arquivos gerados.Arquivos sobrescritos— lista de arquivos atualizados (após confirmação ou--force).- Se arquivos já existirem e
--forcenão foi informado, o comando pergunta se deseja sobrescrever.
Exemplo de saída:
Bloco CMS Text criado com sucesso.
Arquivos criados:
• app-modules/cms/src/Blocks/Text/TextBlock.php
• app-modules/cms/src/Blocks/Text/TextData.php
• app-modules/cms/resources/views/components/blocks/text/default.blade.php
Arquivos sobrescritos:
• app-modules/cms/src/Blocks/Text/TextSchema.php
- Ajuste o
Schemado bloco (app-modules/cms/src/Blocks/<Name>/<Name>Schema.php) para expor os campos do admin — sempre dentro dedata.*. - Implemente defaults e helpers no
Data(DTO) para facilitar as views. - Edite as Views Blade geradas para compor a UI do bloco.
- Teste no painel (
/cms) adicionando o bloco a uma página e validando a renderização pública.
Durante a renderização:
- A página carrega seus
PageBlock. - Cada
PageBlock:- resolve seu
BlockDefinitionviaBlockFactory; - transforma dados persistidos em
BlockData; - determina a view correta com base na variação.
- resolve seu
- A view recebe o
BlockDatatipado.
Exemplo simplificado:
<x-dynamic-component
:component="$block->view()"
:data="$block->content()"
/>O pacote expõe um arquivo de configuração config/cms.php com as seguintes chaves principais:
cms.blocks.path— caminho onde as classes de Block são lidas/geradas. Default:app/Blocks.cms.blocks.namespace— namespace base usado para classes de Block geradas. Default:App\\Blocks.cms.views.path— caminho onde as views (variações) são lidas/geradas. Default:resources/views/components/blocks.cms.views.namespace— namespace/prefixo de views usado pelo métodoview()dos blocos (dot notation). Default:components.blocks(app views).cms.stubs.path— caminho local para stubs customizados (project-level). Default:resources/stubs/cms.cms.stubs.package_path— fallback para os stubs que vêm com o pacote. Default:app-modules/cms/stubs.
Publicar o arquivo de configuração e os stubs para customização:
php artisan vendor:publish --tag="cms-config"
php artisan vendor:publish --tag="cms-stubs"- Os dados de cada bloco são armazenados em
page_blocks.data(JSON). - A variação selecionada faz parte dos dados do bloco.
- A ordenação é feita por
position.
Acesso ao painel de gerenciamento de páginas e blocos:
http://localhost:8000/cms
Cada página criada no CMS é acessível publicamente através do seu slug:
http://localhost:8000/{slug-da-pagina}
Este projeto está em fase de MVP e algumas partes ainda são provisórias:
- O layout da página pública é simples e básico, servindo apenas como prova de conceito.
- Os schemas do Filament também são básicos.
- Os blocos e componentes existentes foram criados principalmente para teste e validação da arquitetura, não como versão final de UI.
Esses pontos serão refinados conforme a evolução do projeto.