Skip to main content

Command Palette

Search for a command to run...

The anatomy of an APEX 26.1 APEXlang file

Published
9 min read
The anatomy of an APEX 26.1 APEXlang file
J
Hi, thanks for stopping by! I am focused on designing and building innovative solutions using AI, the Oracle Database, Oracle APEX, and Oracle REST Data Services (ORDS). I hope you enjoy my blog.

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:

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:

app TEAM-CALENDAR (
    name: Team Calendar
    version: 24.2.1
    authentication {
        publicUser: APEX_PUBLIC_USER
        authenticationScheme: @APEX$8947201266001685638
    }
    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:

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.

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.

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 @APEX\(... 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 @APEX\)... value.

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

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:

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 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.