# What to change first

> A checklist for a new project built from the AppointMe .NET template. Names, branding, committed dev secrets, demo mode, the Keycloak realm, unused modules, licenses, CI and Azure defaults.

Source page: https://appointme.dev/docs/start/what-to-change-first/

* **You'll end with:** A project that carries your name
* **When:** Before your first deploy
* **Touches:** Config, realm, SPA, `infra/`, `.github/`
* **Before you start:** A running stack from the Quick start

This page assumes you generated the project with `dotnet new appointme -n Contoso.Booking`. If you cloned the repo instead, nothing has been renamed yet: start with [Rename your project](/docs/guides/rename-your-project/). Paths below use the upstream `AppointMe` names; in your project they carry yours.

## Names: what `-n` changed and what it didn’t

**`dotnet new -n` renames every brand token it can match without touching the domain word “appointment”. Three build properties still name BravoDev.**

| Item                                                 | After `-n Contoso.Booking`                                                 |
| ---------------------------------------------------- | -------------------------------------------------------------------------- |
| Namespaces, projects, folders, the solution          | `Contoso.Booking.Api`, `src/Contoso.Booking.Aspire`, `Contoso.Booking.sln` |
| The database                                         | `Contoso.Booking`                                                          |
| The Keycloak realm and its file                      | `contoso.booking`, in `contoso.booking-realm.json`                         |
| The Compose project, containers and Aspire resources | `contoso-booking`, `contoso-booking-sql`, `contoso-booking-api`            |
| The demo account                                     | `demo@contoso.booking.dev`, password `ContosoBooking1`                     |
| Domain words                                         | Unchanged: `Appointment`, `/appointments`, `appointments.statistics:view`  |

| What                                  | Where                                          | Why                                                                                                  | How                                          |
| ------------------------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------- |
| `Company`, `Authors`, `RepositoryUrl` | `Directory.Build.props`                        | They’re still `BravoDev` and `github.com/bravodev-hub/...`, and every assembly you build embeds them | Set your company, authors and repository URL |
| The product name in the browser tab   | `src/AppointMe.Frontend/index.html`, `<title>` | `-n` put your dotted name there, for example `Contoso.Booking`                                       | Write the name users should see              |

Directory.Build.props

```xml
<Company>BravoDev</Company>
<Authors>BravoDev</Authors>
<RepositoryUrl>https://github.com/bravodev-hub/appointme.git</RepositoryUrl>
```

`templates/README.md` in the upstream repo documents the rename rules token by token.

## Branding in the frontend

**The SPA’s logo, wordmark and colors live in a handful of files. The wordmark is split across a `<span>`, so `-n` didn’t touch it.**

| What           | Where                                                                                                                                                                                                                                                 | Why                                                                     | How                                                                        |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Wordmark       | `Appoint<span className='font-semibold'>Me</span>` in `src/app/layouts/sidebar/app-sidebar.tsx`, `src/app/layouts/footer/footer.tsx`, `src/app/auth/signup/signup.tsx`, `src/app/onboarding/onboarding.tsx` and `src/app/invitations/invitations.tsx` | It still reads “AppointMe” on every screen                              | Replace it in all five files, or move it into one component first          |
| Sidebar logo   | `src/app/layouts/sidebar/app-logo.tsx`                                                                                                                                                                                                                | `AppLogo` is an inline SVG of the AppointMe mark                        | Swap the `path`, or render your own SVG                                    |
| Favicon        | `src/assets/logo.svg`, linked from `index.html`                                                                                                                                                                                                       | The same mark, as a file                                                | Replace the SVG                                                            |
| Colors         | `src/index.css`, the `:root` and `.dark` blocks                                                                                                                                                                                                       | The palette is neutral grays (`--primary: oklch(0.205 0 0)`)            | Change the tokens. The `@theme inline` block maps them to Tailwind colors. |
| Footer version | `src/app/layouts/footer/version.ts`                                                                                                                                                                                                                   | Shows `VITE_APP_VERSION`, which the Docker build sets, or `dev` locally | Nothing to change, unless you version differently                          |

Paths in this table are relative to `src/AppointMe.Frontend/`. [Frontend overview](/docs/frontend/overview/) covers the rest of the SPA.

## Committed dev secrets and demo mode

**Every local credential is committed on purpose and predictable in every project made from the template. Never reuse one outside your machine, and decide where demo mode stays on.**

| Secret                             | Where                                                                                                                                       | Value                                                         |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| SQL Server `sa` password           | `src/AppointMe.Aspire/Program.cs` (`sqlPassword`), `compose.yaml` (`MSSQL_SA_PASSWORD`), `appsettings.Development.json` (connection string) | `Password1`                                                   |
| Keycloak admin                     | `Program.cs` (`username`, `password`), `compose.yaml` (`KC_BOOTSTRAP_ADMIN_*`)                                                              | `admin` / `admin`                                             |
| `appointme-api` client secret      | `appointme-realm.json`, and `KeycloakAdmin:ClientSecret` in `appsettings.Development.json`                                                  | A fixed 32-character string                                   |
| `appointme-frontend` client secret | `Authentication:Keycloak:FrontendClientSecret` in `appsettings.Development.json`                                                            | A fixed 32-character string                                   |
| Demo user                          | `appointme-realm.json`, and `Demo:User` in `appsettings.Development.json`                                                                   | `demo@appointme.dev` / `AppointMe1`, renamed by `-n` as above |

These only protect containers on your machine. Deployed environments read their secrets from Azure Key Vault, so never copy one of these values into a deployed environment’s settings. If you rotate them, change every place in the row together, and see the gitleaks note under [CI](#ci-and-infra-defaults).

| What              | Where                                                                                                                 | Why                                                                                                 | How                                                                                |
| ----------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `Demo:Enabled`    | `true` in `appsettings.Development.json`, `false` in `appsettings.json`, `true` in `appsettings.Devtest.example.json` | It turns on the demo login, demo data for every new company, and two daily top-up jobs at 03:00 UTC | Keep it for local work. Set it to `false` in any environment real customers use.   |
| Demo seeding      | `src/AppointMe.Api/Demo/DemoSeedingSaga.cs`                                                                           | Every company registered while demo mode is on gets 150 fake customers and about 450 appointments   | Turn demo mode off, or delete the saga and the `SeedDemo*` and `TopUpDemo*` slices |
| Super admins      | `Authentication:SuperAdmins`                                                                                          | The demo user is a super admin in Development, which opens `/admin/jobs`                            | List your own operator emails per environment                                      |
| Dashboard revenue | `src/AppointMe.Frontend/src/app/dashboard/dummy-revenue.ts`                                                           | There’s no payments domain, so revenue is fake data derived from appointment counts                 | Replace it with a real endpoint, or hide the revenue widgets                       |

The demo gate is the first thing the saga checks:

src/AppointMe.Api/Demo/DemoSeedingSaga.cs

```cs
public static DemoSeedingSaga? Start(CompanyRegistered @event, IConfiguration configuration)
{
    if (!configuration.GetValue<bool>("Demo:Enabled"))
    {
        return null;
    }


    return new DemoSeedingSaga
    {
        Id = @event.CompanyId,
        CustomersExpected = CustomerCount,
    };
}
```

## The Keycloak realm

**Keycloak runs only on your machine, from one committed realm file. Two of its settings point at BravoDev or the template’s ports.**

| What            | Where                                                | Why                                                                                                                      | How                                                                                                                           |
| --------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| Google sign-in  | `identityProviders` in `appointme-realm.json`        | It carries BravoDev’s Google OAuth client ID and an empty secret, and “Continue with Google” on the sign-up form uses it | Put in your own Google client ID and secret, or remove the provider and the button in `src/components/signup/signup-form.tsx` |
| Redirect URIs   | The `appointme-frontend` and `appointme-api` clients | They allow only `https://localhost:5173` and `https://localhost:7233`                                                    | Update them if you move the dev ports                                                                                         |
| Email sender    | `smtpServer`                                         | Mail goes from `noreply@appointme.local` to the `Mailpit` host on port 1025                                              | Change the display name if you like. Keep the host for local work.                                                            |
| Login page look | The realm sets no `loginTheme`                       | Users see Keycloak’s default theme locally                                                                               | Add a theme only if local branding matters to you                                                                             |

Keycloak imports the realm only when it doesn’t exist yet, and its container keeps a data volume. To apply an edit, remove the Keycloak container and its volume, then start the stack again; this also deletes the local users you signed up. Deployed environments use Entra External ID instead: see [Entra External ID](/docs/deploy/entra-external-id/).

## Modules, licenses and notices

**Delete the modules you won’t use while the project is young, and keep BravoDev’s copyright line in `LICENSE`.**

| What                     | Where                                                                                                          | Why                                                                                              | How                                                                                                             |
| ------------------------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| Unused modules           | `src/<Module>/`, the `Add<Module>Module()` call in `Program.cs`, the API’s project references, the SPA’s pages | Each one adds tables, endpoints and permissions                                                  | Follow [Remove a module](/docs/guides/remove-a-module/)                                                         |
| `LICENSE`                | Repo root                                                                                                      | It reads `Copyright (c) 2026 BravoDev`. The MIT license requires every copy to keep that notice. | Keep it. Add your own copyright line next to it if you want one.                                                |
| `THIRD-PARTY-NOTICES.md` | Repo root                                                                                                      | A curated list of dependency licenses. Hangfire is LGPL-3.0 (or commercial).                     | Using the unmodified NuGet package is fine. Modifying Hangfire’s own source triggers the LGPL obligations.      |
| Full license report      | The commands at the end of `THIRD-PARTY-NOTICES.md`                                                            | The file isn’t an exhaustive transitive list                                                     | Generate one with `dotnet-project-licenses` and `license-checker-rseidelsohn` before you ship a binary or image |

Gotcha

Don’t replace the BravoDev line in `LICENSE` with your own. Your project is a derivative of an MIT-licensed work, and removing the original notice breaks the license you’re using.

## CI and infra defaults

**The workflows run as soon as you push to GitHub. The Bicep is sized for a demo environment, not production.**

| What                        | Where                                                                              | Why                                                                                                                                                                                                                                                                        | How                                                                                               |
| --------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| Deploy job                  | `.github/workflows/devtest.yml`                                                    | Build and test run on every push to `main`, every `v*` tag and every PR. The deploy job runs on `v*` tags (or a manual run) and needs six secrets (`AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`, `AZURE_RESOURCE_GROUP`, `ACR_NAME`, `APP_SERVICE_NAME`). | Set them as in [GitHub Actions CI/CD](/docs/deploy/ci-cd/), or delete the job until you need it   |
| Secret scanning             | `.github/workflows/secret-scan.yml`, `.gitleaks.toml`                              | gitleaks scans the full history on every PR and push to `main`. The allowlist matches the committed dev values by value.                                                                                                                                                   | If you commit rotated dev values, add them to the allowlist. Better, keep real values out of Git. |
| Code scanning               | `.github/workflows/codeql.yml`                                                     | CodeQL for C# and TypeScript on push, PR and every Monday                                                                                                                                                                                                                  | Keep it. The workflow notes it’s free for public repos.                                           |
| Dependabot                  | `.github/dependabot.yml`                                                           | Weekly NuGet, npm and Actions PRs. It skips Vite+ and container images.                                                                                                                                                                                                    | Bump Vite+ and the images in `Program.cs` and `compose.yaml` by hand                              |
| Template workflow           | `.github/workflows/template.yml`                                                   | Only in a clone: it publishes BravoDev’s package on `v*` tags. Generated projects don’t get it.                                                                                                                                                                            | Delete it in a clone                                                                              |
| Plan and database size      | `infra/modules/app-service-plan.bicep` (`F1`), `infra/modules/sql.bicep` (`Basic`) | F1 unloads the app after about 20 idle minutes and has a daily CPU quota                                                                                                                                                                                                   | Move to B1 or higher before real traffic                                                          |
| Environment and admin login | `infra/main.bicepparam`                                                            | `environmentName = 'devtest'`, SQL admin `appointme_admin`                                                                                                                                                                                                                 | Set yours. The password comes from `SQL_ADMIN_PASSWORD`.                                          |
| Cloudflare Worker route     | `infra/cloudflare-worker/wrangler.jsonc`                                           | Its `routes` and `zone_name` point at a domain derived from your project name                                                                                                                                                                                              | Set your domain, or delete the folder if you don’t front the app with Cloudflare                  |

`infra/README.md` ends with a prod-hardening checklist (private endpoints, WAF, Key Vault purge protection and more). [Production checklist](/docs/deploy/production-checklist/) walks through it.

## Verify it works

**After the changes, the BravoDev name should survive only where it must, and the build, tests and frontend check should still pass.**

```bash
git grep -n -i "bravodev"
git grep -n "Appoint<span"
dotnet build AppointMe.sln
dotnet test AppointMe.sln
cd src/AppointMe.Frontend && npm ci && npm run check
```

Once your generated project is in Git, `bravodev` should match only `LICENSE` and the generated `README.md`, and the wordmark search should find nothing.

| Symptom                                                | Cause                                                                        | Fix                                                                         |
| ------------------------------------------------------ | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| Login fails after you rotated a Keycloak client secret | The realm and `appsettings.Development.json` disagree                        | Use the same value in both, then recreate the Keycloak container and volume |
| Realm edits don’t show up                              | The realm already exists in Keycloak’s data volume, so the import is skipped | Remove the Keycloak container and its volume                                |
| `secret-scan` fails after you rotated dev values       | gitleaks no longer recognizes them as allowlisted                            | Add the new values to `.gitleaks.toml`, or keep them out of Git             |
| “Continue with Google” fails                           | The realm’s Google provider has no client secret                             | Configure your own Google client, or remove the provider and the button     |

### Why commit dev secrets at all?

Committed values let the whole stack start with no setup: Aspire, Compose, the API and the realm all agree on the same passwords from the first `dotnet run`. They protect nothing but containers on your own machine.

The risk is reuse. That’s why deployed environments read Key Vault, why the realm runs only locally, and why gitleaks allowlists these exact values by value rather than by file, so a real secret added to the same files still fails the scan.

## Next

* [Remove a module](/docs/guides/remove-a-module/) (Guide)
* [Production checklist](/docs/deploy/production-checklist/) (Deploy)
* [Build your first feature](/docs/start/first-feature/) (Tutorial)
