# The anatomy of an APEX 26.1 APEXlang file

# Introduction

If you have spent any time reviewing traditional APEX export SQL, you know the problem. The application is there, but it is buried inside hundreds of calls to internal APIs. You can version it, search it, and deploy it, but reading it fluently is hard work.

To be fair, this is not the first time APEX has given us something better than one huge SQL export. Older versions of APEX could export an application using the **Split into Multiple Files** option, and APEX has also had a human-readable YAML export format. Those were useful, especially for review and source control, but the YAML format was read-only, and the split SQL export was fundamentally SQL export syntax.

APEXlang makes that structure easier to work with. It mirrors the APEX Builder mental model in a source format that is intended to be read as APEX metadata: applications contain pages, pages contain regions and components, shared components live together, and SQL, PL/SQL, JavaScript, CSS, and HTML still appear where you would expect them.

In this post, I will walk through the anatomy of an APEXlang `.apx` file and show how to build a mental model of an app quickly.

# The Folder Structure

An APEXlang export is not one giant SQL file. It is exported as a zip file that expands into a folder structure.

For the `customers` sample app, the tree looks like this:

```text
customers/
|-- application.apx
|-- page-groups.apx
|-- pages/
|   `-- p00001-dashboard.apx
|   `-- p00050-customer.apx
|-- shared-components/
|   |-- app-computations.apx
|   |-- app-items.apx
|   |-- app-processes.apx
|   |-- authentications.apx
|   |-- authorizations.apx
|   |-- breadcrumbs.apx
|   |-- build-options.apx
|   |-- classic-navigation-bar-entries.apx
|   |-- component-settings.apx
|   |-- legacy-data-load-definitions.apx
|   |-- lists.apx
|   |-- lovs.apx
|   |-- messages.apx
|   |-- plugins/region/APEXLANG-14855697926908483213/{custom-attributes.apx,plugin.apx}
|   |-- shortcuts.apx
|   |-- static-files.apx
|   |-- report-layouts/report-layouts.apx
|   |-- report-layouts/CUSTOMER-REPORT.rtf
|   |-- static-files/icons/app-icon-32.png
|   `-- themes/universal-theme/{template-option-groups.apx,theme.apx}
|-- supporting-objects/
|   |-- deinstall-script.sql
|   |-- install-scripts.apx
|   |-- install-scripts/activities.sql
|   |-- supporting-objects.apx
|   |-- substitutions.apx
|   |-- upgrade-scripts.apx
|   `-- upgrade-scripts/upgrade-eba-cust-spec-and-body.sql
|-- deployments/default.json
|-- .apex/apexlang.json
`-- workspace-components/app-groups/APEX-184853421316436653.apx
```

`application.apx` is the application-level definition. This is where you find the application name, version, authentication, authorization, navigation, theme, globalization, security settings, substitutions, JavaScript, CSS, and other global configuration.

`pages` contains one file per page. The filenames are practical: `p00001-home.apx`, `p00003-event-details-p3-event-name.apx`, `p00050-customer.apx`, and so on. You can usually tell the page number and purpose before opening the file.

`shared-components` contains the things you would expect from APEX Builder: LOVs, lists, breadcrumbs, authentications, authorizations, app items, app processes, themes, plugins, messages, build options, static files, and report layouts.

`supporting-objects` contains installation, upgrade, substitution, and deinstallation metadata. The actual SQL scripts can live under folders such as `supporting-objects/install-scripts` and `supporting-objects/upgrade-scripts`.

`deployments` contains deployment configuration. In the examples, `default.json` maps the app to an application ID.

`.apex` contains APEXlang metadata. In the examples, `.apex/apexlang.json` identifies the APEXlang metadata version.

This structure matters because it lets you navigate an app the same way you think about an app. That idea existed before APEXlang, but APEXlang makes the files easier to read. You can edit, validate, and import them back into APEX.

# What Lives in `application.apx`

Open `application.apx` first.

It starts with an `app` block:

```apexlang
app TEAM-CALENDAR (
    name: Team Calendar
    version: 24.2.1
    authentication {
        publicUser: APEX_PUBLIC_USER
        authenticationScheme: @administration-rights
    }
    navigation {
        homeUrl: f?p=&APP_ID.:1:&SESSION.
    }
)
```

That reads much closer to a configuration file than an export script. You can scan it and answer basic questions quickly:

*   What is this application called?
    
*   What authentication scheme does it use?
    
*   Is authorization configured globally?
    
*   What is the home page?
    
*   Which theme is current?
    
*   Are there global substitutions?
    
*   Is custom CSS or JavaScript included?
    

You will also see the same APEX ideas you already know: session management, security, globalization, navigation, Progressive Web App settings, and substitutions.

Read `application.apx` like the App Definition screen in APEX Builder. Do not try to understand every reference yet. Get the global shape first.

# How Pages Are Modeled

Page files are where APEXlang becomes especially useful.

A page starts with a `page` block:

```apexlang
page 1 (
    name: Home
    alias: HOME
    title: &APPLICATION_TITLE. - Home
    appearance {
        pageTemplate: @/standard
    }
)
```

After that, the file is organized around page components. In the examples, pages contain:

*   `region`
    
*   `item`
    
*   `button`
    
*   `dynamicAction`
    
*   `validation`
    
*   `computation`
    
*   `process`
    
*   `branch`
    

Again, this follows the APEX Builder mental model. To understand a page, scan the top-level component blocks first.

Regions often contain their own nested configuration. A report region may include a source block, layout settings, template choices, columns, actions, conditions, and attributes.

```apexlang
region APEX$1553489748373581675 (
    name: Events Calendar
    type: calendar
    source {
        location: localDatabase
        type: sqlQuery
        sqlQuery:
            ```sql
            select e.event_id
            ,      e.event_name
            from   eba_ca_events e
            ```
    }
)
```

That is the key pattern: the declarative APEX component is modeled structurally, and the executable code remains embedded in a fenced block.

For form or dialog pages, I would scan in this order:

1.  Page name, alias, template, and security.
    
2.  Regions, especially the main form region.
    
3.  Items and their source/default/session state behavior.
    
4.  Buttons and button positions.
    
5.  Processes and branches.
    
6.  Validations and dynamic actions.
    

You can usually tell whether a page is display-only, a report, a modal form, or a complex transactional page in a couple of minutes.

# Shared Components Become Readable

Shared components are split into focused files. That is one of the biggest readability wins.

For example, `shared-components/lovs.apx` contains `lov` blocks. A static LOV contains nested `entry` blocks. A SQL-based LOV contains a source block with the SQL query.

```apexlang
lov APEX$14836072312031628364 (
    name: USERNAME_FORMAT
    source {
        location: staticValues
    }

    entry APEX$14836072618328628365 (
        sequence: 1
        display: Email Address
        return: EMAIL
    )
)
```

Lists work the same way. `shared-components/lists.apx` contains `list` blocks, and each list contains `entry` blocks with labels, icons, links, current-page logic, and parent-child relationships.

App processes live in `shared-components/app-processes.apx`. Authentication schemes live in `shared-components/authentications.apx`. Plugins live under `shared-components/plugins`, separated by plugin type and id. Themes live under `shared-components/themes`.

This is much easier to review than a traditional SQL export because the file boundaries match the APEX Builder navigation, and the file contents are not wrapped in API calls.

# Understanding References

APEXlang uses references heavily, and learning the reference style is what makes the files click.

You will see `@...` references in exported files. These are references to APEX components by generated identifier. For example, an application may point to an authentication scheme or navigation list using an `@...` value.

You will also see more readable references based on static IDs and names:

```apexlang
authentication {
    scheme: @oracle-apex-accounts
}
userInterface {
    currentTheme: @universal-theme
}
navigationMenu {
    list: @navigation-menu
}
```

That matters because APEX 26.1 adds static IDs across APEX components, and APEXlang uses those IDs to make references more stable and readable.

You will also see `@/...` references, especially for templates:

```apexlang
pageTemplate: @/standard
listTemplate: @/side-navigation-menu
buttonTemplate: @/text-with-icon
```

These are easier to read because the component is referenced by a friendly path-like name.

Page item references still look like APEX page item references. SQL and PL/SQL blocks use bind variables such as `:P50_ID`, `:APP_ID`, and `:APP_USER`. URL targets still use familiar APEX substitution syntax, such as `f?p=&APP_ID.:1:&SESSION.`.

Named component references also appear naturally in places such as authorization checks, build option logic, template references, and links.

The practical rule is simple: if you see `@...`, you are looking at a declarative component reference. If you see `:Pxx_ITEM`, you are looking at the session state. If you see `&APP_ID.` or `#COLUMN#`, you are in familiar APEX substitution territory.

# The Hybrid Reality

APEXlang structures the declarative layer, but it does not remove code from APEX.

SQL queries still live in report sources, LOVs, conditions, and supporting object scripts. PL/SQL still lives in processes, validations, conditions, computations, and application processes. JavaScript can still appear in page JavaScript settings, dynamic actions, and static files. CSS can still be inline on a page or stored as a static file. HTML still appears in help text, templates, report HTML expressions, and PL/SQL output.

APEXlang is not pretending APEX is something it is not. It provides metadata with a readable structure while preserving the hybrid nature of real APEX applications. Just as important, that structure supports real round-tripping: you can search and replace across files, generate apps with AI, validate the result, and import the application back into APEX.

# How the Oracle APEXlang Skill Fits In

The APEXlang files are only half the story. Oracle also released an [APEXlang AI skill package](https://github.com/oracle/skills/tree/main/apex/apexlang) to help agents work with this format safely.

That package is not just a pile of examples. It includes routing metadata, component catalogs, templates, runtime helpers, SQLcl adapters, and validation tools. The skill provides an agent with a workflow for finding the app, loading the correct local context, choosing the appropriate templates, checking component properties against compiler-backed truth, validating the generated APEXlang, and importing only when explicitly approved.

That safety model matters. APEXlang is writable, but it is still application metadata. A good agent workflow should not guess table names, invent columns, silently pick a workspace, or import generated code because the prompt sounded confident. The skill expects authoritative context, such as table metadata, a data model, an API contract, or a live database connection, before it generates schema-dependent APEXlang.

For live validation or import, the practical requirements are also explicit: APEX 26.1 with APEXlang support, SQLcl 26.1.2 or newer, Java 17 or 21, a saved SQLcl connection name, and the corresponding APEX workspace name. The default workflow is check-only first. Import is a separate step that should happen only after the APEXlang check passes and the developer approves it.

For APEX 26.1, APEXlang import is an application import. Single-page APEXlang import is not supported in this release. That does not reduce the value of the format, but it does affect how you plan review, validation, and deployment workflows.

# Conclusion

The most useful way to think about APEXlang is this:

> APEXlang is a readable and writeable source format for an Oracle APEX application.

It builds on ideas APEX has already explored with split exports and readable YAML, but gives developers a practical source format for navigating application metadata without decoding traditional export SQL.

It is still APEX. Your pages, shared components, SQL, PL/SQL, JavaScript, CSS, and HTML are all still there. They are just arranged in a format that humans can read, search, diff, validate, and learn from before importing the application back into APEX.

Once you understand the folder structure, page model, shared component files, and reference syntax, `.apx` files become much less intimidating. You can open an unfamiliar application and start building a useful mental model quickly, which is exactly what a source format should help you do.
