Skip to content

Getting started with the Cratis templates

This tutorial takes you from an empty folder to a running Cratis application: an ASP.NET Core backend with Arc commands and queries, Chronicle storing events locally, and a React page that registers an item and shows it in a list.

The C# path below needs:

  • The .NET 10 SDK. Every .NET template targets net10.0, and net10.0 is its only --Framework choice.
  • Docker with the Compose plugin (docker compose). The generated docker-compose.yml runs the Chronicle development image and an Aspire dashboard.
  • Node.js ^20.19.0 or >=22.12.0 (what Vite 8 accepts) and a package manager: yarn (the default), pnpm, or npm.

The Kotlin and Java variants need a JDK 17 instead of the .NET SDK to build. See the Kotlin template and the Java template.

Terminal window
dotnet new install Cratis.Templates

To install a specific version, append it: dotnet new install Cratis.Templates::<version>.

Terminal window
dotnet new list cratis

You should see four rows: cratis, cratis-aspire, cratis-chronicle-console, and cratis-chronicle-web. The cratis row lists [C#],Java,Kotlin because the package carries all three languages of the web application; --language picks one. Each template documents its own options:

Terminal window
dotnet new cratis --help
Terminal window
dotnet new cratis -n MyStore
cd MyStore

The post-creation actions add the Cratis NuGet packages at their current release (the generated .csproj records the exact versions), restore them, and install the frontend dependencies with yarn. dotnet new asks before it runs the yarn step; accept it. To choose the package manager or database up front, pass them as options:

Terminal window
dotnet new cratis -n MyStore --packageManager npm --Database MongoDB

In a script, CI job, or dev container where there is no interactive terminal, opt in to the yarn step explicitly with --allow-scripts yes. Without it, dotnet new keeps waiting for a yes or no answer it cannot receive.

The project includes a .yarnrc.yml that sets nodeLinker: node-modules, so Yarn 2 and later install into node_modules instead of Plug’n’Play, which the TypeScript 7 compiler cannot resolve. npm, pnpm, and Yarn 1 ignore the file.

Two ways to scaffold: dotnet new and cratis new

Section titled “Two ways to scaffold: dotnet new and cratis new”

The Cratis CLI can scaffold the same templates with its own template engine:

Terminal window
cratis new # interactive wizard
cratis new list # list the templates
cratis new cratis --language csharp -n MyStore -o MyStore

The differences that matter on a first run:

  • --language (csharp, kotlin, or java) is required when you name a template.
  • --allow-scripts defaults to no, so pass --allow-scripts yes to install frontend dependencies.
  • cratis new sets up the project’s AI guidance itself, so you skip the cratis ai update step below.

See Creating projects with cratis new for the full command reference.

Every template ships a .cratis/ai.json that selects the Cratis AI profiles, languages, and coding-agent harnesses for that template. After dotnet new, install the Cratis CLI and run this from the project root:

Terminal window
cratis ai update

It installs the Cratis-managed rules, skills, and harness integration (AGENTS.md plus .claude/, .cursor/, .github/, .opencode/, and .pi/) and records every installed file in .cratis/ai.manifest.json. Commit the result so your team shares the same guidance. Running it again later refreshes only files Cratis installed; cratis ai status reports whether a newer revision is available.

Terminal window
docker compose up -d

This starts the cratis/chronicle:latest-development image, which bundles Chronicle with MongoDB, and an Aspire dashboard at http://localhost:18888. Chronicle is ready when this prints Healthy:

Terminal window
curl --insecure https://localhost:35000/health

Start the backend:

Terminal window
dotnet run

It listens on http://localhost:5000; Swagger UI is at http://localhost:5000/swagger. In a second terminal, start the frontend dev server:

Terminal window
yarn dev

Vite serves the frontend on http://localhost:9000, opens it in your browser, and forwards /api, /.cratis, and /swagger to the backend. Open Demo, select Register, and enter a name. The backend terminal logs Registered: <name> from the sample reactor, and the name appears in the list.

You can also register from the terminal:

Terminal window
curl -X POST http://localhost:5000/api/some-module/some-feature/registration \
-H "Content-Type: application/json" \
-d '{ "name": "Cratis" }'

A successful call returns "isSuccess":true and, in response, the identity the event was appended under.

To see the event itself, open the Chronicle Workbench at https://localhost:35000, accept the self-signed development certificate, and sign in with the development account described in Workbench — Development.

Stop the backend and the Vite server with Ctrl+C, then stop the containers and keep their data:

Terminal window
docker compose stop

To remove the containers instead, run docker compose down. With the default MongoDB setup, events and read models live inside the Chronicle container, so this deletes them. With --Database SQLite, Chronicle writes its files to the chronicle-data folder in your project instead, which docker compose down leaves in place; delete the folder to start over.

  • yarn build reports Cannot find module. Yarn 2 or later installed with Plug’n’Play, usually because .yarnrc.yml is missing (projects scaffolded from earlier template versions do not have one). Add a .yarnrc.yml containing nodeLinker: node-modules and run yarn install again.
  • docker compose up reports that a port is already allocated. Another Chronicle, MongoDB, or dashboard is using 35000, 27017, or 18888. Stop it, or change the host side of the mapping in docker-compose.yml and update Cratis:Chronicle:ConnectionString and Cratis:MongoDB:Server in appsettings.json to match.
  • docker-compose: command not found. Projects scaffolded from older template versions print the standalone docker-compose spelling. The Compose plugin’s docker compose accepts the same arguments.
  • The backend cannot reach Chronicle. Check that the health command above prints Healthy. The first docker compose up downloads the image, which can take several minutes.
Terminal window
dotnet new update

This updates every installed template package. To remove the templates, run dotnet new uninstall Cratis.Templates.