deco-server-functions-invoke
SKILL.md
Sub-documents
| Document | Topic |
|---|---|
| problem.md | The CORS problem — root cause analysis of why createServerFn inside a factory function doesn't work |
| architecture.md | Three-layer invoke architecture and comparison with deco-cx/deco |
| generator.md | The generate-invoke.ts script — how it works, how to run it, how to extend |
| troubleshooting.md | Common issues and how to debug them |
Deco Server Functions & Invoke
How server-side actions (cart, checkout, newsletter, masterdata) are called from the browser in Deco TanStack Start storefronts.
The Problem in One Sentence
TanStack Start's createServerFn compiler only transforms .handler() calls at module top-level — wrapping it in a factory function (createInvokeFn) causes the compiler's "fast path" to skip it, sending raw VTEX API calls to the browser and causing CORS errors.
The Solution in One Sentence
A build-time generator (generate-invoke.ts) reads the action definitions from @decocms/apps and emits invoke.gen.ts with each createServerFn().handler() as a top-level const, which the compiler correctly transforms into RPC stubs.
Quick Reference
Client (useCart)
→ invoke.vtex.actions.addItemsToCart({ data: {...} })
→ createClientRpc("base64id") ← compiler-generated stub
→ POST /_server ← same domain, no CORS
→ TanStack Start server handler
→ addItemsToCart(orderFormId, items) ← pure function from @decocms/apps
→ vtexFetch → VTEX API ← server-to-server, has credentials
→ Response → client
Layer Responsibilities
| Layer | Package | Role |
|---|---|---|
| Commerce functions | @decocms/apps |
Pure async functions (addItemsToCart, subscribe, etc.) — no framework deps |
| Generator | @decocms/start |
generate-invoke.ts script that creates top-level createServerFn declarations |
| Generated bridge | Site (invoke.gen.ts) |
Auto-generated file with RPC-transformable server functions |
| Consumer | Site components | Import invoke from ~/server/invoke.gen |
Setup for a New Site
# 1. Generate the invoke file
npx tsx node_modules/@decocms/start/scripts/generate-invoke.ts
# 2. Import in components
import { invoke } from "~/server/invoke.gen";
const cart = await invoke.vtex.actions.addItemsToCart({
data: { orderFormId, orderItems }
});
Add to package.json:
{
"scripts": {
"generate:invoke": "tsx node_modules/@decocms/start/scripts/generate-invoke.ts",
"build": "npm run generate:blocks && npm run generate:invoke && npm run generate:schema && tsr generate && vite build"
}
}
Key Files
| File | Location | Purpose |
|---|---|---|
generate-invoke.ts |
@decocms/start/scripts/ |
Build-time generator script |
invoke.gen.ts |
Site src/server/ |
Generated file with top-level server functions |
vtex/invoke.ts |
@decocms/apps/ |
Source of truth for action definitions (parsed by generator) |
vtex/actions/*.ts |
@decocms/apps/ |
Pure commerce functions |
When to Re-generate
Re-run npm run generate:invoke when:
- Adding new actions to
@decocms/apps/vtex/invoke.ts - Changing action signatures (input types, return types)
- Updating
@decocms/appsdependency
Weekly Installs
3
Repository
decocms/deco-startFirst Seen
5 days ago
Security Audits
Installed on
claude-code3
github-copilot3
codex3
kimi-cli3
gemini-cli3
cursor3