Building a Custom IFS Aurena Page from Zero
A complete walkthrough of building a new page in IFS Cloud — entity model, projection, Aurena client file, navigation entry, and command buttons — from first file to live in Aurena.
Building a custom page in IFS Aurena from scratch can seem daunting at first. But once you understand the architecture—entity models, projections, client files, and the declarative Marble language—you'll find it's a logical, well-structured process. This guide walks you through every step, from setting up your development environment to deploying a fully functional page with navigation and command buttons.
The Architecture at a Glance
Before diving into code, let's map out what we're building:
- Entity Model – The persistent business entity and generated server API; layered PL/SQL adds business behaviour
- Projection – An OData endpoint that exposes your entity as a consumable API
- Client File – Declarative Marble UI definitions (pages, lists, groups, commands)
- Navigator Entry – Navigation menu integration to make your page discoverable
- Deployment – Grant permissions and test the whole pipeline
Each layer builds on the previous one, and each is defined in Developer Studio.
Prerequisites
Before you start, you'll need:
- IFS Developer Studio aligned to the target IFS Cloud release
- A customer solution repository and workspace containing the owning component
- A non-production build and delivery route in IFS Lifecycle Experience
- Permission to create or extend the relevant component models
- Basic Marble and PL/SQL knowledge for the client, projection, and server layers
- A test user and permission set representative of the eventual audience
Developer Studio installation and workspace setup differ between older remote-development arrangements and current IFS Cloud releases. Follow the development guide for the target release and use the build-place configuration supplied for that customer. An IFS-managed Cloud database is not a general-purpose development database and customers should not expect application-owner JDBC access.
If an older environment exposes Tools → Setup Dev Tools, use that release-provided entry to obtain the matching tool bundle. Current Cloud customers should follow the Lifecycle Experience development guide instead of assuming that menu is present.
Step 1: Setting Up Your Development Environment
Create a Project
Open Developer Studio and create or open the release-aligned customer solution project.
For current IFS Cloud development, use the customer solution repository, workspace, and target release supplied through the customer's Lifecycle Experience/Build Place setup. Open the registered customer component that will own the feature; do not invent a local component or application-owner database connection.
In Apps 10 and older remote-development arrangements, the equivalent setup may use an R&D project and build home:
- Click File → New Project (or right-click in the Projects tab)
- Select IFS R&D Core Project
- Select the workspace and component that will own the feature
- Set the Build Home to the release-matched shared component library
- Check Use Build Home Target Version
- Configure only the supported development connection for that environment, if the release and operating model provides one
- Click Finish
In that older workflow, the build home allows the project to reference existing entities and components without importing the entire library. In current Cloud workflows, the customer solution's configured target release serves the equivalent dependency-resolution purpose.
Verify Component Access
Once your project is created, expand the customer-owned component in the Projects panel and locate its model source. Do not place a customer entity in FNDBAS simply because that component is present in every installation.
Step 2: Creating the Projection
What Is a Projection?
A projection is an OData service definition that exposes your entity to the Aurena UI layer. It's the bridge between your database and your pages. Every client model names a projection, but a new page can reuse an existing projection when that service already has the right contract and security boundary.
Before creating the projection, make sure the InventoryMovement entity exists in the owning component's .entity model, with its key, attributes, references, persistence, and any state machine defined there. A projection publishes or enriches that generated entity; it does not define the table model inline.
Create the Projection File
- Right-click the component that owns your customer entity
- Select New → Projection Model
- Name it (e.g.,
InventoryMovement) - Click Finish
A new file InventoryMovement.projection is created in /Client.
Define Entity Sets
Open your projection file and add an entityset. This is the data source that will feed your pages:
Key concepts:
- @DynamicComponentDependency – Conditionally includes decorated source when an optional component is installed; it is not a mechanism for reducing imports or dynamically loading an entity at runtime.
- entityset – Names an OData resource set and links it to a projection datasource.
- MAIN ENTRY POINTS – The primary data sources for your projection.
- ENTITY DETAILS – Advanced entity configurations (added later if needed).
Grant Permissions
After the projection has been built and delivered to a non-production environment, grant it through IFS permission-set administration. Grant only the read, CRUD, action, and function access the role requires, then grant the page through the page-oriented permission workflow used by the target release. Test with a normal user.
Apps 10 and some customer-managed development environments expose Fnd_Projection_Grant_API. If that API is documented and supported for the target release, a release-specific administration script can grant a projection to a dedicated permission set:
Do not substitute an application-owner or all-powerful role such as IFSAPP_FULL for the dedicated permission set. In IFS-managed Cloud, use the supported permission-set workflow rather than treating this older administrative script as the universal route.
Test the Projection
Verify the OData endpoint works:
https://<server>:<port>/main/ifsapplications/projection/v1/InventoryMovement.svc/InventoryMovements?$top=10
With Accept: application/json, a successful OData request returns JSON data from your entityset. Start with the service's $metadata document to confirm the actual entity-set, key, property, navigation, and action names. Use an approved OAuth client rather than basic authentication or a browser session copied into a script.
Step 3: Building the Client File
Create the Client
- Right-click the component that owns the projection
- Select New → Client Model
- Name it to match your projection (e.g.,
InventoryMovement.client) - Click Finish
A new file InventoryMovement.client is created with four main regions:
Define Visual Components (Lists & Groups)
Start with a list that displays your data:
Field selection, ordering, and ranking matter. Put the fields users scan and act on in the list, and move long notes, audit information, and secondary values to a detail group. fieldranking is supported client syntax and helps the framework prioritise fields in constrained list and card presentations. It does not lazy-load unranked fields or reduce the OData payload, so test the result at the supported desktop and mobile widths.
Now create a detail group for a single record view:
Create Pages
Pages tie together your visual components with data:
Common page compositions and related components:
- List-centric page – Shows multiple records in a table (ideal for grids and work queues)
- Detail page – Uses a group for one record's fields (ideal for viewing or editing)
- Card presentation – A compact record preview used by supported list/card views
- Assistant – Step-by-step wizard (multi-page flow)
Add Commands (Buttons)
Commands are interactive buttons whose execute block can call a projection operation, navigate, open a dialog, or run other supported client behaviour. Define the state-changing operation as an entity-bound action in the projection first:
Generate the projection and implement the exact service-method scaffold produced for the target release. The implementation must recheck state, permissions, and concurrency and then use the entity logic or a supported IFS API. The client calls that action positionally:
Command types:
- call – Invoke a projection action or function with positional arguments
- navigate – Go to another page with its declared context parameters
- dialog/assistant – Collect input or guide a multi-step interaction
- inquire/confirm patterns – Ask for confirmation before the command continues
Enablement rules: Control when buttons appear using conditional logic:
State-based enablement is useful feedback, but the projection action must independently enforce permissions, current state, and concurrency because API callers can bypass the page.
Wire Commands to Pages
Add commands to your pages:
Step 4: Adding Navigator Entries
Navigator entries make your pages discoverable in the Aurena sidebar menu.
The detail page is normally reached from ViewDetails, which supplies the selected key. Publishing an unfiltered single-record page as a separate navigator entry is rarely useful.
Key concepts:
- toplevel – Creates a top-level folder in the navigator (visible at the root level)
- at index – Controls menu ordering (lower numbers appear first)
- label – The text shown in the menu
- entry (sub-entries) – Nested items under a parent
- page – Links the entry to an actual page
You can also create entries under existing IFS modules without using toplevel:
Step 5: Advanced Features
Understanding Marble Syntax in Depth
Marble is the declarative language at the heart of Aurena development. Unlike traditional programming languages, Marble focuses on declaring what your UI should be, not how to build it. Understanding its syntax deeply will help you avoid common mistakes.
Declarations vs. Overrides
When you define a list for the first time, you're creating it:
Later, in a higher layer, override only the delta you need:
Overrides are powerful—they let you extend components without redefining them from scratch.
Using Annotations Effectively
Annotations modify model composition, while most field behaviour is expressed with properties. Do not translate UI concepts into invented annotations. Common field properties include:
editable = [expression]– Controls editability in the clientvisible = [expression]– Controls whether the field is shownrequired = [expression]– Controls required input in the clientlabel = "..."– Overrides the labelmultiline = true– Renders an appropriate multiline text input
Example:
Expression Language in Marble
Marble supports condition expressions for enablement, visibility, and default values:
Common operators:
=– Equality!=– Inequality>,<,>=,<=– Comparisonsand,or– Logical operatorsnot– Negation, for examplenot (ObjState = "Approved")null– Null checks; compare text with""when an empty-string test is appropriate
Dialogs for Input and Confirmation
The dialog content must be a supported visual such as a group, and its buttons reference commands. To collect an approval note, replace the parameterless projection action above with one additional text parameter after the implicit entity key:
The client can then pass the note from the dialog:
For a create flow, use the release's supported CRUD action or assistant pattern so new-record state, save, validation, cancellation, and refresh are handled correctly.
Selectors and Filters
Use selectors to present and change the current entity context. A selector can contain static display fields and be bound to a page; it is not automatically a multi-select filter:
Groups vs. Lists: When to Use Each
It's easy to confuse groups and lists in Aurena. Here's when to use each:
Lists are for displaying and editing multiple records:
Groups are for displaying and editing a single record at a time:
For related data, put the group and child list on the page and bind them to the same selector or navigation property. Do not declare an anonymous group inside a list:
Responsive Design in Aurena
IFS Cloud Web adapts to different screen sizes, but a wide desktop grid can still be poor on a phone. Put the most important fields first and keep the list focused:
fieldranking gives the framework an explicit priority order for constrained presentations, but the exact number and arrangement of visible fields still depends on the release, view mode, and available width. Test the actual page on the devices the customer supports, and use a purpose-built mobile client model when the process needs a different interaction rather than merely fewer columns.
Integrating with IFS Backend Operations
One of IFS Cloud Web's strengths is that commands can call projection actions and functions without custom JavaScript. Declare the operation in the projection, generate its server extension point, and call it from the client.
Define a command that calls a function:
Your backend can accept parameters and return values:
For a bound operation, the selected entity key is implicit; other parameters are passed positionally as declared. Use an action for state changes and a function only for a side-effect-free result. The backend operation can:
- Perform calculations
- Update related records
- Validate business rules
- Generate attachments or reports
- Trigger workflows
All without writing custom JavaScript or HTTP handlers.
Charts and Visualizations
Client models support specific chart definitions—bar, line, pie, stacked, funnel, radar, and others depending on release. Create the chart with Developer Studio's model wizard, bind it to a projection datasource, and select dimensions and measures from that datasource. The grammar is not a generic chartType/xAxis/yAxis object, so copy a release-matched generated chart skeleton rather than translating a JavaScript chart configuration.
Conditional Formatting
Show/hide or enable/disable fields based on conditions:
Step 6: Performance Optimization
Minimizing OData Calls
Fields in one list normally contribute to the selected shape of the list's OData request; they do not each trigger a separate request. Too many expensive calculated properties or expansions can still make the request slow. Follow these best practices:
- Only show necessary fields – Don't include every attribute in your entity
- Put secondary data on a detail view – Do not assume a hidden column is fetched lazily
- Treat child lists deliberately – Related datasources can require additional OData requests
- Measure the real request – Check payload size, expansions, filters, paging, and server duration
The focused list reduces the selected data shape; fieldranking affects presentation priority, not what the service fetches.
Query Optimization
Use the projection contract and client query shape to optimize deliberately. A stable server-side subset can use an entityset predicate:
Confirm the generated state column and stored value before using that predicate. Field selection, ordering, filters, and paging are normally applied by the client as supported OData query options. There is no generic select ...; orderby ...; block in an entityset declaration.
Step 7: Deployment and Testing
Deliver the Client and Projection
Validate and generate the complete affected component, commit the source to the customer solution, create a build in IFS Lifecycle Experience/Build Place, and deliver that immutable build to a non-production environment. Older remote-development setups may offer direct development deployment commands, but they are not a universal or production delivery route.
For Apps 10 and older remote-development workspaces configured against a designated development database, Developer Studio's Deploy action can still be a valid rapid development loop. Use it only where the target release and operating model support it; promote controlled releases through the customer's normal delivery process.
Test Your Page in Aurena
Open Aurena (IFS Cloud Web) and navigate to your page:
https://<server>:<port>/main/ifsapplications/web/page/InventoryMovement/InventoryOverview
You should see:
- Your list populated with data from the projection
- Your commands in the page or list action area
- Your navigator entry in the sidebar
- Full CRUD functionality (Create, Read, Update, Delete) if enabled and granted
Debug Issues
Use the diagnostics available in the target release:
- Inspect the projection and operation contract in IFS API Explorer and
$metadata. - Use the browser's network tools to inspect the failing request and response correlation details.
- Check supported IFS application and build/delivery logs for the environment.
- Reproduce with the affected user's permission sets and business-data scope.
Some Apps 10 and early Cloud clients also expose an Aurena debug console with page information. If it exists in the target release, it can confirm the client and projection names, but browser network evidence and server correlation details remain more useful for request failures.
Common issues:
- "Projection not found" – Check projection name spelling and ensure it's deployed
- "OData query failed" – Verify projection/action grants, request syntax, and business-data access
- "Fields not showing" – Confirm fields exist in your entity and are listed in the client file
- "Commands disabled" – Review your enabled conditions and entity state values
Troubleshooting Common Issues
Issue: "Projection Not Found" Error
Cause: The projection name in the client does not match the deployed service, the build was not delivered, or the user cannot access it.
Solution:
- Verify the projection name is spelled correctly (case-sensitive)
- Ensure the projection is deployed
- Check that the projection exists in your build home or local project
- Grant permissions to the projection
Issue: "OData Query Failed" Error
Cause: Common causes include missing projection grants, invalid query syntax, a contract mismatch, or missing business-data access.
Solution:
- Confirm the service and entity set in API Explorer and
$metadata. - Grant the required projection operations through a test permission set.
- Confirm the user also has the relevant company, site, or other business-data access.
- Inspect the OData response body and correlation details; a validation failure is different from a forbidden response.
For IFS-managed Cloud, do not diagnose this by selecting an assumed table or granting an application-owner role. The generated database name may not be what the model name suggests, and database access is not the projection security model.
Issue: Fields Not Showing in List
Cause: Field names do not match projection properties, the property is not published, or client visibility rules hide it.
Solution:
- Verify field names against the actual entity
- Check the field's
visible,editable, and projection properties - Review enabled/visible conditions
- Confirm the property appears in the deployed projection
$metadata
Issue: Commands Always Disabled
Cause: Incorrect enablement condition or object state mismatch.
Solution:
- Remove the enabled condition to test
- Verify the state field and its possible values
- Inspect the returned record in the browser network response or API Explorer
Once you know the values returned by the projection, restore a condition that uses those exact values:
Complete Example: Inventory Movement Page
Here's a coherent client-file baseline to tie it together. Replace the component and navigator parent with real model references, and validate it against the target release before adding it to a delivery:
The navigator parent above is illustrative: use the actual qualified navigator model from the installed component. Standard create/update controls come from supported CRUD configuration, and approval still requires a projection action plus a server implementation and permission grant.
Key Takeaways
-
Projections are essential – Every data-backed client page consumes a projection contract, whether purpose-built or safely reused.
-
Client files are declarative – You describe the UI, not code it. Aurena handles responsivity, accessibility, and interactions.
-
Commands guide workflows – State-based enablement improves the page, while the server action enforces the real rule.
-
Navigator entries make pages discoverable – Users won't find your page unless it's in the menu. Navigator structure matters.
-
Focused and ranked lists improve mobile UX – Keep secondary and audit information in a detail view, use
fieldrankingdeliberately, and test real breakpoints. -
Dynamic dependencies are conditional – Use
@DynamicComponentDependencyonly for genuinely optional installed components. -
Test early and often – Use
$metadataand API Explorer to verify the service, the page to verify the UI, and supported logs/network diagnostics to troubleshoot. -
Permissions are non-negotiable – Grant the minimum projection, action, page, and business-data access through permission sets.
Next Steps
From here, you can:
- Add more entities – Create projections and clients for related data
- Build assistants – Multi-step wizards for complex processes
- Add charts and dashboards – Visualize KPIs with built-in components
- Integrate with other pages – Navigate between custom and standard IFS pages
- Use supported presentation options – Keep custom client source within the IFS design system rather than injecting global CSS
- Deploy to production – Use layered development to push changes safely
Building custom Aurena pages is as much art as science. The Marble language keeps things clean and maintainable, but understanding your entity model and how data flows through projections to the UI is what separates good pages from great ones.
Deployment Checklist
Before going live, verify:
- Projection created and deployed
- Projection permissions granted
- OData endpoint tested (returns data)
- Client file created and deployed
- All field names match entity attributes
- Navigator entries created and tested
- Commands wired to functions/actions
- Enablement conditions tested
- Page accessible via direct URL
- Page visible in navigator
- Mobile responsive (check on tablet/phone)
- Performance target agreed and met with representative data and network conditions
- Error handling in place (what if no data exists?)
- Tested with different user roles/permissions
- Documentation updated for end-users
Real-World Best Practices
- Use consistent naming conventions –
InventoryMovementfor entity, projection, and client files - Document your projections – Add clear descriptions in the projection file
- Version control everything – Use the customer solution repository; IFS Cloud source development is code
- Test incrementally – Don't build the entire page before testing
- Keep projections focused – Don't expose unnecessary data via OData
- Use dynamic dependencies precisely – Only where an installed component is genuinely optional
- Monitor performance – Use browser dev tools to check network requests
- Follow IFS naming standards – Adhere to your organization's conventions
- Reuse components – Build visual components once, use them many times
- Document state transitions – Make it clear to users what states and transitions are allowed
Learning Resources
- IFS Developer Studio client source reference
- IFS Developer Studio projection source reference
- IFS Cloud 26R1 technical documentation
- IFS Community Forums – Real-world questions and answers; verify examples against the target release
- Developer Studio Help and installed client models – Release-matched syntax and working patterns
Conclusion
Building custom Aurena pages is a blend of declarative thinking, database design, and UX sensibility. You don't need to be a JavaScript expert—Aurena handles interactivity for you. Instead, focus on:
- Clean entity models
- Well-designed projections
- Thoughtful field selection
- Intuitive navigation
- Smart command enablement
Start small. Build a list page. Add a detail page. Introduce commands. Test at each step. Before long, you'll have built a sophisticated, responsive, production-grade page that IFS users love.
Happy building! 🚀
Building custom Aurena pages and want a second pair of eyes?
Syrett Consultancy helps teams design Aurena pages, commands, and navigation flows that work cleanly in real implementations.