15 KiB
AGENT.md
Overview
This project is a mobile-first web application for an advertising agency to organize editorial calendars, important dates, deliveries, assets, and client-facing planning.
The main goal is to replace the current messy Trello workflow with a centralized, secure, responsive application where:
- agency staff can view and manage all clients they are allowed to access;
- each client can access only their own area;
- the calendar shows Brazilian national holidays, commemorative dates, and custom dates;
- specific days can contain content such as post copy, images, notes, status, and attachments;
- the dashboard includes a weekly overview so the team can quickly understand what is done and what is still pending.
The application itself must be fully localized in Brazilian Portuguese (pt-BR). Project documentation and developer-facing instructions may be written in English unless explicitly requested otherwise.
Audience
- Internal users: advertising team, social media team, account managers, designers, managers, and administrators.
- External users: agency clients, initially with read-only access.
- Product tone: clear, professional, direct, and operational.
- UI language: Brazilian Portuguese (
pt-BR).
Technical Stack
Frontend
- JavaScript.
- React 19.
- shadcn/ui.
- Mobile-first and fully responsive.
- UI text in
pt-BR. - Accessible components, including keyboard navigation where applicable.
Backend
- Go 1.25.
- Gin.
- REST API.
- Strong input validation.
- Authentication and role-based authorization.
- Clean, readable, modular structure.
Infrastructure
- Repository: Gitea.
- Hosting: Portainer.
- Configuration: environment variables only.
- Delivery: Dockerfile, Docker Compose, and CI/CD pipelines.
Product Identity
- Project name:
Mira. - Main brand color: orange.
- The UI must support light and dark themes.
- Theme switching must be available in the authenticated application shell.
- The design should feel operational and polished, not like a marketing landing page.
User Roles
Super Admin
The main administrative user for the agency.
- Created from Portainer environment variables.
- Can access all clients.
- Can create, edit, and remove users.
- Can create email invitations.
- Can manage clients, calendars, custom dates, and content.
- Can grant access to internal users and clients.
Expected variables:
SUPER_ADMIN_EMAILSUPER_ADMIN_PASSWORD
Agency User
Internal operational user.
- Can view assigned clients.
- Can create and edit calendar content according to permissions.
- Can view the weekly dashboard.
- Can attach assets to calendar days.
- Can update delivery/content statuses.
Client Viewer
External user linked to a specific client.
- Can log in.
- Can view only their own client area.
- Cannot create, edit, or delete content in the first version.
- Cannot access other clients.
Authentication and Invitations
- The application must have a login screen.
- There must be no public registration screen.
- The super admin can create users and send email invitations.
- Invitations must use a unique token, expiration date, and single-use flow.
- Passwords must be stored with a strong hash, never as plaintext.
- Password reset, if implemented, must use temporary tokens.
- Sessions must expire and be revocable.
Permissions Model
Use role-based access control with client scoping.
Minimum roles:
super_adminagency_userclient_viewer
Minimum rules:
super_admincan access everything.agency_usercan access only assigned clients unless explicitly elevated.client_viewercan access only their linked client.- Every sensitive route must validate authentication, role, and client scope.
- Never rely on frontend-only access control.
Core Modules
Login
- Simple, secure, responsive screen.
- Fields: email and password.
- Error messages in Portuguese.
- Brute-force protection.
- Do not reveal whether an email exists.
Weekly Dashboard
General view of the current week.
It should show:
- planned content and commitments for the week;
- pending items;
- completed items;
- relevant holidays and commemorative dates;
- filters by client, status, and owner;
- clear highlight for today.
Client Calendar
The core product surface.
It should support:
- monthly view;
- weekly view;
- day detail view;
- Brazilian national holidays;
- Brazilian commemorative dates;
- client-specific custom dates;
- content/posts attached to a date;
- attachments such as images, files, and text;
- content status.
Day Content
Each day can contain one or more items.
Suggested fields:
- title;
- description;
- content type;
- status;
- owner;
- client;
- date;
- optional time;
- copy/text;
- images and attachments;
- internal notes;
- client-visible notes;
- change history.
Suggested statuses:
rascunhoplanejadoem_producaoem_revisaoaprovadopublicadocancelado
Keep status values compatible with Portuguese UI labels.
Custom Dates
Allow custom dates globally or per client.
Examples:
- company anniversary;
- store anniversary;
- institutional date;
- recurring campaign;
- commercial milestone;
- internal event.
Suggested fields:
- name;
- description;
- date;
- annual recurrence flag;
- optional client;
- visibility;
- color or category.
Clients
Each client has their own area.
Suggested fields:
- name;
- slug;
- status;
- contacts;
- linked users;
- calendar settings;
- custom dates;
- display preferences.
Brazilian Calendar
The application must support:
- Brazilian national holidays;
- Brazilian commemorative dates;
- internal custom dates;
- client-specific custom dates.
Recommended implementation:
- keep an internal table/cache for holidays and commemorative dates;
- sync holidays by year from a configurable external provider;
- allow manual fallback if the external API fails;
- separate official holidays from non-official commemorative dates;
- allow administrative review of imported dates.
Provider decision:
- Initial provider: BrasilAPI.
- Regional holidays, municipal holidays, client-specific dates, and agency-specific commemorative dates will be added manually through the application.
- The backend must still use a provider abstraction so another provider can be added later without rewriting calendar features.
Providers considered:
- BrasilAPI: Brazilian public API with national holiday endpoints.
- Nager.Date: international public holiday API by country, with public endpoints that do not require an API key.
- Feriados API or feriados.dev: Brazil-focused services with national, state, and city coverage.
- Calendarific: international paid/freemium API with support for countries and regions.
Initial recommendation:
- implement a backend
CalendarProviderabstraction; - configure the provider through
CALENDAR_PROVIDER, defaulting tobrasilapi; - persist provider results in the database;
- allow manual registration of commemorative dates;
- never depend on real-time external API availability to render the calendar.
Expected variables:
CALENDAR_PROVIDERCALENDAR_API_BASE_URLCALENDAR_API_KEYCALENDAR_CACHE_TTL_HOURS
Security
The project must strictly follow OWASP best practices.
Minimum requirements:
- validate and sanitize all inputs;
- protect against XSS;
- protect against CSRF where applicable;
- protect against SQL injection using parameterized queries or safe ORM patterns;
- enforce backend access control on all protected routes;
- use strong password hashing;
- use secure cookies if cookie-based sessions are used;
- use restrictive CORS;
- rate-limit login and sensitive routes;
- set HTTP security headers;
- avoid sensitive data in logs;
- handle uploads securely;
- limit file size;
- validate MIME type and extension;
- store attachments safely;
- audit administrative actions;
- use environment variables for secrets;
- never commit credentials.
OWASP references to consider during implementation:
- OWASP Top 10.
- OWASP ASVS.
- OWASP Cheat Sheet Series.
Suggested Repository Structure
.
|-- AGENT.md
|-- README.md
|-- docker-compose.yml
|-- .env.example
|-- .gitea
| `-- workflows
| `-- ci.yml
|-- frontend
| |-- Dockerfile
| |-- package.json
| |-- src
| | |-- app
| | |-- components
| | |-- features
| | |-- lib
| | |-- routes
| | `-- styles
| `-- public
|-- backend
| |-- Dockerfile
| |-- go.mod
| |-- cmd
| | `-- api
| | `-- main.go
| |-- internal
| | |-- auth
| | |-- calendar
| | |-- clients
| | |-- config
| | |-- content
| | |-- database
| | |-- mail
| | |-- users
| | `-- security
| `-- migrations
`-- docs
|-- architecture.md
|-- security.md
`-- api.md
Database
Database decision: PostgreSQL.
PostgreSQL is the correct fit because the application is relational by nature: users, clients, permissions, invitations, calendar items, attachments, statuses, and audit logs all need strong consistency and queryable relationships.
Initial entities:
- users;
- clients;
- client_users;
- invitations;
- calendar_dates;
- holidays;
- commemorative_dates;
- calendar_items;
- calendar_item_attachments;
- audit_logs;
- sessions or refresh_tokens, depending on authentication strategy.
Use consistent timestamps:
created_atupdated_atdeleted_atwhen soft delete is needed.
Timezone rules:
- handle dates and times carefully;
- use
America/Sao_Pauloas the default operational timezone; - store instants in UTC when time is involved;
- store calendar-only dates as
date, not timestamp.
Uploads and Attachments
Attachments are a critical security surface.
Requirements:
- limit file size;
- restrict allowed file types;
- validate actual file content;
- rename files in storage;
- avoid serving uploads directly from the same domain without protection;
- prevent execution of uploaded files;
- store metadata in the database;
- support logical deletion.
Expected variables:
UPLOAD_MAX_SIZE_MBUPLOAD_ALLOWED_MIME_TYPESSTORAGE_DRIVERSTORAGE_LOCAL_PATHSTORAGE_S3_ENDPOINTSTORAGE_S3_BUCKETSTORAGE_S3_ACCESS_KEYSTORAGE_S3_SECRET_KEY
Used for invitations and possibly password reset.
Expected variables:
SMTP_HOSTSMTP_PORTSMTP_USERSMTP_PASSWORDSMTP_FROM_EMAILSMTP_FROM_NAMEAPP_PUBLIC_URL
Minimum Environment Variables
APP_ENV=production
APP_PUBLIC_URL=https://app.example.com.br
APP_TIMEZONE=America/Sao_Paulo
SUPER_ADMIN_EMAIL=admin@example.com.br
SUPER_ADMIN_PASSWORD=change-me-secure-password
DATABASE_URL=postgres://user:change-me-secure-password@postgres:5432/mira?sslmode=disable
JWT_SECRET=change-me-with-a-long-random-secret
JWT_ACCESS_TOKEN_TTL_MINUTES=15
JWT_REFRESH_TOKEN_TTL_DAYS=7
CORS_ALLOWED_ORIGINS=https://app.example.com.br
CALENDAR_PROVIDER=brasilapi
CALENDAR_API_BASE_URL=https://brasilapi.com.br
CALENDAR_API_KEY=
CALENDAR_CACHE_TTL_HOURS=24
SMTP_HOST=smtp.example.com.br
SMTP_PORT=587
SMTP_USER=
SMTP_PASSWORD=
SMTP_FROM_EMAIL=no-reply@example.com.br
SMTP_FROM_NAME=Mira
UPLOAD_MAX_SIZE_MB=10
UPLOAD_ALLOWED_MIME_TYPES=image/jpeg,image/png,image/webp,application/pdf
STORAGE_DRIVER=local
STORAGE_LOCAL_PATH=/var/lib/mira/uploads
Backend API
Standards:
- versioned routes under
/api/v1; - consistent JSON responses;
- errors in
pt-BR; - payload validation before business logic;
- authentication middleware;
- authorization middleware;
- rate limit middleware;
- security headers middleware;
- structured logs.
Suggested initial routes:
POST /api/v1/auth/login
POST /api/v1/auth/logout
POST /api/v1/auth/refresh
GET /api/v1/me
GET /api/v1/clients
POST /api/v1/clients
GET /api/v1/clients/:clientId
PATCH /api/v1/clients/:clientId
GET /api/v1/calendar/week
GET /api/v1/clients/:clientId/calendar
GET /api/v1/clients/:clientId/calendar/days/:date
POST /api/v1/clients/:clientId/calendar-items
GET /api/v1/calendar-items/:itemId
PATCH /api/v1/calendar-items/:itemId
DELETE /api/v1/calendar-items/:itemId
POST /api/v1/calendar-items/:itemId/attachments
DELETE /api/v1/attachments/:attachmentId
GET /api/v1/calendar/holidays
POST /api/v1/commemorative-dates
PATCH /api/v1/commemorative-dates/:dateId
DELETE /api/v1/commemorative-dates/:dateId
GET /api/v1/users
POST /api/v1/users/invitations
POST /api/v1/invitations/:token/accept
Frontend
Principles:
- mobile-first;
- dense, clear, operational screens;
- no landing page;
- first screen after login should be the weekly dashboard;
- calendar must be easy to navigate on mobile;
- use shadcn/ui consistently;
- keep visible UI text in
pt-BR; - do not rely on color alone to communicate status;
- support loading, error, empty, and success states.
Initial screens:
- login;
- weekly dashboard;
- client list;
- client calendar;
- day detail;
- calendar item detail/create/edit;
- users and invitations;
- custom date settings.
Gitea CI/CD
Minimum pipeline:
- frontend lint;
- frontend tests;
- frontend build;
- backend lint/vet;
- backend tests;
- backend build;
- Docker image builds;
- vulnerability checks where possible.
Expected file:
.gitea/workflows/ci.yml
Docker and Portainer
Expected deliverables:
frontend/Dockerfilebackend/Dockerfiledocker-compose.yml.env.example
Docker Compose should include:
- frontend;
- backend;
- PostgreSQL;
- database volume;
- local upload volume when
STORAGE_DRIVER=local.
All configuration must come from environment variables to support Portainer-based operation.
Testing
Backend:
- business rule unit tests;
- authorization tests;
- calendar tests;
- invitation tests;
- validation tests;
- upload tests.
Frontend:
- tests for critical components;
- calendar rendering tests;
- login flow tests;
- role-based visibility tests.
E2E, when possible:
- super admin login;
- client creation;
- user invitation;
- client read-only access;
- calendar item creation;
- weekly view.
MVP Acceptance Criteria
The MVP must allow:
- login with the super admin loaded from environment variables;
- client creation;
- internal and client users created through invitations;
- role-based access control;
- clients to view only their own page;
- agency users to view all permitted clients;
- monthly calendar per client;
- general weekly dashboard;
- Brazilian national holiday display;
- custom date registration;
- content creation per day;
- attachment of allowed images or files;
- responsive mobile UI;
- Docker Compose deployment through Portainer;
- basic Gitea CI/CD pipeline.
Out of Scope for the Initial MVP
These can be planned after the MVP:
- public registration;
- client editing permissions;
- formal approval workflows;
- direct Instagram, Facebook, TikTok, or LinkedIn integration;
- automated publishing;
- real-time comments;
- push notifications;
- full kanban board;
- complex subscription-based multi-tenancy.
Implementation Principles
- Prioritize clarity and security.
- Keep frontend, backend, and infrastructure separated.
- Avoid hard coupling to a single calendar provider.
- Protect all backend routes.
- Log important administrative actions.
- Create reusable components only when there is a real need.
- Prefer clear names over premature abstractions.
- Document relevant technical decisions in
docs/architecture.md. - Never commit secrets.