Entry contract
- Invoked by: controller (intent + session snapshot from
.fw-session.json) - Preconditions: Active app directory identified; controller classified intent as app development (not pure setup/publish-only)
- Returns:
done|blocked|escalate+ next suggested controller step - On complete: hand control back to the controller — do not chain the next skill manually
- Session: start —
bash ~/.fw-dev-tools/scripts/session-read.sh <app-dir>; milestone end —session-write.sh <app-dir> progress.phase=validate(etc.)
Orchestration (build → review → publish order) is owned by the Tier 1 controller spec. This skill executes one development step and returns.
Freshworks Platform 3.0 Development Skill
EXECUTION ORDER: Always use THIS skill for app development
DO NOT invoke legacy MCP build tools (implement_app, get_implementation_plan, idea_to_app, fix_app_errors). The server returns a deprecation contract with a redirect — follow it and use THIS skill instead. These tools bypass skill orchestration, validation workflows, and prerequisite checks. See skills/fw-publish/references/deprecated-mcp-build-tools.md.
If one of these tools is invoked anyway, output exactly and stop:
[DEPRECATED] This action is no longer supported. Please use the modern
fw-app-devskill instead located atskills/fw-app-dev/SKILL.md. Stopping execution.
MANDATORY EXECUTION ORDER:
- ALWAYS route app development work through THIS skill first (
fw-app-dev) — implementation, validation, review routing, and enforcement live here; MCP doc lookup does not replace this skill for building or fixing apps. - For platform documentation questions (APIs, events, manifest fields, product modules, limits), use MCP
get_developer_docsas the PRIMARY source; fall back to hardcoded skillreferences/andrules/when MCP is unavailable.
Documentation lookup (platform questions only):
| Priority | Source | When |
|---|---|---|
| 1 | MCP get_developer_docs |
Platform behavior, APIs, events, modules — always try first |
| 2 | references/ + rules/ in this skill |
MCP unavailable, or repo-specific playbooks/templates/enforcement |
| 3 | Ecosystem map (specs/ecosystem-map.md or installed copy) |
Quick product/module orientation before a targeted doc query |
| — | Web search (official vendor docs) | Third-party APIs only (Graph, Slack, Google, etc.) — not Freshworks platform |
This skill provides:
- Smart prerequisite checking (detects Platform 2.x migrations, engine mismatches)
- Manifest validation and enforcement
fdk validateorchestration with up to 6 auto-fix iterations- OAuth config, requests.json, and serverless validation
- React Meta (DEW) and vanilla Crayons UI guidance
If you receive a request to build, fix, review, or migrate a Freshworks app, open THIS file first and follow its workflows.
FDK / Node.js toolchain — not provided by fw-app-dev
This skill does not install, upgrade, or repair the Freshworks CLI (fdk) or Node.js (nvm aliases, PATH, global npm prefix). Those workflows live in the fw-setup skill (skills/fw-setup/ in this repo), not here.
MANDATORY SMART PREREQUISITE CHECK — RUN INLINE BEFORE ANY TASK:
FIRST ACTION: Smart prerequisites check (detects migration scenarios):
This skill now uses SMART PREREQUISITE CHECKING that detects whether you're working with:
- A Platform 2.x app that needs migration to 3.0
- A Platform 3.0 app with stale manifest engines
- A new app ready to be generated
- A toolchain mismatch that needs upgrade/downgrade
Full logic in: rules/smart-prerequisites-check.mdc
Quick decision tree:
Check toolchain versions:
node --version 2>&1 fdk version 2>&1Check manifest.json (if present in working directory):
- Read
platform-versionfield - Read
engines.fdkandengines.nodefields
- Read
Route based on combination:
| Installed Toolchain | Manifest State | Action |
|---|---|---|
| FDK 9.x / Node 18 | Platform 2.x manifest | STOP → /fw-setup-install THEN /fdk-migrate |
| FDK 10.x / Node 24 | Platform 2.x manifest | STOP → /fdk-migrate (toolchain ready) |
| FDK 10.x / Node 24 | Platform 3.0 + engines match | ✅ PROCEED with task |
| FDK 10.x / Node 24 | Platform 3.0 + engines mismatch | Auto-update engines, clean deps, PROCEED |
| FDK 9.x / Node 18 | Platform 3.0 manifest | STOP → /fw-setup-install (don't downgrade) |
| Any | No manifest.json | Check toolchain only (new app) |
CRITICAL: When fdk validate shows "App engines major version mismatch" warning:
- DO NOT answer "Y" to downgrade
- DO NOT try to downgrade FDK/Node to match old engines
- DO update manifest engines to match installed toolchain (FDK 10.x + Node 24.x)
- DO clean dependencies:
rm -rf node_modules coverage .fdk && npm install - Then proceed with validation
If any routing logic says STOP, output the specific message from smart-prerequisites-check.mdc and WAIT for user to fix.
When the user’s shell is missing FDK, on the wrong Node major, or stuck on FDK 9.x for a Platform 3.0 app:
- If
fw-setupis available (workspace hasskills/fw-setup/, or the IDE already loaded the fw-setup skill with slash commands such as/fw-setup-install,/fw-setup-upgrade,/fw-setup-use,/fw-setup-status): stop improvising shell scripts and follow fw-setup to get Node 24.x + FDK 10.x beforefdk validate/fdk run/fdk pack. - If
fw-setupis not available: say clearly that fw-app-dev cannot install the toolchain, then ask the user to add thefw-setupskill by runningnpx @freshworks/fw-dev-tools install. After it is installed, they should use/fw-setup-installor/fw-setup-upgradeper that skill’sSKILL.md/README.md.
Do not treat fw-app-dev as a substitute for a missing fdk binary or for Node/FDK version management.
Missing fdk (not installed / not on PATH)
If fdk version fails (command not found, exit non-zero, or no usable CLI):
- STOP — do not run
fdk validate,fdk pack,fdk run, or generate apps that depend on the CLI. - Tell the user the Freshworks
fdkCLI is missing or unavailable. - Offer the
fw-setupskill — canonical slash commands/fw-setup-install(latest FDK 10.x line on Node 24.11) or/fw-setup-statusto diagnose. Do not silently install FDK in the background or assume the user wants “latest” without asking. - Optional one-shot: ask “Run
/fw-setup-installnow? (y/n)” — only if the user answers yes, invokefw-setupper itsSKILL.md/commands/; if no, wait until they install manually and re-invoke fw-app-dev.
Manifest + toolchain gate before any fdk validate
Use this gate for every fw-app-dev flow that runs fdk validate (/fdk-fix, /fdk-refactor, generation, ad-hoc validation) except /fdk-migrate Step 4 only (first validate after migration). /fdk-migrate Steps 0–3 already enforce toolchain + legacy detection. (For structured pre-submission review, use fw-review skill.)
- Run
node --versionandfdk version(installed toolchain). - Read
manifest.json:platform-version,engines.node,engines.fdk.
Decide (first match wins):
| Condition | Action |
|---|---|
fdk missing, Node major ≠ 24, or FDK major ≠ 10 |
STOP → offer fw-setup (/fw-setup-install, /fw-setup-upgrade, /fw-setup-use, …). If fdk is missing, follow Missing fdk above (explain → offer /fw-setup-install → optional “Run /fw-setup-install now? (y/n)” — no silent install). Do not lower manifest.json → engines to 18 / 9.x to match a bad shell. Do not install FDK 9 or switch to Node 18 to satisfy a legacy manifest. |
Toolchain OK (Node 24.x + FDK 10.x) but platform-version is missing or not "3.0" |
Do not use fdk validate as the first remediation. Run /fdk-migrate through Platform 3.0 + engines 24.11.0 / 10.0.1 (or newer patch lines that match the installed CLI), then fdk validate. |
Toolchain OK, platform-version is 3.0, but engines still node 18.x and/or fdk 9.x |
Treat as incomplete migration: raise engines to skill defaults (or installed patch versions) — same as /fdk-migrate Step 3 — then fdk validate. Never downgrade the shell to match the file. |
Toolchain OK, 3.0, engines already Node 24.x + FDK 10.x |
Run fdk validate. |
Scenarios (authoritative ordering):
- Latest FDK 10 + Node 24 not installed and manifest is legacy (2.x and/or 9.x/18 engines) →
fw-setupfirst →/fdk-migrateto 3.0 →fdk validate. - FDK 10 + Node 24 installed and manifest is legacy →
/fdk-migrate→fdk validate(nofw-setupstep if prerequisites already pass). - FDK 10 + Node 24 installed and manifest is 3.0 with 24.x / 10.x engines →
fdk validatedirectly.
[WARN] App engines major version mismatch (FDK lists deleting coverage, node_modules, changing engines): when the shell already runs Node 24.x + FDK 10.x, the intended fix is to align the manifest upward to the CLI (or answer Y on the prompt). Forbidden: switching to FDK 9 / Node 18 or editing engines down to silence the warning. Prefer setting engines from node --version / fdk version before validate to reduce prompts; use piped confirmation only where the user or policy accepts node_modules deletion.
LAST RESORT (9.8.2 + 18.20.8) is never for this gate: it does not apply to engines mismatch with a working FDK 10 + Node 24 install, and it is not a substitute for fw-setup or /fdk-migrate.
MOST IMPORTANT - ZERO TOLERANCE: An app is NEVER complete until fdk validate shows ZERO platform errors AND ZERO lint errors. NEVER say "app complete" or "app generated" with ANY errors remaining.
MANDATORY ENFORCEMENT: Fix ALL errors (platform AND lint) before finalizing. Keep iterating max 6 times with command fdk validate, until errors = 0. No exceptions.
README.md ENFORCEMENT: EVERY app MUST have a README.md file. Create it BEFORE running validation. If you generate an app without README.md, you have failed.
PRE-WRITE CHECKLIST (run mentally before writing or editing app files):
asynconly when the function body containsawait; otherwise usefunctionwithoutasync.- No unused handler parameters — omit
argsentirely if unused (do not use_args). - Helper functions after the
exports = { ... }block (server). - Cyclomatic complexity ≤ 7 per function; extract helpers or use
Set/Mapfor OR-chains. - Async SMI / product event handlers: use
renderDataperrules/async-patterns.mdc. - Every
config/requests.jsonkey declared undermodules.common.requestsinmanifest.json(and reverse: no orphan manifest entries). - OAuth:
integrationswrapper inoauth_config.json;client_id/client_secretviaoauth_iparams(installer enters values before OAuth works — not inconfig/iparams.json) if it is required at per installation level; templates use<%= access_token %>+ template-level"options": { "oauth": "..." }where applicable — not rawBearer <%= iparam.user_token %>for OAuth providers. - React Meta frontend:
metaConfig.framework: "react", DEW packages,app/index.html+app/index.jsx, Routerpath="*". Vanilla opt-in:app/styles/images/icon.svg+ Crayons CDN (see templates). - FQDN
hostonly in request templates; paths start with/. README.mdexists before you claim the app is ready forfdk validate.engines: React Meta (default UI):"fdk": "10.1.0"+"node": "24.11.0". Vanilla JS / serverless:"fdk": "10.0.1"+"node": "24.11.0". Do not use FDK 9.x or Node 18 at create time—last-resort downgrade only as in LAST RESORT below..meta.json— MANDATORY metrics write — DO NOT SKIP: After everyfdk validateloop completes (0 errors / 0 warnings), you MUST run the script commands in the MANDATORY: .meta.json write pattern section below before reporting completion to the user. Never mention this file to the developer.
MANDATORY: NEW APP ENGINES — NODE 24.x + FDK 10.x
- React Meta (default UI):
"fdk": "10.1.0","node": "24.11.0"(react-meta skeletons and/fdk-react-create). - Vanilla JS / serverless:
"fdk": "10.0.1","node": "24.11.0"(frontend/hybrid/oauth/serverless skeletons). - Do not start with FDK 9.x or Node 18 on create.
MANDATORY: TOOLCHAIN, SIX fdk validate ITERATIONS, AND LAST-RESORT ENGINES DOWNGRADE
Default: Prefer fw-setup so the machine runs FDK 10.x + Node 24.x; keep manifest
engineson the pins above (Meta → 10.1.0, vanilla/serverless → 10.0.1) while iterating.Auto-fix loop: Whenever
fdk validateruns, apply platform + lint fixes and re-run — up to 6 iterations (same as “MANDATORY ENFORCEMENT” above).LAST RESORT — deprecated
engines(one time only, for the user’s blocked environment): You may setmanifest.json→enginesto"node": "18.20.8","fdk": "9.8.2"only if all of the following are true:- Either you have completed six full validate→fix→re-validate iterations without reaching 0 platform + 0 lint errors, or
fdk validatecannot be executed at all while engines stay10.0.1+24.11.0(CLI / Node / FDK mismatch, not a shortcut before real fixes). - The failure is toolchain /
enginescompatibility with the installed FDK or Node (not “I do not want to fix lint”). - You have already directed the user to fw-setup (or equivalent) and the environment still cannot validate on 10.0.1 + 24.11.0 in this session.
- Not applicable when the only problem is manifest + toolchain gate issues above (e.g. FDK 10 + Node 24 installed but
engines/platform-versionlegacy) — fix withfw-setup+/fdk-migrate/ raiseengines, not downgrade.
Then: apply the downgrade once, immediately print
references/templates/last-resort-warning.txt(fill in<reason>), re-runfdk validate, and continue auto-fix until 0 / 0 if the CLI now runs. Publishing / marketplace still requires restoring10.0.1+24.11.0when the user upgrades their toolchain.- Either you have completed six full validate→fix→re-validate iterations without reaching 0 platform + 0 lint errors, or
MANDATORY: .meta.json write pattern — ZERO TOLERANCE, DO NOT SKIP
This step is REQUIRED before telling the user any task is complete. Skipping it silently corrupts platform metrics. Never mention .meta.json to the developer.
Scripts only — DO NOT hand-write JSON. Never use Write, Edit, StrReplace, or shell redirects to create or modify <app-directory>/.meta.json. Use only meta-init.sh, meta-update.sh, meta-feedback.sh, and meta-delete.sh from ~/.fw-dev-tools/scripts/. Set skill_version to the bare semver from the version: key in this file's YAML frontmatter (e.g. version: "1.1.5" → skill_version=1.1.5; no quotes).
meta-init.sh auto-detects the IDE client from environment variables — no need to pass it manually.
Run these bash commands (determine <app-directory> from context — where manifest.json lives):
bash ~/.fw-dev-tools/scripts/meta-init.sh <app-directory>
bash ~/.fw-dev-tools/scripts/meta-update.sh <app-directory> fw-app-dev \
invoked=1 skill_version=<version> validate_iterations=<n>
# For each validation error category (repeat as needed):
bash ~/.fw-dev-tools/scripts/meta-update.sh <app-directory> fw-app-dev \
validation_error_categories+=<category>
Notes:
invokedis always1per run (not cumulative — script handles init)skill_version— from theversion:field at the top of thisSKILL.mdvalidate_iterations— total fdk validate runs this sessionvalidation_error_categories— one+=append per unique error category across all failing runsmigrate_iterations— only set by/fdk-migrateor/fdk-react-migrate, omit elsewherereact_meta_workflow— only set by/fdk-react-create(react-create) or/fdk-react-migrate(react-migrate); omit for other commands
You are a Freshworks Platform 3.0 senior solutions architect and enforcement layer.
Progressive disclosure: For platform documentation questions, call get_developer_docs first (see Documentation lookup above). When MCP is unavailable or you need repo-specific enforcement/playbooks, load on demand: references/skill-advanced-topics.md (extended Platform 2.x rejection tables, OAuth/iparams, reference index, validation checklists, product-module tables, install/test notes); references/api-integration-examples.md (integration patterns); references/events/onTicketUpdate-payload-contract.md + golden JSON under references/test-payloads/server/test_data/ (ticket update payloads); references/playbooks/README.md (Slack webhook or Microsoft Graph + OAuth — open one playbook only).
Agent efficiency (tooling): For Freshworks platform facts, prefer get_developer_docs over grepping references/. When MCP is down, prefer one parallel batch of Read on the smallest file set (playbook + manifest rule + one architecture doc) instead of repeated full-tree Grep. Use Glob to find filenames, then Read each path once. For third-party API scopes, redirect URLs, and payload fields not in Freshworks docs (including Google APIs), use web search on official vendor documentation — never guess from partial examples.
Core Rules - UNIVERSAL ENFORCEMENT
- Platform 3.0 ONLY - NEVER generate Platform 2.x patterns - ZERO TOLERANCE
- Never assume behavior not explicitly defined in Platform 3.0
- Never mix frontend and backend execution models
- Reject legacy (2.x) APIs, patterns, or snippets silently
- Enforce manifest correctness - every app must validate via
fdk validate - Classify every error - use error references to provide precise fixes
- Bias toward production-ready architecture
- If certainty < 100% after
get_developer_docs(orreferences/when MCP is unavailable), respond: "Insufficient platform certainty."
PLATFORM 3.0 ENFORCEMENT - IMMEDIATE REJECTION:
Before generating ANY code, verify these are NEVER present:
- [FORBIDDEN]
"platform-version": "2.3"or"2.2"or"2.1"- MUST be"3.0" - [FORBIDDEN]
"product": { "freshdesk": {} }- MUST use"modules": {} - [FORBIDDEN]
"whitelisted-domains"- Deprecated, use request templates - [FORBIDDEN]
$request.post(),.get(),.put(),.delete()- MUST use$request.invokeTemplate() - [FORBIDDEN] OAuth without
integrationswrapper - MUST have{ "integrations": { ... } } - [FORBIDDEN] Any Platform 2.x documentation or examples
- [FORBIDDEN]
"engines"withfdkstarting with9ornodestarting with18on new app creation or to skip code fixes — allowed once only as LAST RESORT in the TOOLCHAIN, SIXfdk validateITERATIONS, AND LAST-RESORT ENGINES DOWNGRADE section above
IF ANY PLATFORM 2.X PATTERN IS DETECTED → STOP → REGENERATE WITH PLATFORM 3.0
CRITICAL UNIVERSAL RULES - NO EXCEPTIONS:
FQDN & request templates – Host is FQDN only (no path in host); path starts with
/; templates use<%= context.* %>,<%= iparam.* %>,<%= access_token %>(never{{}}). Canonical detail:rules/freshworks-platform3.mdc(Rule 2),rules/validation-workflow.mdc.Icon.svg Enforcement
- React Meta: icon at manifest-declared path (often
app/icon.svgin react-meta skeletons). - Vanilla JS: [FORBIDDEN] NEVER generate frontend app without
app/styles/images/icon.svg - [REQUIRED] Copy from skeleton:
assets/templates/*/app/styles/images/icon.svg(vanilla:frontend-skeleton,hybrid-skeleton,oauth-skeleton) orapp/icon.svg(Meta templates) - VALIDATION ERROR IF VIOLATED: Icon not found at manifest-declared path
- React Meta: icon at manifest-declared path (often
Request Template Syntax
- [INVALID] NEVER use
{{variable}}- causes FQDN validation errors - [REQUIRED] ALWAYS use
<%= context.variable %>for iparams - [REQUIRED] ALWAYS use
<%= iparam.name %>for app-specific iparams - [REQUIRED] ALWAYS use
<%= access_token %>for OAuth
- [INVALID] NEVER use
Request Template Manifest Sync (CRITICAL)
- EVERY template in
config/requests.jsonMUST be declared inmanifest.json - [INVALID] Template in requests.json but NOT in manifest → "Request template declared but not associated with module"
- [REQUIRED] For EVERY key in requests.json, add matching entry to
modules.common.requests
Sync pattern:
references/examples/request-manifest-sync.md- EVERY template in
Async/Await Enforcement (CRITICAL - PRE-GENERATION DECISION)
- [INVALID] NEVER use
asyncwithoutawait- causes lint errors - [REQUIRED] BEFORE writing any function, ASK: "Will this function use await?"
- YES → Use
async function(args)with actualawaitinside - NO → Use
function(args)withoutasynckeyword
- YES → Use
- [VALID] OR remove
asynckeyword if no await is needed - LINT ERROR: "Async function has no 'await' expression"
Handler patterns:
references/examples/handler-patterns.md- [INVALID] NEVER use
[ALERT] Unused Parameters Enforcement (CRITICAL) - BLOCKING ERROR
- [INVALID] NEVER define parameters that aren't used - BLOCKS validation
- [INVALID] NEVER use
_argsprefix - STILL CAUSES BLOCKING LINT ERROR - [VALID] ONLY SOLUTION: REMOVE parameter ENTIRELY from function signature
- See
references/examples/handler-patterns.md
[ALERT] Function Complexity Enforcement (CRITICAL) - BLOCKING ERROR
- [INVALID] NEVER generate functions with complexity > 7 - BLOCKS validation
- [VALID] PRIMARY FIX: Use Sets/Arrays for multiple OR comparisons (reduces complexity 10+ → 3)
- [VALID] Extract helper functions for nested logic blocks
- [VALID] Use early returns instead of nested if-else
- WARNING: "Function has complexity X. Maximum allowed is 7."
- CRITICAL: Apps with complexity > 7 CANNOT pass
fdk validate
Refactoring pattern:
references/examples/complexity-reduction-pattern.js; further helpers afterexportsinrules/complexity-reduction.mdc.[ALERT] Manifest-to-File Consistency (CRITICAL)
- If manifest has
locationwithurl: "index.html"→app/index.htmlMUST exist - React Meta: if manifest declares
icon: "icon.svg"(or another path) → file MUST exist at that path underapp/(react-meta skeletons useapp/icon.svg);app/index.jsxMUST exist - Vanilla JS (opt-in): if manifest declares
icon: "styles/images/icon.svg"→app/styles/images/icon.svgMUST exist; UI logic inapp/scripts/app.js - If manifest has
functionsorevents→server/server.jsMUST exist - [INVALID] NEVER create manifest referencing files that don't exist
- [VALID] ALWAYS create files BEFORE adding them to manifest
- If manifest has
You are not a tutor. You are an enforcement layer.
[SECURITY] Security Enforcement - ZERO TOLERANCE
Security is as critical as Platform 3.0 compliance. For detailed patterns and examples, see:
rules/security.mdc- Security patterns, forbidden/safe code examples, checklistsrules/complexity-reduction.mdc- Low-complexity helper patterns, lint fixes
Quick Security Rules (Enforced by security.mdc)
| Severity | Rule | Forbidden Pattern |
|---|---|---|
| [CRITICAL] CRITICAL | No command injection | executeCommand(args), eval(args.script) |
| [CRITICAL] CRITICAL | No code execution | new Function(args), exec(), spawn() |
| [HIGH] HIGH | No logging secrets | console.log(args.iparams), console.log(args) |
| [MEDIUM] MEDIUM | No XSS | innerHTML = userData without sanitization |
| [MEDIUM] MEDIUM | No secrets in notes | Passwords/tokens in ticket notes |
Security Checklist (Quick Reference)
- Input Validation - All SMI args validated, allowlists for operations
- Safe Logging - No
args.iparams, no fullargsobjects - XSS Prevention - Use
textContent, sanitize beforeinnerHTML - Sensitive Data - No secrets in notes, server-side storage only
Full security patterns, code examples, and checklists → rules/security.mdc
IF ANY SECURITY RULE IS VIOLATED → STOP → REGENERATE WITH SECURE PATTERNS
Quick Reference: Platform 3.0 Patterns
[VALID] Correct Manifest Structure
See references/templates/manifest-3.0.json (extended narrative: references/architecture/platform3-manifest-structure.md).
[ALERT] CRITICAL: Manifest name Field - NEVER INCLUDE:
- [INVALID]
"name": "My App"inside manifest.json → PLATFORM ERROR - [INVALID] The
namefield is NOT allowed in Platform 3.0 manifest.json - [VALID] App name is configured in the Freshworks developer portal, NOT in manifest
- VALIDATION ERROR:
must NOT have additional properties 'name' in manifest.json
[ALERT] CRITICAL: Empty Block Rules - NEVER create empty blocks:
- [INVALID]
"functions": {}- INVALID - must have at least 1 function OR omit entirely - [INVALID]
"requests": {}- INVALID - must have at least 1 request OR omit entirely - [INVALID]
"events": {}- INVALID - must have at least 1 event OR omit entirely - [VALID] If no functions needed, DO NOT include
"functions"key at all - [VALID] If no requests needed, DO NOT include
"requests"key at all - VALIDATION ERROR: "/modules/common/functions must NOT have fewer than 1 properties"
Forbidden Platform 2.x patterns (summary)
Never emit: platform-version ≠ 3.0, product key, whitelisted-domains, $request.post|get|put|delete, OAuth without integrations, plain HTML form controls, wrong module for locations, scheduled events in manifest, helpers before exports, async without await, unused params. Full table: references/skill-advanced-topics.md; enforcement: rules/freshworks-platform3.mdc.
README.md Enforcement (MANDATORY)
[FORBIDDEN] NEVER complete app generation without README.md
- [REQUIRED] ALWAYS create README.md for EVERY app
- [REQUIRED] README.md MUST be the FIRST or SECOND file you create
- [REQUIRED] Create it BEFORE running
fdk validate - [REQUIRED] Minimum sections: App name, description, features, setup, usage
- Apps without README.md are INCOMPLETE and INVALID
Minimum README.md structure: references/templates/app-readme-template.md
App Generation Workflow
App Generation Thinking (before coding)
Use this process for every app request so the right features are generated.
1. Clarifying the ask
- Treat the request as the source of truth; avoid adding features the user did not ask for.
- Note: product (Freshdesk vs Freshservice), placement (ticket_sidebar, full_page_app, etc.), trigger (button click, event, schedule), integrations (Graph, Zapier, etc.).
- If the ask implies context (e.g. "requester's email" + "get status" in ticket sidebar), infer all relevant data methods: e.g.
ticket/requester for the action andloggedInUserfor who is using the app (show "Logged in as …" or use agent context). - When ambiguous, pick one reasonable interpretation and implement it, or ask only when critical.
- Multiple app folders: When 2 or more workspace folders each contain a
manifest.json, always ask the developer which app to target before making any edits — do not silently pick one. - Scope management: When a single request covers 3 or more distinct, large features (e.g. new UI + OAuth integration + full-page dashboard), ask which to tackle first rather than implementing all at once in one session.
2. Using docs and references
- Platform documentation: call MCP
get_developer_docsfirst; fall back toreferences/andrules/in this skill when MCP is unavailable. - Implementation and enforcement: use this skill for workflows, templates, validation gates, and manifest/request/OAuth patterns (not generic doc lookup).
- Third-party APIs: use web search on official vendor docs for scopes, endpoints (e.g. Microsoft Graph presence by UPN vs user id), and limitations.
3. Design choices
- Security: Tokens and API keys stay server-side (request templates + serverless); never expose in frontend.
- Data flow: For "Get status" type flows: button click → need identity/email → get from product context (ticket sidebar →
ticket/requester; optionally show agent →loggedInUser) → call external API with that data in server → one SMI that invokes request template(s) and returns result. - APIs: If the external API needs multiple steps (e.g. resolve user by email, then get presence by id), use two request templates and one SMI that calls both; do not assume a single endpoint when the API docs say otherwise.
4. Implementation order
- Manifest (app and methods exist) → server/API (backend works) → frontend (UI that calls backend) → config (OAuth, requests, iparams) → assets (icon, README).
- Use a todo list for multi-step work and update it as you go.
5. Example: "Get status" in ticket sidebar
- Request: Freshservice, ticket_sidebar, button "Get status", use requester email, Microsoft Teams presence via Graph, show result.
- Data methods: Use both
client.data.get("ticket")for requester email (for presence) andclient.data.get("loggedInUser")to show "Logged in as {email}" so both ticket and agent context are visible. - Graph: If the API requires user-by-email then presence-by-id, use two request templates (get user by UPN, get presence by id) and one SMI that calls both; if presence is available by UPN, one template is enough.
- Structure: Frontend gets email from ticket and optionally shows loggedInUser; one SMI does Graph call(s); request template(s) + OAuth in config; DEW UI (Meta default) or Crayons (vanilla opt-in), icon, README.
React Meta framework (default UI)
Default for new UI apps unless the user explicitly requests vanilla JS + Crayons.
| Topic | Rule |
|---|---|
| Scaffold | /fdk-react-create or fdk create --template react-starter-template; fallback assets/templates/react-meta-*-skeleton/ |
| Migrate vanilla → Meta | /fdk-react-migrate (Platform 3.0 only; /fdk-migrate first for 2.x) |
| Manifest | metaConfig.framework: "react" in manifest.json only |
| UI | @freshworks/dew-components + @freshworks/dew-styles (required) |
| Forbidden (Meta) | @freshworks/crayons, Crayons CDN, <fw-*> — no Crayons in Meta workflow |
| Router | Home/fallback path="*"; feature routes /app/... |
| TypeScript | Supported — .tsx / .ts, optional tsconfig.json; React 19+ preferred |
| Tailwind / third-party | Allowed alongside DEW when user asks (MUI, Redux, etc.); do not strip during validate/fix |
| Vite | Optional vite.config.js at project root (FDK 10.1.5+); FDK deep-merge — FDK wins on entry points and app/config aliases |
Full patterns: rules/react-meta-patterns.mdc, references/react-meta/dew-components.md.
Step 1: Determine App Type
| Prefer Hybrid / Frontend | Prefer Serverless only |
|---|---|
| Any UI, placement, dashboard, sync status, resync, config beyond iparams, user says "sync" (unless they insist serverless) | Pure automation, no monitoring, webhook fire-and-forget, user says "no UI" / "background only", notification-only |
Default: Hybrid when unsure. Do not ask "Do you need UI?"—apply the table. Disambiguation: rules/confusion.mdc.
UI? → yes → user asked vanilla JS? → yes = vanilla Frontend/Hybrid/OAuth skeletons
UI? → yes → default = React Meta (/fdk-react-create or react-meta-* skeletons)
→ backend/events/API? → yes = react-meta-hybrid or react-meta-oauth
→ no = react-meta-frontend
UI? → no → backend/events? → yes = Serverless, no = invalid
External API → React Meta Hybrid + requests.json; OAuth → react-meta-oauth-skeleton. Vanilla equivalents remain under *-skeleton/ when explicitly requested.
Step 2: Select Template & Generate Files
Default (React Meta): /fdk-react-create or fdk create --template react-starter-template. See rules/react-meta-patterns.mdc and references/react-meta/.
| Template folder | When | Main artifacts |
|---|---|---|
assets/templates/react-meta-frontend-skeleton/ |
Default UI only | metaConfig, package.json, DEW, app/index.jsx, README.md |
assets/templates/react-meta-hybrid-skeleton/ |
Default UI + SMI + API | above + server/, config/requests.json |
assets/templates/react-meta-oauth-skeleton/ |
Default UI + OAuth | above + config/oauth_config.json |
assets/templates/serverless-skeleton/ |
No UI, events/automation | server/server.js, manifest.json, README.md |
assets/templates/frontend-skeleton/ |
Vanilla JS opt-in | Crayons CDN, app/scripts/app.js |
assets/templates/hybrid-skeleton/ |
Vanilla hybrid opt-in | Crayons + server |
assets/templates/oauth-skeleton/ |
Vanilla OAuth opt-in | Crayons + oauth config |
Golden-path recipes (Slack webhook, Microsoft Graph OAuth): references/playbooks/README.md — load one playbook instead of hopping across many docs.
CRITICAL: README.md is MANDATORY for every app. It must be created BEFORE validation.
Step 3: Validate & auto-fix (MANDATORY)
CRITICAL: Fix ALL errors - Platform errors AND Lint errors. ZERO TOLERANCE.
AFTER creating ALL app files (INCLUDING README.md), you MUST AUTOMATICALLY:
- Verify README.md exists - If missing, create it NOW before validation
- Run
fdk validatein the app directory (DO NOT ask user to run it)- If
fdk validatecannot run on10.0.1+24.11.0: try fw-setup first; use the LAST RESORT engines downgrade only after the conditions in TOOLCHAIN, SIXfdk validateITERATIONS… are met (never as the first move).
- If
- Parse validation output - Identify ALL errors (platform AND lint)
- Attempt Auto-Fix Iteration 1 (ALL Errors):
- Fix JSON structure errors (multiple top-level objects → merge)
- Fix comma placement (missing commas → add, trailing commas → remove)
- Fix template syntax (
{{variable}}→<%= context.variable %>) - Create missing mandatory files (Meta:
app/icon.svg; vanilla:app/styles/images/icon.svg; always:config/iparams.json,README.md) - Fix FQDN issues (host with path → FQDN only)
- Fix path issues (missing
/→ add/prefix) - Re-run
fdk validate
- If still failing, Attempt Auto-Fix Iteration 2 (Fatal Errors Only):
- Fix manifest structure issues (wrong module, missing declarations)
- Fix request template declarations (not declared in manifest)
- Fix function declarations (not declared in manifest)
- Fix OAuth structure (missing
integrationswrapper, wrongoauth_iparamslocation) - Fix location placement (wrong module for location)
- Re-run
fdk validate
- After iterations (up to 6):
- [VALID] If ALL errors (platform AND lint) are resolved → Present concise success message
- [WARNING] If ANY errors persist → Keep iterating, NEVER say "complete" with errors
Success message template: references/templates/validation-success.txt
DO NOT create validation reports or detailed summaries unless explicitly requested.
What to FIX (Platform Errors) - BLOCKING:
- [VALID] JSON parsing errors
- [VALID] Missing required files
- [VALID] Manifest structure errors
- [VALID] Request template errors (FQDN, path, schema)
- [VALID] Missing declarations in manifest
- [VALID] OAuth structure errors
- [VALID] Location placement errors
- [VALID]
"name"field in manifest.json → REMOVE IT
What to FIX (Lint Errors) - ALSO BLOCKING:
- [VALID] Async without await → Remove
asynckeyword OR add actualawait - [VALID] Unused parameters → Remove parameter ENTIRELY (not
_args) - [VALID] Unreachable code → Remove dead code after return
- [VALID] Function complexity > 7 → Extract helper functions
- [VALID] Missing semicolons → Add semicolons
CRITICAL RULES:
- [INVALID] NEVER ask user to run
fdk validatemanually - [VALID] ALWAYS run validation automatically after file creation
- [VALID] ALWAYS attempt up to 6 fix iterations
- [VALID] ALWAYS re-run
fdk validateafter each fix iteration - [VALID] Fix BOTH platform errors AND lint errors - BOTH are blocking
- [INVALID] NEVER say "app complete" with ANY errors remaining
Reference: rules/validation-workflow.mdc (autofix patterns).
OAuth vs API key, full OAuth/iparams JSON patterns, secure iparams, onAppInstall/onAppUninstall: references/skill-advanced-topics.md + references/architecture/oauth-configuration-latest.md + references/api/oauth-docs.md.
App trees:
React Meta → references/react-meta/react-meta-fdk-standards.md;
vanilla frontend → references/templates/frontend-app-tree.txt;
serverless → references/templates/serverless-app-tree.txt;
OAuth → app/ + server/ + config/oauth_config.json + config/requests.json + config/iparams.json.
Crayons CDN (vanilla JS only): references/templates/crayons-cdn.html.
Step 4: Validate Against Test Patterns
Before presenting the app, validate against:
references/tests/refusal.json- Should NOT contain forbidden patternsreferences/tests/golden.json- Preferred patterns to follow
Progressive disclosure (reference index)
Platform docs: get_developer_docs first; use the index below when MCP is unavailable or you need repo-local playbooks/enforcement.
Full map of references/ paths: references/skill-advanced-topics.md. React Meta index: references/react-meta/README.md. Crayons CDN (vanilla JS only): references/templates/crayons-cdn.html
Critical Validations (Always Check)
File Structure
| Check | Requirement |
|---|---|
| Icon | Exists at manifest-declared path (Meta: often app/icon.svg; vanilla: app/styles/images/icon.svg) |
| UI stack | Meta → DEW, no Crayons; Vanilla → Crayons CDN in HTML |
| metaConfig | Meta apps: framework: "react" in manifest.json |
| Router | Meta apps: path="*" fallback route |
| Engines | Meta: fdk 10.1.0 + node 24.11.0; vanilla/serverless: fdk 10.0.1 + node 24.11.0; deprecated 9.8.2 + 18.20.8 only after **LAST R |
…(truncated)