Teaching AI coding assistants Oracle APEX
The problem of working with niche technologies
#If you ask AI to create a website, it will do an excellent job and most likely utilize React and Tailwind CSS. These technologies are open source, widely used (many GitHub projects), and well documented. So the AI is heavily trained on them and can work with them fluently.
Oracle is different. Closed source, niche, and not much public code on the internet. It’s still great to see how well Claude performs in creating PL/SQL packages, but we probably all have seen AI hallucinating some kind of APEX API package that doesn’t exist. So instead we have to teach the AI about APEX concepts and APIs.
Teaching AI about APEX through context
#This issue might sound familiar. We can solve it by just giving the AI context about our technology stack. If we give AI the right context, it can use that information instead of making things up.
But the issue is that context is a balancing act. Not enough context and the AI will hallucinate; too much context and the AI will be expensive, slow, and – most importantly – perform worse.
The answer is to give just enough context needed to solve the current issue. Instead of always teaching all APEX APIs, icons, views, etc., we only give Template Component context when the task is Template Component related. This is essentially a search problem; we need to find and surface only the relevant information. This concept is called Retrieval Augmented Generation (RAG).
For our coding agents, there is an emerging spec that makes it easy to give ad hoc context called SKILL.md.
So we could create a SKILL.md file for APEX Template Components and in that teach how they work and how the AI can assist us in creating one for us. When we ask about Template Components the LLM will see that there is a matching SKILL.md file available (ignoring any irrelevant ones), read it, and use the information to provide accurate and relevant results.
AI, create me a template component
#So as I use Claude Code, I just created a .claude/skills/template-components/SKILL.md file. In it I carefully wrote down all the relevant (basic) information that will help Claude to create helpful ones. Then I let Claude refine this file for clarity and conciseness, since context should be as clear as possible for LLMs to use effectively.
---
name: template-component
description: Create a template component for Oracle APEX applications
---
Generate an Oracle APEX Template Component based on user description. Write files to `src/template-components/<component-name>/`.
## Output Files
Create these files in `src/template-components/<component-name>/`:
| File | Required | Description |
| ----------------------- | -------- | --------------------------------------------------------------------------------------- |
| `partial.html` | Yes | Renders individual row data with `#COLUMN_NAME#` substitutions |
| `report-row.html` | Yes | Wrapper for each partial (default: `<li #APEX$ROW_IDENTIFICATION#>#APEX$PARTIAL#</li>`) |
| `report-body.html` | Yes | Wrapper for all rows (default: `<ul>#APEX$ROWS#</ul>`) |
| `report-container.html` | No | Outer wrapper using `#APEX$REPORT_BODY#` and `#APEX$DOM_ID#` |
| `index.css` | No | Component styles |
| `index.js` | No | Client-side interactivity using APEX APIs |
| `README.md` | Yes | Setup instructions and sample query |
## APEX Template Substitution Syntax
**Column values:** `#COLUMN_NAME#` → replaced by query column value
**Conditionals:**
```html
{case STATUS/}{when ACTIVE/}green{when INACTIVE/}gray{otherwise/}blue{endcase/}
{if IS_VISIBLE/}Show this{else/}Hide this{endif/}
```
**Loops (for JSON arrays):**
```html
{loop "," TAGS/}<span class="tag">&APEX$ITEM.</span>{endloop/}
```
**Built-in placeholders:**
- `#APEX$PARTIAL#` - inserts partial template
- `#APEX$ROWS#` - inserts all report rows
- `#APEX$ROW_IDENTIFICATION#` - row CSS ID/class for selection
- `#APEX$REPORT_BODY#` - inserts report body
- `#APEX$DOM_ID#` - unique component DOM ID
## Required User Input
Ask the user for:
1. **Component name** (kebab-case for directory, e.g., "employee-cards")
2. **Query columns** with types (e.g., `EMP_ID NUMBER, NAME VARCHAR2, SKILLS JSON_ARRAY`)
3. **Visual description** of the component layout
## Defaults
- Use APEX utility classes
- Include ARIA attributes for accessibility
- Use `rem`/`em` units in CSS
- Template components should take up the whole width of their container by default
Making them look like APEX
#The results are excellent, and I would have spent a lot of time to create something like that myself. But they do not look like APEX components. Again, remember that AI is trained on plenty of projects but not much on APEX projects. If you want your app to look cohesive rather than like a patchwork of different styles, you also need to teach your AI about APEX utility classes and CSS variables.
I remembered that I have a project for Alfred (macOS Spotlight search) that lets me look up information quickly. I can hit CMD+Space, type apex css variables primary and get filtered results like --ut-palette-primary or --ut-palette-primary-contrast (More on that project here).
AI should know that as well. So we just create more SKILL.md files with the relevant information. When I asked Claude Code to make the template component look more APEX native, it did an outstanding job by utilizing the utility classes and CSS variables I taught it in the SKILL.md files.
apex-css-vars/SKILL.md
#Display CSS variables SKILL.md
---
name: apex-css-vars
description: Returns Oracle APEX CSS custom properties (variables) for styling components
---
When asked about APEX CSS variables or when styling APEX components, return the relevant CSS variables from the data below.
## Usage
Use these CSS variables with `var(--variable-name)` in your CSS. For example:
```css
.my-component {
background-color: var(--ut-component-background-color);
color: var(--ut-component-text-default-color);
border-radius: var(--ut-component-border-radius);
}
```
## Available CSS Variables
```
cssVars[51]{name,description}:
u-color-1,Color palette #1 (up to 45)
u-color-2,Color palette #2 (up to 45)
u-color-3,Color palette #3 (up to 45)
u-color-1-contrast,Color palette #1 contrast (up to 45)
u-color-2-contrast,Color palette #2 contrast (up to 45)
u-color-3-contrast,Color palette #3 contrast (up to 45)
ut-palette-primary,Primary color in the palette
ut-palette-primary-contrast,Contrast color for primary palette color
ut-palette-primary-shade,Shade of the primary palette color
ut-palette-primary-text,Text color of the primary palette that is readable on the shade
ut-palette-danger,Danger color in the palette
ut-palette-danger-contrast,Contrast color for danger palette color
ut-palette-danger-shade,Shade of the danger palette color
ut-palette-danger-text,Text color of the danger palette that is readable on the shade
ut-palette-warning,Warning color in the palette
ut-palette-warning-contrast,Contrast color for warning palette color
ut-palette-warning-shade,Shade of the warning palette color
ut-palette-warning-text,Text color of the warning palette that is readable on the shade
ut-palette-success,Success color in the palette
ut-palette-success-contrast,Contrast color for success palette color
ut-palette-success-shade,Shade of the success palette color
ut-palette-success-text,Text color of the success palette that is readable on the shade
ut-palette-info,Info color in the palette
ut-palette-info-contrast,Contrast color for info palette color
ut-palette-info-shade,Shade of the info palette color
ut-palette-info-text,Text color of the info palette that is readable on the shade
ut-component-background-color,Component Background Color
ut-component-border-color,Component Border Color
ut-component-border-width,Component Border Width
ut-component-border-radius,Component Border Radius
ut-component-box-shadow,Component Shadow
ut-component-highlight-background-color,Component Highlight Background Color (example: hover state)
ut-component-toolbar-background-color,Component Toolbar Background Color
ut-component-inner-border-width,Component Inner Border Width
ut-component-inner-border-color,Component Inner Border Color
ut-component-text-default-color,Component Default Text Color
ut-component-text-title-color,Component Default Title Color
ut-component-text-subtitle-color,Component Default Subtitle Color
ut-component-text-muted-color,Component Default Muted Color (example: description text)
ut-component-icon-background-color,Component Icon Background Color
ut-component-icon-color,Component Icon Color
ut-component-badge-background-color,Component Badge Background Color
ut-component-badge-text-color,Component Badge Text Color
ut-component-badge-border-radius,Component Badge Border Radius
ut-shadow-sm,Shadow Small
ut-shadow-md,Shadow Medium
ut-shadow-lg,Shadow Large
a-base-font-family,Base Font Family
a-base-font-family-serif,Serif Base Font Family
a-base-font-family-mono,Monospace Base Font Family
ut-hero-region-title-font-family,Hero Region Title Font Family
```
## Categories
### Color Palette
Variables starting with `u-color-` provide numbered colors (1-45) with matching contrast colors.
### Semantic Colors
Variables with `ut-palette-` prefix provide semantic colors:
- **primary** - Main brand/action color
- **danger** - Error/destructive actions
- **warning** - Caution/attention
- **success** - Positive/confirmation
- **info** - Informational
Each semantic color has variants: base, `-contrast`, `-shade`, and `-text`.
### Component Styles
Variables with `ut-component-` prefix control component appearance including backgrounds, borders, text colors, icons, and badges.
### Shadows
`ut-shadow-sm`, `ut-shadow-md`, `ut-shadow-lg` for consistent elevation.
### Typography
`a-base-font-family`, `a-base-font-family-serif`, `a-base-font-family-mono` for font stacks.
apex-utility-classes/SKILL.md
#Display utility classes SKILL.md
---
name: apex-utility-classes
description: Returns Oracle APEX utility CSS classes for styling and layout
---
When asked about APEX utility classes or when styling APEX components, return the relevant CSS classes from the data below.
## Usage
Apply these classes directly to HTML elements. For example:
```html
<div class="padding-md">
<span class="u-text-bold u-success-text">Success!</span>
</div>
## Available Utility Classes
```
items[179]{name,description,category}:
col-xxs-[1-12],CSS class prefix for extra extra small screens (479px and below),Grid Layout / Responsive
col-xs-[1-12],CSS class prefix for extra small screens (480px to 639px),Grid Layout / Responsive
col-sm-[1-12],CSS class prefix for small screens (640px to 767px),Grid Layout / Responsive
col-md-[1-12],CSS class prefix for medium screens (768px to 991px),Grid Layout / Responsive
col-lg-[1-12],CSS class prefix for large screens (992px to 1199px),Grid Layout / Responsive
col-xl-[1-12],CSS class prefix for extra large screens (1200px to 1399px),Grid Layout / Responsive
col-xxl-[1-12],CSS class prefix for extra extra large screens (1400px and above),Grid Layout / Responsive
u-color-1,Applies Color palette #1 as a block color (up to 45),Color and Status Modifiers
u-color-1-text,Applies Color palette #1 to text (up to 45),Color and Status Modifiers
u-color-1-bg,Applies Color palette #1 as a background color (up to 45),Color and Status Modifiers
u-color-1-border,Applies Color palette #1 as a border color (up to 45),Color and Status Modifiers
u-color-2,Applies Color palette #2 as a block color (up to 45),Color and Status Modifiers
u-color-2-text,Applies Color palette #2 to text (up to 45),Color and Status Modifiers
u-color-2-bg,Applies Color palette #2 as a background color (up to 45),Color and Status Modifiers
u-color-2-border,Applies Color palette #2 as a border color (up to 45),Color and Status Modifiers
u-color-3,Applies Color palette #3 as a block color (up to 45),Color and Status Modifiers
u-color-3-text,Applies Color palette #3 to text (up to 45),Color and Status Modifiers
u-color-3-bg,Applies Color palette #3 as a background color (up to 45),Color and Status Modifiers
u-color-3-border,Applies Color palette #3 as a border color (up to 45),Color and Status Modifiers
u-normal,Applies normal state color as a block color,Color and Status Modifiers
u-normal-text,Applies normal state color to text,Color and Status Modifiers
u-normal-bg,Applies normal state color as a background color,Color and Status Modifiers
u-normal-border,Applies normal state color as a border color,Color and Status Modifiers
u-hot,Applies hot state color as a block color,Color and Status Modifiers
u-hot-text,Applies hot state color to text,Color and Status Modifiers
u-hot-bg,Applies hot state color as a background color,Color and Status Modifiers
u-hot-border,Applies hot state color as a border color,Color and Status Modifiers
u-warning,Applies warning state color as a block color,Color and Status Modifiers
u-warning-text,Applies warning state color to text,Color and Status Modifiers
u-warning-bg,Applies warning state color as a background color,Color and Status Modifiers
u-warning-border,Applies warning state color as a border color,Color and Status Modifiers
u-danger,Applies danger state color as a block color,Color and Status Modifiers
u-danger-text,Applies danger state color to text,Color and Status Modifiers
u-danger-bg,Applies danger state color as a background color,Color and Status Modifiers
u-danger-border,Applies danger state color as a border color,Color and Status Modifiers
u-info,Applies info state color as a block color,Color and Status Modifiers
u-info-text,Applies info state color to text,Color and Status Modifiers
u-info-bg,Applies info state color as a background color,Color and Status Modifiers
u-info-border,Applies info state color as a border color,Color and Status Modifiers
u-success,Applies success state color as a block color,Color and Status Modifiers
u-success-text,Applies success state color to text,Color and Status Modifiers
u-success-bg,Applies success state color as a background color,Color and Status Modifiers
u-success-border,Applies success state color as a border color,Color and Status Modifiers
u-opacity-10,Applies 10% opacity to an element,Color and Status Modifiers
u-opacity-20,Applies 20% opacity to an element,Color and Status Modifiers
u-opacity-30,Applies 30% opacity to an element,Color and Status Modifiers
u-opacity-40,Applies 40% opacity to an element,Color and Status Modifiers
u-opacity-50,Applies 50% opacity to an element,Color and Status Modifiers
u-opacity-60,Applies 60% opacity to an element,Color and Status Modifiers
u-opacity-70,Applies 70% opacity to an element,Color and Status Modifiers
u-opacity-80,Applies 80% opacity to an element,Color and Status Modifiers
u-opacity-90,Applies 90% opacity to an element,Color and Status Modifiers
u-opacity-100,Applies 100% opacity to an element,Color and Status Modifiers
u-shadow-none,Clears any shadow applied to an element,Color and Status Modifiers
u-shadow-sm,Small shadow applied to an element,Color and Status Modifiers
u-shadow-md,Medium shadow applied to an element,Color and Status Modifiers
u-shadow-lg,Large shadow applied to an element,Color and Status Modifiers
margin-none,No margin,Layout Modifiers
margin-sm,8 px margin | Specify direction like this: margin-left-sm,Layout Modifiers
margin-md,16 px margin | Specify direction like this: margin-left-md,Layout Modifiers
margin-lg,32 px margin | Specify direction like this: margin-left-lg,Layout Modifiers
margin-auto,Aligns content into the center,Layout Modifiers
padding-none,No padding,Layout Modifiers
padding-sm,8 px padding | Specify direction like this: padding-left-sm,Layout Modifiers
padding-md,16 px padding | Specify direction like this: padding-left-md,Layout Modifiers
padding-lg,32 px padding | Specify direction like this: padding-left-lg,Layout Modifiers
w[10-800],Width to specified value in pixels. Sizes in 10px increments,Layout Modifiers
w[5-100]p,Width to specified percentage. Percentages in 5% increments,Layout Modifiers
mnw[10-800],Min-width to specified value in pixels. Sizes in 10px increments,Layout Modifiers
mxw[10-800],Max-width to specified value in pixels. Sizes in 10px increments,Layout Modifiers
h[10-800],Height to specified value in pixels. Sizes in 10px increments,Layout Modifiers
mxh[10-800],Max-height to specified value in pixels. Sizes in 10px increments,Layout Modifiers
u-textStart,Align text to the start of the container,Content Modifiers
u-textCenter,Align text to the center of the container,Content Modifiers
u-textEnd,Align text to the end of the container,Content Modifiers
u-textUpper,Sets the text to use all uppercase,Content Modifiers
u-textLower,Sets the text to use all lowercase,Content Modifiers
u-textInitCap,Sets the first letter in each word to use uppercase,Content Modifiers
u-italics,Italicize text,Content Modifiers
u-underline,Underline text,Content Modifiers
u-hidden,Hide text,Content Modifiers
u-visible,Show text,Content Modifiers
u-nowrap,Text stays on one line and does not wrap,Content Modifiers
u-lineclamp-1,Limit text to 1 line, adding ellipsis if it exceeds,Content Modifiers
u-lineclamp-2,Limit text to 2 lines, adding ellipsis if it exceeds,Content Modifiers
u-lineclamp-3,Limit text to 3 lines, adding ellipsis if it exceeds,Content Modifiers
u-lineclamp-4,Limit text to 4 lines, adding ellipsis if it exceeds,Content Modifiers
u-lineclamp-5,Limit text to 5 lines, adding ellipsis if it exceeds,Content Modifiers
u-VisuallyHidden,Make text visually hidden, but still accessible for assistive technologies,Content Modifiers
u-text-heading-2xl,Largest heading size / Alias: u-text-title-1,Content Modifiers
u-text-heading-xl,Extra large heading / Alias: u-text-title-2,Content Modifiers
u-text-heading-lg,Large heading / Alias: u-text-title-3,Content Modifiers
u-text-heading-md,Medium heading / Alias: u-text-title-4,Content Modifiers
u-text-heading-sm,Small heading / Alias: u-text-title-5,Content Modifiers
u-text-heading-xs,Extra small heading / Alias: u-text-title-6,Content Modifiers
u-text-subheading-2xl,Largest subheading / Alias: u-text-subtitle-1,Content Modifiers
u-text-subheading-xl,Extra large subheading / Alias: u-text-subtitle-2,Content Modifiers
u-text-subheading-lg,Large subheading / Alias: u-text-subtitle-3,Content Modifiers
u-text-subheading-md,Medium subheading / Alias: u-text-subtitle-4,Content Modifiers
u-text-subheading-sm,Small subheading / Alias: u-text-subtitle-5,Content Modifiers
u-text-subheading-xs,Extra small subheading / Alias: u-text-subtitle-6,Content Modifiers
u-text-body-xl,Extra large body text,Content Modifiers
u-text-body-lg,Large body text / Alias: u-text-body-1,Content Modifiers
u-text-body-md,Medium body text / Alias: u-text-title-2,Content Modifiers
u-text-body-sm,Small body text / Alias: u-text-title-3,Content Modifiers
u-text-caption-1,Primary caption text / Alias: u-text-subheading-xs,Content Modifiers
u-text-caption-2,Secondary caption text / Alias: u-text-subheading-xs,Content Modifiers
u-text-serif,Serif font family,Content Modifiers
u-text-sansserif,Sans-serif font family / Alias: u-text-sans-serif,Content Modifiers
u-text-mono,Monospace font family / Alias: u-fixedFont,Content Modifiers
u-text-ultralight,Ultra light font weight / Alias: u-text-lighter,Content Modifiers
u-text-normal,Normal font weight,Content Modifiers
u-text-semibold,Semi-bold font weight / Alias: u-text-semi-bold,Content Modifiers
u-text-bold,Bold font weight / Alias: u-bold,Content Modifiers
u-text-heavy,Heavy font weight / Alias: u-text-bolder,Content Modifiers
u-hyphenate,Hyphenates long words / Alias: u-hyphen,Content Modifiers
u-truncate,Truncates text to single line, similar to u-lineclamp-1,Content Modifiers
u-text-default-color,Default text color,Content Modifiers
u-text-title-color,Title text color,Content Modifiers
u-text-subtitle-color,Subtitle text color,Content Modifiers
u-text-muted-color,Muted text color,Content Modifiers
```
## Categories
### Grid Layout / Responsive
- **Column classes** (`col-{size}-[1-12]`): 12-column grid for different breakpoints
- **Visibility** (`hidden-{size}-up/down`): Show/hide content at breakpoints
**Breakpoints:**
| Size | Range |
|------|-------|
| xxs | 479px and below |
| xs | 480px - 639px |
| sm | 640px - 767px |
| md | 768px - 991px |
| lg | 992px - 1199px |
| xl | 1200px - 1399px |
| xxl | 1400px and above |
### Color and Status Modifiers
- **Palette colors** (`u-color-[1-45]`): Numbered colors with `-text`, `-bg`, `-border` variants
- **Semantic states**: `u-normal`, `u-hot`, `u-warning`, `u-danger`, `u-info`, `u-success`
- **Opacity** (`u-opacity-[10-100]`): Opacity in 10% increments
- **Shadows** (`u-shadow-{none|sm|md|lg}`): Box shadow utilities
### Layout Modifiers
- **Spacing**: `margin-{none|sm|md|lg}`, `padding-{none|sm|md|lg}`
- **Sizing**: `w[10-800]`, `h[10-800]`, `w[5-100]p` (percentage)
- **Float/Align**: `u-pullLeft`, `u-pullRight`, `u-alignTop`, etc.
### Content Modifiers
- **Text alignment**: `u-textStart`, `u-textCenter`, `u-textEnd`
- **Text transform**: `u-textUpper`, `u-textLower`, `u-textInitCap`
- **Typography**: Headings, subheadings, body sizes, font families, weights
- **Truncation**: `u-lineclamp-[1-5]`, `u-truncate`, `u-nowrap`
- **Visibility**: `u-hidden`, `u-visible`, `u-VisuallyHidden`
Note I removed some layout utility classes (like u-flex or u-justify-content-center) as LLMs probably are better at just writing CSS directly.
Icons and Search
#For CSS vars and utility classes, it makes sense to give LLMs the full picture, as understanding the system is crucial. But for icons, it works differently. You mostly just search for icons that match your needs. You don’t want to browse through a list of 1000 icons and their names to find the one you need; you just search for “user icon” and get the relevant results.
This should also work this way for the coding assistant. So I enhanced the Alfred project to also have a CLI to search through its data. And created an alias in my .zshrc to be able to call it from anywhere.
alias apex-grep="node /Users/phartenfeller/Documents/Code/_uc/alfred-apex-documentation/cli.js"
If I search for mail, I get the following results:
apex-grep --type=icons --query=mail
results[15]{name,search,category,synonyms}:
fa-reply-all,mail,WEB_APPLICATION,""
fa-reply,mail,WEB_APPLICATION,respond back answer
fa-envelope-open,mail,WEB_APPLICATION,""
fa-mail-forward,mail share,WEB_APPLICATION,""
fa-share,mail forward,WEB_APPLICATION,send forward
fa-envelope-o,"email,support,email,letter,mail,notification",WEB_APPLICATION,mail email message contact inbox
fa-envelope,"email,email,letter,support,mail,notification",WEB_APPLICATION,mail email message contact inbox
fa-home,"main,house",WEB_APPLICATION,dashboard start main landing
fa-flag-im,"man,isle",FLAG,""
fa-map-marker-o,"map,pin,location,coordinates,localize,address,travel,where,place",WEB_APPLICATION,""
fa-flag-ky,"cayman,islands",FLAG,""
fa-male,"man,user,person,profile",WEB_APPLICATION,""
fa-map-marker-face-smile,"pin,navigation,location,way finding,directions,emoji,happy",MAPS,""
fa-map-marker-face-smile-o,"pin,navigation,location,way finding,directions,emoji,happy",MAPS,""
fa-materialized-view,"",WEB_APPLICATION,""
Then I created another SKILL.md file for icons where I just teach it how to use icons and how to use my search tool to find the right icons for the right use case.
---
name: apex-icons
description: Search and retrieve Oracle APEX icon names and their corresponding CSS classes
---
When asked about APEX icons or when styling APEX components, return the relevant icon names and their corresponding CSS classes from the data below.
## Usage
Apply these classes directly to HTML elements. For example:
```html
<span class="fa fa-times" aria-hidden="true"></span>
```
## Available Icons
Search for icons using the following cli:
```bash
apex-grep --type=icons --query=<search-term>
```
And voilà, the coding assistant can now also utilize icons in an APEX native way.
Conclusion
#SKILL.md files are a great way to teach AI coding assistants about niche technologies like Oracle APEX. This will be way more important in the future when APEXlang releases, adding a whole file based language for APEX app definitions. The hope is that we can let assistants work on these definitions directly, so they can create and modify APEX apps in a quick but also accurate way.
I keep experimenting with my SKILL.md files. I also want to solve searching through the APEX PL/SQL documentation, where the assistant can also filter for procedures and then visit the documentation page and extract the relevant information. I will probably share my findings in a future blog post, so stay tuned!
If you are interested in running apex-grep on your machine, the code is open source and available on my GitHub: https://github.com/United-Codes/uc-alfred-orclapex
Also, if you are eager to learn more about agentic AI and get a better understanding of how LLMs work in detail, check out the AI workshop I am hosting.