Generating file ...

Approach 2: Developing in a local directory

If an application reaches a certain complexity, you may prefer to switch to a directory-first approach. This is also how TEI Publisher itself is developed. The advantages:

  • you have a safe copy of your work in a local directory at any point

  • you can immediately commit changes to git or undo them later if needed

  • coding agents (Claude Code, Cursor etc.) work better in a directory context

  • you can use any tools you like, including the editor of your choice

On the downside, this requires some familiarity with the command line. However, modern IDEs (see below) make this much easier.

Command line utilities

We strongly suggest to install a few command line tools if you use a directory-first approach. They allow you to control most Jinks and eXist-db operations and will make your life a lot easier. Also, installing the tools is a must if you want to use the coding agent skills which ship with TEI Publisher:

jinks-cli

A command line interface to Jinks. Allows you to create, update and manage applications from profiles, run actions, download .xar archives and more.

xst

A command line interface to eXist-db. Allows you to install or remove packages, browse collections, upload single files, run queries and more.

First, make sure you have Node.js and npm available on your system. Both command line utilities are distributed as npm packages and require a recent Node.js release. Check your version by running:

node -v

You need Node.js 20.19 or newer (22.11 or newer is also supported). If your version is too old, install a current LTS release from the Node.js website before continuing.

Install the two utilities globally:

npm install -g @teipublisher/jinks-cli @existdb/xst

This provides the jinks and xst commands on your path. jinks-cli talks to the Jinks app running in eXist-db (create or update applications from profiles, run actions, download .xar archives and more). xst is a command line interface to eXist-db itself (install or remove packages, browse collections, upload single files and more).

Confirm that both tools are available:

jinks --version xst --version

Setting up a local directory

To work on your edition in a folder on your own computer, you first need to obtain a copy of the application. Jinks stores everything inside the database, so you have to export it once. The standard exchange format for eXist-db applications is a .xar file — think of it as a single ZIP archive containing all the files that make up your edition. You can create this archive in two ways:

Using the browser

This is the simplest option and does not require any command line tools:

  1. Open Jinks in your web browser and select your application from the list on the left.

  2. Click the Download button in the toolbar at the bottom of the page (next to Apply).

  3. Your browser will save a file named after your application's short name (its abbreviation — for example barth.xar if you chose barth when creating the app). It will usually land in your Downloads folder.

For more background on what a .xar file is, see the section on downloading the application earlier in this guide.

Using the command line

If you have installed jinks-cli (see the section on command line utilities above), you can download the same package without opening the browser. Open a terminal window and run:

jinks run barth download -o ~/Downloads

Replace barth with the abbreviation of your application, and adjust the path after -o if you would like the file saved somewhere else. The command writes a barth.xar file into the folder you specified.

By default, jinks-cli connects to a Jinks instance running on your own machine. If you use a different server or login, see the tool's documentation for connection options.

Once you have the .xar file, unpack it into a folder of your choice. Despite the different file extension, a .xar is a normal ZIP archive — standard tools like unzip can extract it as-is. If your system's archive utility does not recognize the .xar extension (for example when double-clicking does nothing), rename it to .zip first, or extract it from the command line. You now have a local directory containing the complete application, ready to open in an editor or to put under version control with git.

Setting up your development environment

For sure you can use any editor you like, but we do provide a set of extensions for some popular IDEs to make your life easier. This includes all IDEs compatible with Visual Studio Code, i.e. vscode itself, but also Cursor, Antigravity, VSCodium and others. The following extensions are available and can be installed from within the respective IDE:

eXist-db VSCode Extension

Adds XQuery language support and a sync task to Visual Studio Code and other IDEs derived from it

ODDity

An extension for ODD editing. Mimics the visual ODD editor in the TEI Publisher web application, but operates on the file system. Allows you to switch between source XML and a visual representation of the ODD.

Synchronizing changes to the database

If you make your changes in a directory first, you obviously have to synchronize them to the database. The easiest way to do so is to rebuild the .xar every time and install it via the dashboard. However, reinstalling the entire application may take a while and therefore slow you down.

You can also upload single files using eXide, the file browser in jinks, using xst, or via oXygen's eXist-db integration. But again, this is a manual process. Better options are:

Using an IDE with the eXist-db extension

The eXist-db extension for the IDE you are using will provide a sync task. Once activated, it will continuously watch for changes in the monitored directories and synchronize them to the database.

Cursor editor with active sync task in bottom panel
Using jinks watch

If you have installed jinks-cli, you can start a file watcher from the command line instead. Open a terminal in your application's local directory and run:

jinks watch

This keeps running in the background and uploads every file you save to the corresponding collection in eXist-db. It reads the target collection and login details from the application's repo.xml, and respects ignore patterns from .existdb.json when present. Stop it with Ctrl+C when you are done editing.

Updating the application via Jinks

Uploading individual files (as described above) is enough when you edit something you already own — a custom stylesheet, your own HTML page, or a TEI document. Regeneration with Jinks is a different step: it updates the application from its configuration and the profiles it extends. You need to run it when:

  • you change settings in config.json (theme, features, menu entries, ODDs, and similar options)

  • you add or remove a profile on the Profiles tab (or in the extends list in config.json)

  • a new version of TEI Publisher / Jinks is available and the profiles your app uses have changed upstream

In the browser, open your application in Jinks and press Apply. That updates the copy living in the database and does not touch the files on disk — you still need a download or sync afterwards.

From the command line, ask Jinks to regenerate the application and pull the updated files back into your local directory. Name the application by its abbreviation (replace barth with yours):

jinks update barth --sync

This is enough after installing a newer Jinks release, for example, simply to pick up upstream changes in the profiles your app extends — even if you did not touch config.json.

If you have edited config.json in your local directory, pass it with -c so the server uses your local settings. The abbreviation is then taken from the file, so you do not need to type the short name:

jinks update -c config.json --sync

Run these commands from the root of your application folder (where config.json lives). The options mean:

--sync

After regenerating, copy the updated files from the database back into your local directory. Without --sync, only the database copy changes and your folder can fall out of date. Always pass this option when you work directory-first.

-c config.json

Send your local configuration to the server and use it for regeneration. Without this flag, Jinks regenerates from the configuration already stored in the database and ignores your local edits to config.json.

If Jinks reports a conflict for some files, see the section on applying updates for how to resolve them.