---
title: "Academy Article"
canonical_url: "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app"
locale: en
meta:
  "og:title": "Academy Article"
---

[Go to home](https://academy.laioutr.com/en)

- [For developers](https://academy.laioutr.com/en/bereiche/for-developers)

- [Developer start](https://academy.laioutr.com/en/leitfaeden/developer-start)

- [Build and release a first custom app](https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app)

# Build and release a first custom app

A custom app starts from the App Starter: set the package name, register Sections, Blocks or Orchestr handlers with registerLaioutrApp and test them in the playground. npm publish and laioutr app release then bring the version to Cockpit, and an environment's next deployment rolls it out.

## Before you start

<dl>

<dt>Plan</dt>
<dd>Any plan, including Starter</dd>

<dt>Role</dt>
<dd>Member of the organisation; for the release an organisation API key with the registry:publish and app:publish scopes</dd>

<dt>Duration</dt>
<dd>20 min</dd></dl>

### Prerequisites

- A working local development environment
- Login to the npm.laioutr.cloud registry

Last reviewed on October 15, 2026

All integrations in Laioutr are apps, and every app is a Nuxt module. A custom app can connect a backend through **Orchestr** (queries, actions, links, component resolvers), provide **Sections and Blocks** for Studio, or wrap every page as a page wrapper, for example for analytics.

The central call is `registerLaioutrApp` in `src/module.ts`. The module's `configKey` must match the package name in `package.json`, because Laioutr passes the app configuration from `laioutrrc.json` by this name.

Three separate steps lead from the repository to the storefront: **npm publish** puts the version into the registry, **laioutr app release** makes it known to Cockpit with its settings form, and only a **deployment** builds an environment with the selected version. On its first release, a third-party app appears as a private app of the developer's own organisation.

## Step by step

1. 1 ### Step 1: Set the package identity

   Set `name`, `description` and `repository` in `package.json` and replace the template placeholders. Check that `src/module.ts` uses the same name as `configKey`.
2. 2 ### Step 2: Register features

   Add the directories for `orchestrDirs`, `sections` and `blocks` in `registerLaioutrApp`. Handlers are files such as `product/by-slug.query.ts` under `src/runtime/server/orchestr/`.
3. 3 ### Step 3: Test in the playground

   Run `pnpm dev` and call queries and actions in the DevTools **Orchestr Request Editor**. Check Sections and Blocks in Studio via **Developer: Use Localhost**.
4. 4 ### Step 4: Publish the package

   Add `laioutr.manifest.json` to `files` in `package.json` and publish the package to the `npm.laioutr.cloud` registry with `npm publish`.
5. 5 ### Step 5: Release the version to Cockpit

   Run `npx @laioutr/cli app release` in the package folder with a key that has the `app:publish` scope. Pre-releases such as `1.5.0-beta.1` go to the **testing** channel, all others to **stable**.
6. 6 ### Step 6: Roll out to an environment

   Select the version in the environment's **Package Management**, save values under **Configuration** and deploy the environment. Saved values take effect with the next deployment.

## Check the result

The new version appears in **Package Management** without the **Settings not released** badge, and the settings form shows the manifest fields. After the deployment, the storefront serves the app's Sections or data.

## Frequently asked questions

Why does Cockpit show no settings form?

Usually `laioutr.manifest.json` is missing from the published package (check with `npm pack --dry-run`), or `laioutr app release` was not run for that version. A fixed manifest needs a new version.

Is the app then visible in all projects?

No. A third-party app starts as a private app of the organisation and appears in no app catalogue. Listing it in the catalogue requires coordination with Laioutr.

Is the App Starter required?

No, but it already provides the structure, scripts and registration, so work starts directly with the app logic.

## Related

- [Set up a local development environment](https://academy.laioutr.com/en/artikel/set-up-a-local-development-environment)15 min

  With the App Starter, a login to the Laioutr npm registry and the project configuration from Cockpit, a custom Laioutr app runs locally within minutes. The Studio command Developer: Use Localhost then shows the local version directly in Studio.
- [Define custom Sections and Blocks for Studio](https://academy.laioutr.com/en/artikel/define-custom-sections-and-blocks-for-studio)15 min

  Every Section and Block is a Vue file with an exported definition, created with defineSection or defineBlock. It sets the component name, Studio metadata, fields and slots, and Studio builds its picker and sidebar from it.
- [Orchestr: entities, queries, actions and resolvers](https://academy.laioutr.com/en/artikel/orchestr-entities-queries-actions-and-resolvers)8 min

  Orchestr is Laioutr's data layer and runs server-side in the Nuxt server. Queries return entity IDs, component resolvers load the data for them, actions perform changes, and tokens form the contract between frontend, Orchestr and apps.
- [Find, install and configure apps](https://academy.laioutr.com/en/artikel/find-install-and-configure-apps)6 min

  Apps are listed in the Cockpit catalogue under Apps, installed per environment and set up under Configuration. The storefront uses them from the next deployment onwards.
- [The Laioutr CLI: commands and authentication](https://academy.laioutr.com/en/artikel/laioutr-cli-commands-and-authentication)6 min

  The Laioutr CLI fetches the project configuration laioutrrc.json, releases app versions to Cockpit and triggers deployments. Install it with pnpm install -g @laioutr/cli@latest or run it without installation via npx.

## Learn it in a lesson

- [The first custom app](https://academy.laioutr.com/en/lektionen/developer-build-a-first-app)12 min

## [Developer start](https://academy.laioutr.com/en/leitfaeden/developer-start)

Search this guide

1. [Set up a local development environment](https://academy.laioutr.com/en/artikel/set-up-a-local-development-environment)15 min
2. [The Laioutr CLI: commands and authentication](https://academy.laioutr.com/en/artikel/laioutr-cli-commands-and-authentication)6 min
3. [Build and release a first custom app](https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app)20 min
4. [Define custom Sections and Blocks for Studio](https://academy.laioutr.com/en/artikel/define-custom-sections-and-blocks-for-studio)15 min
5. [Orchestr: entities, queries, actions and resolvers](https://academy.laioutr.com/en/artikel/orchestr-entities-queries-actions-and-resolvers)8 min
6. [Declare content collections in code](https://academy.laioutr.com/en/artikel/declare-content-collections-in-code)15 min
7. [Performance and technical SEO in code](https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code)10 min

## Structured Data

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@id": "https://academy.laioutr.com/#website",
      "@type": "WebSite",
      "inLanguage": "en",
      "name": "Default",
      "url": "https://academy.laioutr.com/",
      "translationOfWork": {
        "@id": "https://academy.laioutr.com/#website"
      }
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app#webpage",
      "name": "Academy Article",
      "url": "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app",
      "@type": [
        "WebPage",
        "FAQPage"
      ],
      "breadcrumb": {
        "@id": "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app#breadcrumb"
      },
      "isPartOf": {
        "@id": "https://academy.laioutr.com/#website"
      },
      "mainEntity": [
        {
          "@id": "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app#/schema/question/1"
        },
        {
          "@id": "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app#/schema/question/2"
        },
        {
          "@id": "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app#/schema/question/3"
        }
      ],
      "potentialAction": [
        {
          "@type": "ReadAction",
          "target": [
            "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app"
          ]
        }
      ]
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app#breadcrumb",
      "@type": "BreadcrumbList",
      "itemListElement": [
        {
          "@type": "ListItem",
          "name": "Home",
          "item": "https://academy.laioutr.com/en",
          "position": 1
        },
        {
          "@type": "ListItem",
          "name": "For developers",
          "item": "https://academy.laioutr.com/en/bereiche/for-developers",
          "position": 2
        },
        {
          "@type": "ListItem",
          "name": "Developer start",
          "item": "https://academy.laioutr.com/en/leitfaeden/developer-start",
          "position": 3
        },
        {
          "@type": "ListItem",
          "name": "Build and release a first custom app",
          "item": "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app",
          "position": 4
        }
      ]
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app#/schema/question/1",
      "@type": "Question",
      "inLanguage": "en",
      "name": "Why does Cockpit show no settings form?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<p>Usually <code>laioutr.manifest.json</code> is missing from the published package (check with <code>npm pack --dry-run</code>), or <code>laioutr app release</code> was not run for that version. A fixed manifest needs a new version.</p>"
      }
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app#/schema/question/2",
      "@type": "Question",
      "inLanguage": "en",
      "name": "Is the app then visible in all projects?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<p>No. A third-party app starts as a private app of the organisation and appears in no app catalogue. Listing it in the catalogue requires coordination with Laioutr.</p>"
      }
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app#/schema/question/3",
      "@type": "Question",
      "inLanguage": "en",
      "name": "Is the App Starter required?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<p>No, but it already provides the structure, scripts and registration, so work starts directly with the app logic.</p>"
      }
    }
  ]
}
```
