Convenção de módulos

TLDR: projetos com mais de um runtime independente colocam cada um em modules/<nome>/; nada de módulo solto na raiz. .module/ é para o módulo o que .project/ é para o repo.

Este repo tem dois módulos: modules/frontend (React + Vite) e modules/backend (Rails).

Layout

```

/ ├── modules/ │ ├── frontend/ │ │ ├── .module/ # metadados do módulo (análogo ao .project/ do repo) │ │ │ ├── make/ │ │ │ │ └── main.mk # alvos de make específicos do módulo │ │ │ └── docker/ │ │ │ └── compose.yml # overrides de docker do módulo (porta, working_dir) │ │ ├── .infra/ # k8s + terraform do deploy deste módulo │ │ │ ├── k8s/ │ │ │ │ ├── base/ │ │ │ │ └── overlays/staging/ + production/ │ │ │ └── terraform/ │ │ ├── Makefile # inclui o stack do commons + .module/make/main.mk │ │ ├── src/ │ │ ├── package.json │ │ └── ... │ └── backend/ │ ├── .module/ │ │ ├── make/main.mk │ │ └── docker/compose.yml │ ├── .infra/ │ └── Makefile ├── .project/ │ └── docs/ # toda a documentação do repo, centralizada ├── .commons -> ... ├── Makefile # delega: frontend.%, backend.% ├── compose.yml # inclui o stack do commons + .module/docker/ de cada módulo ├── .env.example └── .gitignore ``` ## Por que `modules/` e não `apps/` ou `packages/` | Nome | Por que não | |---|---| | `apps/` | Sugere só aplicação de usuário final — exclui workers, jobs, scripts | | `packages/` | Sugere pacotes npm / bibliotecas compartilhadas | | `modules/` | Genérico: cobre qualquer componente executável ou deployável de forma independente, em qualquer stack. E não conflita com o `app/` do Rails quando um back-end Rails entra | ## Regras - Todo módulo vive dentro de `modules/` — nunca na raiz do projeto. - Cada módulo é autocontido: manifesto próprio (`package.json`, `mix.exs`, `Gemfile`…), config de tooling própria, dependências próprias. - Sem import de código entre módulos no nível da linguagem. - A raiz do projeto contém apenas: `modules/`, `.project/`, symlink `.commons`, `Makefile`, `compose.yml`, `.env.example`, `.gitignore`, `.tool-versions`. - Módulo ainda não implementado (placeholder) tem só `.module/` e `Makefile` — não precisa de `.gitkeep`. ## A convenção `.module/` `.module/` é para o módulo o que `.project/` é para o repo: metadados e config de tooling com escopo daquele módulo. | Caminho | Para quê | |---|---| | `.module/make/main.mk` | Alvos de make específicos do módulo — incluídos pelo `Makefile` dele | | `.module/docker/compose.yml` | Overrides de docker: `working_dir`, portas expostas, env vars — incluídos pelo `compose.yml` da raiz | **O que NÃO vai em `.module/`:** - **Documentação** — toda documentação vive em `.project/docs/` na raiz do repo, centralizada. Não existe `.module/docs/` nem `.module/specs/`. - **Infraestrutura** — vai em `.infra/`, dentro do módulo. ## Delegação no Makefile O `Makefile` da raiz inclui `commons/make/main.makefile` e delega por módulo: ```makefile frontend.%: @$(MAKE) -C modules/frontend $* backend.%: @$(MAKE) -C modules/backend $* ``` O `Makefile` de cada módulo inclui o stack do commons + o seu próprio `.module/make/main.mk`: ```makefile include $(COMMONS_DIR)/make/main.makefile include .module/make/main.mk ``` ## compose.yml O `compose.yml` da raiz inclui o stack do commons de cada módulo + o override de docker do módulo: ```yaml name: nectar-charges include: - path: - .commons/docker/compose/stacks/react.yml - modules/frontend/.module/docker/compose.yml ``` O `.module/docker/compose.yml` do módulo define apenas o que é específico dele (porta, `working_dir`) — nunca duplica o que o commons já fornece. ## Detecção de stack O Makefile do commons detecta a stack a partir de arquivos na raiz do projeto. Em projeto multi-módulo, o arquivo de detecção (`package.json`, `mix.exs`, etc.) fica dentro de `modules//`, não na raiz. Se necessário, informe o caminho do módulo explicitamente em `.project/make/overrides.mk`. ## Quando criar um módulo novo Crie um módulo quando o componente tem runtime, pipeline de build ou alvo de deploy próprios: - `modules/frontend/` — SPA React - `modules/backend/` — API Elixir/Phoenix, Ruby on Rails ou Node.js - `modules/worker/` — processador de jobs em background com processo próprio - `modules/mobile/` — app Expo/React Native - `modules/jobs/` — scripts de processamento em lote Não crie módulo para uma biblioteca compartilhada entre dois outros módulos — coloque o código compartilhado no módulo mais relevante, ou extraia para um repositório separado. ## Referências - [Camadas do app React](architecture/frontend_layers.md) - [Camadas do app Rails](architecture/backend_layers.md) - [Spec: estrutura mono-módulo](specs/20260721163000_mono_module_structure.md)