Local Development
Summary
This document describes how to get set up for local development or test driving on a local instance of Zeeq.
Key technologies
| Component | Technology |
|---|---|
| Frontend | Vue 3, Nuxt UI (Tailwind CSS), Pinia, Vite |
| Backend | C#/.NET 10, ASP.NET Core Minimal APIs, OpenIddict, EF Core + Npgsql, Testcontainers, TUnit |
| Database | PostgreSQL 18, pg_vector, pg_cron, pg_partman (container is defined in build/postgres/Dockerfile) |
| Messaging | Postgres, Google Cloud Pub/Sub |
Baseline setup
| Tooling | Description | Install from... |
|---|---|---|
| Mise | Manages local environment variables and tooling | brew install mise See Installing mise |
| Docker | Containerization and orchestration | Docker |
mise first; that should install the other dependencies.Once dotnet CLI is available, restore the tools:
# Restore all tools
dotnet tool restore
Setting local secrets
The runtime requires several local secrets to execute.
These are managed using .NET local user secrets.
cd src/backend/Zeeq.Runtime.Server
# Non-secret settings are in appsettings.Development.json
# Initialize the secrets store
dotnet user-secrets init
# Add secrets to the store (see: src/backend/Zeeq.Runtime.Server/appsettings.Development.json)
# (✅ REQUIRED: Needed to generate embeddings for the search)
# The API key to use for generating embeddings (always needed since there is no UI for this)
dotnet user-secrets set AppSettings:Llm:Embeddings:ApiKey secret-value
# (☑️ OPTIONAL: Required or use in-app managed keys; code reviews will not work without this)
# The API key to use with the default "fast" LLM tier model.
# Not needed if using in-app configured self-managed services.
dotnet user-secrets set AppSettings:Llm:Models:Fast:ApiKey secret-value
# (☑️ OPTIONAL: Only needed for testing signed imports)
# The signing key used for importable Zeeq library export packages
dotnet user-secrets set AppSettings:Documents:LibraryExportSigningKey "$(openssl rand -base64 48 | tr -d '\n')"
# (☑️ OPTIONAL: Only needed for GH integration testing locally)
# The DEV GitHub app webhook secret (other configuration directly in file)
# This is needed to test GitHub webhook flows locally since the GH app only has one webhook URL
# Alternate: configure custom webhooks: https://github.com/zeeq-ai/zeeq-app/settings/hooks
dotnet user-secrets set AppSettings:GitHub:WebhookSecret secret-value
# (☑️ OPTIONAL: Only needed for GH integration testing locally)
# The DEV GitHub app private key PEM for local testing
dotnet user-secrets set AppSettings:GitHub:PrivateKeyPem secret-value
# (☑️ OPTIONAL: Use the mock OAuth provider without need to hook up Google or GH OAuth)
# The client secrets for OAuth providers (e.g. GitHub, Google, etc.) used for user login
# Order matches appsettings.Development.json
dotnet user-secrets set AppSettings:Auth:Providers:0:ClientSecret secret-value # Google
dotnet user-secrets set AppSettings:Auth:Providers:1:ClientSecret secret-value # GitHub
# (☑️ OPTIONAL: Use only for access to the system platform management panel)
# The account identifiers prefixed with the provider that designate system level admins
# The user will need to have an account first locally (or you already know the subject ID)
dotnet user-secrets set AppSettings:Platform:SystemAdminSubjects:0 secret-value
Starting the runtime
Zeeq runs using Aspire as the orchestration layer which launches all processes and containers.
Assuming you have mise set up properly, switching into the source directory:
# Smoke test
dotnet --version
# Start aspire which will start the stack
aspire run --detach --non-interactive
# To stop the stack since it is detached in the background
aspire stop
The Aspire stack is now at http://localhost:15010:

The application uses YARP to run on the following endpoints:
| Endpoint | Description |
|---|---|
| http://zeeq-web.localhost:8095 | The main application entrypoint |
| http://zeeq-docs.localhost:8095/docs | The local docs app backed by the docs-root Aspire parameter |
| http://zeeq-api.localhost:8095/scalar | The local Scalar UI for the API |
| http://zeeq-inspector.localhost:8095 | The local MCP inspector UI for the API |
127.0.0.1 zeeq-web.localhost
127.0.0.1 zeeq-api.localhost
127.0.0.1 zeeq-docs.localhost
127.0.0.1 zeeq-inspector.localhost
Connecting
Follow the guide in Connecting Agents but use the endpoint: http://zeeq-web.localhost:8095/mcp as the target.
Common problems
gcp-pubsub-emulator) to be ready. This container may take a bit of time to download. You may occasionally need to run aspire stop and aspire run --detach --non-interactive again to reconnect to the container.devtunnels integration with Aspire or using ngrok yourself.devtunnel has a relatively short lifetime so you are likely going to need to reauthenticate once a day.Normal development workflow
During normal development, you should not need to manually stop and start the Aspire stack.
On rebuilds:
# Rebuild and restart the resource.
aspire resource zeeq-server --rebuild
When changes are made in the backend, the API stubs are automatically re-generated via a .NET background build process that will output the OpenAPI schema to src/web/src/api/zeeq-api.json. Kubb is used to generate the client stub from here.
Build and test
Typical operations for building and testing:
dotnet build && dotnet test --no-restore --no-build