Rayfin

Project structure

Understand the Rayfin scaffold layout, including rayfin.yml, deployment metadata, environment files, and the 1.36 universal app workspace.

Rayfin templates keep backend configuration, deployment state, and frontend code in predictable places. Flat templates and the 1.36 default blankapp template share root commands, but the default now creates the Universal App npm workspace.

Flat template layout

my-app/
├── rayfin/
│   ├── data/
│   │   ├── schema.ts
│   │   └── Todo.ts
│   ├── .env
│   ├── .project.json
│   ├── .deployments.json
│   ├── rayfin.yml
│   └── tsconfig.json
├── src/
├── package.json
├── tsconfig.json
└── README.md

Universal App workspace

Changed in 1.36

The CLI-facing blankapp template now creates the Universal App workspace. The hidden universal-app template name is still accepted, but users normally choose blankapp or the default prompt. The root owns orchestration scripts and rayfin/rayfin.yml; packages own runtime code.

my-app/
├── package.json
├── tsconfig.base.json
├── tsconfig.json
├── rayfin/
│   ├── .env
│   ├── .project.json
│   ├── .deployments.json
│   └── rayfin.yml
└── packages/
    ├── frontend/
    ├── data/
    └── shared/
PackageStable nameOwns
packages/frontend@rayfin-app/frontendReact, Vite, Fabric auth wiring, browser UI, and static output.
packages/data@rayfin-app/dataEntity registration and schema exports.
packages/shared@rayfin-app/sharedTypes shared across browser, data, and Functions code.
packages/functions@rayfin-app/functionsAdded only when the Functions capability pack is applied.

Root scripts coordinate the workspace:

package.json
{
  "workspaces": ["packages/*"],
  "scripts": {
    "dev": "rayfin dev",
    "dev:frontend": "npm run -w @rayfin-app/frontend dev",
    "build:fabric": "npm run -w @rayfin-app/shared build && npm run -w @rayfin-app/data build && npm run -w @rayfin-app/frontend build:fabric",
    "rayfin:up": "rayfin up"
  }
}

rayfin/rayfin.yml

rayfin.yml is the checked-in service declaration that rayfin dev and rayfin up sync to Fabric.

rayfin/rayfin.yml
id: universal-app
name: Universal App
version: 1.0.0
services:
  auth:
    enabled: true
    fabric:
      enabled: true
      externalEntraExchange: true
    allowedRedirectUris:
      - http://localhost:5173
  data:
    enabled: false
    path: packages/data
    buildCommand: npm run build
  staticHosting:
    enabled: true
    path: packages/frontend
    folder: dist
    buildCommand: npm run build:fabric
    indexDocument: index.html
    assetAccess: protected
    embedded:
      only: false

services.staticHosting.assetAccess replaces the older anonymousAccess authoring shape. New in 1.35.1

Service configuration fields

FieldTypeDescription
idstringProject slug and default Fabric item name.
namestringHuman-readable app name.
versionstringProject version.
services.auth.enabledbooleanEnables Rayfin auth services.
services.auth.fabric.enabledbooleanEnables Microsoft Entra ID through Fabric SSO.
services.auth.allowedRedirectUrisstring[]Origins allowed to complete auth callbacks and Fabric SSO handoffs. Keep the local dev origin and deployed hosting origins.
services.data.enabledbooleanEnables the data service. Fabric deployments use dialect: mssql.
services.data.pathstringData package directory for workspace layouts.
services.data.buildCommandstringCommand run from the data service path before packaging.
services.staticHosting.pathstringFrontend package directory for static hosting.
services.staticHosting.folderstringBuilt asset folder, usually dist.
services.staticHosting.assetAccessprotected | publicHosted asset access posture. New in 1.35.1
services.functions.enabledbooleanEnables Rayfin Functions.
services.functions.auth.typeapplicationRequired for enabled Functions. Changed in 1.36

String values in rayfin.yml support ${VAR} and ${VAR:-default} interpolation from rayfin/.env and the shell environment. See Environment variables.

Generated and local files

FilePurposeCommit it
rayfin/.envRAYFIN_PUBLIC_*, local dev port, and interpolation values.No
.env.localFramework-specific values generated from rayfin/.env; in a universal app it lives under packages/frontend.No
rayfin/.project.jsonScaffold lineage identifier used for telemetry correlation.Usually yes
rayfin/.deployments.jsonFabric workspace IDs, item IDs, item names, publishable keys, hosting URLs, and active deployment.No
rayfin/.temp/Generated backend artifacts.No

Data and TypeScript files

Flat templates keep entity classes under rayfin/data/ and register them in rayfin/data/schema.ts. Universal apps keep data code under packages/data, and services.data.path tells the CLI where to build it.

Rayfin decorators require an ES2022 or later target. Templates already configure TypeScript and Vite; do not enable emitDecoratorMetadata, and do not switch to @vitejs/plugin-react-swc.

rayfin/tsconfig.json and root tsconfig.json

The Rayfin CLI compiles decorated entity files as a TypeScript project. Flat templates include rayfin/tsconfig.json and a project reference from the root tsconfig.json:

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable", "ESNext.Decorators"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "skipLibCheck": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx"
  },
  "include": ["src"],
  "references": [{ "path": "./rayfin" }]
}

Do not set emitDecoratorMetadata to true. It requires legacy decorators, which are incompatible with Rayfin's TC39 decorators.

Vite configuration

Templates set an ES2022 target in Vite so decorator syntax is parsed consistently:

vite.config.ts
import { rayfinLocalDev } from '@microsoft/rayfin-local-dev/vite';
import react from '@vitejs/plugin-react-swc';
import { defineConfig, loadEnv } from 'vite';

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), 'VITE_');
  const port = env.VITE_PORT ? Number(env.VITE_PORT) : undefined;

  return {
    plugins: [react(), rayfinLocalDev()],
    ...(port ? { server: { port, strictPort: true } } : {}),
    build: { target: 'es2022' },
    esbuild: { target: 'es2022' },
    optimizeDeps: {
      esbuildOptions: { target: 'es2022' },
    },
  };
});

The rayfinLocalDev() plugin is development-only. It serves local rayfin.config.json, proxies Rayfin backend routes, routes local Functions calls, and supports local automatic sign-in for protected static assets.

Frontend environment generation

rayfin dev, rayfin up, and rayfin env map RAYFIN_PUBLIC_* values from rayfin/.env into the frontend framework's .env.local. For Vite, the generated variables use the VITE_ prefix:

Rayfin valueVite value
RAYFIN_PUBLIC_API_URLVITE_RAYFIN_API_URL
RAYFIN_PUBLIC_PUBLISHABLE_KEYVITE_RAYFIN_PUBLISHABLE_KEY
RAYFIN_PUBLIC_WORKSPACE_IDVITE_FABRIC_WORKSPACE_ID
RAYFIN_PUBLIC_ITEM_IDVITE_FABRIC_ITEM_ID
RAYFIN_PUBLIC_PORTAL_URLVITE_FABRIC_PORTAL_URL
RAYFIN_PUBLIC_FRONTEND_PORTVITE_PORT
RAYFIN_PUBLIC_FUNCTIONS_URLVITE_RAYFIN_FUNCTIONS_URL

In a workspace layout, the file is written under services.staticHosting.path, such as packages/frontend/.env.local.

rayfin/.temp

rayfin/.temp/ contains generated backend artifacts, including compiled entity metadata and Data API Builder configuration. If the backend appears stale, restart rayfin dev or run npx rayfin up so the CLI regenerates and reapplies the artifacts.

PromptExplain my Rayfin project layout
Inspect my Rayfin project's package.json, rayfin/rayfin.yml, rayfin/.env, rayfin/.deployments.json, and any npm workspaces. Tell me whether it is a flat template or the 1.36 universal app layout, identify the data and static-hosting service paths, and explain which files are committed versus generated or gitignored.

Next

Something wrong on this page?Report an issueEdit this page

On this page