@cimplify/cli 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/{add-YJDP63WM.mjs → add-5JU6S6MB.mjs} +1 -1
  2. package/dist/{chunk-WLLH5HFI.mjs → chunk-2Y4JWLPE.mjs} +2 -2
  3. package/dist/{chunk-O36TGF2L.mjs → chunk-7RQTL7FM.mjs} +1 -1
  4. package/dist/{chunk-2BO4H6VP.mjs → chunk-JOUXICGV.mjs} +1 -1
  5. package/dist/{chunk-VE74N3YS.mjs → chunk-MXYUAJEW.mjs} +3 -1
  6. package/dist/{chunk-4ZVTPMUZ.mjs → chunk-NC3GKHDD.mjs} +2 -2
  7. package/dist/{chunk-SN6E73KY.mjs → chunk-RHAO6VWV.mjs} +138 -6
  8. package/dist/{deploy-N3GTTUI5.mjs → deploy-M37L5P6H.mjs} +4 -4
  9. package/dist/{dev-ABPRBTPU.mjs → dev-AQP6TMYK.mjs} +2 -2
  10. package/dist/dispatcher.mjs +37 -22
  11. package/dist/{domains-7Y23SAEM.mjs → domains-2ZQ7AG27.mjs} +2 -2
  12. package/dist/{env-H6M4G4V6.mjs → env-FDBPGU3W.mjs} +2 -2
  13. package/dist/{link-QPWA5Q6Z.mjs → link-P4K2HRXY.mjs} +1 -1
  14. package/dist/{list-DS4C3JRB.mjs → list-FDJZCW22.mjs} +1 -1
  15. package/dist/{login-JFDAQ7T5.mjs → login-RSKGT6GU.mjs} +1 -1
  16. package/dist/{logs-EABEQBEV.mjs → logs-E2AGTDCF.mjs} +2 -2
  17. package/dist/{projects-L7JEO3KO.mjs → projects-IHDG76PK.mjs} +2 -2
  18. package/dist/{repo-54HUIBFC.mjs → repo-XMMLZHLC.mjs} +3 -3
  19. package/dist/{rollback-YTKRECZ5.mjs → rollback-36O4NOEL.mjs} +3 -3
  20. package/dist/{status-IFJIYWRQ.mjs → status-6AT4HF63.mjs} +2 -2
  21. package/dist/{update-UH2HKLOK.mjs → update-4FJNHZYC.mjs} +1 -1
  22. package/dist/{whoami-INHDUHWA.mjs → whoami-DIJZYZIN.mjs} +1 -1
  23. package/package.json +1 -1
  24. package/templates/storefront-bakery/.env.example +6 -0
  25. package/templates/storefront-bakery/app/.well-known/ucp/route.ts +66 -0
  26. package/templates/storefront-bakery/package.json +1 -1
  27. package/templates/storefront-fashion/.env.example +6 -0
  28. package/templates/storefront-fashion/app/.well-known/ucp/route.ts +66 -0
  29. package/templates/storefront-fashion/package.json +1 -1
  30. package/templates/storefront-grocery/.env.example +6 -0
  31. package/templates/storefront-grocery/app/.well-known/ucp/route.ts +66 -0
  32. package/templates/storefront-grocery/package.json +1 -1
  33. package/templates/storefront-restaurant/.env.example +6 -0
  34. package/templates/storefront-restaurant/app/.well-known/ucp/route.ts +66 -0
  35. package/templates/storefront-restaurant/package.json +1 -1
  36. package/templates/storefront-retail/.env.example +6 -0
  37. package/templates/storefront-retail/app/.well-known/ucp/route.ts +66 -0
  38. package/templates/storefront-retail/package.json +1 -1
  39. package/templates/storefront-services/.env.example +6 -0
  40. package/templates/storefront-services/app/.well-known/ucp/route.ts +66 -0
  41. package/templates/storefront-services/package.json +1 -1
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { pollDeployment } from './chunk-2BO4H6VP.mjs';
3
- import { fetchCloneToken } from './chunk-WLLH5HFI.mjs';
2
+ import { pollDeployment } from './chunk-JOUXICGV.mjs';
3
+ import { fetchCloneToken } from './chunk-2Y4JWLPE.mjs';
4
4
  import { promptYesNo } from './chunk-L6474RPL.mjs';
5
- import { TOKEN_PURPOSE, ENV_SCOPE, DEPLOY_TRIGGER, DEPLOYMENT_STATUS } from './chunk-VE74N3YS.mjs';
5
+ import { TOKEN_PURPOSE, ENV_SCOPE, DEPLOY_TRIGGER, DEPLOYMENT_STATUS } from './chunk-MXYUAJEW.mjs';
6
6
  import { parseArgs, flagBool, flagString } from './chunk-4SBJVRGM.mjs';
7
- import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
7
+ import { ApiClient } from './chunk-NC3GKHDD.mjs';
8
8
  import { readAuth, readProjectLink, writeProjectState } from './chunk-JJYWETGA.mjs';
9
9
  import { CliError, CLI_ERROR_CODE, step, info, dim, success, result, EXIT_CODE } from './chunk-NZ4RG62Z.mjs';
10
10
  import { spawn } from 'child_process';
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { parseEnvFile, formatEnvFile } from './chunk-4YSOZ6LY.mjs';
3
- import { ENV_SCOPE, PUBLIC_ENV_PREFIX } from './chunk-VE74N3YS.mjs';
3
+ import { ENV_SCOPE, PUBLIC_ENV_PREFIX } from './chunk-MXYUAJEW.mjs';
4
4
  import { parseArgs, flagBool } from './chunk-4SBJVRGM.mjs';
5
- import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
5
+ import { ApiClient } from './chunk-NC3GKHDD.mjs';
6
6
  import { readAuth, readProjectLink } from './chunk-JJYWETGA.mjs';
7
7
  import { info, CliError, CLI_ERROR_CODE, dim } from './chunk-NZ4RG62Z.mjs';
8
8
  import { spawn } from 'child_process';
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { package_default } from './chunk-O36TGF2L.mjs';
3
- import { TEMPLATES } from './chunk-SN6E73KY.mjs';
2
+ import { package_default } from './chunk-7RQTL7FM.mjs';
3
+ import { TEMPLATES } from './chunk-RHAO6VWV.mjs';
4
4
 
5
5
  // src/dispatcher.ts
6
6
  var VERSION = package_default.version ?? "unknown";
@@ -115,24 +115,24 @@ Need the mock storefront server? It ships with @cimplify/sdk:
115
115
  bunx @cimplify/sdk mock [flags] Boot the local Cimplify API mock
116
116
  `;
117
117
  var COMMANDS = {
118
- login: () => import('./login-JFDAQ7T5.mjs'),
118
+ login: () => import('./login-RSKGT6GU.mjs'),
119
119
  logout: () => import('./logout-ZFZLSJ32.mjs'),
120
- whoami: () => import('./whoami-INHDUHWA.mjs'),
121
- projects: () => import('./projects-L7JEO3KO.mjs'),
122
- link: () => import('./link-QPWA5Q6Z.mjs'),
120
+ whoami: () => import('./whoami-DIJZYZIN.mjs'),
121
+ projects: () => import('./projects-IHDG76PK.mjs'),
122
+ link: () => import('./link-P4K2HRXY.mjs'),
123
123
  unlink: () => import('./unlink-5ABCT7B6.mjs'),
124
- deploy: () => import('./deploy-N3GTTUI5.mjs'),
125
- rollback: () => import('./rollback-YTKRECZ5.mjs'),
126
- env: () => import('./env-H6M4G4V6.mjs'),
127
- domains: () => import('./domains-7Y23SAEM.mjs'),
128
- logs: () => import('./logs-EABEQBEV.mjs'),
129
- status: () => import('./status-IFJIYWRQ.mjs'),
130
- dev: () => import('./dev-ABPRBTPU.mjs'),
131
- repo: () => import('./repo-54HUIBFC.mjs'),
132
- list: () => import('./list-DS4C3JRB.mjs'),
133
- add: () => import('./add-YJDP63WM.mjs'),
134
- update: () => import('./update-UH2HKLOK.mjs'),
135
- upgrade: () => import('./update-UH2HKLOK.mjs')
124
+ deploy: () => import('./deploy-M37L5P6H.mjs'),
125
+ rollback: () => import('./rollback-36O4NOEL.mjs'),
126
+ env: () => import('./env-FDBPGU3W.mjs'),
127
+ domains: () => import('./domains-2ZQ7AG27.mjs'),
128
+ logs: () => import('./logs-E2AGTDCF.mjs'),
129
+ status: () => import('./status-6AT4HF63.mjs'),
130
+ dev: () => import('./dev-AQP6TMYK.mjs'),
131
+ repo: () => import('./repo-XMMLZHLC.mjs'),
132
+ list: () => import('./list-FDJZCW22.mjs'),
133
+ add: () => import('./add-5JU6S6MB.mjs'),
134
+ update: () => import('./update-4FJNHZYC.mjs'),
135
+ upgrade: () => import('./update-4FJNHZYC.mjs')
136
136
  };
137
137
  var GLOBAL_FLAGS = /* @__PURE__ */ new Set(["--json", "--yes", "-y"]);
138
138
  function extractGlobalFlags(argv) {
@@ -157,11 +157,18 @@ async function main() {
157
157
  const [maybeSub, ...rest] = cleaned.args;
158
158
  const TOP_LEVEL_FLAGS = /* @__PURE__ */ new Set(["--help", "-h", "help", "--version", "-v", "version"]);
159
159
  if (!maybeSub) {
160
- console.log(HELP);
160
+ if (cleaned.json) {
161
+ process.stdout.write(
162
+ `${JSON.stringify({ ok: true, data: { help: true, version: VERSION } })}
163
+ `
164
+ );
165
+ } else {
166
+ console.log(HELP);
167
+ }
161
168
  return;
162
169
  }
163
170
  if (TOP_LEVEL_FLAGS.has(maybeSub)) {
164
- return await runDispatcherFlag(maybeSub);
171
+ return await runDispatcherFlag(maybeSub, cleaned.json);
165
172
  }
166
173
  const sub = maybeSub;
167
174
  const args = rest;
@@ -313,8 +320,16 @@ async function emitError(sub, err) {
313
320
  }
314
321
  console.error(`cimplify ${sub}:`, String(err));
315
322
  }
316
- async function runDispatcherFlag(flag) {
317
- if (flag === "-h" || flag === "--help" || flag === "help") {
323
+ async function runDispatcherFlag(flag, json) {
324
+ const isHelp = flag === "-h" || flag === "--help" || flag === "help";
325
+ if (json) {
326
+ process.stdout.write(
327
+ `${JSON.stringify({ ok: true, data: isHelp ? { help: true, version: VERSION } : { version: VERSION } })}
328
+ `
329
+ );
330
+ return;
331
+ }
332
+ if (isHelp) {
318
333
  console.log(HELP);
319
334
  return;
320
335
  }
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { promptYesNo } from './chunk-L6474RPL.mjs';
3
- import { ENV_SCOPE, DOMAIN_TYPE } from './chunk-VE74N3YS.mjs';
3
+ import { ENV_SCOPE, DOMAIN_TYPE } from './chunk-MXYUAJEW.mjs';
4
4
  import { parseArgs, flagBool, flagString } from './chunk-4SBJVRGM.mjs';
5
- import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
5
+ import { ApiClient } from './chunk-NC3GKHDD.mjs';
6
6
  import { readAuth, readProjectLink } from './chunk-JJYWETGA.mjs';
7
7
  import { CliError, CLI_ERROR_CODE, info, dim, result, bold, success } from './chunk-NZ4RG62Z.mjs';
8
8
 
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { formatEnvFile, parseEnvFile, parseKeyValueArg } from './chunk-4YSOZ6LY.mjs';
3
3
  import { promptYesNo } from './chunk-L6474RPL.mjs';
4
- import { ENV_SCOPE, PUBLIC_ENV_PREFIX, SECRET_MASK } from './chunk-VE74N3YS.mjs';
4
+ import { ENV_SCOPE, PUBLIC_ENV_PREFIX, SECRET_MASK } from './chunk-MXYUAJEW.mjs';
5
5
  import { parseArgs, flagString, flagBool } from './chunk-4SBJVRGM.mjs';
6
- import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
6
+ import { ApiClient } from './chunk-NC3GKHDD.mjs';
7
7
  import { readAuth, readProjectLink } from './chunk-JJYWETGA.mjs';
8
8
  import { CliError, CLI_ERROR_CODE, info, dim, result, bold, success } from './chunk-NZ4RG62Z.mjs';
9
9
  import { promises } from 'fs';
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { parseArgs } from './chunk-4SBJVRGM.mjs';
3
- import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
3
+ import { ApiClient } from './chunk-NC3GKHDD.mjs';
4
4
  import { readAuth, writeProjectLink } from './chunk-JJYWETGA.mjs';
5
5
  import { CliError, CLI_ERROR_CODE, success, info, dim, result } from './chunk-NZ4RG62Z.mjs';
6
6
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { REGISTRY_INDEX } from './chunk-SN6E73KY.mjs';
2
+ import { REGISTRY_INDEX } from './chunk-RHAO6VWV.mjs';
3
3
  import { parseArgs, flagBool } from './chunk-4SBJVRGM.mjs';
4
4
  import { CliError, CLI_ERROR_CODE, info, bold, dim, green, result } from './chunk-NZ4RG62Z.mjs';
5
5
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { parseArgs, flagString, flagBool } from './chunk-4SBJVRGM.mjs';
3
- import { resolveBaseUrl, ApiClient } from './chunk-4ZVTPMUZ.mjs';
3
+ import { resolveBaseUrl, ApiClient } from './chunk-NC3GKHDD.mjs';
4
4
  import { writeAuth } from './chunk-JJYWETGA.mjs';
5
5
  import { CliError, CLI_ERROR_CODE, success, result, isJsonMode, step, info, dim } from './chunk-NZ4RG62Z.mjs';
6
6
  import os from 'os';
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { TERMINAL_DEPLOYMENT_STATUSES } from './chunk-VE74N3YS.mjs';
2
+ import { TERMINAL_DEPLOYMENT_STATUSES } from './chunk-MXYUAJEW.mjs';
3
3
  import { parseArgs, flagString, flagBool } from './chunk-4SBJVRGM.mjs';
4
- import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
4
+ import { ApiClient } from './chunk-NC3GKHDD.mjs';
5
5
  import { readAuth, readProjectLink, readProjectState } from './chunk-JJYWETGA.mjs';
6
6
  import { CliError, CLI_ERROR_CODE, isJsonMode, failure, result, red } from './chunk-NZ4RG62Z.mjs';
7
7
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { REPO_PROVIDER } from './chunk-VE74N3YS.mjs';
2
+ import { REPO_PROVIDER } from './chunk-MXYUAJEW.mjs';
3
3
  import { parseArgs, flagString, flagBool } from './chunk-4SBJVRGM.mjs';
4
- import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
4
+ import { ApiClient } from './chunk-NC3GKHDD.mjs';
5
5
  import { readAuth } from './chunk-JJYWETGA.mjs';
6
6
  import { CliError, CLI_ERROR_CODE, info, dim, result, bold, success } from './chunk-NZ4RG62Z.mjs';
7
7
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- export { run as default, fetchCloneToken } from './chunk-WLLH5HFI.mjs';
2
+ export { run as default, fetchCloneToken } from './chunk-2Y4JWLPE.mjs';
3
3
  import './chunk-L6474RPL.mjs';
4
- import './chunk-VE74N3YS.mjs';
4
+ import './chunk-MXYUAJEW.mjs';
5
5
  import './chunk-4SBJVRGM.mjs';
6
- import './chunk-4ZVTPMUZ.mjs';
6
+ import './chunk-NC3GKHDD.mjs';
7
7
  import './chunk-JJYWETGA.mjs';
8
8
  import './chunk-NZ4RG62Z.mjs';
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { pollDeployment } from './chunk-2BO4H6VP.mjs';
3
- import { DEPLOYMENT_STATUS, DEPLOY_TRIGGER } from './chunk-VE74N3YS.mjs';
2
+ import { pollDeployment } from './chunk-JOUXICGV.mjs';
3
+ import { DEPLOYMENT_STATUS, DEPLOY_TRIGGER } from './chunk-MXYUAJEW.mjs';
4
4
  import { parseArgs, flagBool } from './chunk-4SBJVRGM.mjs';
5
- import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
5
+ import { ApiClient } from './chunk-NC3GKHDD.mjs';
6
6
  import { readAuth, readProjectLink, writeProjectState } from './chunk-JJYWETGA.mjs';
7
7
  import { CliError, CLI_ERROR_CODE, step, success, info, dim, result, EXIT_CODE } from './chunk-NZ4RG62Z.mjs';
8
8
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { DEPLOYMENT_STATUS } from './chunk-VE74N3YS.mjs';
2
+ import { DEPLOYMENT_STATUS } from './chunk-MXYUAJEW.mjs';
3
3
  import { parseArgs } from './chunk-4SBJVRGM.mjs';
4
- import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
4
+ import { ApiClient } from './chunk-NC3GKHDD.mjs';
5
5
  import { readAuth, readProjectLink, readProjectState } from './chunk-JJYWETGA.mjs';
6
6
  import { bold, dim, info, result } from './chunk-NZ4RG62Z.mjs';
7
7
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { package_default } from './chunk-O36TGF2L.mjs';
2
+ import { package_default } from './chunk-7RQTL7FM.mjs';
3
3
  import { promptYesNo } from './chunk-L6474RPL.mjs';
4
4
  import { parseArgs, flagBool, flagString } from './chunk-4SBJVRGM.mjs';
5
5
  import { success, bold, info, dim, result, failure, CliError, CLI_ERROR_CODE, step, isJsonMode } from './chunk-NZ4RG62Z.mjs';
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { ApiClient } from './chunk-4ZVTPMUZ.mjs';
2
+ import { ApiClient } from './chunk-NC3GKHDD.mjs';
3
3
  import { readAuth } from './chunk-JJYWETGA.mjs';
4
4
  import { info, bold, dim, result } from './chunk-NZ4RG62Z.mjs';
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cimplify/cli",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Cimplify CLI — deploy, manage env vars, link projects, and scaffold storefronts",
5
5
  "keywords": [
6
6
  "cimplify",
@@ -14,3 +14,9 @@ NEXT_PUBLIC_CIMPLIFY_BUSINESS_ID=bus_default_akua_bakery
14
14
  # and OpenGraph metadata. Set this on production deploys (Vercel auto-injects
15
15
  # via VERCEL_URL but Next prefers an explicit value).
16
16
  NEXT_PUBLIC_SITE_URL=https://example.com
17
+
18
+ # Business handle (human-readable slug, e.g. "akua-bakery"). Used by the
19
+ # UCP manifest endpoint at /.well-known/ucp so AI agents (Claude / ChatGPT /
20
+ # Gemini) can discover this storefront's commerce capabilities. Set this
21
+ # on production deploys; leave empty in dev unless you're testing UCP.
22
+ NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE=
@@ -0,0 +1,66 @@
1
+ import { NextResponse } from "next/server";
2
+
3
+ /**
4
+ * UCP (Universal Commerce Protocol) manifest discovery endpoint.
5
+ *
6
+ * Agents — Claude, ChatGPT, Gemini, MCP clients — probe
7
+ * `https://<your-domain>/.well-known/ucp` to learn what commerce
8
+ * capabilities your storefront supports. We forward the request to
9
+ * Cimplify, which returns the canonical manifest; the response body
10
+ * tells agents to make subsequent UCP calls directly to
11
+ * `api.cimplify.io/ucp/v1/<handle>/*` (no per-request proxy here).
12
+ *
13
+ * Edge-cached for an hour because capabilities change rarely.
14
+ */
15
+ const UCP_API_BASE =
16
+ process.env.NEXT_PUBLIC_CIMPLIFY_API_URL || "https://api.cimplify.io";
17
+
18
+ export const revalidate = 3600;
19
+
20
+ export async function GET() {
21
+ const businessHandle = process.env.NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE;
22
+
23
+ if (!businessHandle) {
24
+ return NextResponse.json(
25
+ {
26
+ error: "NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE not set",
27
+ remediation:
28
+ "Set NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE in .env.local (and your deployment env) to your business handle.",
29
+ },
30
+ { status: 500 },
31
+ );
32
+ }
33
+
34
+ try {
35
+ const response = await fetch(
36
+ `${UCP_API_BASE}/ucp/v1/${businessHandle}/manifest`,
37
+ {
38
+ headers: { "Content-Type": "application/json" },
39
+ next: { revalidate: 3600 },
40
+ },
41
+ );
42
+
43
+ if (!response.ok) {
44
+ return NextResponse.json(
45
+ { error: `Upstream UCP manifest fetch failed: ${response.status}` },
46
+ { status: response.status },
47
+ );
48
+ }
49
+
50
+ const manifest = await response.json();
51
+ return NextResponse.json(manifest, {
52
+ headers: {
53
+ "Content-Type": "application/json",
54
+ "Cache-Control": "public, max-age=3600, s-maxage=3600",
55
+ },
56
+ });
57
+ } catch (error) {
58
+ return NextResponse.json(
59
+ {
60
+ error: "Failed to fetch UCP manifest",
61
+ detail: error instanceof Error ? error.message : String(error),
62
+ },
63
+ { status: 500 },
64
+ );
65
+ }
66
+ }
@@ -17,7 +17,7 @@
17
17
  "check": "bun run typecheck && bun run test:run"
18
18
  },
19
19
  "dependencies": {
20
- "@cimplify/sdk": "^0.45.0",
20
+ "@cimplify/sdk": "^0.45.1",
21
21
  "next": "^16.2.4",
22
22
  "react": "^19.0.0",
23
23
  "react-dom": "^19.0.0"
@@ -14,3 +14,9 @@ NEXT_PUBLIC_CIMPLIFY_BUSINESS_ID=bus_studio_frx
14
14
  # and OpenGraph metadata. Set this on production deploys (Vercel auto-injects
15
15
  # via VERCEL_URL but Next prefers an explicit value).
16
16
  NEXT_PUBLIC_SITE_URL=https://example.com
17
+
18
+ # Business handle (human-readable slug, e.g. "akua-bakery"). Used by the
19
+ # UCP manifest endpoint at /.well-known/ucp so AI agents (Claude / ChatGPT /
20
+ # Gemini) can discover this storefront's commerce capabilities. Set this
21
+ # on production deploys; leave empty in dev unless you're testing UCP.
22
+ NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE=
@@ -0,0 +1,66 @@
1
+ import { NextResponse } from "next/server";
2
+
3
+ /**
4
+ * UCP (Universal Commerce Protocol) manifest discovery endpoint.
5
+ *
6
+ * Agents — Claude, ChatGPT, Gemini, MCP clients — probe
7
+ * `https://<your-domain>/.well-known/ucp` to learn what commerce
8
+ * capabilities your storefront supports. We forward the request to
9
+ * Cimplify, which returns the canonical manifest; the response body
10
+ * tells agents to make subsequent UCP calls directly to
11
+ * `api.cimplify.io/ucp/v1/<handle>/*` (no per-request proxy here).
12
+ *
13
+ * Edge-cached for an hour because capabilities change rarely.
14
+ */
15
+ const UCP_API_BASE =
16
+ process.env.NEXT_PUBLIC_CIMPLIFY_API_URL || "https://api.cimplify.io";
17
+
18
+ export const revalidate = 3600;
19
+
20
+ export async function GET() {
21
+ const businessHandle = process.env.NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE;
22
+
23
+ if (!businessHandle) {
24
+ return NextResponse.json(
25
+ {
26
+ error: "NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE not set",
27
+ remediation:
28
+ "Set NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE in .env.local (and your deployment env) to your business handle.",
29
+ },
30
+ { status: 500 },
31
+ );
32
+ }
33
+
34
+ try {
35
+ const response = await fetch(
36
+ `${UCP_API_BASE}/ucp/v1/${businessHandle}/manifest`,
37
+ {
38
+ headers: { "Content-Type": "application/json" },
39
+ next: { revalidate: 3600 },
40
+ },
41
+ );
42
+
43
+ if (!response.ok) {
44
+ return NextResponse.json(
45
+ { error: `Upstream UCP manifest fetch failed: ${response.status}` },
46
+ { status: response.status },
47
+ );
48
+ }
49
+
50
+ const manifest = await response.json();
51
+ return NextResponse.json(manifest, {
52
+ headers: {
53
+ "Content-Type": "application/json",
54
+ "Cache-Control": "public, max-age=3600, s-maxage=3600",
55
+ },
56
+ });
57
+ } catch (error) {
58
+ return NextResponse.json(
59
+ {
60
+ error: "Failed to fetch UCP manifest",
61
+ detail: error instanceof Error ? error.message : String(error),
62
+ },
63
+ { status: 500 },
64
+ );
65
+ }
66
+ }
@@ -19,7 +19,7 @@
19
19
  "check": "bun run typecheck && bun run test:run"
20
20
  },
21
21
  "dependencies": {
22
- "@cimplify/sdk": "^0.45.0",
22
+ "@cimplify/sdk": "^0.45.1",
23
23
  "next": "^16.2.4",
24
24
  "react": "^19.0.0",
25
25
  "react-dom": "^19.0.0"
@@ -14,3 +14,9 @@ NEXT_PUBLIC_CIMPLIFY_BUSINESS_ID=bus_freshmart
14
14
  # and OpenGraph metadata. Set this on production deploys (Vercel auto-injects
15
15
  # via VERCEL_URL but Next prefers an explicit value).
16
16
  NEXT_PUBLIC_SITE_URL=https://example.com
17
+
18
+ # Business handle (human-readable slug, e.g. "akua-bakery"). Used by the
19
+ # UCP manifest endpoint at /.well-known/ucp so AI agents (Claude / ChatGPT /
20
+ # Gemini) can discover this storefront's commerce capabilities. Set this
21
+ # on production deploys; leave empty in dev unless you're testing UCP.
22
+ NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE=
@@ -0,0 +1,66 @@
1
+ import { NextResponse } from "next/server";
2
+
3
+ /**
4
+ * UCP (Universal Commerce Protocol) manifest discovery endpoint.
5
+ *
6
+ * Agents — Claude, ChatGPT, Gemini, MCP clients — probe
7
+ * `https://<your-domain>/.well-known/ucp` to learn what commerce
8
+ * capabilities your storefront supports. We forward the request to
9
+ * Cimplify, which returns the canonical manifest; the response body
10
+ * tells agents to make subsequent UCP calls directly to
11
+ * `api.cimplify.io/ucp/v1/<handle>/*` (no per-request proxy here).
12
+ *
13
+ * Edge-cached for an hour because capabilities change rarely.
14
+ */
15
+ const UCP_API_BASE =
16
+ process.env.NEXT_PUBLIC_CIMPLIFY_API_URL || "https://api.cimplify.io";
17
+
18
+ export const revalidate = 3600;
19
+
20
+ export async function GET() {
21
+ const businessHandle = process.env.NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE;
22
+
23
+ if (!businessHandle) {
24
+ return NextResponse.json(
25
+ {
26
+ error: "NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE not set",
27
+ remediation:
28
+ "Set NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE in .env.local (and your deployment env) to your business handle.",
29
+ },
30
+ { status: 500 },
31
+ );
32
+ }
33
+
34
+ try {
35
+ const response = await fetch(
36
+ `${UCP_API_BASE}/ucp/v1/${businessHandle}/manifest`,
37
+ {
38
+ headers: { "Content-Type": "application/json" },
39
+ next: { revalidate: 3600 },
40
+ },
41
+ );
42
+
43
+ if (!response.ok) {
44
+ return NextResponse.json(
45
+ { error: `Upstream UCP manifest fetch failed: ${response.status}` },
46
+ { status: response.status },
47
+ );
48
+ }
49
+
50
+ const manifest = await response.json();
51
+ return NextResponse.json(manifest, {
52
+ headers: {
53
+ "Content-Type": "application/json",
54
+ "Cache-Control": "public, max-age=3600, s-maxage=3600",
55
+ },
56
+ });
57
+ } catch (error) {
58
+ return NextResponse.json(
59
+ {
60
+ error: "Failed to fetch UCP manifest",
61
+ detail: error instanceof Error ? error.message : String(error),
62
+ },
63
+ { status: 500 },
64
+ );
65
+ }
66
+ }
@@ -17,7 +17,7 @@
17
17
  "check": "bun run typecheck && bun run test:run"
18
18
  },
19
19
  "dependencies": {
20
- "@cimplify/sdk": "^0.45.0",
20
+ "@cimplify/sdk": "^0.45.1",
21
21
  "next": "^16.2.4",
22
22
  "react": "^19.0.0",
23
23
  "react-dom": "^19.0.0"
@@ -14,3 +14,9 @@ NEXT_PUBLIC_CIMPLIFY_BUSINESS_ID=bus_mamas_kitchen
14
14
  # and OpenGraph metadata. Set this on production deploys (Vercel auto-injects
15
15
  # via VERCEL_URL but Next prefers an explicit value).
16
16
  NEXT_PUBLIC_SITE_URL=https://example.com
17
+
18
+ # Business handle (human-readable slug, e.g. "akua-bakery"). Used by the
19
+ # UCP manifest endpoint at /.well-known/ucp so AI agents (Claude / ChatGPT /
20
+ # Gemini) can discover this storefront's commerce capabilities. Set this
21
+ # on production deploys; leave empty in dev unless you're testing UCP.
22
+ NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE=
@@ -0,0 +1,66 @@
1
+ import { NextResponse } from "next/server";
2
+
3
+ /**
4
+ * UCP (Universal Commerce Protocol) manifest discovery endpoint.
5
+ *
6
+ * Agents — Claude, ChatGPT, Gemini, MCP clients — probe
7
+ * `https://<your-domain>/.well-known/ucp` to learn what commerce
8
+ * capabilities your storefront supports. We forward the request to
9
+ * Cimplify, which returns the canonical manifest; the response body
10
+ * tells agents to make subsequent UCP calls directly to
11
+ * `api.cimplify.io/ucp/v1/<handle>/*` (no per-request proxy here).
12
+ *
13
+ * Edge-cached for an hour because capabilities change rarely.
14
+ */
15
+ const UCP_API_BASE =
16
+ process.env.NEXT_PUBLIC_CIMPLIFY_API_URL || "https://api.cimplify.io";
17
+
18
+ export const revalidate = 3600;
19
+
20
+ export async function GET() {
21
+ const businessHandle = process.env.NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE;
22
+
23
+ if (!businessHandle) {
24
+ return NextResponse.json(
25
+ {
26
+ error: "NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE not set",
27
+ remediation:
28
+ "Set NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE in .env.local (and your deployment env) to your business handle.",
29
+ },
30
+ { status: 500 },
31
+ );
32
+ }
33
+
34
+ try {
35
+ const response = await fetch(
36
+ `${UCP_API_BASE}/ucp/v1/${businessHandle}/manifest`,
37
+ {
38
+ headers: { "Content-Type": "application/json" },
39
+ next: { revalidate: 3600 },
40
+ },
41
+ );
42
+
43
+ if (!response.ok) {
44
+ return NextResponse.json(
45
+ { error: `Upstream UCP manifest fetch failed: ${response.status}` },
46
+ { status: response.status },
47
+ );
48
+ }
49
+
50
+ const manifest = await response.json();
51
+ return NextResponse.json(manifest, {
52
+ headers: {
53
+ "Content-Type": "application/json",
54
+ "Cache-Control": "public, max-age=3600, s-maxage=3600",
55
+ },
56
+ });
57
+ } catch (error) {
58
+ return NextResponse.json(
59
+ {
60
+ error: "Failed to fetch UCP manifest",
61
+ detail: error instanceof Error ? error.message : String(error),
62
+ },
63
+ { status: 500 },
64
+ );
65
+ }
66
+ }
@@ -17,7 +17,7 @@
17
17
  "check": "bun run typecheck && bun run test:run"
18
18
  },
19
19
  "dependencies": {
20
- "@cimplify/sdk": "^0.45.0",
20
+ "@cimplify/sdk": "^0.45.1",
21
21
  "next": "^16.2.4",
22
22
  "react": "^19.0.0",
23
23
  "react-dom": "^19.0.0"
@@ -14,3 +14,9 @@ NEXT_PUBLIC_CIMPLIFY_BUSINESS_ID=bus_currents_electronics
14
14
  # and OpenGraph metadata. Set this on production deploys (Vercel auto-injects
15
15
  # via VERCEL_URL but Next prefers an explicit value).
16
16
  NEXT_PUBLIC_SITE_URL=https://example.com
17
+
18
+ # Business handle (human-readable slug, e.g. "akua-bakery"). Used by the
19
+ # UCP manifest endpoint at /.well-known/ucp so AI agents (Claude / ChatGPT /
20
+ # Gemini) can discover this storefront's commerce capabilities. Set this
21
+ # on production deploys; leave empty in dev unless you're testing UCP.
22
+ NEXT_PUBLIC_CIMPLIFY_BUSINESS_HANDLE=