GFTSolutions Lab

Guide

How to use this template

This solution is the GFT Tech Office Azure template. To spin up a new prototype, clone it, rebrand it, point the infra at a unique name, and deploy — the deploy also registers the solution on the Solutions Lab Hub. The steps below are the manual runbook (creating the Azure DevOps repo is not automated).

  1. 1

    Create the repository in Azure DevOps

    Each solution lives in its own repo under the Tech Office Azure DevOps project, named GftUs.SolutionsLab.<Name>. Create it, seed it from this template, then clone it locally.

    • In Azure DevOps (org GFT-SE, project KE-065357-007) → Repos → New repository. Name it GftUs.SolutionsLab.<Name> (Git).
    • Bring the template code in: either import this repo as the initial commit, or push the template contents as your first commit.
    • Clone your new repo locally and work from there.
    git clone https://dev.azure.com/GFT-SE/KE-065357-007/_git/GftUs.SolutionsLab.<Name>
    cd GftUs.SolutionsLab.<Name>
  2. 2

    Rebrand the solution

    Everything in the UI (wordmark, page titles, hero copy) reads from one file. Edit it and the whole app renames.

    • Edit app/lib/brand.ts — wordmark, name, description, eyebrow, headline.
    • Don't hardcode the product name anywhere else; the UI already reads it from brand.ts.
    app/lib/brand.ts
  3. 3

    Set the infrastructure names

    Infra names are parameterised in Terraform. Copy the example tfvars and set a unique service name, database name/user and vanity hostname under azure.techoffice.gftus.com.

    • Copy terraform/terraform.tfvars.example to terraform/terraform.tfvars.
    • Set service_name (the Container App name), db_name, db_user and app_hostname (a unique subdomain — the parent zone azure.techoffice.gftus.com already exists).
    • Set the Hub metadata vars (solution_key, solution_name, solution_summary, solution_team, solution_owner, solution_repo, solution_tags) so the entry reads as your solution. Keep a 'Azure' tag so the Hub groups it under the Azure stack.
    cd terraform
    cp terraform.tfvars.example terraform.tfvars
    # edit terraform.tfvars
  4. 4

    Edit the Terraform state key by hand

    Terraform backends can't use variables, so the remote-state key must be changed by hand — once per solution. Pick a unique slug so you don't clash with the template's own state lock or Hub entry.

    • In terraform/providers.tf, change the backend key from solutions/solutionslab-template-azure/terraform.tfstate to solutions/<your-slug>/terraform.tfstate.
    key = "solutions/<your-slug>/terraform.tfstate"
  5. 5

    Implement application-level authentication

    There is NO platform sign-in (no EasyAuth). Authentication is the app's job and is mandatory before you expose the deployment — otherwise every visitor is treated as the same user. The single integration point is resolveAuthenticatedEmail() in app/lib/auth.ts.

    • Add a login gate (login page + session cookie, a shared passcode, or an in-app identity provider).
    • Make resolveAuthenticatedEmail() return the verified signed-in email, and null when there's no session so the app redirects to your login.
    • Roles still live in the users table: first sign-in is bootstrapped as admin (or seed SOLUTION_ADMIN_EMAILS).
    app/lib/auth.ts
  6. 6

    Authenticate the CLIs

    A single apply builds the image in the shared ACR, talks to Azure, and publishes the Hub entry to the shared (GCP) registry bucket — so both the Azure CLI and gcloud must be authenticated on the machine running apply.

    • az login and az account set --subscription d68eb082-646c-48b8-97fc-7fcb9bd04d38 (the Tech Office subscription).
    • gcloud auth application-default login (only needed for the Solutions Lab Hub registration step; the Hub registry lives on GCP).
    • No Entra permissions are needed: the image pulls with the shared ACR admin account and Blob uses the storage access key — no managed identity or RBAC role assignments.
  7. 7

    Deploy to Azure Container Apps

    A single apply builds the image via az acr build, provisions the database + role on the shared Flexible Server, deploys the Container App into the shared Container Apps environment, and binds the vanity domain with a managed certificate. The shared Database, Network, Registry and ContainerApps stacks must already exist.

    • Run terraform init then terraform apply from the terraform/ directory.
    • The managed TLS cert for the vanity domain finishes provisioning a few minutes after the DNS records (asuid TXT + CNAME) resolve.
    • Prerequisites (one-time, shared): the shared Container Apps environment (GftUs.TechOffice.ContainerApps), the Flexible Server allowing Azure-internal connections ('Allow Azure services'), and the shared ACR admin account enabled (admin_enabled = true).
    cd terraform
    terraform init
    terraform apply
  8. 8

    Confirm the Solution Hub listing

    The same apply publishes solutions/<key>/solution.json to the shared Hub registry bucket, so the solution appears on the Solutions Lab Hub automatically. No separate step is needed.

    • Open the Solutions Lab Hub and confirm your solution is listed under Azure with the right name, status and tags.
    • Re-running apply re-publishes the metadata; bump solution_updated_at (or let it default to the apply date).
    • To remove the listing, set register_with_hub = false (or terraform destroy).
  9. 9

    Build your first feature

    The Team Backlog is the reference CRUD slice. To model whatever your prototype tracks, copy it end to end and rename.

    • Schema: add a table to SCHEMA_SQL (and DROP_SQL) in data/seed-core.ts; seed sample rows in data/seed-data.ts.
    • Types → queries.ts (read) → actions.ts (write, each guarded by requireAdmin()) → a route under app/app/<feature>/ + a <Feature>View.tsx.
    • Add the page to the nav array in components/Header.tsx.