|
| 1 | +# Umbraco CMS Development Guide |
| 2 | + |
| 3 | +Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here. |
| 4 | + |
| 5 | +## Working Effectively |
| 6 | + |
| 7 | +Bootstrap, build, and test the repository: |
| 8 | + |
| 9 | +- Install .NET SDK (version specified in global.json): |
| 10 | + - `curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --version $(jq -r '.sdk.version' global.json)` |
| 11 | + - `export PATH="/home/runner/.dotnet:$PATH"` |
| 12 | +- Install Node.js (version specified in src/Umbraco.Web.UI.Client/.nvmrc): |
| 13 | + - `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash` |
| 14 | + - `export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"` |
| 15 | + - `nvm install $(cat src/Umbraco.Web.UI.Client/.nvmrc) && nvm use $(cat src/Umbraco.Web.UI.Client/.nvmrc)` |
| 16 | +- Fix shallow clone issue (required for GitVersioning): |
| 17 | + - `git fetch --unshallow` |
| 18 | +- Restore packages: |
| 19 | + - `dotnet restore` -- takes 50 seconds. NEVER CANCEL. Set timeout to 90+ seconds. |
| 20 | +- Build the solution: |
| 21 | + - `dotnet build` -- takes 4.5 minutes. NEVER CANCEL. Set timeout to 10+ minutes. |
| 22 | +- Install and build frontend: |
| 23 | + - `cd src/Umbraco.Web.UI.Client` |
| 24 | + - `npm ci --no-fund --no-audit --prefer-offline` -- takes 11 seconds. |
| 25 | + - `npm run build:for:cms` -- takes 1.25 minutes. NEVER CANCEL. Set timeout to 5+ minutes. |
| 26 | +- Install and build Login |
| 27 | + - `cd src/Umbraco.Web.UI.Login` |
| 28 | + - `npm ci --no-fund --no-audit --prefer-offline` |
| 29 | + - `npm run build` |
| 30 | +- Run the application: |
| 31 | + - `cd src/Umbraco.Web.UI` |
| 32 | + - `dotnet run --no-build` -- Application runs on https://localhost:44339 and http://localhost:11000 |
| 33 | + |
| 34 | +## Validation |
| 35 | + |
| 36 | +- ALWAYS run through at least one complete end-to-end scenario after making changes. |
| 37 | +- Build and unit tests must pass before committing changes. |
| 38 | +- Frontend build produces output in src/Umbraco.Web.UI.Client/dist-cms/ which gets copied to src/Umbraco.Web.UI/wwwroot/umbraco/backoffice/ |
| 39 | +- Always run `dotnet build` and `npm run build:for:cms` before running the application to see your changes. |
| 40 | +- For login-only changes, you can run `npm run build` from src/Umbraco.Web.UI.Login and then `dotnet run --no-build` from src/Umbraco.Web.UI. |
| 41 | +- For frontend-only changes, you can run `npm run dev:server` from src/Umbraco.Web.UI.Client for hot reloading. |
| 42 | +- Frontend changes should be linted using `npm run lint:fix` which uses Eslint. |
| 43 | + |
| 44 | +## Testing |
| 45 | + |
| 46 | +### Unit Tests (.NET) |
| 47 | +- Location: tests/Umbraco.Tests.UnitTests/ |
| 48 | +- Run: `dotnet test tests/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj --configuration Release --verbosity minimal` |
| 49 | +- Duration: ~1 minute with 3,343 tests |
| 50 | +- NEVER CANCEL: Set timeout to 5+ minutes |
| 51 | + |
| 52 | +### Integration Tests (.NET) |
| 53 | +- Location: tests/Umbraco.Tests.Integration/ |
| 54 | +- Run: `dotnet test tests/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj --configuration Release --verbosity minimal` |
| 55 | +- NEVER CANCEL: Set timeout to 10+ minutes |
| 56 | + |
| 57 | +### Frontend Tests |
| 58 | +- Location: src/Umbraco.Web.UI.Client/ |
| 59 | +- Run: `npm test` (requires `npx playwright install` first) |
| 60 | +- Frontend tests use Web Test Runner with Playwright |
| 61 | + |
| 62 | +### Acceptance Tests (E2E) |
| 63 | +- Location: tests/Umbraco.Tests.AcceptanceTest/ |
| 64 | +- Requires running Umbraco application and configuration |
| 65 | +- See tests/Umbraco.Tests.AcceptanceTest/README.md for detailed setup (requires `npx playwright install` first) |
| 66 | + |
| 67 | +## Project Structure |
| 68 | + |
| 69 | +The solution contains 30 C# projects organized as follows: |
| 70 | + |
| 71 | +### Main Application Projects |
| 72 | +- **Umbraco.Web.UI**: Main web application project (startup project) |
| 73 | +- **Umbraco.Web.UI.Client**: TypeScript frontend (backoffice) |
| 74 | +- **Umbraco.Web.UI.Login**: Separate login screen frontend |
| 75 | +- **Umbraco.Core**: Core domain models and interfaces |
| 76 | +- **Umbraco.Infrastructure**: Data access and infrastructure |
| 77 | +- **Umbraco.Cms**: Main CMS package |
| 78 | + |
| 79 | +### API Projects |
| 80 | +- **Umbraco.Cms.Api.Management**: Management API |
| 81 | +- **Umbraco.Cms.Api.Delivery**: Content Delivery API |
| 82 | +- **Umbraco.Cms.Api.Common**: Shared API components |
| 83 | + |
| 84 | +### Persistence Projects |
| 85 | +- **Umbraco.Cms.Persistence.SqlServer**: SQL Server support |
| 86 | +- **Umbraco.Cms.Persistence.Sqlite**: SQLite support |
| 87 | +- **Umbraco.Cms.Persistence.EFCore**: Entity Framework Core abstractions |
| 88 | + |
| 89 | +### Test Projects |
| 90 | +- **Umbraco.Tests.UnitTests**: Unit tests |
| 91 | +- **Umbraco.Tests.Integration**: Integration tests |
| 92 | +- **Umbraco.Tests.AcceptanceTest**: End-to-end tests with Playwright |
| 93 | +- **Umbraco.Tests.Common**: Shared test utilities |
| 94 | + |
| 95 | +## Common Tasks |
| 96 | + |
| 97 | +### Frontend Development |
| 98 | +For frontend-only changes: |
| 99 | +1. Configure backend for frontend development: |
| 100 | + ```json |
| 101 | + <!-- Add to src/Umbraco.Web.UI/appsettings.json under Umbraco:Cms:Security: --> |
| 102 | + ```json |
| 103 | + "BackOfficeHost": "http://localhost:5173", |
| 104 | + "AuthorizeCallbackPathName": "/oauth_complete", |
| 105 | + "AuthorizeCallbackLogoutPathName": "/logout", |
| 106 | + "AuthorizeCallbackErrorPathName": "/error" |
| 107 | + ``` |
| 108 | +2. Run backend: `cd src/Umbraco.Web.UI && dotnet run --no-build` |
| 109 | +3. Run frontend dev server: `cd src/Umbraco.Web.UI.Client && npm run dev:server` |
| 110 | + |
| 111 | +### Backend-Only Development |
| 112 | +For backend-only changes, disable frontend builds: |
| 113 | +- Comment out the target named "BuildStaticAssetsPreconditions" in src/Umbraco.Cms.StaticAssets.csproj: |
| 114 | + ``` |
| 115 | + <!--<Target Name="BuildStaticAssetsPreconditions" BeforeTargets="AssignTargetPaths"> |
| 116 | + [...] |
| 117 | + </Target>--> |
| 118 | + ``` |
| 119 | +- Remember to uncomment before committing |
| 120 | + |
| 121 | +### Building NuGet Packages |
| 122 | +To build custom NuGet packages for testing: |
| 123 | +```bash |
| 124 | +dotnet pack -c Release -o Build.Out |
| 125 | +dotnet nuget add source [Path to Build.Out folder] -n MyLocalFeed |
| 126 | +``` |
| 127 | + |
| 128 | +### Regenerating Frontend API Types |
| 129 | +When changing Management API: |
| 130 | +```bash |
| 131 | +cd src/Umbraco.Web.UI.Client |
| 132 | +npm run generate:server-api-dev |
| 133 | +``` |
| 134 | +Also update OpenApi.json from /umbraco/swagger/management/swagger.json |
| 135 | + |
| 136 | +## Database Setup |
| 137 | + |
| 138 | +Default configuration supports SQLite for development. For production-like testing: |
| 139 | +- Use SQL Server/LocalDb for better performance |
| 140 | +- Configure connection string in src/Umbraco.Web.UI/appsettings.json |
| 141 | + |
| 142 | +## Clean Up / Reset |
| 143 | + |
| 144 | +To reset development environment: |
| 145 | +```bash |
| 146 | +# Remove configuration and database |
| 147 | +rm src/Umbraco.Web.UI/appsettings.json |
| 148 | +rm -rf src/Umbraco.Web.UI/umbraco/Data |
| 149 | + |
| 150 | +# Full clean (removes all untracked files) |
| 151 | +git clean -xdf . |
| 152 | +``` |
| 153 | + |
| 154 | +## Version Information |
| 155 | + |
| 156 | +- Target Framework: .NET (version specified in global.json) |
| 157 | +- Current Version: (specified in version.json) |
| 158 | +- Node.js Requirement: (specified in src/Umbraco.Web.UI.Client/.nvmrc) |
| 159 | +- npm Requirement: Latest compatible version |
| 160 | + |
| 161 | +## Known Issues |
| 162 | + |
| 163 | +- Build requires full git history (not shallow clone) due to GitVersioning |
| 164 | +- Some NuGet package security warnings are expected (SixLabors.ImageSharp vulnerabilities) |
| 165 | +- Frontend tests require Playwright browser installation: `npx playwright install` |
| 166 | +- Older Node.js versions may show engine compatibility warnings (check .nvmrc for current requirement) |
| 167 | + |
| 168 | +## Timing Expectations |
| 169 | + |
| 170 | +**NEVER CANCEL** these operations - they are expected to take time: |
| 171 | + |
| 172 | +| Operation | Expected Time | Timeout Setting | |
| 173 | +|-----------|--------------|-----------------| |
| 174 | +| `dotnet restore` | 50 seconds | 90+ seconds | |
| 175 | +| `dotnet build` | 4.5 minutes | 10+ minutes | |
| 176 | +| `npm ci` | 11 seconds | 30+ seconds | |
| 177 | +| `npm run build:for:cms` | 1.25 minutes | 5+ minutes | |
| 178 | +| `npm test` | 2 minutes | 5+ minutes | |
| 179 | +| `npm run lint` | 1 minute | 5+ minutes | |
| 180 | +| Unit tests | 1 minute | 5+ minutes | |
| 181 | +| Integration tests | Variable | 10+ minutes | |
| 182 | + |
| 183 | +Always wait for commands to complete rather than canceling and retrying. |
0 commit comments