All skills
catalystbyzoho avatar

/catalyst-slate

@e6e3f9b

Catalyst Slate — Git-based frontend hosting for React, Next.js, Vue, Angular, Svelte, Astro, SolidJS, Preact and other frameworks with preview deploys. Trigger on 'Slate', 'frontend hosting', 'slate-config.toml', 'deploy React app', or 'cross-domain Slate to function'. Do NOT use for backend APIs or server-side logic — use catalyst-appsail or catalyst-functions instead.

Use this Skill: https://skilld.dev/gh/catalystbyzoho/agent-skills/catalyst-slate

This session only. Nothing lands on disk.

referencesslate-basics.md

≈3.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Slate is the preferred frontend deployment for all new Catalyst projects. It supersedes legacy Web Client Hosting with modern Git-based workflows and native framework support.

Key Features

  • Native support: Next.js, React (Vite/CRA), Vue, Angular, Svelte, Astro, SolidJS, Preact, static HTML
  • Git-based deployment (GitHub/GitLab repos)
  • Auto build and deploy on push
  • Preview deployments for branches
  • Custom domain mapping
  • Environment variables
  • SSR and ISR support (Next.js)

CLI Commands

catalyst slate:create --name <name> --framework <framework> --default  # Add Slate app
catalyst slate:link               # ⚠️ Interactive — link existing dir
catalyst slate:unlink             # Unlink a Slate app
catalyst serve --only slate       # Serve locally
catalyst deploy slate             # Deploy all Slate apps to Development
catalyst deploy slate -m "msg"    # Deploy with message
catalyst deploy --only slate:name # Deploy specific app
catalyst deploy slate --production # Deploy to Production ⚠️

Slate URL format (varies by data center):

DC URL format
US https://<subdomain>.onslate.com
EU https://<subdomain>.onslate.eu
IN https://<subdomain>.onslate.in
AU https://<subdomain>.onslate.au
CA https://<subdomain>.onslate.ca

Supported Frameworks

Framework Value Detection Build Output
static HTML/CSS/JS . or public/
react-vite React + Vite dist/
nextjs Next.js out/ or .next/
vue Vue.js dist/
angular Angular dist/<project-name>
svelte SvelteKit dist/ or build/
astro Astro dist/
solidjs SolidJS dist/
preact Preact dist/
create-react-app CRA build/

Manual Setup (Non-Interactive)

catalyst slate:link is interactive-only. For automated environments:

Step 1 — Create .catalyst/slate-config.toml inside the build output directory:

framework = "static"
deployment_name = "default"

No build step (pure static HTML/CSS/JS)? Your source directory is the output directory. Place .catalyst/slate-config.toml directly inside your client/ (or equivalent) folder. No build command needed.

Step 2 — Add to catalyst.json with absolute source path:

"slate": [{ "name": "my-frontend", "source": "/absolute/path/to/client" }]

Step 3 — Deploy:

catalyst deploy slate -m "initial deploy"

After deploying, load the hosted Slate URL and confirm it serves the fresh build — a successful deploy of the wrong source directory silently re-serves the previous build's assets.

Local Development — Calling Functions from Slate

catalyst serve starts three servers on separate ports:

What URL
Function (API gateway) http://localhost:3000/server/api/
Slate (catalyst proxy) http://localhost:3001
Slate (Vite HMR — what you open in the browser) http://localhost:4800

The silent failure: relative paths like /server/api/execute resolve against the Vite port (4800). Vite's SPA fallback returns index.html with status 200 — not a function response, not an error. Your fetch succeeds but you get HTML, not JSON.

Fix — use environment-specific base URLs:

# client/ui/.env.development
VITE_API_BASE=http://localhost:3000/server/api/execute

# client/ui/.env.production
VITE_API_BASE=https://<project>.development.catalystserverless.com/server/api/execute
const API = import.meta.env.VITE_API_BASE;
const res = await fetch(API, { credentials: 'include' });

Port 3000 (the function) is stable. Port 4800 (Vite) may increment if already in use — never hardcode it. Always point VITE_API_BASE at port 3000.


Common Errors

Deploy succeeds in CLI but app is not updated

catalyst deploy slate can exit with a success status even when the build failed on the server side. Always verify the deployment actually completed by checking: Console → Slate → your app → Deployments → confirm the latest entry shows Success and the build log has no errors.

slate-config.toml wiped by clean builds

The .catalyst/slate-config.toml lives inside the build output directory (e.g., dist/). Build commands that clean the output (--clean, rm -rf dist/) delete this file.

# Recreate after every clean build (Vite/React example):
npm run build && mkdir -p dist/.catalyst && \
  echo -e 'framework = "static"\ndeployment_name = "default"' > dist/.catalyst/slate-config.toml && \
  catalyst deploy slate

# Expo web example:
npx expo export --platform web --clear && \
  mkdir -p dist/.catalyst && \
  echo -e 'framework = "static"\ndeployment_name = "default"' > dist/.catalyst/slate-config.toml && \
  catalyst deploy slate

baseUrl breaks assets on Slate

If your build config has a baseUrl or basePath set to a non-root path, all JS/CSS URLs get prefixed. Since Slate serves from root /, every asset returns 404.

Fix: Remove baseUrl/basePath from your build config before building for Slate. Only set it when serving from inside a function or AppSail sub-path.

Slate + Serverless Functions cross-origin (works with correct setup)

  1. Add Slate domain to Authorized Domains: Console → Authentication → Whitelisting → + Add Domain → enable CORS toggle
  2. Do NOT set CORS headers in function code for production origins — gateway injects them automatically
  3. Only set CORS headers for localhost (local dev)

Slate + AppSail (cross-domain)

Slate (*.onslate.com) and AppSail (*.catalystappsail.com) run on separate domains. Register the Slate domain via MCP and remove any manual CORS headers from AppSail code — Catalyst injects them automatically. See catalyst-appsail/references/appsail-crossorigin.md for the full setup.


Slate vs Legacy Web Client Hosting

IMPORTANT: Slate and Web Client Hosting are different services with different behaviors. Understanding the difference is critical for authentication and routing.

Aspect Slate Legacy Web Client Hosting
Serves from Root / — *.onslate.com /app/ path — same domain as functions
Function call URLs Must be absolute — https://<project>.catalystserverless.com/server/<fn>/execute Can be relative — /server/<fn>/execute
Routing controlled by Framework router + _redirects client-package.json
client-package.json role Optional, SDK hints only Required, defines routing
SPA fallback _redirects or .catalyst/slate-config.toml Automatic
Build output Any (dist/, build/, out/) Must be client/
Deployment command catalyst deploy slate catalyst deploy (deploys client)
Environment variables Build-time only (no runtime config) Build-time only
Modern framework support React, Next.js, Vue, Angular, Svelte, etc. Basic HTML/CSS/JS

⚠️ Migrating from legacy client hosting to Slate? Relative function URLs like /server/fn/execute that worked before silently break on Slate — Slate is served from *.onslate.com while functions live on *.catalystserverless.com. Find and replace every relative /server/... path with its absolute https://<project>.catalystserverless.com/server/... equivalent, and add generateAuthToken() headers to each call.

client-package.json for Slate

The file is OPTIONAL for Slate. If included, the SDK reads login_redirect and homepage values to determine redirect behavior after authentication, but these do NOT control your app's actual routing.

Best practice for Slate + Embedded Auth:

{
  "name": "your-app-name",
  "version": "0.0.1",
  "homepage": "/",
  "login_redirect": "/"
}

Place in public/ (Vite/CRA) or static/ (Next.js) so it's copied to build output. Paths MUST start with / to avoid legacy /app/ prefix.


SPA Routing (React, Vue, Angular)

Single-Page Applications use client-side routing. All paths must serve index.html to let the framework router handle navigation.

Method 1: _redirects File (Recommended)

Create public/_redirects (Vite/CRA) or static/_redirects (Next.js):

/* /index.html 200

This file is automatically copied to build output and instructs Slate to:

  1. Serve index.html for ALL paths
  2. Return 200 status (not 302 redirect)
  3. Let client-side router handle navigation

Method 2: slate-config.toml

For frameworks without public folder, add to .catalyst/slate-config.toml:

framework = "react-vite"
deployment_name = "default"

[[redirects]]
from = "/*"
to = "/index.html"
status = 200

Important: This file lives in build output (dist/.catalyst/slate-config.toml). Clean builds delete it. Recreate after each build or use _redirects method instead.

Framework-Specific Notes

Vite/React: Use public/_redirects (automatically copied to dist/)
Create React App: Use public/_redirects (automatically copied to build/)
Next.js Static: Not needed (Next.js handles fallback)
Angular: Use src/assets/_redirects (configure angular.json to copy to dist)
Vue: Use public/_redirects (automatically copied to dist/)

Testing SPA Routing

After deployment:

  1. Visit root URL → Should load
  2. Visit nested route (e.g., /marketplace/123) → Should load (not 404)
  3. Refresh on nested route → Should stay on that route (not 404)

If step 2 or 3 fails, SPA fallback is not configured.


Environment Variables for Slate

Slate deployments are static builds. There is NO runtime environment variable configuration in the Console. All environment variables must be set at build time.

Vite / React (CRA) / Vue

  1. Create .env.production in project root:
VITE_API_BASE=https://your-function.catalystserverless.in/server/your_api
VITE_CATALYST_ZAID=your_production_zaid
  1. Build:
npm run build
  1. Deploy:
catalyst deploy slate

Variables are bundled into the static assets and cannot be changed without rebuilding.

Next.js (SSR/ISR)

Next.js on Slate supports runtime variables via NEXT_PUBLIC_* prefix:

// next.config.js
module.exports = {
  env: {
    NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
  }
}

Set during build:

NEXT_PUBLIC_API_URL=https://... npm run build
catalyst deploy slate

Angular

Use environment.prod.ts:

export const environment = {
  production: true,
  apiUrl: 'https://your-function.catalystserverless.in/server/api'
};

Build: ng build --configuration production

Key Principle

Build-time only. Changing variables requires rebuilding and redeploying. This is different from serverless functions which support runtime environment variables in the Console.


Web SDK Setup (Required for Auth)

Two scripts are required, in this exact order:

<!-- 1. Main Catalyst CDN bundle — MUST come first -->
<script src="https://static.zohocdn.com/catalyst/sdk/js/4.6.1/catalystWebSDK.js"></script>
<!-- 2. Project-specific init -->
<script src="/__catalyst/sdk/init.js"></script>

Without catalystWebSDK.js, init.js crashes immediately and window.catalyst is never set — auth calls fail silently.


Slate + Embedded Auth: Legacy /app/ Path Handling

CRITICAL: When using Embedded Authentication with Slate, the Catalyst SDK may redirect to /app/ (legacy Web Client Hosting path). Since Slate serves from root /, this causes 404 errors.

Symptom

  • User accesses Slate URL
  • Redirected to https://your-app.onslate.com/app/
  • Returns 404 or "PATTERN_NOT_MATCHED" error

Root Cause

The /__catalyst/sdk/init.js script contains legacy redirect logic from Web Client Hosting that appends /app/ when:

  • login_redirect doesn't start with / in client-package.json, OR
  • Certain Console authentication configurations are set

Legacy Web Client Hosting served apps from /app/ path. Slate serves from /.

Solution (React Router / SPA frameworks)

Add catch-all routes that redirect /app/* back to root:

// React Router v6
import { Navigate } from "react-router-dom";

<Routes>
  {/* ... other routes ... */}
  
  {/* Legacy /app/ redirect for Catalyst SDK compatibility */}
  <Route path="/app" element={<Navigate to="/" replace />} />
  <Route path="/app/*" element={<Navigate to="/" replace />} />
  
  <Route path="*" element={<NotFound />} />
</Routes>
// Vue Router
{
  path: '/app/:pathMatch(.*)*',
  redirect: '/'
}
// Angular
{
  path: 'app',
  redirectTo: '/',
  pathMatch: 'full'
},
{
  path: 'app/**',
  redirectTo: '/'
}

Solution (Static HTML / No Router)

Add to public/_redirects:

/app/* / 200

Prevention

Ensure client-package.json paths start with /:

{
  "homepage": "/",
  "login_redirect": "/"
}

Note: For Slate apps, client-package.json is read by the SDK but does NOT control actual routing (unlike legacy hosting). It only influences SDK redirect behavior.

Source: SKILL.md on GitHub

No alerts1mo3 checks · Risk SAFE
  • Gen Agent Trust Hub1mo

    The skill provides standard documentation and instructions for deploying frontend applications using Catalyst Slate. It includes guidance on CLI commands, framework configuration, and handling cross-domain authentication safely using official Catalyst domains.

  • Socket1mo

    No alerts

  • Snyk1mo

    Risk: LOW · No issues

Signed by skilld at e6e3f9b. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 weeks ago.

Activeupdated 2 months ago
metadata
{
  "version": "2.0.1"
}

README badge

README badge for catalystbyzoho/agent-skills/catalyst-slate