Best Practices

State

Application state semantic descriptors are represented in UpperCamelCase starting with a capital letter.

"descriptor": [
  {"id": "BlogPosting", "type": "semantic", "def": "https://schema.org/BlogPosting", "descriptor": [
    {"href": "#id"},
    {"href": "#articleBody"},
    {"href": "#dateCreated"},
    {"href": "#blog"}
  ]}
]

Safe State Transitions

Semantic descriptors with type safe add the prefix go to the destination descriptor. (RFC8288)

[
  {"id": "goHome", "type": "safe", "rt": "#Home"},
  {"id": "goFirst", "type": "safe", "rt": "#TodoList"},
  {"id": "goPrevious", "type": "safe", "rt": "#TodoList"}
]

Semantic descriptors that are not safe should use the prefix do.

[
  {"id": "doEditUser", "type": "idempotent", "rt": "#UserList"},
  {"id": "doDeleteUser", "type": "idempotent", "rt": "#UserList"}
]

IMPORTANT: Safe transitions (go*) MUST include the target state name in their id.

[
  {"id": "goProductList", "type": "safe", "rt": "#ProductList"},
  {"id": "goUserProfile", "type": "safe", "rt": "#UserProfile"},
  {"id": "goCheckout", "type": "safe", "rt": "#Checkout"}
]

This rule ensures consistency and makes the diagram self-documenting. When a transition has no source state (entry point), it will be displayed as originating from UnknownState in the diagram.

Invalid examples:

[
  {"id": "goStart", "type": "safe", "rt": "#ProductList"},
  {"id": "goNext", "type": "safe", "rt": "#Checkout"}
]
  • goStart → should be goProductList
  • goNext → should be goCheckout

Elements

Semantic descriptors that are not defined as application states, i.e., elements, are written in lowerCamelCase starting with a lowercase letter.

[
    {"id": "articleBody"},
    {"id": "dateCreated"}
]

ALPS File Structure

The semantic descriptors in ALPS files are divided into three blocks in the following order:

  1. Semantic descriptor groups with meaning definitions using def and doc (ontology)
  2. Semantic descriptor groups with inclusion relationships (taxonomy)
  3. State transition semantic descriptor groups (choreography)
{"descriptor" : [
    {"id" : "name", "type" : "semantic", "def": "http://schema.org/identifier"},
    {"id" : "age", "type" : "semantic", "def": "http://schema.org/title"},

    {"id" : "Person", "type": "semantic", "descriptor":[
      {"href": "#name"},
      {"href": "#age"}
    ]}
    
    {"id": "goPerson", "type": "safe", "rt": "#Person"},
]

Hierarchical Structure Outside ALPS

In ALPS, hierarchical meanings can be expressed by position.

{"descriptor": [
    {"id": "name", "def": "https://schema.org/name"},
    {"id": "Product", "descriptor":[
      {"href": "#name"}
    ]}
    {"id": "Person", "descriptor":[
      {"href": "#name"}
    ]}
]
  • In the example above, name is shared between Product/name and Person/name.
  • When expressing such terms in formats with only flat hierarchies, it’s basic practice to follow the conventions of each format.
  • In HTML, they are expressed in lower camel case.
<form>
    <input name="productName" type="text">
    <input name="personName" type="text">
</form>

Adding Schema References

When creating ALPS profiles, it is recommended to add schema references.

{
  "$schema": "https://alps-io.github.io/schemas/alps.json",
  "alps" : {
  }
}
<alps 
  version="1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="https://alps-io.github.io/schemas/alps.xsd">
</alps>  

Tag Naming

Tags classify descriptors along multiple orthogonal axes. Use prefixed names for supplementary categories and leave the most fundamental category — the domain — unprefixed.

Prefix Category Examples
(none) Domain catalog, order, checkout
flow- Workflow flow-purchase, flow-register
actor- Actor actor-admin, actor-customer

The domain category is unprefixed because it is the most universal dimension — nearly every descriptor belongs to a domain. Prefixing it (e.g. domain-catalog) would add noise without information. This follows the same principle as default namespaces in programming languages.

A single descriptor can carry tags from multiple axes:

{"id": "doAddCart", "type": "unsafe", "rt": "#Cart",
  "tag": "cart flow-purchase actor-customer"}

Here cart is the domain, flow-purchase is the workflow, and actor-customer is who performs the action.

When a profile grows beyond a handful of tags, document the tag taxonomy in a separate file (e.g. tag.md) and link it from the profile:

{
  "alps": {
    "link": [
      {"rel": "describedby", "href": "tag.md", "title": "Tag taxonomy"}
    ]
  }
}

This keeps the tag definitions human-readable and reviewable outside the profile itself.

Implementation Examples

Semantic Elements

Basic element definitions:

<descriptor id="title" title="Title" doc="Article title. Maximum 100 characters."/>
<descriptor id="content" title="Content" doc="Article body. Supports Markdown format."/>
<descriptor id="publishedAt" title="Publication Date" doc="Article publication date and time. ISO 8601 format."/>
{"descriptor": [
    {"id": "title", "title": "Title", "doc": {"value": "Article title. Maximum 100 characters."}},
    {"id": "content", "title": "Content", "doc": {"value": "Article body. Supports Markdown format."}},
    {"id": "publishedAt", "title": "Publication Date", "doc": {"value": "Article publication date and time. ISO 8601 format."}}
]}

Reusing basic elements:

<descriptor id="blogPost">
    <doc>User-created article. After publication, visible to all users.</doc>
    <descriptor href="#title"/>
    <descriptor href="#content"/>
    <descriptor href="#publishedAt"/>
</descriptor>

<descriptor id="pagePost">
    <doc>Static page. Permanent content such as site basic information.</doc>
    <descriptor href="#title"/>
    <descriptor href="#content"/>
</descriptor>
{"descriptor": [
    {"id": "blogPost", "doc": {"value": "User-created article. After publication, visible to all users."}, "descriptor": [
        {"href": "#title"},
        {"href": "#content"},
        {"href": "#publishedAt"}         
    ]},
    {"id": "pagePost", "doc": {"value": "Static page. Permanent content such as site basic information."}, "descriptor": [
        {"href": "#title"},
        {"href": "#content"}
    ]}
]}

Operation Definitions

<descriptor id="goBlog" type="safe" rt="#Blog" doc="Display blog homepage. Shows latest 10 articles."/>

<descriptor id="doCreateBlogPost" type="unsafe" rt="#BlogPost">
    <doc>Create new article. Saved in draft state.</doc>
    <descriptor href="#title"/>
    <descriptor href="#content"/>
</descriptor>

<descriptor id="doPublishBlogPost" type="idempotent" rt="#BlogPost">
    <doc>Publish article. Current time is set to publishedAt.</doc>
    <descriptor href="#id"/>
</descriptor>
{"descriptor": [
    {"id": "goBlog", "type": "safe", "rt": "#Blog", "doc": {"value": "Display blog homepage. Shows latest 10 articles."}},
    {"id": "doCreateBlogPost", "type": "unsafe", "rt": "#BlogPost", "doc": {"value": "Create new article. Saved in draft state."}, "descriptor": [
        {"href": "#title"},
        {"href": "#content"}
    ]},
    {"id": "doPublishBlogPost", "type": "idempotent", "rt": "#BlogPost", "doc": {"value": "Publish article. Current time is set to publishedAt."}, "descriptor": [
        {"href": "#id"}
    ]}
]}