Deploying Custom Tags via Extensions
Deploying Custom Tags via Extensions
Lucee extensions (.lex files) can ship custom tags by copying files directly into the Lucee server context. This allows an extension to provide reusable tags — in classic .cfm or component-based .cfc format — that are immediately available to all applications on the server after the extension is installed.
How Extensions Copy Files into the Context
A .lex file is a ZIP archive. Any files placed in a context/ folder inside the extension are automatically copied to the corresponding location under /lucee-server/context/ when the extension is installed.
For example, if your extension contains:
context/
whatever/
MyTag.cfm
AnotherTag.cfc
After installation, those files will be available at:
/lucee-server/context/whatever/MyTag.cfm
/lucee-server/context/whatever/AnotherTag.cfc
A real-world example of this pattern is the YAML extension, which copies a single .cfc file into context/components/org/lucee/cfml/tools/, making it importable as a component.
The /lucee-server Mapping
Lucee provides a built-in mapping /lucee-server that points to the /lucee-server/context/ directory. This means files copied there by an extension are immediately reachable via this virtual path — no additional mapping configuration is needed.
Note: Since Lucee 7 only supports Single Mode,
/lucee-serveris the recommended mapping to use. In earlier versions of Lucee 6 running in Multi Mode,/luceepointed to the web context (WEB-INF/lucee), which was a different location. With Multi Mode removed in Lucee 7, prefer/lucee-serverfor clarity and forward compatibility.
Using cfimport with Extension-Provided Tags
Once an extension copies tag files into a subfolder of the server context, you can import them using cfimport with a custom prefix:
<cfimport prefix="elvis" taglib="/lucee-server/whatever/">
<elvis:myTag />
<elvis:anotherTag />
Or in script syntax:
cfimport( prefix="elvis", taglib="/lucee-server/whatever/" );
Important: Tag files must be placed directly in the target folder — subdirectories within the taglib path are not searched. If your extension puts tags in context/whatever/, the taglib must point to /lucee-server/whatever/ exactly, and all tags must be at that level with no further nesting.
Note: The
importkeyword cannot be used for custom tags — onlycfimportsupports theprefixandtaglibattributes for this purpose.
Supported Tag Formats
Both classic and component-based custom tags are supported:
.cfmfiles: Classic custom tag format, callable viacf_tagnameorcfimport.cfcfiles: Component-based custom tags, also callable viacf_tagnameorcfimport
Deployment Locations and Their Prefixes
Depending on where inside context/ you place your tags, they become available in different ways:
| Extension path | Installed at | How to use |
|---|---|---|
context/library/tag/ |
/lucee-server/context/library/tag/ |
<cftagname> (built-in tag style — can even override Lucee's own tags like <cflog>) |
context/customtags/ |
/lucee-server/context/customtags/ |
<cf_tagname> (custom tag style) |
context/whatever/ |
/lucee-server/context/whatever/ |
<cfimport prefix="myprefix" taglib="/lucee-server/whatever/"> |
Using a dedicated folder (like context/whatever/) and importing it with cfimport is the recommended approach when you want your extension to provide a clearly namespaced tag library.
Example: Extension Structure
my-extension.lex (ZIP)
├── META-INF/
│ └── MANIFEST.MF
└── context/
└── mytags/
├── Button.cfm
├── Form.cfm
└── Input.cfc
After installation, in your CFML code:
<cfimport prefix="ui" taglib="/lucee-server/mytags/">
<ui:Form action="submit.cfm">
<ui:Input name="email" />
<ui:Button label="Submit" />
</ui:Form>
Related Documentation
- Custom Tag Mappings — Defining custom tag paths in Application.cfc and the Lucee Administrator
- tag-import —
cfimporttag reference - Extensions — How to build and install Lucee extensions
- Single Mode vs Multi Mode — Understanding the
/lucee-servervs/luceemappings