Last modified: Mar 17, 2026

Custom Templates

How to set up custom templates in Altinn Studio for app creation

Custom Template Setup Guide

This guide explains how to manually set up custom templates in an Altinn Studio content repository.

🚧 Experimental Feature - Feature Flag Required

Custom templates is currently in an exploration phase and requires a feature flag to access. To enable this feature, add the query parameter ?featureFlags=customTemplates when creating a new app in Altinn Studio (e.g., https://altinn.studio/dashboard/app-dashboard/self/new?featureFlags=customTemplates).

This feature is experimental and may change significantly or be removed in future versions.

Overview

Custom templates allow organizations to create reusable application templates. Templates are stored in a dedicated content repository in Gitea following the naming convention {org}-content (e.g., digdir-content).

Repository Structure

Your content repository must follow this structure:

{org}-content/
└── Templates/
    β”œβ”€β”€ templatemanifest.json   # List of all available templates
    β”œβ”€β”€ {template-id-1}/
    β”‚   β”œβ”€β”€ template.json       # Template configuration
    β”‚   └── content/            # Template files to copy
    β”‚       β”œβ”€β”€ App/
    β”‚       β”œβ”€β”€ config/
    β”‚       └── ... (any app files)
    └── {template-id-2}/
        β”œβ”€β”€ template.json
        └── content/
            β”œβ”€β”€ App/
            β”œβ”€β”€ config/
            └── ... (any app files)

File Requirements

1. templatemanifest.json

Located at Templates/templatemanifest.json, this file lists all available templates in the repository. Each entry provides a summary of a template, containing only a subset of its properties (such as id, owner, name, and description), not the full configuration. This manifest is used to present template options to end users when they are choosing a template to base their application on. Full details and validation rules for each template are defined in the corresponding template.json file.

Format:

[
    {
        "id": "my-template",
        "owner": "digdir",
        "name": "Min fΓΈrste mal",
        "description": "Dette er en detaljert beskrivelse av hva malen gjΓΈr og hva den inneholder"
    }
]

Requirements:

  • Must be a valid JSON array
  • Each template entry must include: id, owner, name, and description

2. template.json

Located at Templates/{template-id}/template.json for each template.

This file contains the complete configuration for a single template.

Properties in template.json

PropertyTypeRequiredDescription
schemaVersionstringYesWhich JSON Schema version the template follows. Currently, only 0.1 is supported.
idstringYesUnique ID for the template.
ownerstringYesOwner of the template (organization short name).
namestringYesName of the template.
descriptionstringYesDescription of the template.
removearrayNoList of relative file paths or globs to remove from the application repo.
packageReferencesarrayNoList of NuGet packages to add to specified project files (.csproj).
nextStepsarrayNoList of next steps to guide users after template application.

Format:

{
    "schemaVersion": "0.1",
    "id": "my-template",
    "owner": "digdir",
    "name":  "Min fΓΈrste mal",
    "description": "Dette er en detaljert beskrivelse av hva malen gjΓΈr og hva den inneholder",        
    "remove": [
        "App/TestDummy.cs",
        ".editorconfig"
    ],
    "packageReferences": [
        {
            "project": "App/*.csproj",
            "include": "Altinn.App.Clients.Fiks",
            "version": "8.10.0"
        }
    ],
    "nextSteps": [
        {
            "title": "Configure Fiks Integration",
            "description": "Follow the guide to configure your Fiks Arkiv integration settings in applicationmetadata.json",
            "type": "configuration",
            "links": [
                {
                    "label": "Fiks Integration Guide",
                    "ref": "https://docs.altinn.studio/nb/fiks/"
                }
            ]
        }
    ]
}

Requirements:

All template.json files must comply with customtemplate.schema.json.

Review the schema file for required fields, types, and validation rules or paste your template below for quick confirmation of whether it complies with the schema.

Property Details

packageReferences

The packageReferences array allows you to specify NuGet packages that should be added to or updated in project files when the template is applied.

Properties:

PropertyTypeRequiredDescription
projectstringYesRelative path or glob pattern to .csproj file(s). No absolute paths allowed.
includestringYesNuGet package name (e.g., “Newtonsoft.Json”).
versionstringYesPackage version (e.g., “1.2.3”, “1.2.3-preview”, “[1.2.3]”, “1.2.*”).

Example:

"packageReferences": [
    {
        "project": "App/*.csproj",
        "include": "Altinn.App.Clients.Fiks",
        "version": "8.10.0"
    },
    {
        "project": "App/App.csproj",
        "include": "Newtonsoft.Json",
        "version": "13.0.1"
    }
]

Behavior:

  • If the package already exists in the project file, the version will be updated.
  • If the package does not exist, it will be added to an existing <ItemGroup> with other package references, or a new <ItemGroup> will be created.
  • The project pattern must match exactly one .csproj file.
nextSteps

The nextSteps array provides guidance to users after the template has been applied, helping them understand what configuration or code changes are needed next.

Properties:

PropertyTypeRequiredDescription
titlestringYesTitle of the next step (minimum 5 characters).
descriptionstringYesDetailed description of the step (minimum 20 characters).
typestringNoType of step: configuration, codechange, or documentation.
linksarrayNoArray of related links with label and ref properties.

Example:

"nextSteps": [
    {
        "title": "Configure Fiks Integration",
        "description": "Follow the guide to configure your Fiks integration settings in applicationmetadata.json",
        "type": "configuration",
        "links": [
            {
                "label": "Fiks Integration Guide",
                "ref": "https://docs.altinn.studio/nb/fiks/"
            }
        ]
    },
    {
        "title": "Implement Custom Validation Logic",
        "description": "Add your custom validation logic in the ValidationHandler.cs file to validate form data according to your business rules.",
        "type": "codechange",
        "links": [
            {
                "label": "Validation Documentation",
                "ref": "https://docs.altinn.studio/app/development/logic/validation/"
            }
        ]
    }
]

Supported Type Values:

  • configuration / konfigurasjon - Configuration-related steps
  • codechange / kodeendring - Code modification steps
  • documentation / dokumentasjon - Documentation-related steps

(One value per language is accepted)

3. content/ folder

Located at Templates/{template-id}/content/, this folder contains all files that will be copied to the target application repository when the template is applied.

Structure example:

Templates/my-template/content/
β”œβ”€β”€ App/
β”‚   β”œβ”€β”€ models/
β”‚   β”œβ”€β”€ ui/
β”‚   β”‚   β”œβ”€β”€ layouts/
β”‚   β”‚   └── Settings.json
β”‚   β”œβ”€β”€ logic/  
β”‚   └── config/   
β”‚   β”‚   └── applicationmetadata.json  
└── README.md

All files and folders within content/ will be recursively copied to the root of the target application repository.

Setup Checklist

  1. Create Templates/ folder in the root of {org}-content repository
  2. Create templatemanifest.json with all template entries
  3. For each template:
    • Create Templates/{template-id}/ folder
    • Create template.json with complete configuration
    • Create content/ subfolder
    • Add all template files to content/ folder
  4. Validate that all JSON files comply with the schema
  5. Commit and push to the main branch

Best Practices

  • Use descriptive template IDs that clearly indicate the template’s purpose
  • Test template application before making it available to users
  • Document template contents in the description field
  • Use the remove array to clean up unused files from default app templates
  • Keep content folder organized following Altinn app structure conventions