Skip to content
StarLive demo →
TutorialChecked against main · 31 Oct 20268 min read

Quick start

Run AppointMe locally. Install the .NET 10 template from NuGet or clone the repo, trust the dev certificate, then start the stack with .NET Aspire or Docker Compose.

You'll get
The full stack running on localhost
Time
Minutes, plus the first image pull
Touches
Nothing: the committed defaults run as is
Before you start
.NET 10 SDK, Docker, Node 24

Install three tools and trust one certificate. The versions come from the repo’s own pins.

Requirement Version Pinned in Check with
.NET SDK 10.0.0 or later, no previews (rollForward: latestMajor) global.json dotnet --version
Docker Running. Docker Desktop or another OCI-compatible runtime. — docker info
Node.js 24 recommended. The engines field accepts ^22.18.0 || ^24.11.0 || >=26.0.0. src/AppointMe.Frontend/.node-version, package.json node --version
HTTPS dev certificate Trusted, once per machine Checked by src/AppointMe.Aspire/DevCertificate.cs dotnet dev-certs https --check --trust

The first run pulls three container images and restores the NuGet and npm packages, so it takes a few minutes. Later runs reuse the containers.

Three paths: generate a renamed copy from NuGet and run Aspire, clone and run Aspire, or clone and run Docker Compose.

  1. Get the code. Generate a renamed copy from the NuGet template, or clone the repo as it is.

    Terminal window
    dotnet new install BravoDev.AppointMe.Templates::1.2.1
    dotnet new appointme -n Contoso.Booking
    cd Contoso.Booking

    -n must be a dotted .NET identifier such as Contoso.Booking, because it becomes namespaces, project names and folders. A name like my-booking-app generates a solution that doesn’t compile, and dotnet new still reports success. In a generated project, read AppointMe in the paths below as your name, for example src/Contoso.Booking.Aspire.

  2. Trust the HTTPS dev certificate. The API, the frontend and Keycloak all serve HTTPS locally.

    Terminal window
    dotnet dev-certs https --trust

    If it’s still reported as untrusted (for example, a certificate created by an older SDK), run dotnet dev-certs https --clean and trust it again.

  3. Start the stack. Aspire runs everything. Compose runs only the backing services, so you start the API and the frontend yourself.

    Terminal window
    cd src/AppointMe.Aspire
    dotnet run

    Or open AppointMe.sln in Visual Studio or Rider, set AppointMe.Aspire as the startup project and press F5. The Aspire dashboard opens in your browser. Wait until every resource shows Running.

  4. Open the app. Go to https://localhost:5173, then create an account or use the demo login.

Aspire starts each resource after the ones it depends on. The API applies every module’s migrations as it starts.

AppHostchecks the dev certificate
ContainersSQL Server, Keycloak, Mailpit
APIwaits for all three, then migrates
Frontendnpm install --no-save, then Vite on 5173
Figure 1. The start order Aspire enforces with WaitFor.
Step Done by Where
Checks the HTTPS dev certificate. Exits if it’s untrusted, or only warns on Linux. AppHost src/AppointMe.Aspire/DevCertificate.cs
Starts SQL Server, Keycloak and Mailpit as persistent containers, which later runs reuse AppHost src/AppointMe.Aspire/Program.cs
Imports the appointme realm: clients, roles, the demo user and SMTP to Mailpit Keycloak src/AppointMe.Aspire/appointme-realm.json
Applies EF Core migrations for Identity, Organizations, CRM and Booking, each in its own schema API src/AppointMe.Shared/Database/Migrations/DatabaseMigrations.cs
Creates its message tables (wolverine_*, in dbo at this commit) and its job tables in the hangfire schema Wolverine, Hangfire src/AppointMe.Api/Wolverine, src/AppointMe.Api/Hangfire
Installs npm packages without rewriting package-lock.json, then starts the dev server AppHost AddViteApp(...) in Program.cs

There’s no demo data yet at this point. It’s created per company: when a company is registered and Demo:Enabled is on, DemoSeedingSaga seeds 150 customers and about 450 appointments for it. Under Compose, the API steps run when you start the API.

The app is on https://localhost:5173. Every credential below is a committed local default.

What URL Sign in with
The app https://localhost:5173 An account you sign up, or the demo login
Demo login https://localhost:5173/api/v1/login/demo Nothing: it signs in demo@appointme.dev
API https://localhost:7233 (also http://localhost:5179) The app’s cookie, or a bearer token
OpenAPI document https://localhost:7233/openapi/v1.json Anonymous, Development only
Hangfire dashboard https://localhost:5173/admin/jobs A super admin, which is demo@appointme.dev locally
Aspire dashboard https://localhost:17082 (Aspire only) The URL the AppHost prints in its console
Keycloak admin console https://localhost:8082 admin / admin
Mailpit http://localhost:8026 —
SQL Server localhost,60740 sa / Password1

The demo user’s password is AppointMe1, if you’d rather sign in on the Keycloak page. Local services & ports lists every image, port and volume, and What to change first covers why you must never reuse these values.

Sign-up runs through the app, and Keycloak’s verification email lands in Mailpit.

  1. Sign up. Open https://localhost:5173/auth/signup and enter your name and email. There’s no password field: the API creates the user in Keycloak with two required actions, VERIFY_EMAIL and UPDATE_PASSWORD, and asks Keycloak to send the verification email.

  2. Open the email in Mailpit. Go to http://localhost:8026. The message comes from noreply@appointme.local, which Keycloak sends to the SMTP host Mailpit.

  3. Follow the link. Keycloak verifies the address and has you set a password. The link then returns you to the app’s sign-in page with returnUrl=/onboarding.

  4. Create your company. Onboarding registers your first company. With Demo:Enabled on, it gets the seeded customers and appointments, and the dashboard has data to show.

https://localhost:5173/api/v1/login/demo signs you in as the seeded demo user, with no form and no email.

The endpoint signs the Demo:User credentials in to Keycloak with a password grant, sets the app’s auth cookie and redirects to Frontend:BaseUrl. It’s the same flow as the public live demo. From there, complete onboarding to create a company.

src/AppointMe.Api/appsettings.Development.jsonView source ↗
"Demo": {
"Enabled": true,
"User": {
"Email": "demo@appointme.dev",
"Password": "AppointMe1",
"Name": "John Doe"
}
}

appsettings.json sets Demo:Enabled to false, so outside Development the endpoint answers 404:

src/AppointMe.Api/Authentication/DemoLogin/DemoLoginEndpoint.csView source ↗
if (!demoOptions.Value.Enabled || demoOptions.Value.User is not { } demoUser)
{
return TypedResults.NotFound();
}

In Development the demo user is also listed in Authentication:SuperAdmins, which is what opens the Hangfire dashboard.

Most first-run failures are the certificate, a port, or the API launch profile. The full list is in Troubleshooting.

Symptom Cause Fix
The AppHost exits with error: the ASP.NET Core HTTPS development certificate is missing or not trusted. The dev certificate is missing or untrusted dotnet dev-certs https --trust. If that doesn’t help, --clean first, then --trust.
appointme-api stays in Waiting It waits for SQL Server, Keycloak and Mailpit, and the first run is still pulling images Wait, or open each container’s logs in the Aspire dashboard
Bind for 0.0.0.0:60740 failed: port is already allocated Aspire and Compose use the same host ports, and Aspire’s containers keep running after you stop the AppHost Stop one set: docker compose stop, or stop the Aspire containers in Docker
Under Compose, the app can’t reach the API The API was started without --launch-profile https Restart it with --launch-profile https
Under Compose, Keycloak never turns healthy docker/keycloak/certs/keycloak.crt and keycloak.key don’t exist yet Run ./docker/keycloak/export-dev-cert.sh, then docker compose up -d --force-recreate keycloak
/api/v1/login/demo returns 404 Demo:Enabled is false, or there’s no Demo:User Set both in appsettings.Development.json
The generated solution doesn’t compile -n wasn’t a dotted identifier Generate again with a name like Contoso.Booking
Why does the AppHost refuse to start without a trusted certificate?1 min · optional

Without a trusted dev certificate, the API’s https launch profile can’t start, and Aspire quietly serves Keycloak over plain HTTP. Nothing fails at startup. The first sign of trouble is an unexplained 500 from the login endpoint, much later.

Running dotnet dev-certs https --check --trust up front turns that into an error that names the fix. Linux has no single trust store the tool can check, so a failure there is often a false negative, and the AppHost only warns.