Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,18 @@ export DATABRICKS_WORKSPACE_DIR=your-workspace-dir # The source workspace direct

## Generating App templates

To generate app templates, run the following command:
The single source template (`template/`) is used to generate app variants for the [`app-templates`](https://github.com/databricks/app-templates) repository. The variants and post-processing steps are defined in `tools/generate-app-templates.ts`.

```bash
pnpm generate:app-templates
```

By default, the command will generate app templates in the `../app-templates` directory, assuming that you have the [`app-templates`](https://github.com/databricks/app-templates) repository cloned in the same parent directory as this one.
By default, this outputs to `../app-templates`, assuming the repo is cloned alongside this one.

You can override the output directory by setting the `APP_TEMPLATES_OUTPUT_DIR` environment variable.

By default, the command will use the `databricks` CLI to generate the app templates. You can override the CLI by setting the `DATABRICKS_CLI` environment variable to provide a different binary name or path.
| Variable | Default | Description |
|----------|---------|-------------|
| `APP_TEMPLATES_OUTPUT_DIR` | `../app-templates` | Output directory |
| `DATABRICKS_CLI` | `databricks` | CLI binary name or path |

## Contributing to AppKit documentation

Expand Down
95 changes: 95 additions & 0 deletions docs/docs/development/templates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
sidebar_position: 6
---

# Templates

AppKit uses a template system powered by the Databricks CLI's `databricks apps init` command. Templates define the project structure, and `.tmpl` files are processed with Go's `text/template` engine to generate customized output.

## How `.tmpl` files work

Any file ending in `.tmpl` is processed by the CLI during `databricks apps init`:

1. The `.tmpl` suffix is stripped (e.g. `.env.tmpl` → `.env`)
2. Go template expressions are evaluated and substituted
3. The rendered file is written to the output directory

Files named with a `_` prefix are renamed to `.` prefix (e.g. `_gitignore` → `.gitignore`).

### Template variables

| Variable | Description |
|----------|-------------|
| `.projectName` | Project name from `--name` or interactive prompt |
| `.workspaceHost` | Databricks workspace URL |
| `.profile` | Databricks CLI profile name (empty if using host-based auth) |
| `.appDescription` | App description |
| `.plugins.<name>` | Non-nil for each selected plugin, enabling conditionals |
| `.dotEnv.content` | Generated `.env` content from plugin resources |
| `.dotEnv.example` | Generated `.env.example` content with placeholders |
| `.bundle.*` | Generated `databricks.yml` sections (variables, resources, target variables) |
| `.appEnv` | Generated `app.yaml` env entries |

### Conditional content

Use Go template conditionals to include/exclude code based on selected plugins:

```go
{{- if .plugins.analytics}}
import { analytics } from '@databricks/appkit';
{{- end}}
```

## `appkit.plugins.json`

The plugin manifest drives the CLI's behavior during `databricks apps init`:

- **Plugin selection UI** — selectable plugins shown in the interactive prompt
- **Resource prompts** — required/optional resources prompt the user for values (e.g. SQL Warehouse ID)
- **`.dotEnv` population** — resource fields with an `env` property are written to `.env`
- **`app.yaml` generation** — resource fields produce `env` + `valueFrom` entries
- **`databricks.yml` generation** — resource fields produce bundle variables and app resource entries

### Resource field properties

Each resource field in the manifest can have these properties:

| Property | Description |
|----------|-------------|
| `env` | Environment variable name written to `.env` and `app.yaml` |
| `description` | Shown in the interactive prompt and bundle variable description |
| `localOnly` | Only written to `.env` for local dev; excluded from `app.yaml` and bundle variables |
| `bundleIgnore` | Excluded from `databricks.yml` variables (but still in `.env`) |
| `value` | Default value used when no user input is provided |
| `resolve` | Auto-populated by CLI from API calls instead of prompting (see below) |
| `examples` | Example values shown in field descriptions |

### Resolvers

Fields with a `resolve` property are auto-populated by the CLI from API calls rather than user prompts. The format is `<type>:<field>`.

Currently only the `postgres` resource type has a resolver. Given the user-provided `branch` and `database` resource names, it derives:

| Resolve key | Description |
|-------------|-------------|
| `postgres:host` | Postgres host from the branch's read-write endpoint |
| `postgres:databaseName` | Postgres database name from the database resource |
| `postgres:endpointPath` | Lakebase endpoint resource name from the branch's endpoints |

Example field definition:

```json
{
"host": {
"env": "PGHOST",
"localOnly": true,
"resolve": "postgres:host",
"description": "Postgres host for local development."
}
}
```

## See also

- [Plugin management](../plugins/plugin-management.md) — `appkit plugin sync`, `appkit plugin create`
- [Configuration](../configuration.mdx) — environment variables
13 changes: 11 additions & 2 deletions tools/generate-app-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,19 @@ console.log(
function postProcess(appDir: string, app: AppTemplate): void {
console.log(` Post-processing ${app.name}...`);

// 1. Delete .env — end users get it from `databricks apps init`, but published
// templates should not ship credentials from the generator's environment.
// 1. Delete .env (contains resolved credentials from the generator's CLI profile)
// and write .env.tmpl with a header comment so that `databricks apps init`
// can render it for end users when they scaffold from the published template.
rmSync(join(appDir, ".env"), { force: true });

const envTmplHeader = [
"# This file is a Go template processed by `databricks apps init --template <path>`.",
"# Template variables are substituted and the result is written as .env.",
"",
].join("\n");
const envTmplBody = readFileSync(join(TEMPLATE_PATH, ".env.tmpl"), "utf-8");
writeFileSync(join(appDir, ".env.tmpl"), envTmplHeader + envTmplBody);

// 2. Sync appkit.plugins.json based on server imports (discovers available plugins
// and marks the ones used in the plugins array as required).
const syncStatus = run(
Expand Down
Loading