Skip to main content

Documentation index: llms.txt. This page is also available as markdown: append .md to this URL or send Accept: text/markdown.

Build a Coalesce App

A Coalesce App is a folder under apps/ in your workspace that holds a Node.js web server. Coalesce starts the server when someone opens the app, and shows the server's pages in a builder tab. You can write an app by hand or ask your AI agent to write one.

How Coalesce Runs Your App​

  1. Coalesce lists every folder in apps/ that has a valid package.json. Folders whose names start with . are skipped.
  2. The first time someone opens the app, Coalesce runs its start script from inside the app's folder, with the same Node.js runtime that runs Coalesce: the one bundled with Coalesce Desktop, or the one that runs coa serve.
  3. Coalesce waits for the server to answer HTTP requests on PORT, then loads the app in a builder tab at http://<app-id>.localhost:<coalesce-port>/, on the same port Coalesce itself uses. Coalesce forwards those requests to your server.
  4. The server keeps running until Coalesce Desktop or coa serve stops.

Folder Layout​

apps/
└── order-explorer/
├── package.json
├── server.js
└── public/
└── index.html

The folder name is the app's ID. Use lowercase letters, digits, and hyphens. Coalesce uses the ID in the app's address, so other characters are replaced with hyphens, and two folders whose names differ only in case or punctuation can't both run.

package.json​

Coalesce reads these fields. Only scripts.start is required.

FieldRequiredWhat Coalesce does with it
scripts.startYesRuns it to start the app. See Start Script Rules.
nameNoShows it in the Apps menu. Defaults to the folder name.
version, repositoryNoSet by the App Marketplace when it installs an app, so Coalesce can recognize the installed version. You don't need them for your own app.
{
"name": "Order Explorer",
"scripts": {
"start": "node server.js"
}
}

Start Script Rules​

Coalesce runs the start script directly, without npm or a shell.

  • The script must be node <file>, optionally followed by arguments.
  • Shell syntax isn't allowed, including quotes, &&, pipes, redirects, $VARIABLES, and wildcards.
  • Use forward slashes in paths, such as node dist/server.js.
  • Coalesce doesn't run npm install.

Avoid Dependencies​

Write your app against the modules built into Node.js, such as http, fs, and path, with no npm dependencies.

An app's server runs with your access to your computer, so it matters what code it runs. Without dependencies, everything the app runs is in its own folder, where your team can see it and review changes to it. It also runs anywhere Coalesce runs, with nothing to install.

If You Need a Dependency​

Dependencies are discouraged, but apps can use them. If your app truly needs a dependency, bundle it and your server into a single file with a bundler such as esbuild, and commit that file. Coalesce runs the bundle, so nobody who uses the app installs anything.

  1. Vet the package before you add it. Check that it's the package you meant, not a similar name. Check that it's widely used and maintained. If your AI agent suggests a package, confirm it exists and is the one you expect: attackers register package names that agents tend to invent.

  2. Install it as a development dependency, at an exact version, and commit package-lock.json:

    npm install --save-dev --save-exact yaml esbuild
  3. Add a build script to package.json, and point the start script at the bundle:

    {
    "scripts": {
    "build": "esbuild server.js --bundle --platform=node --outfile=dist/server.js",
    "start": "node dist/server.js"
    }
    }

    Only you run npm run build. Coalesce runs only start.

  4. Keep node_modules out of Git. Add a .gitignore to the app's folder with the line node_modules/.

  5. Build, then commit the source, the lockfile, and dist/server.js together. Rebuild and commit again whenever the source or a dependency changes, so the bundle always matches the source next to it.

Keep the bundle reviewable:

  • Don't minify. esbuild doesn't minify unless you pass --minify. A readable bundle lets reviewers search it and read its diffs.
  • Review dependency upgrades like code. A version bump changes code that runs with your access to your computer.
  • Don't use native add-ons. Packages that compile native code don't run on the Node.js runtime bundled with Coalesce Desktop.
  • Bundle browser libraries too. Serve them from your app's server rather than loading them from a CDN at runtime. Code loaded from a CDN skips your review, and the app breaks when you're offline. Build them with --platform=browser.

Environment​

Your server gets the environment that Coalesce runs in, plus these variables:

VariableValue
PORTThe port your server must listen on. Coalesce picks a free port between 8400 and 8500.
WORKSPACE_DIRThe absolute path of the workspace folder.

Listen on PORT, and answer any HTTP request to /. Coalesce connects to localhost, which resolves to 127.0.0.1 or ::1 depending on the computer, so listen on both loopback addresses. Don't listen on all interfaces: that exposes your app, and your workspace files, to your network. Coalesce treats the app as started when the port answers. If the server exits or doesn't answer within about 15 seconds, the tab shows App <app-id> failed to start. If the server exited early, the tab also shows its error output.

Read and Write Workspace Files​

Use WORKSPACE_DIR to find your workspace's files, such as nodes/ and nodeTypes/. For the files Coalesce reads and their formats, see What Gets Committed.

  • Reading workspace files is always safe.
  • Writing Node files changes your pipeline. Coalesce Desktop picks up the change and updates the graph, the same as when your AI agent edits a file.
  • Store your app's own data in a folder outside the reserved folders, such as model/ at the workspace root. Coalesce leaves folders it doesn't reserve alone, so your app's data is committed with the workspace.

Browser Code​

The app's pages load in a builder tab, on the app's own origin, <app-id>.localhost. Browser code can't call Coalesce's local API or read the Coalesce page. Send workspace requests to your own server with relative URLs, such as fetch("/api/orders"), so requests go to your server whatever port it gets.

Browser code can't read the Coalesce page, its storage, or your Coalesce sign-in. Put anything that needs workspace files or other access in your server. File downloads and browser dialogs (alert, confirm, prompt) don't work in the tab.

Start From a Minimal App​

This app has no dependencies. It lists the Node files in the workspace.

apps/node-list/server.js
const fs = require("fs");
const http = require("http");
const path = require("path");

const port = Number(process.env.PORT);
const nodesDir = path.join(process.env.WORKSPACE_DIR, "nodes");

const handler = (req, res) => {
if (req.url === "/api/nodes") {
const files = fs.existsSync(nodesDir) ? fs.readdirSync(nodesDir) : [];
res.writeHead(200, { "Content-Type": "application/json" });
return res.end(JSON.stringify(files));
}
res.writeHead(200, { "Content-Type": "text/html" });
res.end(`<!doctype html>
<h1>Nodes</h1>
<ul id="nodes"></ul>
<script>
fetch("/api/nodes").then((r) => r.json()).then((files) => {
document.getElementById("nodes").innerHTML = files.map((f) => "<li>" + f + "</li>").join("");
});
</script>`);
};

for (const host of ["127.0.0.1", "::1"]) {
http.createServer(handler).listen(port, host).on("error", (e) => console.error(`Can't listen on ${host}: ${e.message}`));
}
apps/node-list/package.json
{
"name": "Node List",
"scripts": { "start": "node server.js" }
}

Reload Coalesce, select Apps on the builder rail, and choose Node List.

Develop and Debug​

  • Logs: Your server's output goes to the Desktop log file in Coalesce Desktop, or to the coa serve output, on lines that start with [App:<app-id>].
  • Server changes: Coalesce starts your server once. Restart Coalesce Desktop or coa serve to run a changed server.
  • Page changes: If your server reads its HTML and other files from disk on each request, reload the tab to see changes.
  • New apps: Reload Coalesce after you add a folder to apps/.

Share Your App​

Commit the app's folder to your workspace repository. Everyone who opens the repository in Coalesce Desktop or coa serve gets the app. The App Marketplace lists only apps that Coalesce publishes.

What's Next?​