Copilot instructions
.github/copilot-instructions.mdCopilot instructions
Quality
84/100
Scores the file, not the repository.Length
3,341 words
134 headings · 33 code blocksRepository
949
— · pushed 0 days agoLast changed
today
First indexed 3 days ago.1# Copilot Coding Agent Instructions for dotCMS Core23> **Purpose**: This file provides essential information for AI coding agents working with the dotCMS repository. It contains critical patterns, common errors, and workflows to work efficiently.45## Repository Overview67dotCMS is a **Universal Content Management System** - a large-scale enterprise Java/Angular CMS with:8- **Maven multi-module project** (~30+ modules) for backend9- **Nx monorepo** for Angular frontend applications and libraries10- **Mature codebase** with 15+ years of history (mix of modern and legacy patterns)1112**Tech Stack:**13- **Backend**: Java 21 runtime (Java 11 syntax for core), Maven 3.9+, JAX-RS REST APIs14- **Frontend**: Angular 20+, TypeScript 5.6+, Nx 20.5+, PrimeNG 17.18+15- **Infrastructure**: Docker, PostgreSQL, Elasticsearch, Tomcat 916- **Testing**: JUnit 5, Jest, Spectator, Playwright, Postman1718**Key Characteristics:**19- Monolithic architecture with modular design20- Heavy use of dependency injection (CDI/Guice)21- Immutable objects pattern (Immutables library)22- RESTful APIs with OpenAPI/Swagger documentation23- Reactive patterns with signals in frontend2425## Environment Requirements2627**CRITICAL: Build will fail without correct versions**2829| Tool | Version | Installation | Verification |30|------|---------|--------------|--------------|31| Java | 21.0.8+ | `sdk env install` (SDKMAN) | `java -version` |32| Node.js | 22.22.3+ | `nvm use` (from `.nvmrc`) | `node --version` |33| Maven | 3.9+ | Wrapper included (`./mvnw`) | `./mvnw --version` |34| Docker | Latest | [Docker Desktop](https://www.docker.com/products/docker-desktop) | `docker --version` |3536**Common Setup Error #1 - Wrong Java Version:**37```bash38# Error: "Building this project requires JDK version 21 or higher"39# Solution: Install Java 21 with SDKMAN40sdk env install # Uses .sdkmanrc file41sdk use java 21.0.8-ms42```4344## Build Commands (Choose the Right One!)4546**⚠️ CRITICAL**: Build times vary significantly (2-15 min). Choose based on your changes.4748### Quick Reference49```bash50# ❌ WRONG - Missing dependencies51./mvnw install -pl :dotcms-core -DskipTests52# Error: "Cannot resolve in-project dependency: com.dotcms:dotcms-core-web"5354# ✅ CORRECT - For simple backend changes (~2-3 min)55./mvnw install -pl :dotcms-core --am -DskipTests56# The --am flag builds required dependencies5758# ✅ Full build without Docker (~5-8 min)59./mvnw clean install -DskipTests -Ddocker.skip6061# ✅ Full build with Docker image (~8-15 min)62./mvnw clean install -DskipTests63```6465### Using Just Commands (Optional)66```bash67# Just provides shorter aliases for common tasks68brew install just # Install once6970just build-quicker # Same as: ./mvnw install -pl :dotcms-core --am -DskipTests71just build # Same as: ./mvnw clean install -DskipTests72just build-no-docker # Same as: ./mvnw clean install -DskipTests -Ddocker.skip73```7475## Testing Commands7677**⚠️ CRITICAL: Never run full integration suite (60+ min). Always target specific tests.**7879### Backend Testing Strategy8081**Common Test Error - Tests Silently Skipped:**82```bash83# ❌ WRONG - Tests are skipped by default!84./mvnw verify -pl :dotcms-integration85# No error, but tests don't run8687# ✅ CORRECT - Explicit flag required88./mvnw verify -pl :dotcms-integration -Dcoreit.test.skip=false -Dit.test=MyTest89```9091**Recommended Testing Workflow:**9293```bash94# 1. Specific integration test class (~2-10 min) - RECOMMENDED95./mvnw verify -pl :dotcms-integration -Dcoreit.test.skip=false -Dit.test=ContentTypeAPIImplTest9697# 2. Specific test method (~30 sec - 2 min)98./mvnw verify -pl :dotcms-integration -Dcoreit.test.skip=false -Dit.test=MyTest#testMethod99100# 3. IDE debugging workflow (FASTEST iteration)101just test-integration-ide # Start services (PostgreSQL + Elasticsearch + dotCMS)102# → Run/debug individual tests in your IDE (10-30 sec per test)103just test-integration-stop # Clean up when done104105# 4. JVM unit tests only (~30 sec)106./mvnw test -pl :dotcms-core107108# 5. Postman API tests (specific collection)109./mvnw verify -pl :dotcms-postman -Dpostman.test.skip=false -Dpostman.collections=ai110just test-postman ai # Shorter command111112# ⚠️ NEVER DO THIS during development (60+ min):113./mvnw verify -Dcoreit.test.skip=false # Runs ALL integration tests114```115116### Frontend Testing Commands117```bash118cd core-web119120# Install dependencies first121pnpm install # Required before first test122123# Run specific component tests (RECOMMENDED)124nx run dotcms-ui:test --testNamePattern="ContentTypeComponent"125126# Run all tests in a file127nx run dotcms-ui:test --testPathPattern="dot-edit-content"128129# Run all unit tests130nx run dotcms-ui:test131132# Test only affected by your changes133nx affected -t test --exclude='tag:skip:test'134135# Lint code136nx run dotcms-ui:lint --fix137138# Development server (separate from backend)139nx run dotcms-ui:serve # Available at http://localhost:4200140```141142## Project Structure143144```145core/146├── dotCMS/ # Main backend Java code147│ ├── src/main/java/com/ # Java source files148│ │ ├── dotcms/ # Modern domain-driven packages149│ │ └── dotmarketing/ # Legacy packages150│ └── src/main/webapp/ # JSP views, static assets151├── core-web/ # Frontend (Angular/Nx monorepo)152│ ├── apps/ # Applications153│ │ ├── dotcms-ui/ # Main admin UI154│ │ ├── dotcms-block-editor/ # Block editor app155│ │ └── dotcms-binary-field-builder/156│ └── libs/ # Shared libraries157│ ├── sdk/ # External SDKs (client, react, angular)158│ ├── data-access/ # API services159│ ├── ui/ # Shared UI components160│ ├── portlets/ # Feature modules161│ └── dotcms-models/ # TypeScript interfaces162├── dotcms-integration/ # Integration tests163├── dotcms-postman/ # Postman API tests164├── test-karate/ # Karate API tests165├── e2e/ # E2E tests (Playwright)166├── bom/ # Bill of Materials167│ └── application/pom.xml # ⚠️ DEPENDENCY VERSIONS GO HERE168├── parent/pom.xml # Plugin management169├── pom.xml # Root aggregator POM170├── justfile # Task runner commands171└── .github/workflows/ # CI/CD pipelines172 ├── cicd_1-pr.yml # PR builds173 ├── cicd_2-merge-queue.yml # Merge queue174 ├── cicd_3-trunk.yml # Trunk builds175 └── cicd_4-nightly.yml # Nightly builds176```177178## Critical Patterns (Always Follow)179180### Maven Dependency Management181182**⚠️ CRITICAL RULE: Add dependency versions ONLY to `bom/application/pom.xml`**183184```xml185<!-- ❌ WRONG - Adding version to module POM -->186<!-- In dotCMS/pom.xml -->187<dependency>188 <groupId>com.example</groupId>189 <artifactId>my-library</artifactId>190 <version>1.2.3</version> <!-- NO! This will cause conflicts -->191</dependency>192193<!-- ✅ CORRECT - Version in BOM, no version in module -->194<!-- Step 1: In bom/application/pom.xml -->195<properties>196 <my-library.version>1.2.3</my-library.version>197</properties>198<dependencyManagement>199 <dependencies>200 <dependency>201 <groupId>com.example</groupId>202 <artifactId>my-library</artifactId>203 <version>${my-library.version}</version>204 </dependency>205 </dependencies>206</dependencyManagement>207208<!-- Step 2: In dotCMS/pom.xml or other module -->209<dependency>210 <groupId>com.example</groupId>211 <artifactId>my-library</artifactId>212 <!-- NO version here - inherited from BOM -->213</dependency>214```215216**Why**: Centralized version management prevents conflicts across 30+ modules.217218### Java Coding Patterns219220**ALWAYS use these dotCMS utility classes (not standard Java equivalents):**221222```java223// ✅ Configuration - Use Config class (NOT System.getProperty)224import com.dotmarketing.util.Config;225String value = Config.getStringProperty("key", "default");226boolean enabled = Config.getBooleanProperty("feature.enabled", false);227int timeout = Config.getIntProperty("timeout.seconds", 30);228229// ✅ Logging - Use Logger class (NOT System.out or Log4j directly)230import com.dotmarketing.util.Logger;231Logger.info(this, "Operation completed successfully");232Logger.error(this, "Error occurred: " + e.getMessage(), e);233Logger.debug(this, () -> "Expensive string: " + computeExpensiveString());234235// ✅ Services - Use APILocator (NOT direct instantiation)236import com.dotcms.api.system.APILocator;237ContentletAPI contentletAPI = APILocator.getContentletAPI();238UserAPI userAPI = APILocator.getUserAPI();239PermissionAPI permissionAPI = APILocator.getPermissionAPI();240241// ✅ Null checking - Use UtilMethods (NOT manual null checks)242import com.dotmarketing.util.UtilMethods;243if (UtilMethods.isSet(myString)) { // Checks null, empty, "null" string244 processString(myString);245}246247// Safe supplier pattern for nested null checks248String value = UtilMethods.isSet(() -> complex.getObject().getValue())249 ? complex.getObject().getValue()250 : "default";251252// ✅ Collections - Use CollectionsUtils253import com.dotcms.util.CollectionsUtils;254List<String> list = CollectionsUtils.list("item1", "item2");255Map<String, Object> map = CollectionsUtils.map("key1", "value1", "key2", "value2");256```257258### Immutable Objects Pattern259260**Use Immutables library for data objects:**261262```java263import org.immutables.value.Value;264import com.fasterxml.jackson.databind.annotation.JsonDeserialize;265import com.fasterxml.jackson.databind.annotation.JsonSerialize;266267@Value.Immutable268@JsonSerialize(as = ImmutableMyEntity.class)269@JsonDeserialize(as = ImmutableMyEntity.class)270public abstract class MyEntity {271 public abstract String name();272 public abstract Optional<String> description();273274 @Value.Default275 public boolean enabled() { return true; }276277 // Builder convenience method278 public static Builder builder() {279 return ImmutableMyEntity.builder();280 }281}282283// ⚠️ IMPORTANT: Run ./mvnw compile after creating @Value.Immutable classes284// The annotation processor generates ImmutableMyEntity at compile time285286// Usage:287MyEntity entity = MyEntity.builder()288 .name("test")289 .description("optional description")290 .enabled(false)291 .build();292```293294### REST API Patterns (JAX-RS)295296**Complete REST endpoint pattern with OpenAPI documentation:**297298```java299import javax.ws.rs.*;300import javax.ws.rs.core.*;301import io.swagger.v3.oas.annotations.*;302import io.swagger.v3.oas.annotations.media.*;303import io.swagger.v3.oas.annotations.parameters.*;304import io.swagger.v3.oas.annotations.responses.*;305import io.swagger.v3.oas.annotations.tags.Tag;306import com.dotcms.rest.WebResource;307import com.dotcms.rest.annotation.NoCache;308309@Path("/v1/resource")310@Tag(name = "Resource", description = "Resource operations")311public class ResourceEndpoint {312 private final WebResource webResource = new WebResource();313314 @GET315 @Path("/{id}")316 @Operation(317 summary = "Get by ID",318 description = "Retrieves a resource by its identifier"319 )320 @ApiResponse(321 responseCode = "200",322 description = "Resource found",323 content = @Content(324 mediaType = MediaType.APPLICATION_JSON,325 schema = @Schema(implementation = ResponseEntityResourceView.class)326 )327 )328 @ApiResponse(responseCode = "404", description = "Resource not found")329 @ApiResponse(responseCode = "401", description = "Unauthorized")330 @Produces(MediaType.APPLICATION_JSON)331 @NoCache332 public Response getById(333 @Context HttpServletRequest request,334 @Context HttpServletResponse response,335 @Parameter(description = "Resource ID", required = true)336 @PathParam("id") String id) {337338 // ALWAYS initialize request context for authentication/permissions339 InitDataObject initData = webResource.init(request, response, true);340 User user = initData.getUser();341342 // Business logic here343 Resource resource = resourceAPI.findById(id, user);344345 return Response.ok(new ResponseEntityResourceView(resource)).build();346 }347}348```349350**⚠️ CRITICAL: OpenAPI Documentation Rules**351- ALWAYS add `@Tag` at class level352- ALWAYS add `@Operation` to every endpoint353- ALWAYS add `@ApiResponse` for 200 and error codes354- ALWAYS specify `@Schema(implementation = SpecificView.class)` - NEVER use generic `ResponseEntityView.class`355- For path parameters: Use `@PathParam` with matching `@Path` placeholder356- For query parameters: Use `@QueryParam` (e.g., `?filter=value`)357- ALWAYS add `@NoCache` for REST endpoints that return dynamic data358359### Angular/Frontend Patterns360361**Modern Angular syntax (REQUIRED - no legacy patterns):**362363```typescript364// ✅ CORRECT: Modern control flow (Angular 19+)365@if (condition()) {366 <div>Content</div>367}368@for (item of items(); track item.id) {369 <div>{{ item.name }}</div>370}371372// ❌ WRONG: Legacy structural directives373<div *ngIf="condition">Content</div>374<div *ngFor="let item of items">{{ item.name }}</div>375376// ✅ CORRECT: Modern inputs/outputs (signals)377export class MyComponent {378 data = input<string>(); // NOT @Input()379 onChange = output<string>(); // NOT @Output()380381 // Computed values382 displayValue = computed(() => this.data().toUpperCase());383}384385// ✅ CORRECT: Testing with Spectator386describe('MyComponent', () => {387 let spectator: Spectator<MyComponent>;388389 beforeEach(() => {390 spectator = createComponentFactory({391 component: MyComponent392 })();393 });394395 it('should update on input change', () => {396 // ✅ ALWAYS use spectator.setInput()397 spectator.setInput('data', 'test value');398 spectator.detectChanges();399400 // ✅ ALWAYS use data-testid for selectors401 const button = spectator.query('[data-testid="submit-button"]');402 expect(button).toBeVisible();403404 // ✅ Test user interactions405 spectator.click('[data-testid="submit-button"]');406 expect(spectator.query('[data-testid="success-message"]')).toExist();407 });408});409410// ❌ WRONG: Direct property access in tests411spectator.component.data = 'value'; // NO! Use setInput()412```413414## Security Guidelines415416**⚠️ CRITICAL: Security violations are unacceptable and will fail code review.**417418### Never Do These (Security Violations)419420```java421// ❌ NEVER: Hardcoded secrets or credentials422String apiKey = "sk-1234567890"; // SECURITY VIOLATION423String password = "admin123"; // SECURITY VIOLATION424425// ❌ NEVER: Direct input injection without validation426String sql = "SELECT * FROM users WHERE name = '" + userInput + "'"; // SQL INJECTION427428// ❌ NEVER: Exposing sensitive data in logs429Logger.info(this, "Password: " + password); // SECURITY VIOLATION430Logger.info(this, "API Key: " + apiKey); // SECURITY VIOLATION431432// ❌ NEVER: Using System.out/err for any output433System.out.println("Debug info"); // Use Logger instead434```435436### Always Do These (Security Best Practices)437438```java439// ✅ ALWAYS: Validate and sanitize user input440import com.dotmarketing.util.UtilMethods;441442public void processInput(String userInput) {443 // Null/empty check444 if (!UtilMethods.isSet(userInput)) {445 throw new DotDataException("Input cannot be empty");446 }447448 // Format validation (whitelist approach)449 if (!userInput.matches("^[a-zA-Z0-9\\s\\-_\\.]+$")) {450 Logger.warn(this, "Invalid input format attempted");451 throw new DotSecurityException("Invalid input format");452 }453454 // Length validation455 if (userInput.length() > 255) {456 throw new DotDataException("Input exceeds maximum length");457 }458459 // Process validated input460 processValidatedInput(userInput);461}462463// ✅ ALWAYS: Use Config for sensitive properties464String apiKey = Config.getStringProperty("external.api.key", "");465if (!UtilMethods.isSet(apiKey)) {466 throw new DotDataException("API key not configured");467}468469// ✅ ALWAYS: Use proper exception handling470try {471 riskyOperation();472 Logger.info(this, "Operation completed successfully");473} catch (SQLException e) {474 Logger.error(this, "Database operation failed", e);475 throw new DotDataException("Failed to process request", e);476} catch (Exception e) {477 Logger.error(this, "Unexpected error", e);478 throw new DotRuntimeException("System error occurred", e);479}480481// ✅ ALWAYS: Log safely (no sensitive data)482Logger.info(this, "User authenticated: " + user.getUserId()); // Log ID, not password483Logger.debug(this, () -> "Processing " + items.size() + " items"); // Lazy evaluation484```485486## Common Issues and Solutions487488### Issue #1: Build Fails - Wrong Java Version489490**Error:**491```492[ERROR] Rule 1: org.apache.maven.enforcer.rules.version.RequireJavaVersion failed493[ERROR] Building this project requires JDK version 21 or higher494```495496**Solution:**497```bash498# Check current version499java -version500501# Install Java 21 with SDKMAN502sdk env install # Uses .sdkmanrc file503sdk use java 21.0.8-ms504505# Verify506java -version # Should show 21.0.8507```508509### Issue #2: Build Fails - Missing Dependencies510511**Error:**512```513[ERROR] Failed to calculate checksums for dotcms-core:514Cannot resolve in-project dependency: com.dotcms:dotcms-core-web:war:1.0.0-SNAPSHOT515```516517**Solution:**518```bash519# ❌ WRONG - Missing --am flag520./mvnw install -pl :dotcms-core -DskipTests521522# ✅ CORRECT - Include dependencies with --am flag523./mvnw install -pl :dotcms-core --am -DskipTests524```525526### Issue #3: Tests Are Silently Skipped527528**Symptom:** Test command succeeds but no tests run.529530**Solution:**531```bash532# Tests are skipped by default. Add explicit flags:533-Dcoreit.test.skip=false # For integration tests534-Dpostman.test.skip=false # For Postman tests535-Dkarate.test.skip=false # For Karate tests536537# Example:538./mvnw verify -pl :dotcms-integration -Dcoreit.test.skip=false539```540541### Issue #4: Frontend Build Fails - Node Version542543**Error:**544```545error @angular/compiler-cli@19.2.15: The engine "node" is incompatible546```547548**Solution:**549```bash550# Check required version551cat .nvmrc # Shows: v22.22.3552553# Install and use correct version554nvm install 22.22.3555nvm use 22.22.3556557# Verify558node --version # Should show v22.22.3559```560561### Issue #5: Frontend Build Fails - Puppeteer ARM64562563**Error (on Apple M1/M2 Macs):**564```565[ERROR] The chromium binary is not available for arm64566```567568**Solution:**569```bash570# Install Chromium for ARM64571brew install chromium572573# Set environment variables (add to .zshrc or .bashrc)574export PUPPETEER_EXECUTABLE_PATH=$(which chromium)575export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true576577# Reload shell578source ~/.zshrc579580# Reinstall dependencies581cd core-web && pnpm install582```583584### Issue #6: Dependency Version Conflict585586**Error:**587```588[ERROR] Dependency convergence error for com.example:library:jar589```590591**Solution:**592```bash593# Check dependency tree594./mvnw dependency:tree -pl :dotcms-core | grep "library"595596# Add version to BOM (NOT module POM!)597# Edit bom/application/pom.xml:598<properties>599 <library.version>1.2.3</library.version>600</properties>601<dependencyManagement>602 <dependencies>603 <dependency>604 <groupId>com.example</groupId>605 <artifactId>library</artifactId>606 <version>${library.version}</version>607 </dependency>608 </dependencies>609</dependencyManagement>610```611612### Issue #7: Docker Build Fails613614**Error:** Docker image build fails or times out.615616**Solution:**617```bash618# Skip Docker build during development619./mvnw clean install -DskipTests -Ddocker.skip620621# Or use Just command622just build-no-docker623```624625### Issue #8: "Cannot Find Symbol" After Adding @Value.Immutable626627**Error:**628```629[ERROR] cannot find symbol: class ImmutableMyEntity630```631632**Solution:**633```bash634# Immutables are generated at compile time635# Run compile phase to generate classes636./mvnw compile -pl :dotcms-core637638# Then continue with your build639./mvnw install -pl :dotcms-core --am -DskipTests640```641642## CI/CD and Validation643644### What Triggers CI Builds645646**File patterns that trigger builds** (from `.github/filters.yaml`):647648- **Backend Changes**: `dotCMS/**`, `bom/**`, `parent/**`, `pom.xml`, `dotcms-integration/**`649- **Frontend Changes**: `core-web/**`, `dotCMS/src/main/webapp/html/**/*.{css,js}`650- **CLI Changes**: `tools/dotcms-cli/**`651- **Full Build Trigger**: `.sdkmanrc`, `.nvmrc`, workflow files652653### CI Workflows654655| Workflow | Trigger | Purpose |656|----------|---------|---------|657| `cicd_1-pr.yml` | Pull request | PR validation |658| `cicd_2-merge-queue.yml` | Merge queue | Pre-merge validation |659| `cicd_3-trunk.yml` | Push to main | Trunk integration |660| `cicd_4-nightly.yml` | Schedule (nightly) | Full test suite |661662### Pre-Commit Checklist663664Before committing code, ensure:6656661. ✅ **Build succeeds**: `./mvnw install -pl :dotcms-core --am -DskipTests`6672. ✅ **Tests pass**: Run relevant tests for your changes (specific test classes)6683. ✅ **No hardcoded secrets**: Check for API keys, passwords, credentials6694. ✅ **Dependency versions in BOM**: Check `bom/application/pom.xml`6705. ✅ **OpenAPI annotations**: REST endpoints have complete `@Operation` and `@ApiResponse`6716. ✅ **Security validation**: Input validation, no SQL injection risks6727. ✅ **Logging uses Logger**: No `System.out.println()`673674## Development Workflows675676### Workflow #1: Simple Backend Code Change677678```bash679# 1. Make code changes in dotCMS/src/main/java/680681# 2. Build with dependencies (~2-3 min)682./mvnw install -pl :dotcms-core --am -DskipTests683684# 3. Run specific test (~2-10 min)685./mvnw verify -pl :dotcms-integration -Dcoreit.test.skip=false -Dit.test=MyTest686687# 4. Commit changes688git add .689git commit -m "feat: add new feature"690```691692### Workflow #2: Adding New REST Endpoint693694```bash695# 1. Create endpoint class in dotCMS/src/main/java/com/dotcms/rest/api/v1/696697# 2. Add complete OpenAPI documentation698# - @Tag at class level699# - @Operation for each method700# - @ApiResponse with specific @Schema701702# 3. Build703./mvnw install -pl :dotcms-core --am -DskipTests704705# 4. Test endpoint with Postman or curl706curl -X GET http://localhost:8080/api/v1/myresource/123707708# 5. Run Postman API tests709./mvnw verify -pl :dotcms-postman -Dpostman.test.skip=false -Dpostman.collections=all710```711712### Workflow #3: Frontend Component Development713714```bash715# 1. Navigate to frontend716cd core-web717718# 2. Install dependencies (first time only)719pnpm install720721# 3. Start development server722nx serve dotcms-ui723# Available at http://localhost:4200724725# 4. Make changes in apps/dotcms-ui/src/ or libs/726727# 5. Run component tests728nx run dotcms-ui:test --testNamePattern="MyComponent"729730# 6. Lint and fix731nx run dotcms-ui:lint --fix732733# 7. Build for production734nx build dotcms-ui735```736737### Workflow #4: IDE Integration Test Debugging738739```bash740# 1. Build the project once741./mvnw clean install -DskipTests742743# 2. Start integration test services744just test-integration-ide745# This starts PostgreSQL, Elasticsearch, and dotCMS746747# 3. In your IDE (IntelliJ/Eclipse):748# - Navigate to test class in dotcms-integration/749# - Set breakpoints750# - Right-click test method → Debug751# - Tests run in ~10-30 seconds752753# 4. Make code changes, rebuild754./mvnw install -pl :dotcms-core --am -DskipTests755756# 5. Re-run test in IDE (no need to restart services)757758# 6. Stop services when done759just test-integration-stop760```761762### Workflow #5: Adding New Maven Dependency763764```bash765# 1. Add version to bom/application/pom.xml766<properties>767 <my-library.version>1.2.3</my-library.version>768</properties>769<dependencyManagement>770 <dependencies>771 <dependency>772 <groupId>com.example</groupId>773 <artifactId>my-library</artifactId>774 <version>${my-library.version}</version>775 </dependency>776 </dependencies>777</dependencyManagement>778779# 2. Add dependency to module (NO version)780# In dotCMS/pom.xml or other module781<dependency>782 <groupId>com.example</groupId>783 <artifactId>my-library</artifactId>784</dependency>785786# 3. Build to verify787./mvnw install -pl :dotcms-core --am -DskipTests788789# 4. Check for conflicts790./mvnw dependency:tree -pl :dotcms-core | grep "my-library"791```792793## Key Files Reference794795### Essential Files for Development796797| File | Purpose | When to Edit |798|------|---------|--------------|799| `bom/application/pom.xml` | Dependency versions | Adding/updating dependencies |800| `parent/pom.xml` | Plugin configuration | Changing build plugins |801| `pom.xml` | Root aggregator | Adding new modules |802| `justfile` | Task shortcuts | Creating new commands |803| `.sdkmanrc` | Java version | Never (managed by team) |804| `.nvmrc` | Node version | Never (managed by team) |805| `.github/filters.yaml` | CI triggers | Rarely (CI team) |806| `.github/workflows/` | CI/CD pipelines | Rarely (CI team) |807808### Configuration Files809810| File | Purpose |811|------|---------|812| `dotCMS/src/main/resources/dotcms-config-default.properties` | Default configuration |813| `dotCMS/src/main/webapp/WEB-INF/web.xml` | Web application descriptor |814| `core-web/nx.json` | Nx workspace configuration |815| `core-web/tsconfig.base.json` | TypeScript compiler options |816| `core-web/package.json` | Frontend dependencies |817818### Where to Find Code819820| Feature | Location |821|---------|----------|822| REST APIs | `dotCMS/src/main/java/com/dotcms/rest/api/` |823| Contentlet API | `dotCMS/src/main/java/com/dotcms/contenttype/` |824| Workflow | `dotCMS/src/main/java/com/dotcms/workflow/` |825| Storage | `dotCMS/src/main/java/com/dotcms/storage/` |826| Integrations | `dotCMS/src/main/java/com/dotcms/integrations/` |827| Util classes | `dotCMS/src/main/java/com/dotmarketing/util/` |828| Frontend UI | `core-web/apps/dotcms-ui/` |829| Shared components | `core-web/libs/ui/` |830| SDKs | `core-web/libs/sdk/` |831| Data services | `core-web/libs/data-access/` |832833## Additional Resources834835### Documentation836- **Full Development Guide**: [`CLAUDE.md`](/CLAUDE.md) - Comprehensive patterns and examples837- **Backend Onboarding**: [`dotBackendOnboarding.md`](/dotBackendOnboarding.md) - Setup and build guide838- **Frontend Onboarding**: [`dotFrontendOnboarding.md`](/dotFrontendOnboarding.md) - Angular/Nx guide839- **Core Web Guide**: [`core-web/CLAUDE.md`](/core-web/CLAUDE.md) - Frontend architecture840- **Detailed Docs**: [`docs/`](/docs/) - Organized by domain (backend, frontend, testing, etc.)841842### Quick Links843- [Justfile Commands](/justfile) - All available `just` shortcuts844- [GitHub Actions Workflows](/.github/workflows/) - CI/CD pipeline definitions845- [Contributing Guidelines](/CONTRIBUTING.md) - How to contribute846- [Security Policy](/SECURITY.md) - Security reporting847848---849850## Summary Checklist851852When working with dotCMS:853854### Backend (Java/Maven)855- ✅ Use Java 21 (`sdk env install`)856- ✅ Add versions to `bom/application/pom.xml` ONLY857- ✅ Use `Config`, `Logger`, `APILocator`, `UtilMethods`858- ✅ Build with `./mvnw install -pl :dotcms-core --am -DskipTests`859- ✅ Test specific classes: `-Dit.test=MyTest`860- ✅ Complete OpenAPI docs for REST endpoints861862### Frontend (Angular/TypeScript)863- ✅ Use Node 22.22.3+ (`nvm use`)864- ✅ Modern syntax: `@if`, `@for`, `input()`, `output()`865- ✅ Test with Spectator: `spectator.setInput()`, `data-testid`866- ✅ Build with `nx run dotcms-ui:build`867868### Security & Quality869- ❌ No hardcoded secrets or passwords870- ❌ No `System.out.println()` - use `Logger`871- ❌ No SQL injection - validate all input872- ✅ Validate user input with regex whitelist873- ✅ Use parameterized queries874- ✅ Log safely (no sensitive data)875876### Testing877- ❌ Never run full test suite during development (60+ min)878- ✅ Target specific test classes (~2-10 min)879- ✅ Use IDE debugging with `just test-integration-ide`880- ✅ Add test flags: `-Dcoreit.test.skip=false`881882---883884**Trust these instructions.** They are based on real build attempts and cover common issues. For questions not covered here, search the codebase or refer to [CLAUDE.md](/CLAUDE.md) for comprehensive guidance.885
Also in dotCMS/core
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| dotCMS/corecore-web/apps/dotcms-ui-e2e/AGENTS.md · 949 | AGENTS.md | setupstylearchtesting-strategy+2 | 78/100 | 3 days ago | |
| dotCMS/corecore-web/apps/mcp-server/CLAUDE.md · 949 | CLAUDE.md | setupbuildtestlint-format+5 | 89/100 | 3 days ago | |
| dotCMS/core.cursor/rules/doc-updates.mdc · 949 | Cursor rules | docs | 30/100 | 3 days ago | |
| dotCMS/core.cursor/rules/dotcms-guide.mdc · 949 | Cursor rules | archdo-notdocs | 69/100 | 3 days ago | |
| dotCMS/core.cursor/rules/e2e-rules.mdc · 949 | Cursor rules | setupteststylearch+5 | 89/100 | 3 days ago | |
| dotCMS/core.cursor/rules/frontend-context.mdc · 949 | Cursor rules | teststyledocs | 78/100 | 3 days ago | |
| dotCMS/core.cursor/rules/java-context.mdc · 949 | Cursor rules | buildstyle | 44/100 | 3 days ago | |
| dotCMS/core.cursor/rules/test-context.mdc · 949 | Cursor rules | testtesting-strategy | 54/100 | 3 days ago | |
| dotCMS/core.github/instructions/frontend.instructions.md · 949 | Copilot instructions | testlint-formatstylearch+3 | 69/100 | 3 days ago | |
| dotCMS/coreCLAUDE.md · 949 | CLAUDE.md | setupbuildteststyle+7 | 99/100 | today | |
| dotCMS/corecore-web/AGENTS.md · 949 | AGENTS.md | style | 63/100 | 3 days ago | |
| dotCMS/corecore-web/CLAUDE.md · 949 | CLAUDE.md | teststylearchtesting-strategy+3 | 100/100 | 3 days ago | |
| dotCMS/corecore-web/apps/dotcms-ui/AGENTS.md · 949 | AGENTS.md | buildteststyledependencies+3 | 94/100 | 3 days ago | |
| dotCMS/corecore-web/libs/block-editor/CLAUDE.md · 949 | CLAUDE.md | archdo-not | 69/100 | 3 days ago | |
| dotCMS/corecore-web/libs/new-block-editor/CLAUDE.md · 949 | CLAUDE.md | lint-formatstyledo-notagent-behaviour | 61/100 | 3 days ago | |
| dotCMS/corecore-web/libs/portlets/CLAUDE.md · 949 | CLAUDE.md | setupteststyleui+1 | 77/100 | 3 days ago | |
| dotCMS/corecore-web/libs/portlets/edit-ema/portlet/src/lib/store/CLAUDE.md · 949 | CLAUDE.md | teststylearchtypes+2 | 65/100 | 3 days ago | |
| dotCMS/corecore-web/libs/sdk/client/CLAUDE.md · 949 | CLAUDE.md | setupbuildtestlint-format+9 | 97/100 | 3 days ago | |
| dotCMS/corecore-web/libs/sdk/react/CLAUDE.md · 949 | CLAUDE.md | setupbuildtestlint-format+9 | 97/100 | 3 days ago | |
| dotCMS/coredotCMS/src/main/java/com/dotcms/rest/CLAUDE.md · 949 | CLAUDE.md | typesdatabaseapido-not+1 | 57/100 | 3 days ago |
Diff against core-web/apps/dotcms-ui-e2e/AGENTS.md Diff against core-web/apps/mcp-server/CLAUDE.md Diff against .cursor/rules/doc-updates.mdc Diff against .cursor/rules/dotcms-guide.mdc Diff against .cursor/rules/e2e-rules.mdc Diff against .cursor/rules/frontend-context.mdc Diff against .cursor/rules/java-context.mdc Diff against .cursor/rules/test-context.mdc Diff against .github/instructions/frontend.instructions.md Diff against CLAUDE.md Diff against core-web/AGENTS.md Diff against core-web/CLAUDE.md Diff against core-web/apps/dotcms-ui/AGENTS.md Diff against core-web/libs/block-editor/CLAUDE.md Diff against core-web/libs/new-block-editor/CLAUDE.md Diff against core-web/libs/portlets/CLAUDE.md Diff against core-web/libs/portlets/edit-ema/portlet/src/lib/store/CLAUDE.md Diff against core-web/libs/sdk/client/CLAUDE.md Diff against core-web/libs/sdk/react/CLAUDE.md Diff against dotCMS/src/main/java/com/dotcms/rest/CLAUDE.md
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| chihebnabil/lovable-boilerplate.github/instructions/global.instructions.md · 63 | Copilot instructions | buildlint-formatstylearch+4 | 100/100 | 3 days ago | |
| HerringtonDarkholme/megarepo.github/copilot-instructions.md · 17 | Copilot instructions | setupbuildtestlint-format+7 | 100/100 | 3 days ago | |
| louislam/uptime-kuma.github/copilot-instructions.md · 90k | Copilot instructions | setupbuildtestlint-format+9 | 100/100 | 3 days ago | |
| JCodesMore/ai-website-cloner-template.github/copilot-instructions.md · 31k | Copilot instructions | buildlint-formatstylearch+3 | 97/100 | 2 days ago | |
| bagisto/bagisto.github/copilot-instructions.md · 28k | Copilot instructions | setupbuildteststyle+5 | 97/100 | 3 days ago | |
| darkmatter/nixmac.github/copilot-instructions.md · 24 | Copilot instructions | setupbuildtestlint-format+8 | 96/100 | 3 days ago | |
| nerolis-lab/nerolis-lab.github/copilot-instructions.md · 32 | Copilot instructions | setupbuildtestlint-format+11 | 96/100 | 3 days ago | |
| thangaram611/second-brain.github/copilot-instructions.md · 0 | Copilot instructions | setupteststylearch+4 | 96/100 | 3 days ago |
