commit d4b566509a18adef7c425cd1fa37f775432981e0 Author: Gabriel Sancho Date: Thu Mar 26 13:04:27 2026 -0300 docs: add initial project documentation for Condado Newsletter Bot diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..fed2e9e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,147 @@ +# Condado Newsletter Bot + +A newsletter bot built with **Kotlin** and **Spring Boot**. This file gives Claude persistent +instructions and context about the project so every session starts with the right knowledge. + +--- + +## Project Overview + +- **Language:** Kotlin (JVM) +- **Framework:** Spring Boot 3.x +- **Purpose:** Automate the creation, management, and delivery of newsletters +- **Architecture:** REST API backend with scheduled jobs for sending newsletters + +--- + +## Tech Stack + +| Layer | Technology | +|---------------|-----------------------------------| +| Language | Kotlin | +| Framework | Spring Boot 3.x | +| Build Tool | Gradle (Kotlin DSL - `build.gradle.kts`) | +| Database | PostgreSQL (via Spring Data JPA) | +| Email | Spring Mail (SMTP / JavaMailSender) | +| Scheduler | Spring `@Scheduled` tasks | +| Testing | JUnit 5 + MockK | +| Docs | Springdoc OpenAPI (Swagger UI) | + +--- + +## Project Structure + +``` +src/ +├── main/ +│ ├── kotlin/com/condado/newsletter/ +│ │ ├── CondadoNewsletterApplication.kt # App entry point +│ │ ├── config/ # Spring configuration classes +│ │ ├── controller/ # REST controllers +│ │ ├── service/ # Business logic +│ │ ├── repository/ # Spring Data JPA repositories +│ │ ├── model/ # JPA entities +│ │ ├── dto/ # Data Transfer Objects +│ │ └── scheduler/ # Scheduled tasks +│ └── resources/ +│ ├── application.yml # Main config +│ ├── application-dev.yml # Dev profile config +│ └── templates/ # Email HTML templates (Thymeleaf) +└── test/ + └── kotlin/com/condado/newsletter/ # Tests mirror main structure +``` + +--- + +## Build & Run Commands + +```bash +# Build the project +./gradlew build + +# Run the application (dev profile) +./gradlew bootRun --args='--spring.profiles.active=dev' + +# Run all tests +./gradlew test + +# Run a specific test class +./gradlew test --tests "com.condado.newsletter.service.NewsletterServiceTest" + +# Generate OpenAPI docs (served at /swagger-ui.html when running) +./gradlew bootRun +``` + +--- + +## Coding Standards + +- Use **Kotlin idiomatic** style: data classes, extension functions, and null-safety operators. +- Prefer `val` over `var` wherever possible. +- Use **constructor injection** for dependencies (never field injection with `@Autowired`). +- All DTOs must be **data classes** with validation annotations (`javax.validation`). +- Controller methods must return `ResponseEntity` with explicit HTTP status codes. +- Services must be annotated with `@Service` and **never** depend on controllers. +- Repositories must extend `JpaRepository`. +- Use `@Transactional` on service methods that modify data. +- All public functions must have **KDoc** comments. +- Use **`snake_case`** for database columns and **`camelCase`** for Kotlin properties. +- Keep controllers thin — business logic belongs in services. + +--- + +## Naming Conventions + +| Artifact | Convention | Example | +|----------------|-----------------------------------|-----------------------------| +| Classes | PascalCase | `NewsletterService` | +| Functions | camelCase | `sendNewsletter()` | +| Variables | camelCase | `subscriberList` | +| Constants | SCREAMING_SNAKE_CASE | `MAX_RETRIES` | +| DB tables | snake_case (plural) | `newsletter_subscribers` | +| REST endpoints | kebab-case | `/api/v1/newsletter-issues` | +| Packages | lowercase | `com.condado.newsletter` | + +--- + +## Testing Guidelines + +- Every service class must have a corresponding unit test class. +- Use **MockK** for mocking (not Mockito). +- Integration tests use `@SpringBootTest` and an **H2 in-memory** database. +- Test method names follow the pattern: `should_[expectedBehavior]_when_[condition]`. +- Minimum 80% code coverage for service classes. + +--- + +## Environment Variables + +| Variable | Description | +|-----------------------|-----------------------------------| +| `SPRING_DATASOURCE_URL` | PostgreSQL connection URL | +| `SPRING_DATASOURCE_USERNAME` | DB username | +| `SPRING_DATASOURCE_PASSWORD` | DB password | +| `MAIL_HOST` | SMTP host | +| `MAIL_PORT` | SMTP port | +| `MAIL_USERNAME` | SMTP username | +| `MAIL_PASSWORD` | SMTP password | + +> ⚠️ Never hardcode credentials. Always use environment variables or a `.env` file (gitignored). + +--- + +## Key Domain Concepts + +- **Subscriber:** A person who opted in to receive newsletters. +- **NewsletterIssue:** A single newsletter edition with a subject and HTML body. +- **Campaign:** A scheduled or triggered dispatch of a `NewsletterIssue` to a group of subscribers. +- **SendLog:** A record of each email send attempt (status: PENDING / SENT / FAILED). + +--- + +## Git Workflow + +- Branch naming: `feature/`, `fix/`, `chore/` +- Commit messages follow [Conventional Commits](https://www.conventionalcommits.org/): `feat:`, `fix:`, `chore:`, `docs:`, `test:` +- PRs require at least one passing CI check before merging. +- Never commit directly to `main`.