Creating Template Packs
Want generated code that matches your team's conventions? Build your own template pack. This guide walks through the author's flow: creating a pack, writing templates, and publishing and sharing it.
Anatomy of a Pack
A template pack is made of the pieces below. The flow is: create → save (draft) → deploy (publish a version) → make public or invite members (share).
| Component | Description |
|---|---|
| Template | The unit that produces one file — a Velocity body plus Installation rules. |
| Group | A tree folder that organizes templates. The generation modal shows the same structure. |
| Language Profile | The pack's declaration of its target language — type mappings and global/entity/field variable definitions. |
| Draft | Your workspace copy. Saving it does not make it visible to anyone else. |
| Version | An immutable snapshot created by deploying. This is what other users and projects consume. |
Creating a Pack
Open the Template Pack page from the left menu.

Click [New]
The [New] button above the pack list on the left opens the creation modal.
Pick a name and language
Choosing Java or TypeScript pre-fills the type mappings and variable definitions with proven presets. For other languages, choose "Custom…" and type the language name (go, python, ...).
Fill in the basics
Refine the name, author, and description in the top card. The language profile details are managed later in the Settings tab.
Already have a pack as a folder or ZIP? Use [Import...] to load it. If a pack with the same name exists, you choose whether to merge into it or add it as a new pack.
Writing Templates
The "Pack Details" tab is your workspace: the group/template tree on the left, and the editor for the selected item on the right.

Group tree
Create items with the [Add root group] · [New template] buttons or the right-click menu, and move them with drag & drop. This tree appears as-is in the generation modal, so organize it for the people who will use it.
Template properties & body
Set the name, type, description, and tags, then write the Velocity body. The editor supports find & replace. Tags become filters in the generation modal.
Installation rules
Define where and how the output lands on disk. The desktop app's "Install selected" follows these rules.

| Option | Meaning |
|---|---|
| Install type | "Write/replace file" creates a new file at the target path; "Inject snippet" inserts a code fragment at a placeholder inside an existing file. |
| Install path · filename | Variables are allowed — combine module path, package, and entity name to build the file location. |
| Overwrite | Replaces an existing file. Turn it off to write to the "alternative path" and preserve the original. |
| Read only | Makes the generated file read-only at the OS level — protects regeneration-managed files from manual edits. |
| Git Add | Runs git add right after the file is created. |
Template Syntax (Velocity)
Template bodies use Apache Velocity syntax. At generation time, table data and user-entered settings are injected as variables. (Velocity User Guide)
| Variable | Contents |
|---|---|
$entity | The current table (entity) — name and its variants (var, snakeLower, kebabLower, ...), the field list (fields), Soft Delete settings, plus the entity-variable values the pack declared |
$field | A field (column) — used when iterating fields. Name, comment, resolved type mapping (mappedType), plus the pack's field-variable values |
$env | Project-wide variables — what users entered in Templates Variables in Project Configuration. Dotted keys become nested access (e.g. $env.package.core) |
$types | Type helper (language-agnostic) — from a field's resolved type: simple name ($types.typeOf), full name for imports ($types.importOf), category checks ($types.isDate, $types.isNumber, ...) |
$codegen | General generation helper — naming conversion (toUpperCamel, toLowerCamel, toUpperUnderscore), DBMS checks (isOracle, isMySQL, ...), PK lookups, and more |
$java · $ts · $py | Optional per-language helpers — convenient, but $types alone is enough for the basics |
Example — a Java entity class
The typical pattern: iterate fields and print each type and name.
package ${env.package.core};
public class ${entity.name} {
#foreach($field in $entity.fields)
private $types.typeOf($field) $field.name;
#end
}The full list of available object properties and tool functions is documented in the Velocity Reference.
Note: The most accurate way to check rendering is the "Generate Source Code..." modal in a project, using real tables. If you have edit rights on the pack, you can even switch the preview to edit mode, fix the template, and save it right there.
Language Profile (Settings tab)
The Settings tab is where a pack declares "I generate this language, and I need these inputs." These declarations drive the consumer-side forms and type defaults.

Type mappings
NeoSQL converts DB column types to intermediate types automatically. As the author you only map each intermediate type to this language's target type, import, and category. Unmapped types fall back to the Fallback settings.
Declaring variables — global / entity / field
Declaring a variable automatically creates an input form on the consumer side. Define the key, label, input type, default, required flag, and options (for selects).
| Kind | Where users enter it | Access in templates |
|---|---|---|
| Global variables | Project Configuration → Templates Variables on the pack tab | $env.<key> |
| Entity variables | Table detail → Code Generator tab → per-pack entity form | $entity.<key> |
| Field variables | Pack-specific columns in the field grid | $field.<key> |
A dot in a key creates a namespace — declare package.core and access it as $env.package.core in templates. "Reset to defaults" restores the language preset at any time.
Saving & Publishing
[Save Pack] writes to your draft (workspace). Drafts apply to your own projects immediately but are invisible to everyone else. To let other people and projects use your pack, publish a version with [Deploy].

Click [Deploy]
The deploy dialog offers "Deploy as new version" or "Overwrite current version".
Deploy as new version
Creates an immutable snapshot with a bumped version number. Projects using the pack see an upgrade notice and upgrade whenever they choose.
Overwrite current version
Replaces the latest version in place. Use it for changes that don't deserve a version bump, like fixing a typo.
Versions tab
Browse published versions, [Restore to draft] to continue working from a past version, or [Republish as latest] to roll back.

Note: In git terms: the draft is your working copy, and deploying is a push. Published versions are immutable, so you can keep editing the draft without ever breaking consumer projects.
Visibility & Members
Share a finished pack by listing it in the Store, or keep it private and invite specific collaborators as members.
Public / Private
[Make Public] lists the pack in the Store where anyone can Add, Clone, or Favorite it. [Make Private] reverts it to a private pack accessible to members only.
Inviting members
In the Members tab, enter emails (comma-separated), pick a role, and send invites. Pending invites can be cancelled before they are accepted.

| Role | What it allows |
|---|---|
ROLE_OWNER | Everything — manage members and roles, switch visibility, delete the pack |
ROLE_MAINTAINER | Edit templates, deploy, invite CONTRIBUTOR/VIEWER members |
ROLE_CONTRIBUTOR | Edit templates (draft work) |
ROLE_VIEWER | View and use |
Note: Members can remove themselves with "Leave template pack" (the pack itself remains). The owner's "Delete pack" removes every version, member, and workspace — it cannot be undone.
Export · Import
Packs can be exported to and imported from a folder or a ZIP file. Both formats share the same structure.
| Format | Use case |
|---|---|
| To folder (for external editing) | Edit template files directly in an IDE or external editor, then bring them back with [Import...]. |
| To ZIP file | Back up the pack or hand it over as a file without going through the Store. |
