App manifest and menus

The app manifest is the file that defines the app's name and description along with the menus to register in the web console. Without this file, installing the app puts nothing in the console.

Place the manifest at src/main/resources/sonar_app.json. A sonar_app_logo.png file has to sit in the same directory.

{
  "manifest_version": "5.0.2603.0",
  "app_code": "sample",
  "bundle_symbolic_name": "com.logpresso.sonar.sample",
  "name": "Logpresso Sample App",
  "description": "Example app for the Logpresso App SDK.",
  "names": {
    "en": "Sample App",
    "ko": "샘플 앱",
    "ja": "サンプルアプリ"
  },
  "descriptions": {
    "en": "Example app for the Logpresso App SDK.",
    "ko": "로그프레소 앱 SDK 예제 앱입니다.",
    "ja": "Logpresso アプリ SDK のサンプルアプリです。"
  },
  "menus": [
    {
      "code": "subnet-groups",
      "names": {
        "en": "Subnet Groups",
        "ko": "네트워크 대역",
        "ja": "サブネットグループ"
      },
      "route": "/app-loader/sample/subnet-groups"
    }
  ]
}

Manifest fields

FieldRequiredDescription
manifest_versionYesThe Logpresso Sonar version the app targets
app_codeYesThe code identifying the app. Its format is constrained.
bundle_symbolic_name The bundle name. Set it to the same value as Bundle-SymbolicName in the Maven configuration.
nameYesThe default app name
names.ko, names.enYesLocalized app names. Korean and English are required.
names.ja The Japanese app name
description The default app description
descriptions.ko, .enYesLocalized app descriptions. Korean and English are required.
descriptions.ja The Japanese app description
menus The menus to register in the web console. An app with screens must define this.

A missing required field is rejected during installation or validation.

App code

The app code identifies the app and has to follow this format.

^[a-z][a-z0-9-]*$

It starts with a lowercase letter and may contain only lowercase letters, digits, and hyphens. Uppercase letters, underscores, spaces, and non-Latin characters are not allowed.

The app code is not merely an identifier — it is part of an address. Screen resources are served from /app/{app_code}/, the code appears in menu routes, and by convention it appears in REST API addresses as well. Because it has to be unique across the platform, use a value that identifies the vendor or the product.

A generic word like sample or test can collide with another app. For a real app, name both the vendor and the product, as in acme-firewall.

Changing the app code later changes every screen address. You have to update the Vite base path, the menu routes, and the REST API addresses together, so decide carefully up front.

Registering a menu

A menu item consists of a code, localized names, and a route.

{
  "code": "subnet-groups",
  "names": { "en": "Subnet Groups", "ko": "네트워크 대역" },
  "route": "/app-loader/sample/subnet-groups"
}

The route follows this form.

/app-loader/{app_code}/{app internal path}

/app-loader is the route the web console uses to open an app screen. Drop that prefix and write something like /sample/subnet-groups, and the console cannot resolve the path.

The app internal path is the part the app interprets itself. The app loader only passes it through to the iframe address without interpreting it, so you are free to shape it around your screens. With a single screen you can point at the app root, as in /app-loader/sample/.

Registering several screens

An app with several screens can build a hierarchical menu with children.

"menus": [
  {
    "code": "discovery",
    "names": { "en": "Discovery", "ko": "탐지" },
    "children": [
      {
        "code": "board",
        "names": { "en": "Board", "ko": "현황판" },
        "route": "/app-loader/acme-firewall/discovery/board"
      },
      {
        "code": "inbox",
        "names": { "en": "Inbox", "ko": "수신함" },
        "route": "/app-loader/acme-firewall/discovery/inbox"
      }
    ]
  },
  {
    "code": "query",
    "names": { "en": "Query", "ko": "쿼리" },
    "route": "/query"
  }
]

A parent item carries no route, only children.

As in the last item, a menu can point at one of Logpresso Sonar's own screens. Adding an item that opens the query screen, so users can immediately run the query commands the app extended, is one example. In that case you use the web console's route as-is rather than /app-loader.

Use the same approach to link to a dashboard the app ships.

{
  "code": "dashboard",
  "names": { "en": "Dashboard", "ko": "대시보드" },
  "route": "/dashboard/f06330d6-4af7-4afb-aa39-cae757130319"
}

An app can include a dashboard as a resource, so putting that dashboard's identifier in the route lets users open it straight from the app menu.

Logo

The sonar_app_logo.png file has to be in the same directory as the manifest, and validation rejects the app without it. Use a 64×64 PNG file with a transparent background.

Agent prompt

Use this when you delegate menu configuration to an agent.

Register menus in a Logpresso app manifest.

App code: sample
Screens to register: (list the screen names and what they are for)

Comply with:
- route follows /app-loader/{app_code}/{internal path}
- names requires ko and en; ja is recommended
- a parent menu carries no route, only children
- app_code matches ^[a-z][a-z0-9-]*$

Reference: https://docs.logpresso.com/en/app-sdk/app-manifest

Menu names have to follow product terminology. Do not invent new terms; if
something needs confirming, mark it as needing confirmation.

The next section explains how the web console and the app exchange navigation.