TenonAdmin's public reference app: a real back office that installs the package, ships to production, and you can click through right now.
🔗 Live demo · 📦 TenonAdmin kernel · 📋 Execution ledger
An ordinary business system that happens to have TenonAdmin installed. It is not part of the kernel, and not one line of it is written "for the demo" — this is what your own code looks like after you adopt TenonAdmin.
It exists to skip the "read three days of docs before you know whether it's worth trying" step: there's a deployment you can click, and a repo you can clone and run. CRM is its first business module and more will grow beside it. No reusable kernel capability is developed here; that belongs to the TenonAdmin repo.
Log in to the live demo with any account below and open 客户管理 (Customers):
| Account | Password | Data scope | Rows | Also gets |
|---|---|---|---|---|
总部管理员 (HQ admin) |
Trial@123456 |
Every organization | 214 | CRM + the whole system console |
华南区域经理 (South China manager) |
Trial@123456 |
South China region and its branches | 128 | CRM only |
深圳专员 (Shenzhen specialist) |
Trial@123456 |
Shenzhen branch only | 42 | CRM only |
superAdmin |
not published (locally: whatever TenonAdmin:Seed:AdminPassword says) |
Unrestricted | 214 | Every module, every button |
Three numbers, one endpoint, one piece of frontend code — and the CustomerService behind it doesn't contain a single organization filter. The kernel attaches that filter outside your business code entirely. One query, three numbers (in Chinese) walks through where it attaches, and why that's worth far more than saving a few lines.
The three trial accounts hold read-only permissions on the customer endpoints, so the add/edit/delete buttons never render at all. HQ admin additionally holds the kernel's full system-management menu through ordinary role grants, not a super-admin bypass — that path is exactly what this repo is here to show, which is why superAdmin sits out the live demo: it bypasses [RolePermission], so publishing its password would hand every visitor a super admin. The login page has one-click buttons for the three, so nobody has to type a password.
You need the .NET 10 SDK, plus Node.js 22 if you want the frontend.
docker compose up -d --buildBrings up MySQL, Redis, the backend, and a Caddy-served build of the frontend. The frontend listens on TENON_WEB_PORT (default 8090) and reverse-proxies /api and /health* to the backend. Override secrets and ports in a .env file next to docker-compose.yml (TENON_DB_PASSWORD, TENON_JWT_SECRET, TENON_ADMIN_PASSWORD, TENON_API_PORT, TENON_WEB_PORT) and never commit the real values.
dotnet restore
dotnet build -c Release
dotnet runDefaults to SQLite, so there's no database to install first. The first startup creates the schema, loads seed data, and prints a random super-admin password to the console. Once it's up, /health, /health/ready, and /openapi/v1.json are all reachable.
Don't delete Properties/launchSettings.json. It pins ASPNETCORE_ENVIRONMENT=Development; without it the host resolves to Production, where CodeFirst schema creation is disabled by design, and startup fails outright on the missing seed tables. The full story is in the v0.3.2 upgrade record.
Run the frontend in a separate terminal, and don't make it compete with the backend's verification processes for memory:
Set-Location web
npm install
npm run gen:api
npm run devThe dev server proxies the API and the OpenAPI contract to http://localhost:5100. npm run typecheck and npm run lint are the two to run before committing.
Customer import is dry-run by default (CrmDemo:ImportDryRun=true): trial accounts can complete upload / preview / validate / commit, and the commit result is clearly marked as not written to the database. Export uses the same query as the list and still respects data scope.
The public deploy additionally turns on CrmDemo:ReadOnly (DemoReadOnlyFilter): every non-GET except login and import returns 403 / 41002. Menus, buttons and forms still render and still respond — they just can't reach the database. The three trial passwords above are public; what protects the live demo is this gate, not the passwords. Don't substitute the kernel's TenonAdmin:DemoMode for it: that one has no allowlist and would block the import POSTs too.
Locally ReadOnly defaults to false, so all four accounts (super admin included) really can add, edit and delete; set ImportDryRun to false as well and import writes for real.
The host registers TenonAdmin.Workflow@0.7.1, and Vue includes definition/designer, start, todo, CC, mine, done, monitor and delegation pages. Framework menu ownership stays unchanged: governance in System, employee approval in Business; CRM remains module 1000.
Grant workflow menus to separate local roles as needed; the public trial accounts get no new workflow grants. CrmDemo:ReadOnly also blocks workflow writes. The isolated human-approval validation is not customer-change approval, and this change has not been deployed to the live demo. See the upgrade evidence and local validation commands.
The 0.7.0 ordinary-manager permission blocker is fixed by the published 0.7.1 packages and matching Vue permission checks. Ordinary-manager design/assignment/publishing has been revalidated locally; see the upgrade record for the complete acceptance boundary.
Currently pinned to the stable 0.7.1 release: TenonAdmin / TenonAdmin.Excel / TenonAdmin.Workflow / TenonAdmin.Templates 0.7.1 on NuGet, source tag v0.7.1; workflow pages and required shared changes migrated from Tenon-Net/TenonAdmin/web#v0.7.1 onto the existing Vue app (CRM, login, branding and tooling retained). Upgrade notes: v0.7.1 upgrade record.
The version in tenon-example.csproj must match that paragraph exactly. Every kernel release gets bumped and re-verified here — this repo doubles as the kernel's permanent integration canary, and a canary running an old version isn't in the cage.
Bootstrap artifacts only (the template does not wire CRM or workflow; clone this repository to run this consumer):
Run these only in a new empty directory, never over this consumer's customized web/. Workflow still needs the host registrations documented in the upgrade record.
dotnet new install TenonAdmin.Templates@0.7.1
dotnet new tenon-app --output tenon-example
Set-Location tenon-example
dotnet add package TenonAdmin --version 0.7.1
dotnet add package TenonAdmin.Excel --version 0.7.1
dotnet add package TenonAdmin.Workflow --version 0.7.1
npx degit Tenon-Net/TenonAdmin/web#v0.7.1 webThen follow the two sections above. Staged implementation records, verification evidence, and the list of things that bit us as a consumer all live in docs/.


