Templates
Use built-in, local, git, and registered Rayfin templates, including the 1.36 universal-app starter and registry behavior.
Templates scaffold the files for a Rayfin project before rayfin init applies Rayfin
identity, service, package, and agent-file setup. Sources can be built in, local folders,
git repositories, or registry entries.
Where templates come from
- Built-in templates ship inside
@microsoft/rayfin-cliand work offline. - Local directories let you test a template on disk.
- Git repositories are cloned on demand from HTTPS, SSH,
git@, orfile://URLs. - Template registries are YAML files that give git sources stable names for
--list-templatesand the picker.
External and local sources are discovered through rayfin-template.yml. Built-ins use the
metadata packaged with the CLI.
Built-in templates
Run the installed CLI to see the exact names available in your version:
npx rayfin init --list-templatesIn Rayfin 1.36.2 the visible built-ins are:
| CLI name | Display name | Notes |
|---|---|---|
blankapp | ✨ Use default template | Same CLI name as 1.35, but in 1.36 it scaffolds the Universal App instead of the bare-bones Blank App. The canonical universal-app name is hidden from --list-templates but still accepted for automation. Changed in 1.36 |
dataapp | Data App | Fabric analytics app starter. |
gettingstartedauth | A Todo App with Auth and Getting Started Docs | Todo starter with Fabric auth and getting-started docs. |
todoapp | Basic Todo App | Todo CRUD starter with a Rayfin data model and per-user row-level security. |
blankapp remains the visible built-in template name. In 1.36, it now scaffolds the Universal App instead of the bare-bones Blank App from 1.35; use universal-app only when automation needs the hidden canonical template name. Changed in 1.36
Every bundled template's dev script is rayfin dev; dev:frontend starts the frontend
without recursively invoking the CLI.
Scaffold from a built-in template
npm create @microsoft/rayfin@latest my-app -- --template todoappTo select the hidden universal starter explicitly:
npm create @microsoft/rayfin@latest my-app -- --template universal-appList templates
--list-templates prints JSON with schemaVersion, bundled, registry, and optional
warnings fields. It lists built-ins and registry entries only; arbitrary git URLs passed
to -t are not listed.
Scaffold from a local directory
npx rayfin init my-app -t .\my-templateA bare -t value is resolved as a built-in or registry name. Use .\, ..\, or an
absolute Windows path for a local directory.
Scaffold from a git repository
npx rayfin init my-app -t https://github.com/example-org/rayfin-template.git#v1.2.0Supported forms are HTTPS, SSH, git@host:org/repo.git, and file://. Pin with
#<ref>; use a branch, tag, or full 40-character commit SHA. The CLI shallow-clones the
source, scaffolds from it, then removes the clone.
Private repositories use ambient git credentials. Configure Git Credential Manager, SSH,
or gh auth setup-git; Rayfin does not store git credentials.
Multi-template sources
A rayfin-template.yml can contain multiple entries. Interactive runs show a picker;
non-interactive runs need --template-name:
npx rayfin init my-app -t https://github.com/example-org/templates.git --template-name admin-app --yes--template-name selects a leaf entry by name or path from the source named by
-t/--template.
Add a template registry
Registries are YAML files that add named git sources to --list-templates and the
interactive picker.
| Tier | Path |
|---|---|
| User-global | ~\.rayfin\template-registries.yml |
| Project-local | .rayfin\template-registries.yml |
| Bundled | @microsoft/rayfin-cli assets/template-registries.yml |
The bundled 1.36.2 registry contains a protected first-class dataapp entry pointing at
https://github.com/microsoft/fabric-apps-analytic-templates with ref: v1 and
templateName: Data App.
Registry entries load in tier order: bundled, user-global, project-local. The first
occurrence of a name wins. Protected bundled entries cannot be overridden; conflicts are
reported in warnings.
Registry file format
registries:
- name: team-templates
displayName: Team Templates
description: Our team's reusable starters
url: https://github.com/example-org/rayfin-templates.git
ref: v1.2.0
path: catalogs/official
templateName: admin-app| Field | Required | Description |
|---|---|---|
name | yes | Unique registry identifier. |
url | yes | Git URL. |
displayName | no | Label shown in pickers and listings. |
description | no | Short description. |
ref | no | Git tag, branch, or full commit SHA. CLI-shipped registries must use a release tag or full SHA, not a moving branch. |
path | no | Subdirectory in the repository that contains rayfin-template.yml. |
templateName | no | Entry name or path to pre-select from a multi-template source. |
default | no | Protected bundled fallback behavior for CLI-shipped entries. |
firstClass | no | CLI-shipped entries route before bundled templates of the same name and can fall back to a bundled template on supported clone errors. |
Author a template
A template directory contains rayfin-template.yml and one or more entry paths. Files under
an entry are copied to the target, then Rayfin's scaffold transforms run.
payments-template\
├── rayfin-template.yml
└── template\
├── package.json
└── rayfin\
└── rayfin.ymlapiVersion: v1
metadata:
name: payments
displayName: Payments starter
description: Fabric-authenticated payments dashboard
entries:
- name: payments
path: .\templateManifest reference
| Key | Required | Description |
|---|---|---|
apiVersion | yes | Must be v1. |
metadata.name | yes | Manifest identifier. |
metadata.displayName | no | Display label. |
metadata.description | no | Description shown in source-level pickers. |
metadata.version | no | Informational. |
metadata.tags | no | Informational. |
entries | yes | One or more entries. Entries can be direct leaves or nested groups. |
entries[].name | leaf | Template entry identifier. |
entries[].path | leaf | Directory to copy. |
entries[].description | no | Entry description for local pickers. |
entries[].group | group | Nested entries for larger collections. Local templates and git-backed templates both support grouped entries. |
Nested entries
apiVersion: v1
metadata:
name: company-starters
entries:
- group:
name: dashboards
displayName: Dashboards
entries:
- name: sales-dashboard
path: .\dashboards\sales
- name: finance-dashboard
path: .\dashboards\finance
- name: api-service
path: .\api-serviceSingle-entry vs. multi-entry manifests
A single-entry manifest auto-selects its only entry with no picker:
apiVersion: v1
metadata:
name: payments
entries:
- name: payments
path: .\templateA multi-entry manifest shows an interactive picker. Non-interactive runs must pass
--template-name with an entry name or path:
apiVersion: v1
metadata:
name: company-starters
entries:
- name: dashboard
path: .\dashboard
- name: operations
path: .\operationsGrouped entries are supported for nested navigation in both local and git-backed sources:
apiVersion: v1
metadata:
name: company-starters
entries:
- group:
name: dashboards
displayName: Dashboards
entries:
- name: sales-dashboard
path: .\dashboards\sales
- name: finance-dashboard
path: .\dashboards\finance
- name: api-service
path: .\api-serviceWhat's currently supported
package.jsonnameis rewritten to the generated project slug when the file is valid JSON.README.mdreplaces{{PROJECT_NAME}},{{PROJECT_NAME_KEBAB}}, and{{PROJECT_NAME_PASCAL}}.__projectName__in filenames is replaced with the project name.rayfin-template.yml,.git,node_modules,.DS_Store, andThumbs.dbare skipped.- Symlinks are not followed.
- If the template ships
rayfin.yml, init preserves service details and applies only explicit identity, dialect, and service edits.
Agent-file ownership
After scaffolding, rayfin init installs Rayfin-managed agent files from the installed CLI.
Template authors should design around that ownership model:
- The CLI owns
.agents/skills/rayfin/,.agents/skills/rayfin-functions/,.agents/skills/rayfin-connectors/, and the storage skill when storage is enabled. Do not ship files in.agents/skills/rayfin/or other Rayfin-owned skill directories from a template. - The CLI owns only the
mcpServers.rayfinkey inside.mcp.json. A template may ship a.mcp.jsonwith its own MCP servers, but it must not includemcpServers.rayfin; the initializer adds or updates that key. - A template may ship its own
AGENTS.md. If the file exists after template copy, Rayfin treats it as user/template-owned content.rayfin init ai-files installis a one-time install forAGENTS.mdand never overwrites an existing file, even with--force. - Commit
rayfin/.lockfile.jsonafter scaffolding if you want the team to share the same managed Rayfin skill and MCP baseline.
Authentication for private repositories
The CLI uses the git credentials already configured on the machine. SSH keys, Git Credential Manager, GitHub CLI authentication, and other git credential helpers all work. Rayfin does not read, store, or prompt for repository credentials.
Interactive git credential prompts are disabled during scaffolding. A private repository with missing credentials fails quickly instead of hanging. For GitHub repositories, run this once before scaffolding:
gh auth setup-gitThen scaffold with the same -t syntax used for public repositories.
Conflict handling
Registries load in this order:
- Bundled entries from the CLI package.
- User-global entries from
~\.rayfin\template-registries.yml. - Project-local entries from
.rayfin\template-registries.yml.
The first entry for a name wins. A later registry entry with the same name is skipped and
reported in the warnings array from --list-templates. Protected bundled entries cannot
be overridden by user or project registries.
Rename one of the entries to fix a conflict. Do not rely on tier order to shadow a CLI
entry; an agent reading --list-templates should treat every returned name as the accepted
choice for that installed CLI.
Publish and share it
Keep reusable templates in a git repository and pin consumers to a tag or full commit SHA. Do not ask teams to scaffold from a moving branch.
# Initialize and publish the template repository
git init
git add .
git commit -m "Initial Rayfin template"
git remote add origin https://github.com/example-org/rayfin-templates.git
git push -u origin main
# Tag a release for consumers
git tag v1.0.0
git push origin v1.0.0Consumers can scaffold from the URL directly:
npx rayfin init my-app -t https://github.com/example-org/rayfin-templates.git#v1.0.0For repeated team use, add the repository to a registry file and pin ref to the same tag:
registries:
- name: team-starters
displayName: Team starters
description: Approved Rayfin project templates for this repository
url: https://github.com/example-org/rayfin-templates.git
ref: v1.0.0Then consumers scaffold by name:
npx rayfin init my-app -t team-startersBump the tag and update registry ref whenever you ship a meaningful template change.
Try it locally before publishing
Use a local path so you can test the manifest, copied files, package rename, rayfin.yml
identity edits, and agent-file installation before pushing to git.
npx rayfin init test-output -t .\payments-template --yesInspect the generated project before deleting it:
cd test-output
npx rayfin init ai-files status
npx rayfin --helpGotchas
--list-templateslists built-in and registered templates only. A raw git URL passed to-tis never included in that list.- A bare
-tvalue is a template or registry name, not a file path. Use.\,..\, or an absolute path for local folders. - Non-interactive scaffolding from a multi-entry source needs
--template-name; otherwise the CLI cannot choose an entry. - The CLI shallow-clones one ref. Template tooling that needs other branches or history will not have them during scaffold.
- Private repositories rely on ambient git credentials, and prompts are disabled.
- Do not include a
mcpServers.rayfinkey in a template's.mcp.json; Rayfin owns that key. Template-authoredAGENTS.mdis respected as a one-time install and is not overwritten.
Create a local Rayfin template folder named payments-template with a rayfin-template.yml
manifest and one entry at .\template. Include a minimal package.json and rayfin/rayfin.yml,
then test it with `npx rayfin init test-payments -t .\payments-template --yes`.