Backend Local Setup (Windows)¶
This guide walks you through setting up the LBS.Foundry backend locally on Windows. It assumes you have already completed the steps in prerequisites.md (pgAdmin, PostgreSQL, Docker Desktop, .NET SDK, Visual Studio, Node.js, pnpm, Git).
1. Set up the local databases (pgAdmin)¶
Set up the databases first, before cloning the repo. This way, when you build and run the project later, everything is already wired up and won't fail with "database does not exist" errors.
The backend connects to two PostgreSQL databases that must exist before the project can run: foundry and ballr. You will create them inside pgAdmin (installed in the prerequisites step).
1.1 Open pgAdmin¶
- Press the Windows key, search for pgAdmin 4, and open it.
- If it asks for the master password, set one — your choice. Remember it; it only protects pgAdmin itself, not Postgres.
1.2 Create a Server Group named DEV¶
This keeps your local dev servers organized and separate from any production servers you might add later.
- In the left sidebar (Object Explorer), right-click Servers.
- Choose Create → Server Group...
- Name:
DEV - Click Save.
1.3 Register the local Postgres server inside DEV¶
- Right-click the new DEV group → Register → Server...
- In the dialog that opens, fill in two tabs:
General tab:
| Field | Value |
|---|---|
| Name | Foundry |
Connection tab:
| Field | Value |
|---|---|
| Host name/address | localhost |
| Port | 5432 |
| Maintenance database | postgres (default) |
| Username | postgres |
| Password | supremo |
| Save password? | ON (toggle the switch) |
- Click Save.
Verify: the Foundry server should now appear under DEV, and you should be able to expand it without being asked for a password again.
1.4 Create the foundry and ballr databases¶
- In the left sidebar, expand
DEV— you should seeFoundryunderneath. - Right-click Foundry → Create → Database...
- In the General tab:
- Database:
foundry(lowercase, exactly) - Owner:
postgres(default) - Click Save.
Repeat for the second database:
- Right-click Foundry again → Create → Database...
- Database:
ballr(lowercase, exactly) - Click Save.
Note about
scheduler: theappsettings.Development.jsontemplate below also references aschedulerdatabase, but it is auto-created by the application on first run, so you do not need to create it manually here. If you hit an error about it later, just create it the same way as above.
Verify your setup:
- Expand
DEV → Foundry → Databases— you should see at leastpostgres,foundry, andballr. - Right-click
foundry→ Query Tool → runSELECT 1;— it should return1.
Warning: database names are case-sensitive in the connection strings. Make sure you typed
foundryandballrin lowercase, with no spaces or typos.
2. Create the source folder¶
Open PowerShell:
3. Clone the repo¶
If you get a permission error, request access from your manager to the
LBS.Foundryrepo.
4. Add the Luckbox GitHub Packages NuGet source¶
The project depends on private NuGet packages hosted on GitHub Packages. You need to add this as a package source so dotnet restore can find them.
4.1 Create a GitHub Personal Access Token (PAT)¶
- Go to https://github.com/settings/tokens.
- Click Generate new token (classic).
- Give it a descriptive name (e.g.
nuget-luckbox). - Under Select scopes, check:
read:packages- Click Generate token and copy it immediately — you will not see it again.
Tip: save the token in your password manager. You will need it again if you clear your NuGet sources or set up a new machine.
4.2 Add the source¶
Option A — CLI (quickest):
Open PowerShell and run:
dotnet nuget add source "https://nuget.pkg.github.com/luckboxstudios/index.json" --name "Luckbox" --username "YOUR_GITHUB_USERNAME" --password "YOUR_PAT" --store-password-in-clear-text
Replace YOUR_GITHUB_USERNAME with your GitHub username and YOUR_PAT with the token you just created.
Option B — edit NuGet.Config manually:
- Press Win + R, type
%APPDATA%\NuGetand press Enter. This opens the folder containing your user-level NuGet configuration. - Open the file
NuGet.Configin VS Code or Notepad++. If it does not exist, create it. - Replace the entire file contents with the following:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="Luckbox" value="https://nuget.pkg.github.com/luckboxstudios/index.json" allowInsecureConnections="True" />
</packageSources>
<packageSourceMapping>
<packageSource key="Luckbox">
<package pattern="*" />
</packageSource>
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
</packageSourceMapping>
<packageSourceCredentials>
<Luckbox>
<add key="Username" value="YOUR_GITHUB_USERNAME" />
<add key="ClearTextPassword" value="YOUR_PAT" />
</Luckbox>
</packageSourceCredentials>
</configuration>
- Replace
YOUR_GITHUB_USERNAMEwith your GitHub username andYOUR_PATwith the token you created in step 4.1. - Save the file.
Note: both options store credentials in
%APPDATA%\NuGet\NuGet.Config, not in the repository. ThepackageSourceMappingsection tells NuGet which source to use for each package pattern —nuget.orgis the default fallback for all packages, andLuckboxhandles private packages.
4.3 Verify¶
You should see Luckbox [Enabled] pointing to https://nuget.pkg.github.com/luckboxstudios/index.json.
5. Create the configuration files¶
You will create two config files manually. Below are the full templates — copy them, paste into the file, and fill in the secrets where indicated.
Placeholder legend¶
Throughout the templates below you will see three kinds of placeholders. Here is what each one means and what to do:
| Placeholder | What it means | What you should do |
|---|---|---|
Request for this info |
A team-only secret that only your manager or a senior dev can give you | Message your manager and ask for the value |
Fetch this on your account |
Something you generate yourself from your own dashboard on the platform | Log into the platform, go to API Keys, copy the value |
Create your own |
You make this up yourself (e.g. a JWT secret) | Generate any long random string — full instructions below |
File 1 — launchsettings.json¶
Path:
C:\Users\<YOU>\source\luckboxstudios\LBS.Foundry\src\Aspire\LBS.AspireHost\Properties\launchsettings.json
Replace
<YOU>with your actual Windows username.
How to create:
- Navigate to
C:\Users\<YOU>\source\luckboxstudios\LBS.Foundry\src\Aspire\LBS.AspireHost\Properties\in File Explorer. - If the file already exists, open it in VS Code or Notepad++ and replace its contents.
- If it does not exist, create a new file named exactly
launchsettings.json. - Paste the contents below.
- Replace each marker with the value your manager gives you.
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:17097;http://localhost:15037",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21191",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22279",
"POSTGRES_HOST_AUTH_METHOD": "trust"
}
},
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:15037",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19218",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20252"
}
}
},
"EventStoreDbConnection": "Request for this info",
"EventStoreSchema": "marten_testing"
}
Values to ask your manager for:
EventStoreDbConnection— the EventStore DB connection string
File 2 — appsettings.Development.json¶
Path:
C:\Users\<YOU>\source\luckboxstudios\LBS.Foundry\src\Aspire\LBS.AspireHost\appsettings.Development.json
Replace
<YOU>with your actual Windows username.
How to create:
- Navigate to
C:\Users\<YOU>\source\luckboxstudios\LBS.Foundry\src\Aspire\LBS.AspireHost\in File Explorer. - Create a new file named exactly
appsettings.Development.json. - Paste the contents below.
- Fill in placeholders following the legend above.
{
"ConnectionStrings": {
"foundry": "Server=localhost;Database=foundry;Port=5432;User Id=postgres;Password=supremo;Maximum Pool Size=100",
"scheduler": "Server=localhost;Database=scheduler;Port=5432;User Id=postgres;Password=supremo;Maximum Pool Size=100",
"ballr": "Server=localhost;Database=ballr;Port=5432;User Id=postgres;Password=supremo;Maximum Pool Size=100",
"redis": "localhost:6379"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Aspire.Hosting.Dcp": "Warning",
"LBS.Domain.Core.User.Services.DiscordTokenService": "Debug",
"LBS.Core.Integration.Discord": "Debug"
}
},
"Clerk": {
"SecretKey": "Request for this info",
"Authority": "Request for this info",
"AuthorizedParty": "http://localhost:3000",
"WebhookSecret": "Request for this info"
},
"Jwt": {
"Secret": "create your own",
"Issuer": "LBS.Foundry",
"Audience": "LBS.Foundry.Web",
"ExpirationMinutes": 60,
"RefreshTokenExpirationDays": 30
},
"Modelling": {
"SupercoachModelApi": "Request for this info"
},
"Linear": {
"ApiKey": "",
"TeamId": "",
"ApiUrl": "https://api.linear.app/graphql",
"ParentId": "",
"AssigneeId": ""
},
"Discord": {
"BotToken": "Request for this info",
"ApplicationId": "Request for this info",
"PublicKey": "Request for this info",
"VerifiedRoleName": "Verified",
"VerificationChannelName": "verification",
"LogLevel": "Debug",
"Verification": {
"HmacSecret": "Request for this info",
"BaseUrl": "https://localhost:7125",
"TokenExpiryMinutes": "60"
}
},
"ClickHouse": {
"QueryEndpoint": {
"KeyId": "Request for this info",
"KeySecret": "Request for this info"
},
"Native": {
"Host": "localhost",
"Port": 8123,
"Database": "foundry",
"Username": "default",
"Password": "supremo",
"UseSsl": false
}
},
"Email": {
"ApiKey": "test-apikey",
"FromEmail": "test@lbs.com",
"FromName": "LBS Test Email"
},
"UserSeeding": {
"Enabled": true,
"SkipIfUsersExist": false,
"Users": [
{
"Email": "admin@luckboxstudios.com",
"FirstName": "Admin",
"LastName": "User",
"UserName": "admin",
"Password": "Admin123!",
"AccountType": "Human",
"Status": "Active",
"Roles": [ "Admin", "Member" ],
"EmailVerified": true
},
{
"Email": "system@luckboxstudios.com",
"FirstName": "System",
"LastName": "Account",
"UserName": "system",
"Password": "System123!",
"AccountType": "ServiceAccount",
"Status": "Active",
"Roles": [ "ServiceAccount", "Member" ],
"EmailVerified": true
}
]
},
"BallrUrl": "http://localhost:3000",
"Redis": {
"ChannelPrefix": "foundry",
"KeyPrefix": "subscriptions",
"SubscriptionTtlSeconds": 3600,
"TtlRefreshThresholdSeconds": 1800
},
"StatsPerform": {
"Nrl": {
"UserName": "Request for this info",
"Password": "Request for this info"
}
},
"MailerLite": {
"Enabled": false,
"BaseUrl": "https://connect.mailerlite.com",
"ApiKey": ""
}
}
Values you create yourself¶
Jwt.Secret — how to generate one¶
The JWT secret must be a string that is exactly 32 characters long — no more, no less. The format the project expects looks like:
Replace 32_CHARACTERS_LONG with any random string that is exactly 32 characters.
Easiest way (PowerShell one-liner):
Open PowerShell and run this — it generates a random 32-character alphanumeric string:
You will see output like:
That is exactly 32 characters. Copy it and paste it into appsettings.Development.json:
Alternative (in-browser):
- Go to https://www.random.org/strings/ — set Length to
32, check Numeric digits + Lowercase + Uppercase, generate, copy. - Or open browser DevTools console (F12) and run:
Array.from({length:32}, () => "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[Math.floor(Math.random()*62)]).join('')
Verify your secret is exactly 32 characters:
This should print 32. If it prints anything else, regenerate.
Warning: do not use anything predictable like
12345678901234567890123456789012, your name padded with zeros, or a copy of someone else's secret. Each developer should have their own unique JWT secret for local dev.Tip: save it. If you ever rebuild your machine, reuse the same JWT secret so existing local tokens still validate. Stash it in your password manager.
Values to ask your manager for¶
Message your manager with this list:
Clerk.SecretKeyClerk.AuthorityClerk.WebhookSecretModelling.SupercoachModelApiDiscord.BotTokenDiscord.ApplicationIdDiscord.PublicKeyDiscord.Verification.HmacSecretClickHouse.QueryEndpoint.KeyIdClickHouse.QueryEndpoint.KeySecretStatsPerform.Nrl.UserNameStatsPerform.Nrl.Password
Warning: never commit these files to Git — they contain secrets. They are already in
.gitignore, but double-check before pushing.
6. Build the SDK¶
First, navigate into the LBS.Foundry folder. In PowerShell:
Then run:
This single command builds the .NET solution, regenerates the TypeScript SDK, and compiles it.
7. Build the project in Visual Studio¶
Important — start Docker Desktop FIRST. The Foundry API uses Aspire, which spins up containers (Redis, ClickHouse, etc.) when the project runs. You do not need to install or configure Redis separately — Aspire manages it via Docker. If Docker is not running, the project will fail to start with errors like
Docker engine not availableor hang on container startup.
Before pressing F5:
- Open Docker Desktop from the Start Menu.
- Wait for the whale icon in the system tray to turn green / steady (not animated).
- Run
docker psin PowerShell. If it returns without errors, Docker is ready. - Keep Docker Desktop running the entire time you are working on Foundry.
Then in Visual Studio:
- Open Visual Studio.
- File → Open → Project/Solution.
- Navigate to the
LBS.Foundryfolder and open theLBS.slnxfile. - Press Ctrl + Shift + B to build.
- Press F5 to run.
8. Verify it works¶
Once running, open these URLs in your browser:
| Service | URL |
|---|---|
| Foundry API Docs | <yourhost>/scalar/v1 |
| Ballr API Docs | <yourhost>/api-docs/index.html |
<yourhost>is shown in the Visual Studio output console (something likehttps://localhost:7XXX).
9. Test the Foundry frontend login¶
| Field | Value |
|---|---|
| Request for this info | |
| Password | Request for this info |
Ask your manager for the test account credentials.
Related¶
- Prerequisites — install pgAdmin, PostgreSQL, Docker Desktop, .NET, Node.js, pnpm, Git
- Authentication Testing
- Common Development Tasks
- Debugging & Troubleshooting