umbraco/Umbraco-CMS
Umbraco is a free and open source .NET content management system helping you deliver delightful digital experiences.
Healthy across the board
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit today
- ✓16 active contributors
- ✓Distributed ownership (top contributor 25% of recent commits)
Show 3 more →Show less
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/umbraco/umbraco-cms)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/umbraco/umbraco-cms on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: umbraco/Umbraco-CMS
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/umbraco/Umbraco-CMS shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit today
- 16 active contributors
- Distributed ownership (top contributor 25% of recent commits)
- MIT licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live umbraco/Umbraco-CMS
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/umbraco/Umbraco-CMS.
What it runs against: a local clone of umbraco/Umbraco-CMS — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in umbraco/Umbraco-CMS | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of umbraco/Umbraco-CMS. If you don't
# have one yet, run these first:
#
# git clone https://github.com/umbraco/Umbraco-CMS.git
# cd Umbraco-CMS
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of umbraco/Umbraco-CMS and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "umbraco/Umbraco-CMS(\\.git)?\\b" \\
&& ok "origin remote is umbraco/Umbraco-CMS" \\
|| miss "origin remote is not umbraco/Umbraco-CMS (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f ".github/CONTRIBUTING.md" \\
&& ok ".github/CONTRIBUTING.md" \\
|| miss "missing critical file: .github/CONTRIBUTING.md"
test -f "Directory.Build.props" \\
&& ok "Directory.Build.props" \\
|| miss "missing critical file: Directory.Build.props"
test -f "Directory.Packages.props" \\
&& ok "Directory.Packages.props" \\
|| miss "missing critical file: Directory.Packages.props"
test -f "build/azure-pipelines.yml" \\
&& ok "build/azure-pipelines.yml" \\
|| miss "missing critical file: build/azure-pipelines.yml"
test -f ".github/copilot-instructions.md" \\
&& ok ".github/copilot-instructions.md" \\
|| miss "missing critical file: .github/copilot-instructions.md"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/umbraco/Umbraco-CMS"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Umbraco CMS is a free, open-source .NET-based content management system built on ASP.NET Core that enables organizations to create, manage, and publish digital content through a modern backoffice UI. It provides a headless/traditional CMS architecture with a TypeScript/Angular-powered backoffice interface (17.3M lines) and a C# backend (29.3M lines) for flexible content delivery. Monorepo structure: src/Umbraco.Web.UI.Client contains TypeScript backoffice code (Angular components, manifests, localization), src/Umbraco.Core and src/Umbraco.Web contain C# backend services/APIs. Documentation via docs/ and .github/. Dev tooling configured via .devcontainer/ (Docker), .editorconfig, and .env.example. Custom build skills in .claude/skills/ for version bumping and PR review.
👥Who it's for
.NET developers and content editors building enterprise websites, web applications, and digital experiences who need a flexible, self-hosted CMS alternative to SaaS platforms. Contributors are primarily .NET backend engineers, TypeScript/Angular frontend developers, and localization community members maintaining the backoffice UI.
🌱Maturity & risk
Highly mature and production-ready. The project has been actively developed for over a decade with a large community, maintains CI/CD via Azure Pipelines, ships on NuGet with regular releases, and uses comprehensive testing infrastructure. The codebase shows consistent recent commits, detailed contribution guidelines (see .github/contributing-*.md files), and formal release processes (.github/RELEASE_INSTRUCTION.md).
Low technical risk for production use, but contributors should be aware: the monolithic architecture spans 29M lines of C# and 17M lines of TypeScript (significant codebase to navigate), requires .NET SDK/runtime setup, and breaking changes are formally tracked (.claude/skills/umb-review/references/breaking-changes.md indicates they occur and must be documented). Single points of failure exist around core subsystems like the backoffice deployment pipeline.
Active areas of work
Active development visible through backoffice UI improvements (live preview at backofficepreview.umbraco.com deployed from main branch), formalized review processes (.claude/skills/umb-review with complexity and impact analysis), and structured contribution workflows (.github/CONTRIBUTING.md, .github/contributing-creating-a-pr.md). Version bumping automation and breaking change tracking indicate ongoing release cadence.
🚀Get running
git clone https://github.com/umbraco/Umbraco-CMS.git
cd Umbraco-CMS
# Install .NET SDK (see docs.umbraco.com/umbraco-cms/fundamentals/setup/requirements)
dotnet restore
dotnet build
dotnet run
Use .devcontainer/ setup for Docker-based development environment via VS Code Dev Containers.
Daily commands:
Backend dev server: dotnet run (from root or src/ project). Backoffice UI dev: Navigate to src/Umbraco.Web.UI.Client and use npm/build scripts (standard Node toolchain for TypeScript/Angular compilation). Full stack: Docker Compose via .devcontainer/docker-compose.yml with VS Code Dev Containers extension.
🗺️Map of the codebase
.github/CONTRIBUTING.md— Primary contribution guide that establishes coding standards, PR workflow, and community expectations for all contributors.Directory.Build.props— Central MSBuild configuration that defines shared project properties, package versions, and build behavior across the entire .NET solution.Directory.Packages.props— Centralized NuGet package version management file that controls all dependency versions across the monorepo.build/azure-pipelines.yml— Primary CI/CD pipeline definition that orchestrates builds, tests, and deployments for the entire Umbraco CMS project..github/copilot-instructions.md— AI assistant guidance file that documents coding preferences, patterns, and architectural decisions specific to this codebase..claude/skills/umb-review/references/coding-preferences.md— Detailed coding standards and best practices reference for reviewers ensuring consistency across the Umbraco codebase.CLAUDE.md— Top-level documentation for AI assistance setup and capabilities available in this repository.
🧩Components & responsibilities
- Directory.Build.props & Directory.Packages.props (MSBuild, NuGet) — Central configuration hub defining build behavior, compiler settings, and dependency versions for all .NET projects
- Failure mode: Version conflicts, inconsistent compilation flags, or broken dependency resolution across projects
- GitHub Actions workflows (.github/workflows/) —
🛠️How to make changes
Add a new contribution guideline topic
- Create a new markdown file in .github/ named contributing-[topic].md following the template established in contributing-first-issue.md (
.github/contributing-[topic].md) - Link the new guide from .github/CONTRIBUTING.md in the appropriate section (
.github/CONTRIBUTING.md) - Reference coding patterns from .claude/skills/umb-review/references/coding-preferences.md if applicable (
.claude/skills/umb-review/references/coding-preferences.md)
Add a new GitHub Actions workflow
- Create a new YAML workflow file in .github/workflows/ following the pattern of existing workflows like test-backoffice.yml (
.github/workflows/[workflow-name].yml) - Define reusable job templates in build/templates/ if the workflow uses common build patterns (
build/templates/[template-name].yml) - Reference centralized configuration from Directory.Build.props for build settings (
Directory.Build.props)
Update project-wide dependency versions
- Modify the package version entries in Directory.Packages.props (
Directory.Packages.props) - Update any build-time properties in Directory.Build.props if the dependency version change affects build behavior (
Directory.Build.props) - Run build validation through build/azure-pipelines.yml to ensure compatibility (
build/azure-pipelines.yml)
Customize AI code review behavior
- Update .claude/skills/umb-review/references/coding-preferences.md with new coding standards or patterns (
.claude/skills/umb-review/references/coding-preferences.md) - Add breaking change detection rules to .claude/skills/umb-review/references/breaking-changes.md (
.claude/skills/umb-review/references/breaking-changes.md) - Modify .github/copilot-instructions.md to guide AI assistant behavior on pull requests (
.github/copilot-instructions.md)
🔧Why these technologies
- .NET (C#) — Core language for the Umbraco CMS backend, enabling cross-platform server runtime and rich type system
- Azure Pipelines — Enterprise CI/CD orchestration with tight integration to Microsoft ecosystem and built-in artifact management
- GitHub Actions — Lightweight automation for PR workflows, issue triage, and integrated code quality checks without external dependencies
- Docker & devcontainers — Standardized local development environment ensuring consistency across contributor machines
- MSBuild (Directory.Build.props) — Centralized build configuration reduces duplication and enforces consistent compilation behavior across dozens of projects
⚖️Trade-offs already made
-
Both Azure Pipelines and GitHub Actions for CI/CD
- Why: Azure Pipelines handles core build/test; GitHub Actions handles lightweight PR automation and notifications
- Consequence: Dual-system maintenance overhead but allows specialized tools for different workflow phases
-
Centralized NuGet versions in Directory.Packages.props
- Why: Single source of truth reduces version conflicts and simplifies security updates
- Consequence: All projects tightly coupled to same dependency versions; transitive dependency conflicts require careful resolution
-
AI-assisted code review (claude-review.yml) alongside human review
- Why: Automates detection of common issues (breaking changes, style violations) before human review
- Consequence: Requires maintaining AI guidelines (coding-preferences.md) in sync with human standards
🚫Non-goals (don't propose these)
- Single-file/monolithic architecture—designed as a modular monorepo with hundreds of projects
- Real-time collaboration features—content editing happens asynchronously
- Multi-database support in core (relational DB assumption in MSBuild configuration)
🪤Traps & gotchas
Environment setup: .env.example shows required configuration; database connections and licensing keys may be needed for full feature testing. Localization workflow: Language strings are generated from manifest files (see .github/contributing-localization.md)—direct JSON edits may be overwritten. Build complexity: TypeScript backoffice requires Node toolchain alongside .NET SDK; dev container handles this but local setup requires both. Breaking changes: This project tracks and requires documentation of breaking changes; review .claude/skills/umb-review/references/breaking-changes.md before modifying public APIs. Azure Pipelines: CI is Azure DevOps (not GitHub Actions); build artifacts and logs are there, not in GitHub.
🏗️Architecture
💡Concepts to learn
- Content Tree & Hierarchical Publishing — Umbraco's core abstraction is a content tree with versioning, publishing states, and inheritance; understanding this is essential for backend API design and backoffice UI navigation
- Manifest-Driven Backoffice — The backoffice UI is declaratively configured via JSON manifests (property editors, content types, dashboards); modifying or extending the UI requires understanding this pattern
- Property Editors & Data Types — Custom content handling in Umbraco relies on property editors (TypeScript Angular components) bound to data types (C# value converters); essential for content model extensions
- Dependency Injection & Service Container — Umbraco uses Microsoft.Extensions.DependencyInjection heavily; understanding service lifetimes (singleton, transient, scoped) is critical for backend feature development
- Content Delivery & Output Caching — Umbraco separates content editing (backoffice) from delivery (front-end or API); caching strategies and content composition are key performance concerns
- Localization & Language Variants — Umbraco supports multi-language content with language-specific property variants; the localization system spans manifest generation, JSON translation files, and backoffice UI culture switching
- Plugin Architecture & Composition — Umbraco is extensible via plugins (custom property editors, content apps, dashboards, APIs); understanding manifest composition and module loading is required for custom development
🔗Related repos
umbraco/Umbraco.Cloud— Official Umbraco Cloud hosting platform; companion service for deploying Umbraco instancesumbraco/Umbraco-Headless-CMS-Foundation— Official headless CMS starter using Umbraco backend; shows best practices for decoupled deploymentsDotNetNuke/Dnn.Platform— Alternative .NET CMS with similar monolithic architecture; useful for comparing design decisionsumbraco/Umbraco.Templates— Official .NET project templates for scaffolding new Umbraco projects (consumed bydotnet new umbraco)strapi/strapi— Node.js-based headless CMS for comparison; some Umbraco users evaluate Strapi as alternative
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive CI workflow for backoffice UI component testing
The repo has .github/workflows/test-backoffice.yml and azure-backoffice.yml but no dedicated Jest/unit test CI for the backoffice Angular components. Given the extensive .github/contributing-backoffice.md documentation and the presence of backoffice-specific workflows, there's an opportunity to add a GitHub Actions workflow that runs Jest tests on backoffice changes, improving confidence in UI component refactors and preventing regressions in the management interface.
- [ ] Review existing
.github/workflows/test-backoffice.ymlandazure-backoffice.ymlto understand current testing approach - [ ] Create
.github/workflows/backoffice-jest-tests.ymlthat runs on PR changes to backoffice source files - [ ] Configure the workflow to run Jest with coverage thresholds and fail on coverage drops below acceptable limits
- [ ] Add a step to comment coverage reports on PRs using a coverage badge tool
- [ ] Update
.github/CONTRIBUTING.mdto document the new backoffice test requirements
Enhance contributing-backoffice.md with localization testing guidance
The file structure shows .github/contributing-localization.md exists alongside .github/contributing-backoffice.md, and there are multiple localization-related images in .github/img/contributing/ (including 'searchingThroughLanguageFiles.png', 'localizationCodeSnippetInCode.png'). However, there's no documented workflow for testing backoffice changes that affect localization strings or how to validate localization keys across language files.
- [ ] Review existing
.github/contributing-localization.mdto understand current localization contribution process - [ ] Review
.github/contributing-backoffice.mdto identify gaps in localization-specific guidance - [ ] Add a new section 'Testing Localization Changes' documenting how to run language validation tests
- [ ] Include examples of validating that new backoffice UI strings have corresponding keys in all supported language files
- [ ] Reference the localization validation tooling/scripts with code examples
Implement CodeQL configuration for C# security scanning in GitHub Actions
The repo has .github/config/codeql-config.yml and a .github/workflows/codeql-analysis.yml workflow, but given this is a large .NET CMS project, the CodeQL configuration likely needs C# query customization (reducing false positives on common ORM patterns, data binding, etc.). Adding specific C# security rule tuning would improve the signal-to-noise ratio and prevent issues like SQL injection, authentication bypasses, or dependency vulnerabilities from slipping through.
- [ ] Examine current
.github/config/codeql-config.ymlto see existing configuration scope - [ ] Review
.github/workflows/codeql-analysis.ymlto understand how config is applied - [ ] Enhance the CodeQL config with C# query suites focusing on: data flow analysis for ORM usage, authentication/authorization checks, and dangerous reflection patterns common in .NET
- [ ] Disable low-signal queries known to cause false positives in .NET projects (e.g., overly broad 'dangerous code flow' patterns)
- [ ] Add documentation to
.github/README.mdexplaining the CodeQL strategy and how maintainers should handle CodeQL alerts
🌿Good first issues
- Add missing unit tests for C# service layer in
src/Umbraco.Core/Services/(pick a service with <50% test coverage and write integration tests following existing patterns in sibling test projects) - Improve TypeScript component documentation in
src/Umbraco.Web.UI.Client/src/by adding JSDoc comments to 5 exported service interfaces and their methods (check .github/copilot-instructions.md for preferred doc style) - Translate backoffice UI localization keys for a new language by adding a new JSON language file in
src/Umbraco.Web.UI.Client/src/locales/following the structure in existing locales (pair with .github/contributing-localization.md)
⭐Top contributors
Click to expand
Top contributors
- @AndyButland — 25 commits
- @nielslyngsoe — 18 commits
- @iOvergaard — 14 commits
- @madsrasmussen — 8 commits
- @lauraneto — 8 commits
📝Recent commits
Click to expand
Recent commits
3142691— Update architecture.md (nielslyngsoe)c813481— update UUI for icon manager (nielslyngsoe)11ff2c8— Tests: Fix PublishedValueFallbackTests after ILocalizationService removal (#22772) (iOvergaard)8009870— chore: ignores default log message for MSW (iOvergaard)dff3941— Merge branch 'v18/dev' (leekelleher)072e362— Merge branch 'main' into v18/dev (leekelleher)7248f01— Auth: Un-deprecate getLatestToken and route per-request fetches through it (#22736) (iOvergaard)4fab629— Documents: AliasDocumentVariantStateModelAPI model for backoffice client (#22716) (leekelleher)1a74aa5— Published Content: FixFallback.ToAncestorswith no match throwing exception at property level (closes #22759) (#22763 (AndyButland)396497a— Documents: AliasDocumentVariantStateModelAPI model for backoffice client (#22716) (leekelleher)
🔒Security observations
The Umbraco CMS repository demonstrates reasonable security practices with CI/CD integration and CodeQL scanning. However, there are notable concerns: (1
- High · Hardcoded Credentials in .env.example —
.env.example. The .env.example file contains example credentials including UMBRACO_CLIENT_SECRET with a placeholder value '1234567890'. While marked as example, this file should not contain any secret-like values. Additionally, NODE_TLS_REJECT_UNAUTHORIZED=0 is set, which disables TLS verification and is a security risk. Fix: 1) Remove or mask the CLIENT_SECRET example value. 2) Set NODE_TLS_REJECT_UNAUTHORIZED=1 (default) for production. 3) Add a clear comment that .env.example should never contain real secrets. 4) Document that developers should use a .env.local file (added to .gitignore) for actual credentials. - Medium · Insecure TLS Configuration in Development —
.env.example. The .env.example file disables TLS certificate verification with NODE_TLS_REJECT_UNAUTHORIZED=0. While this may be intended for local development with self-signed certificates, it creates a pattern that could be accidentally committed to production environments. Fix: 1) Document this is development-only. 2) Use conditional logic to only disable TLS in development environments. 3) Provide alternative solutions like proper self-signed certificate handling. 4) Add environment-specific configuration that prevents this in production builds. - Medium · Unclear Secret Management Strategy —
.env.example, .gitignore. The repository includes .env.example with placeholder values but lacks clear documentation on how secrets should be managed. There's no visible .env.example in .gitignore verification or documented secret rotation procedures. Fix: 1) Add comprehensive documentation for secret management in CONTRIBUTING.md. 2) Ensure .env, .env.local, and similar files are in .gitignore. 3) Document use of environment variables, Azure Key Vault, or other secret management solutions. 4) Provide guidance for developers and CI/CD pipelines. - Medium · Potential Client ID Exposure —
.env.example. The UMBRACO_CLIENT_ID is exposed in .env.example. While Client IDs are typically less sensitive than secrets, they should be treated carefully and not hardcoded in examples. Fix: 1) Use placeholder values like '<YOUR_CLIENT_ID>' instead of actual IDs. 2) Add inline comments explaining where to obtain these values. 3) Consider using environment-specific configuration files that are excluded from version control. - Low · Docker Configuration Review Needed —
.devcontainer/Dockerfile, .devcontainer/docker-compose.yml. The .devcontainer setup includes Docker configuration files. Without access to full Dockerfile and docker-compose.yml contents, potential issues like exposed ports, missing security contexts, or base image vulnerabilities cannot be fully assessed. Fix: 1) Ensure base images are from official sources and regularly updated. 2) Use specific version tags (not 'latest'). 3) Run containers with non-root users. 4) Implement proper resource limits. 5) Scan images with tools like Trivy or Snyk. 6) Do not expose unnecessary ports. - Low · Missing Security Headers Documentation —
Application configuration (not visible in provided structure). No visible security headers configuration (CSP, X-Frame-Options, etc.) in the provided file structure. A .NET CMS should implement comprehensive security headers. Fix: 1) Implement security headers middleware (Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, etc.). 2) Document security header strategy in contributing guidelines. 3) Add automated tests to verify headers are present in responses. - Low · CodeQL Configuration Visibility —
.github/config/codeql-config.yml. The repository includes CodeQL configuration (.github/config/codeql-config.yml), which is good practice. However, the configuration details are not visible for review. Fix: 1) Ensure CodeQL scans cover all security-relevant rule sets. 2) Review that the configuration catches common vulnerabilities (SQL injection, XSS, command injection, etc.). 3) Document CodeQL scan results in the CI/CD pipeline.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.