--- name: altinn-studio-app-development description: Build, change, run, and test Altinn Studio apps. Use for app configuration, data models, layouts, texts, process flows, authorization, backend logic, and local testing with studioctl and localtest. --- # Develop Altinn Studio apps Use `studioctl` as the entry point for local Altinn Studio app development. The installed command's help is authoritative; inspect `studioctl --help` and the relevant `studioctl --help` before relying on flags or behavior. ## App anatomy An Altinn Studio app is a .NET ASP.NET Core application. Since Altinn Studio is a low-code platform, lots of features/capabilities are built around configuration. Most behavior lives in `App/`; the repository root holds the solution, container build, and deployment configuration: ```text / |-- App/ | |-- App.csproj Backend project and Altinn.App package versions | |-- Program.cs Service registration and app startup | |-- config/ | | |-- applicationmetadata.json App identity, data types, and allowed parties | | |-- process/process.bpmn Tasks, events, and transitions | | |-- authorization/policy.xml Authorization rules | | `-- texts/resource..json User-facing texts by language | |-- models/ Data-model schemas and generated C# types | |-- ui/ Layout sets, pages, components, and UI settings | |-- options/ Static option lists, when present | |-- logic/, services/, Actions/ Custom backend behavior, when present | `-- wwwroot/ App-specific static assets, when present |-- deployment/ Helm values and deployment configuration |-- Dockerfile `-- App.sln ``` The shape varies by app version and enabled features. Follow the identifiers that connect files: - Task IDs in `config/process/process.bpmn` select the UI for each process task. Newer apps commonly use matching `ui//` directories; older apps map tasks through `ui/layout-sets.json`. - Data-type IDs in `config/applicationmetadata.json` connect tasks, models, and UI settings. Layout components bind fields from the selected model. - `ui//Settings.json` defines page order and settings. Files in `layouts/` define pages and components. - Text keys used by layouts, validation, or code resolve through `config/texts/resource..json`. Keep supported languages aligned when changing user-facing text. - `Program.cs` registers custom C# implementations. Apps usually group them under `logic/`, `services/`, or similar. Read the closest `AGENTS.md`, then inspect the relevant slice of this graph. ## Get an app You may be directed to an existing checkout, if not, use studioctl to checkout an app. Relevant commands: ```sh studioctl auth status --json studioctl auth login studioctl apps search --json "" studioctl app clone / [destination] ``` Ask the user to log in if `auth status` reports no valid login. Search when no specific repository was given; select from `apps[]` using `appId` or `cloneUrl`. `--env` accepts `prod`, `dev`, `staging`, or `local` and defaults to `prod`; Altinn Studio platform developers may use `dev` or `staging`. ## Making changes - Keep task IDs, data-type IDs, model bindings, page references, and text keys consistent across definitions and uses. - Use the `$schema` declared by JSON files when present. Preserve the app's existing version and conventions instead of copying structures from a different template version. - Treat generated models and schemas as one unit. Find the repository's generation path before editing output. - Put backend behavior behind the Altinn.App extension points already used by the app and register implementations in `Program.cs`; follow the app's existing organization. ## Upgrading an app from v8 to v9 `studioctl app upgrade v9` migrates the app and reports what it will not change for you. Read its output before changing anything yourself; it names every file and configuration path it found. Maskinporten needs deliberate handling. A v9 app has **one** Maskinporten identity and never configures its own credentials: it reads whatever the platform provisions for it. Deployed, that is the client Studio provisions. On a local run studioctl is the platform, and it cannot yet hand over the credentials Studio issues - so to test against a real external API you supply a client for studioctl to provision in their place, with `studioctl app maskinporten set`. That is a gap in the local harness, not a second identity for the app. The consequence that matters is about scopes. Maskinporten grants scopes per client registration, and the client a local run uses is not the registration the deployed app uses. So a scope selected in Studio is not thereby available locally, and a scope on your local client is not thereby available once deployed. The same scopes have to be in place in both spots. When the upgrade reports Maskinporten configuration: 1. **Record the scopes before deleting anything.** The upgrade prints a scope list with the evidence for each entry, including the `Scope` value read out of the sections it is telling you to delete. Once the section is gone, that record is gone. 2. **For the deployed app**, select those scopes in Studio under App settings, "Velg scopes fra Maskinporten". This requires an Ansattporten sign-in on behalf of the organization that owns the app, and takes effect the next time the app is built and deployed - so do it _before_ deploying, or the deployed app fails on its first token request. 3. **For local runs**, supply a client with `studioctl app maskinporten set` and make sure that client already has the same scopes in Maskinporten. `studioctl doctor` reports whether one is stored for the detected app. 4. **Do not reintroduce credentials into `appsettings.json`.** v9 does not read them from there in any environment. A section that configures the external `Altinn.ApiClients.Maskinporten` package is the exception and is still read by that package. Do not add the `altinn:serviceowner` scopes anywhere on the app's behalf: Studio adds them to the provisioned credentials automatically when a v9 app is built, and a local run does not need them. ## Run and test From the app root: ```sh studioctl env up studioctl env status --json studioctl run --detach --json studioctl app ps --json ``` For investigating failures, use `studioctl app logs` and `studioctl env logs`. `studioctl doctor` can be used if there are problems with `studioctl` (or there are missing capabilities). If local hostnames do not resolve, inspect `studioctl env hosts status`. `studioctl env hosts add` changes the system hosts file, so explain that effect before running it with the host's normal privilege mechanism. Open the `url` from the `run` result; `logPath` identifies its log file. `app ps` reports status in `running` and `apps[]`, but does not return the app URL. The `http://local.altinn.cloud:8000` root page contains the login form, not the app. ### Test changes to Altinn Studio itself This is mostly for internal Altinn Studio/platform developers, not service owner app developers. Mostly used within the `Altinn/altinn-studio` monorepo. Useful when testing changes to e.g. localtest, pdf3, frontend, workflow-engine-app or other Altinn Studio platform components. - `STUDIOCTL_INTERNAL_DEV=true studioctl env up` builds supported LocalTest/runtime service images from the current monorepo checkout. - `studioctl env up --dev-workflow-engine` routes the workflow-engine component to a host process, normally at `http://localhost:9090`. - `studioctl run --dev-frontend` serves frontend assets from the current monorepo checkout while the app frontend development server is running. ## Stop ```sh studioctl app stop studioctl env down ``` Do not reset state, remove credentials, delete files, or broadly terminate processes unless requested and precisely targeted.