@noodleseed/agent-kit 0.13.0 → 0.15.0
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.
- package/README.md +3 -3
- package/manifest.json +575 -5
- package/package.json +1 -1
- package/skills/claude-code/SKILL.md +7 -2
- package/skills/claude-code/examples/acme-bistro/README.md +51 -0
- package/skills/claude-code/examples/acme-bistro/design/UX-Document.md +435 -0
- package/skills/claude-code/examples/acme-bistro/design/api-contract.md +161 -0
- package/skills/claude-code/examples/acme-bistro/design/wireframe.html +573 -0
- package/skills/claude-code/examples/acme-bistro/noodle.json +5 -0
- package/skills/claude-code/examples/acme-bistro/package.json +20 -0
- package/skills/claude-code/examples/acme-bistro/src/helpers.ts +7 -0
- package/skills/claude-code/examples/acme-bistro/src/server.ts +149 -0
- package/skills/claude-code/examples/acme-bistro/src/views/menu-cart.tsx +159 -0
- package/skills/claude-code/examples/acme-bistro/src/views/widget-style.css +228 -0
- package/skills/claude-code/examples/acme-bistro/test/server.test.ts +21 -0
- package/skills/claude-code/examples/acme-bistro/vitest.config.ts +7 -0
- package/skills/claude-code/examples/acme-discovery/README.md +85 -0
- package/skills/claude-code/examples/acme-discovery/design/UX-Document.md +441 -0
- package/skills/claude-code/examples/acme-discovery/design/wireframe.html +670 -0
- package/skills/claude-code/examples/acme-discovery/noodle.json +5 -0
- package/skills/claude-code/examples/acme-discovery/package.json +20 -0
- package/skills/claude-code/examples/acme-discovery/src/helpers.ts +7 -0
- package/skills/claude-code/examples/acme-discovery/src/server.ts +202 -0
- package/skills/claude-code/examples/acme-discovery/src/views/discovery-carousel.tsx +155 -0
- package/skills/claude-code/examples/acme-discovery/src/views/widget-style.css +207 -0
- package/skills/claude-code/examples/acme-discovery/test/server.test.ts +24 -0
- package/skills/claude-code/examples/acme-discovery/vitest.config.ts +7 -0
- package/skills/claude-code/examples/acme-tasks/README.md +80 -0
- package/skills/claude-code/examples/acme-tasks/design/UX-Document.md +277 -0
- package/skills/claude-code/examples/acme-tasks/design/wireframe.html +603 -0
- package/skills/claude-code/examples/acme-tasks/noodle.json +5 -0
- package/skills/claude-code/examples/acme-tasks/package.json +20 -0
- package/skills/claude-code/examples/acme-tasks/src/helpers.ts +6 -0
- package/skills/claude-code/examples/acme-tasks/src/server.ts +141 -0
- package/skills/claude-code/examples/acme-tasks/src/views/task-list.tsx +177 -0
- package/skills/claude-code/examples/acme-tasks/src/views/widget-style.css +227 -0
- package/skills/claude-code/examples/acme-tasks/test/server.test.ts +22 -0
- package/skills/claude-code/examples/acme-tasks/vitest.config.ts +7 -0
- package/skills/claude-code/examples/food-ordering/README.md +82 -0
- package/skills/claude-code/examples/food-ordering/noodle.json +5 -0
- package/skills/claude-code/examples/food-ordering/package.json +22 -0
- package/skills/claude-code/examples/food-ordering/src/helpers.ts +34 -0
- package/skills/claude-code/examples/food-ordering/src/server.ts +412 -0
- package/skills/claude-code/examples/food-ordering/src/views/capabilities-card.tsx +155 -0
- package/skills/claude-code/examples/food-ordering/src/views/ordering-flow.tsx +659 -0
- package/skills/claude-code/examples/food-ordering/src/views/widget-style.css +682 -0
- package/skills/claude-code/examples/food-ordering/test/server.test.ts +58 -0
- package/skills/claude-code/examples/food-ordering/vitest.config.ts +30 -0
- package/skills/claude-code/examples/hello/README.md +13 -0
- package/skills/claude-code/examples/hello/noodle.json +5 -0
- package/skills/claude-code/examples/hello/package.json +16 -0
- package/skills/claude-code/examples/hello/src/server.ts +29 -0
- package/skills/claude-code/examples/hello/test/server.test.ts +8 -0
- package/skills/claude-code/examples/weather/README.md +54 -0
- package/skills/claude-code/examples/weather/noodle.json +4 -0
- package/skills/claude-code/examples/weather/package.json +16 -0
- package/skills/claude-code/examples/weather/src/server.ts +190 -0
- package/skills/claude-code/examples/weather/test/server.test.ts +8 -0
- package/skills/claude-code/references/chatgpt-compliance.md +63 -0
- package/skills/claude-code/references/connect-an-api.md +76 -0
- package/skills/claude-code/references/examples.md +16 -4
- package/skills/claude-code/references/experience-design.md +142 -0
- package/skills/codex/SKILL.md +7 -2
- package/skills/codex/examples/acme-bistro/README.md +51 -0
- package/skills/codex/examples/acme-bistro/design/UX-Document.md +435 -0
- package/skills/codex/examples/acme-bistro/design/api-contract.md +161 -0
- package/skills/codex/examples/acme-bistro/design/wireframe.html +573 -0
- package/skills/codex/examples/acme-bistro/noodle.json +5 -0
- package/skills/codex/examples/acme-bistro/package.json +20 -0
- package/skills/codex/examples/acme-bistro/src/helpers.ts +7 -0
- package/skills/codex/examples/acme-bistro/src/server.ts +149 -0
- package/skills/codex/examples/acme-bistro/src/views/menu-cart.tsx +159 -0
- package/skills/codex/examples/acme-bistro/src/views/widget-style.css +228 -0
- package/skills/codex/examples/acme-bistro/test/server.test.ts +21 -0
- package/skills/codex/examples/acme-bistro/vitest.config.ts +7 -0
- package/skills/codex/examples/acme-discovery/README.md +85 -0
- package/skills/codex/examples/acme-discovery/design/UX-Document.md +441 -0
- package/skills/codex/examples/acme-discovery/design/wireframe.html +670 -0
- package/skills/codex/examples/acme-discovery/noodle.json +5 -0
- package/skills/codex/examples/acme-discovery/package.json +20 -0
- package/skills/codex/examples/acme-discovery/src/helpers.ts +7 -0
- package/skills/codex/examples/acme-discovery/src/server.ts +202 -0
- package/skills/codex/examples/acme-discovery/src/views/discovery-carousel.tsx +155 -0
- package/skills/codex/examples/acme-discovery/src/views/widget-style.css +207 -0
- package/skills/codex/examples/acme-discovery/test/server.test.ts +24 -0
- package/skills/codex/examples/acme-discovery/vitest.config.ts +7 -0
- package/skills/codex/examples/acme-tasks/README.md +80 -0
- package/skills/codex/examples/acme-tasks/design/UX-Document.md +277 -0
- package/skills/codex/examples/acme-tasks/design/wireframe.html +603 -0
- package/skills/codex/examples/acme-tasks/noodle.json +5 -0
- package/skills/codex/examples/acme-tasks/package.json +20 -0
- package/skills/codex/examples/acme-tasks/src/helpers.ts +6 -0
- package/skills/codex/examples/acme-tasks/src/server.ts +141 -0
- package/skills/codex/examples/acme-tasks/src/views/task-list.tsx +177 -0
- package/skills/codex/examples/acme-tasks/src/views/widget-style.css +227 -0
- package/skills/codex/examples/acme-tasks/test/server.test.ts +22 -0
- package/skills/codex/examples/acme-tasks/vitest.config.ts +7 -0
- package/skills/codex/examples/food-ordering/README.md +82 -0
- package/skills/codex/examples/food-ordering/noodle.json +5 -0
- package/skills/codex/examples/food-ordering/package.json +22 -0
- package/skills/codex/examples/food-ordering/src/helpers.ts +34 -0
- package/skills/codex/examples/food-ordering/src/server.ts +412 -0
- package/skills/codex/examples/food-ordering/src/views/capabilities-card.tsx +155 -0
- package/skills/codex/examples/food-ordering/src/views/ordering-flow.tsx +659 -0
- package/skills/codex/examples/food-ordering/src/views/widget-style.css +682 -0
- package/skills/codex/examples/food-ordering/test/server.test.ts +58 -0
- package/skills/codex/examples/food-ordering/vitest.config.ts +30 -0
- package/skills/codex/examples/hello/README.md +13 -0
- package/skills/codex/examples/hello/noodle.json +5 -0
- package/skills/codex/examples/hello/package.json +16 -0
- package/skills/codex/examples/hello/src/server.ts +29 -0
- package/skills/codex/examples/hello/test/server.test.ts +8 -0
- package/skills/codex/examples/weather/README.md +54 -0
- package/skills/codex/examples/weather/noodle.json +4 -0
- package/skills/codex/examples/weather/package.json +16 -0
- package/skills/codex/examples/weather/src/server.ts +190 -0
- package/skills/codex/examples/weather/test/server.test.ts +8 -0
- package/skills/codex/references/chatgpt-compliance.md +63 -0
- package/skills/codex/references/connect-an-api.md +76 -0
- package/skills/codex/references/examples.md +16 -4
- package/skills/codex/references/experience-design.md +142 -0
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Acme Getaways × ChatGPT — Discovery Top-of-Funnel Wireframes</title>
|
|
7
|
+
<style>
|
|
8
|
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@500;700&display=swap');
|
|
9
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
10
|
+
body { font-family: 'Inter', -apple-system, sans-serif; background: #f4f5f7; color: #1a1d22; line-height: 1.55; }
|
|
11
|
+
.mono { font-family: 'JetBrains Mono', monospace; }
|
|
12
|
+
|
|
13
|
+
/* ── Acme Getaways brand tokens (from server branding) ── */
|
|
14
|
+
:root {
|
|
15
|
+
--ac-teal: #0EA5A4;
|
|
16
|
+
--ac-teal-soft: #E4FAF8;
|
|
17
|
+
--ac-teal-border: #9CE6E3;
|
|
18
|
+
--ac-ink: #0B1B1B;
|
|
19
|
+
--ac-slate: #234A48;
|
|
20
|
+
--ac-green: #1F9D6B;
|
|
21
|
+
--ac-green-soft: #E5F6EE;
|
|
22
|
+
--ac-green-border: #A7E2C7;
|
|
23
|
+
--ac-amber: #C2710C;
|
|
24
|
+
--ac-amber-soft: #FBF1DF;
|
|
25
|
+
--ac-amber-border: #F0D49A;
|
|
26
|
+
--ac-blue: #2563C9;
|
|
27
|
+
--ac-blue-soft: #E8EEFB;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* ── Page Header ── */
|
|
31
|
+
.page-header { background: var(--ac-ink); color: #fff; border-bottom: 3px solid var(--ac-teal); padding: 30px 48px; position: sticky; top: 0; z-index: 100; }
|
|
32
|
+
.page-header h1 { font-size: 22px; font-weight: 800; letter-spacing: -0.4px; }
|
|
33
|
+
.page-header h1 .brand { color: var(--ac-teal); }
|
|
34
|
+
.page-header p { font-size: 13px; color: #9db3b1; margin-top: 4px; }
|
|
35
|
+
.page-header .scope { display: inline-block; margin-top: 10px; font-size: 11px; font-weight: 600; letter-spacing: 0.5px; padding: 4px 12px; background: var(--ac-teal); color: #04201f; border-radius: 4px; }
|
|
36
|
+
|
|
37
|
+
/* ── Section Nav ── */
|
|
38
|
+
.section-nav { background: #fff; border-bottom: 1px solid #e6e8ec; padding: 12px 48px; display: flex; gap: 22px; font-size: 12px; font-weight: 600; position: sticky; top: 100px; z-index: 99; overflow-x: auto; }
|
|
39
|
+
.section-nav a { color: #8a929c; text-decoration: none; white-space: nowrap; }
|
|
40
|
+
.section-nav a:hover { color: var(--ac-teal); }
|
|
41
|
+
|
|
42
|
+
.container { max-width: 1480px; margin: 0 auto; padding: 40px 48px 90px; }
|
|
43
|
+
|
|
44
|
+
/* ── Visual Vocabulary ── */
|
|
45
|
+
.vocab { display: flex; gap: 18px; flex-wrap: wrap; margin: 0 0 26px; padding: 14px 18px; background: #fff; border: 1px solid #e6e8ec; border-radius: 12px; font-size: 12px; color: #555; }
|
|
46
|
+
.vocab-item { display: flex; align-items: center; gap: 8px; }
|
|
47
|
+
.vocab-sw { width: 16px; height: 16px; border-radius: 4px; border: 1px solid rgba(0,0,0,0.1); }
|
|
48
|
+
.vocab-sw.teal { background: var(--ac-teal); }
|
|
49
|
+
.vocab-sw.green { background: var(--ac-green); }
|
|
50
|
+
.vocab-sw.amber { background: var(--ac-amber); }
|
|
51
|
+
.vocab-sw.grey { background: #cdd2d8; }
|
|
52
|
+
.vocab-sw.ink { background: var(--ac-ink); }
|
|
53
|
+
|
|
54
|
+
/* ── Section ── */
|
|
55
|
+
.section { margin-bottom: 68px; }
|
|
56
|
+
.section-label { font-size: 11px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: var(--ac-teal); margin-bottom: 8px; display: block; }
|
|
57
|
+
.section-title { font-size: 26px; font-weight: 800; letter-spacing: -0.5px; margin-bottom: 6px; color: var(--ac-ink); }
|
|
58
|
+
.section-subtitle { font-size: 14px; color: #5c6570; margin-bottom: 22px; max-width: 900px; }
|
|
59
|
+
|
|
60
|
+
/* ── Rationale Block ── */
|
|
61
|
+
.rationale { background: #fff; border: 1px solid #e6e8ec; border-left: 3px solid var(--ac-teal); border-radius: 10px; padding: 16px 20px; margin-bottom: 22px; max-width: 960px; }
|
|
62
|
+
.rationale h4 { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.8px; color: #8a929c; margin-bottom: 8px; }
|
|
63
|
+
.rationale p { font-size: 13px; color: #3d454e; line-height: 1.6; margin-bottom: 8px; }
|
|
64
|
+
.rationale p:last-child { margin-bottom: 0; }
|
|
65
|
+
.r-tag { display: inline-block; font-size: 10px; font-weight: 700; padding: 2px 8px; border-radius: 4px; margin-right: 4px; }
|
|
66
|
+
.r-tag.ux { background: var(--ac-green-soft); color: #15734d; }
|
|
67
|
+
.r-tag.ui { background: var(--ac-blue-soft); color: #1d4fa0; }
|
|
68
|
+
.r-tag.acme { background: var(--ac-teal-soft); color: #067e7c; }
|
|
69
|
+
.r-tag.trust { background: var(--ac-amber-soft); color: #92560a; }
|
|
70
|
+
|
|
71
|
+
/* ── Phone Row ── */
|
|
72
|
+
.phones-row { display: flex; gap: 26px; overflow-x: auto; padding-bottom: 16px; align-items: stretch; }
|
|
73
|
+
.phone-step { flex-shrink: 0; display: flex; flex-direction: column; align-items: center; }
|
|
74
|
+
.step-label { font-size: 11px; font-weight: 600; color: #99a1ab; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 12px; text-align: center; max-width: 320px; }
|
|
75
|
+
.step-label small { font-weight: 400; letter-spacing: 0; text-transform: none; color: #b3bac2; display: block; margin-top: 2px; }
|
|
76
|
+
.phone { width: 322px; min-height: 660px; background: #fff; border: 2px solid var(--ac-ink); border-radius: 32px; overflow: hidden; display: flex; flex-direction: column; }
|
|
77
|
+
.phone.offapp { border-color: #b9c0c8; border-style: dashed; }
|
|
78
|
+
.phone-notch { width: 100px; height: 24px; background: var(--ac-ink); border-radius: 0 0 14px 14px; margin: 0 auto; flex-shrink: 0; }
|
|
79
|
+
.phone.offapp .phone-notch { background: #b9c0c8; }
|
|
80
|
+
.phone-screen { padding: 16px; display: flex; flex-direction: column; gap: 12px; flex: 1; }
|
|
81
|
+
.step-arrow { display: flex; align-items: center; justify-content: center; flex-shrink: 0; align-self: center; width: 34px; font-size: 24px; color: #c6ccd3; }
|
|
82
|
+
|
|
83
|
+
/* ── ChatGPT / Browser Chrome ── */
|
|
84
|
+
.chatgpt-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 0 10px; border-bottom: 1px solid #eef0f2; }
|
|
85
|
+
.chatgpt-header .model-name { font-size: 14px; font-weight: 600; }
|
|
86
|
+
.chatgpt-header .dots { font-size: 18px; color: #aab; letter-spacing: 2px; }
|
|
87
|
+
.browser-header { display: flex; align-items: center; gap: 8px; padding: 8px 0 10px; border-bottom: 1px solid #eef0f2; }
|
|
88
|
+
.browser-header .url { flex: 1; font-size: 9.5px; color: #8a929c; background: #f1f3f5; border-radius: 12px; padding: 6px 10px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
89
|
+
.browser-header .lock { color: var(--ac-green); font-size: 11px; }
|
|
90
|
+
|
|
91
|
+
/* ── Messages ── */
|
|
92
|
+
.msg { max-width: 94%; font-size: 13px; line-height: 1.55; }
|
|
93
|
+
.msg.user { align-self: flex-end; background: var(--ac-ink); color: #fff; padding: 10px 14px; border-radius: 18px 18px 4px 18px; margin-left: auto; }
|
|
94
|
+
.msg.assistant { color: #1a1d22; padding: 2px 0; }
|
|
95
|
+
.msg.assistant strong { font-weight: 600; }
|
|
96
|
+
|
|
97
|
+
/* ── Tool Call ── */
|
|
98
|
+
.tool-call { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: #f7f8f9; border: 1px solid #e6e8ec; border-radius: 10px; font-size: 11px; color: #5c6570; }
|
|
99
|
+
.tool-call .icon { width: 20px; height: 20px; background: var(--ac-teal); border-radius: 5px; display: flex; align-items: center; justify-content: center; font-size: 12px; flex-shrink: 0; font-weight: 800; color: #04201f; }
|
|
100
|
+
.tool-call .label { font-weight: 700; color: #3d454e; }
|
|
101
|
+
.mono-tool { font-family: 'JetBrains Mono', monospace; color: #8a929c; }
|
|
102
|
+
|
|
103
|
+
/* ── Widget card (DiscoveryCarousel shell) ── */
|
|
104
|
+
.wcard { border: 1.5px solid #e0e3e7; border-radius: 14px; background: #fff; overflow: hidden; }
|
|
105
|
+
.wcard-head { padding: 11px 14px; background: var(--ac-ink); color: #fff; display: flex; align-items: center; gap: 8px; }
|
|
106
|
+
.wcard-head .wc-logo { width: 20px; height: 20px; background: var(--ac-teal); border-radius: 5px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
|
|
107
|
+
.wcard-head .wc-logo svg { width: 13px; height: 13px; stroke: #04201f; fill: none; stroke-width: 2; }
|
|
108
|
+
.wcard-head .wc-title { font-size: 12px; font-weight: 700; letter-spacing: 0.2px; }
|
|
109
|
+
.wcard-head .wc-sub { font-size: 10px; color: #9db3b1; margin-left: auto; }
|
|
110
|
+
.wc-status { font-size: 10px; color: #9db3b1; }
|
|
111
|
+
.wcard-body { padding: 13px 14px; display: flex; flex-direction: column; gap: 10px; }
|
|
112
|
+
.wc-chip { font-size: 9px; font-weight: 700; padding: 2px 7px; background: rgba(255,255,255,0.14); color: #cfeeed; border-radius: 10px; }
|
|
113
|
+
|
|
114
|
+
/* ── Destination cards inside carousel ── */
|
|
115
|
+
.dest-track { display: flex; flex-direction: column; gap: 9px; }
|
|
116
|
+
.dcard { border: 1.5px solid #e6e8ec; border-radius: 11px; padding: 10px 11px; display: flex; flex-direction: column; gap: 5px; }
|
|
117
|
+
.dcard.active { border-color: var(--ac-teal); background: var(--ac-teal-soft); }
|
|
118
|
+
.dcard-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
|
|
119
|
+
.dcard-name { font-size: 14px; font-weight: 800; color: var(--ac-ink); }
|
|
120
|
+
.dcard-price { font-size: 11px; font-weight: 700; color: var(--ac-slate); white-space: nowrap; }
|
|
121
|
+
.dcard-region { font-size: 10.5px; color: #7b838d; }
|
|
122
|
+
.dcard-why { font-size: 11px; color: #3d454e; line-height: 1.45; }
|
|
123
|
+
.dcard-btn { align-self: flex-start; font-size: 10.5px; font-weight: 700; padding: 4px 11px; border-radius: 20px; border: 1.5px solid #d4d8dd; color: #4a525c; background: #fff; }
|
|
124
|
+
.dcard-btn.on { background: var(--ac-teal); border-color: var(--ac-teal); color: #04201f; }
|
|
125
|
+
|
|
126
|
+
/* ── CTA / note ── */
|
|
127
|
+
.cta { padding: 9px 10px; background: var(--ac-teal); border-radius: 9px; text-align: center; font-size: 12px; font-weight: 700; color: #04201f; display: flex; align-items: center; justify-content: center; gap: 6px; }
|
|
128
|
+
.cta svg { width: 13px; height: 13px; stroke: #04201f; fill: none; stroke-width: 2; }
|
|
129
|
+
.cta.disabled { background: #cdeceb; color: #5f8a89; }
|
|
130
|
+
.note { font-size: 11px; color: #5c6570; background: #f7f8f9; border-radius: 8px; padding: 8px 10px; line-height: 1.5; }
|
|
131
|
+
.note.why { border-left: 3px solid var(--ac-teal); }
|
|
132
|
+
.standing { font-size: 10px; color: #8a929c; text-align: center; font-style: italic; }
|
|
133
|
+
|
|
134
|
+
/* ── Off-app destination ── */
|
|
135
|
+
.dest { border: 1.5px solid #e0e3e7; border-radius: 10px; padding: 11px; }
|
|
136
|
+
.dest .dh { font-size: 12px; font-weight: 800; color: var(--ac-ink); margin-bottom: 6px; }
|
|
137
|
+
.dest .dl { font-size: 11px; color: #5c6570; line-height: 1.5; }
|
|
138
|
+
.kv { display: flex; justify-content: space-between; gap: 10px; font-size: 11px; padding: 5px 0; border-bottom: 1px dashed #eceef1; }
|
|
139
|
+
.kv:last-child { border-bottom: none; }
|
|
140
|
+
.kv .k { color: #7b838d; }
|
|
141
|
+
.kv .v { font-weight: 600; color: #2c3540; text-align: right; }
|
|
142
|
+
|
|
143
|
+
/* ── Gallery ── */
|
|
144
|
+
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 22px; }
|
|
145
|
+
.spec-frame { display: flex; flex-direction: column; gap: 8px; }
|
|
146
|
+
.spec-frame .sf-name { font-size: 12px; font-weight: 700; color: var(--ac-ink); }
|
|
147
|
+
.spec-frame .sf-name span { font-weight: 400; color: #8a929c; }
|
|
148
|
+
|
|
149
|
+
/* ── API appendix ── */
|
|
150
|
+
.api-panel { background: #fff; border: 1px solid #e6e8ec; border-radius: 12px; padding: 18px 20px; margin-bottom: 18px; max-width: 1040px; }
|
|
151
|
+
.api-panel h4 { font-size: 13px; font-weight: 800; color: var(--ac-ink); margin-bottom: 4px; }
|
|
152
|
+
.api-panel .ap-sub { font-size: 12px; color: #8a929c; margin-bottom: 12px; }
|
|
153
|
+
.api-step { display: flex; gap: 10px; padding: 9px 0; border-top: 1px dashed #eceef1; }
|
|
154
|
+
.api-step .an { font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 700; color: var(--ac-teal); flex-shrink: 0; width: 26px; }
|
|
155
|
+
.api-step .ac { flex: 1; }
|
|
156
|
+
.api-step .tool { font-family: 'JetBrains Mono', monospace; font-size: 11.5px; font-weight: 700; color: #2c3540; }
|
|
157
|
+
.api-step .tool .kind { font-family: 'Inter'; font-size: 9px; font-weight: 700; color: #067e7c; background: var(--ac-teal-soft); padding: 1px 6px; border-radius: 4px; margin-left: 6px; text-transform: uppercase; letter-spacing: 0.3px; }
|
|
158
|
+
.api-note { font-size: 11px; color: #5c6570; margin-top: 3px; line-height: 1.5; }
|
|
159
|
+
.api-note code { font-family: 'JetBrains Mono', monospace; font-size: 10.5px; background: #f1f3f5; padding: 1px 5px; border-radius: 4px; color: #3d454e; }
|
|
160
|
+
|
|
161
|
+
/* ── Audit table ── */
|
|
162
|
+
.audit-table { width: 100%; border-collapse: collapse; font-size: 12px; max-width: 1160px; background: #fff; border: 1px solid #e6e8ec; border-radius: 12px; overflow: hidden; }
|
|
163
|
+
.audit-table th { text-align: left; padding: 10px 14px; background: #f7f8f9; color: #5c6570; font-weight: 700; font-size: 11px; text-transform: uppercase; letter-spacing: 0.4px; border-bottom: 1px solid #e6e8ec; }
|
|
164
|
+
.audit-table td { padding: 11px 14px; border-bottom: 1px solid #eef0f2; vertical-align: top; color: #3d454e; line-height: 1.5; }
|
|
165
|
+
.audit-table tr:last-child td { border-bottom: none; }
|
|
166
|
+
.audit-table td.req { font-weight: 700; color: var(--ac-ink); width: 210px; }
|
|
167
|
+
.pass { font-size: 10px; font-weight: 800; padding: 2px 9px; border-radius: 20px; white-space: nowrap; }
|
|
168
|
+
.pass.ok { background: var(--ac-green-soft); color: #15734d; border: 1px solid var(--ac-green-border); }
|
|
169
|
+
.pass.flag { background: var(--ac-amber-soft); color: #92560a; border: 1px solid var(--ac-amber-border); }
|
|
170
|
+
.audit-sub { font-size: 13px; font-weight: 800; color: var(--ac-ink); margin: 26px 0 12px; }
|
|
171
|
+
|
|
172
|
+
.footer { text-align: center; font-size: 11px; color: #99a1ab; padding: 30px; border-top: 1px solid #e6e8ec; }
|
|
173
|
+
</style>
|
|
174
|
+
</head>
|
|
175
|
+
<body>
|
|
176
|
+
|
|
177
|
+
<div class="page-header">
|
|
178
|
+
<h1><span class="brand">Acme Getaways</span> × ChatGPT — Discovery Top-of-Funnel Wireframes</h1>
|
|
179
|
+
<p>Prepared by Noodle Seed · a fuzzy feeling → four grounded getaways → shortlist → signed handoff to book on Acme</p>
|
|
180
|
+
<span class="scope">FUNNEL BOUNDARY: discover & shape the trip in ChatGPT · book / date / pay OFF-APP on acme.example</span>
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
<div class="section-nav">
|
|
184
|
+
<a href="#legend">Legend</a>
|
|
185
|
+
<a href="#flow">End-to-End Flow</a>
|
|
186
|
+
<a href="#discover">1 · Discovery</a>
|
|
187
|
+
<a href="#shortlist">2 · Shortlist & Re-shape</a>
|
|
188
|
+
<a href="#handoff">3 · Handoff</a>
|
|
189
|
+
<a href="#gallery">Widget Gallery</a>
|
|
190
|
+
<a href="#tools">MCP Tools</a>
|
|
191
|
+
<a href="#audit">Compliance Audit</a>
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
<div class="container">
|
|
195
|
+
|
|
196
|
+
<!-- LEGEND -->
|
|
197
|
+
<div class="section" id="legend">
|
|
198
|
+
<div class="vocab">
|
|
199
|
+
<div class="vocab-item"><span class="vocab-sw teal"></span> Acme accent — primary CTA & "Shortlisted" only</div>
|
|
200
|
+
<div class="vocab-item"><span class="vocab-sw green"></span> Positive / in-season fit</div>
|
|
201
|
+
<div class="vocab-item"><span class="vocab-sw amber"></span> Caution / honest limit</div>
|
|
202
|
+
<div class="vocab-item"><span class="vocab-sw ink"></span> ChatGPT system surface</div>
|
|
203
|
+
<div class="vocab-item"><span class="vocab-sw grey"></span> Off-app (dashed phone)</div>
|
|
204
|
+
</div>
|
|
205
|
+
<div class="rationale">
|
|
206
|
+
<h4>How to read these wireframes</h4>
|
|
207
|
+
<p>Solid-border phones are the <strong>in-ChatGPT app</strong> (the discovery & shortlist loop — no account, no transaction). Dashed-border phones are <strong>off-app destinations</strong> (Acme's booking flow at <span class="mono">book.acme.example</span>) reached only after the handoff. Every card is <strong>grounded</strong>: the place, "from" price, best-months, region, and reason all come from Acme's own curated catalog and are shown verbatim — the app never invents a destination or a number.</p>
|
|
208
|
+
<p><span class="r-tag ux">UX</span> flow rationale <span class="r-tag ui">UI</span> interface rationale <span class="r-tag acme">ACME</span> brand / catalog fit <span class="r-tag trust">TRUST</span> honesty / boundary guardrail</p>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
|
|
212
|
+
<!-- END TO END FLOW -->
|
|
213
|
+
<div class="section" id="flow">
|
|
214
|
+
<span class="section-label">The whole journey</span>
|
|
215
|
+
<h2 class="section-title">End-to-End: a fuzzy feeling → a shortlisted getaway → booked on Acme</h2>
|
|
216
|
+
<p class="section-subtitle">A traveler frames a vibe and a month, sees four grounded Acme getaways, shortlists the one they love, re-shapes if the mood changes, then hands off to Acme to pick dates and pay. Everything left of the dashed phone is account-free and transaction-free.</p>
|
|
217
|
+
|
|
218
|
+
<div class="phones-row">
|
|
219
|
+
|
|
220
|
+
<!-- Step 1 -->
|
|
221
|
+
<div class="phone-step">
|
|
222
|
+
<div class="step-label">1 · Frame the feeling<small>vibe · month · travelers</small></div>
|
|
223
|
+
<div class="phone">
|
|
224
|
+
<div class="phone-notch"></div>
|
|
225
|
+
<div class="phone-screen">
|
|
226
|
+
<div class="chatgpt-header"><span class="model-name">ChatGPT</span><span class="dots">···</span></div>
|
|
227
|
+
<div class="msg user">Where should we go for a beach trip in June? Just the two of us.</div>
|
|
228
|
+
<div class="tool-call"><span class="icon">A</span><span><span class="label">discover_getaways</span><br><span class="mono-tool">vibe=beach · month=June · travelers=2</span></span></div>
|
|
229
|
+
<div class="msg assistant">Acme's getaways, shaped for a beach June for two —</div>
|
|
230
|
+
<div class="wcard">
|
|
231
|
+
<div class="wcard-head">
|
|
232
|
+
<span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span>
|
|
233
|
+
<span class="wc-title">Acme Getaways</span><span class="wc-chip">Discover</span>
|
|
234
|
+
</div>
|
|
235
|
+
<div class="wcard-body">
|
|
236
|
+
<div class="dest-track">
|
|
237
|
+
<div class="dcard active">
|
|
238
|
+
<div class="dcard-head"><span class="dcard-name">Coral Bay</span><span class="dcard-price">from $890</span></div>
|
|
239
|
+
<div class="dcard-region">Adriatic coast · best May–Sep</div>
|
|
240
|
+
<div class="dcard-why">Calm swimming coves and a walkable old town — easy for a relaxed first trip.</div>
|
|
241
|
+
<span class="dcard-btn">Shortlist</span>
|
|
242
|
+
</div>
|
|
243
|
+
<div class="dcard">
|
|
244
|
+
<div class="dcard-head"><span class="dcard-name">Old Quarter</span><span class="dcard-price">from $640</span></div>
|
|
245
|
+
<div class="dcard-region">Central Europe · best Apr–Oct</div>
|
|
246
|
+
<div class="dcard-why">Dense museum district and food halls, all reachable on foot.</div>
|
|
247
|
+
<span class="dcard-btn">Shortlist</span>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
<div class="cta disabled">Continue on Acme · Coral Bay</div>
|
|
251
|
+
<div class="standing">Booking and payment happen on acme.example — never inside chat.</div>
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
|
|
258
|
+
<div class="step-arrow">→</div>
|
|
259
|
+
|
|
260
|
+
<!-- Step 2 -->
|
|
261
|
+
<div class="phone-step">
|
|
262
|
+
<div class="step-label">2 · Shortlist the pick<small>local, non-destructive</small></div>
|
|
263
|
+
<div class="phone">
|
|
264
|
+
<div class="phone-notch"></div>
|
|
265
|
+
<div class="phone-screen">
|
|
266
|
+
<div class="chatgpt-header"><span class="model-name">ChatGPT</span><span class="dots">···</span></div>
|
|
267
|
+
<div class="msg user">Shortlist Coral Bay.</div>
|
|
268
|
+
<div class="tool-call"><span class="icon">A</span><span><span class="label">shortlist_getaway</span><br><span class="mono-tool">destination="Coral Bay"</span></span></div>
|
|
269
|
+
<div class="wcard">
|
|
270
|
+
<div class="wcard-head">
|
|
271
|
+
<span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span>
|
|
272
|
+
<span class="wc-title">Acme Getaways</span><span class="wc-chip">Discover</span>
|
|
273
|
+
</div>
|
|
274
|
+
<div class="wcard-body">
|
|
275
|
+
<div class="wc-status" style="color:#067e7c;">Shortlisted Coral Bay.</div>
|
|
276
|
+
<div class="dest-track">
|
|
277
|
+
<div class="dcard active">
|
|
278
|
+
<div class="dcard-head"><span class="dcard-name">Coral Bay</span><span class="dcard-price">from $890</span></div>
|
|
279
|
+
<div class="dcard-region">Adriatic coast · best May–Sep</div>
|
|
280
|
+
<div class="dcard-why">Calm swimming coves and a walkable old town — easy for a relaxed first trip.</div>
|
|
281
|
+
<span class="dcard-btn on">✓ Shortlisted</span>
|
|
282
|
+
</div>
|
|
283
|
+
<div class="dcard">
|
|
284
|
+
<div class="dcard-head"><span class="dcard-name">Harbor City</span><span class="dcard-price">from $980</span></div>
|
|
285
|
+
<div class="dcard-region">Pacific rim · best Sep–Nov</div>
|
|
286
|
+
<div class="dcard-why">Waterfront nightlife and day-trip islands a short ferry away.</div>
|
|
287
|
+
<span class="dcard-btn">Shortlist</span>
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
<div class="cta"><svg viewBox="0 0 24 24"><path d="M14 4h6v6"/><path d="m20 4-9 9"/><path d="M20 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5"/></svg>Continue on Acme · Coral Bay</div>
|
|
291
|
+
<div class="standing">Booking and payment happen on acme.example — never inside chat.</div>
|
|
292
|
+
</div>
|
|
293
|
+
</div>
|
|
294
|
+
</div>
|
|
295
|
+
</div>
|
|
296
|
+
</div>
|
|
297
|
+
|
|
298
|
+
<div class="step-arrow">→</div>
|
|
299
|
+
|
|
300
|
+
<!-- Step 3 -->
|
|
301
|
+
<div class="phone-step">
|
|
302
|
+
<div class="step-label">3 · Re-shape the trip<small>vibe switch → re-render</small></div>
|
|
303
|
+
<div class="phone">
|
|
304
|
+
<div class="phone-notch"></div>
|
|
305
|
+
<div class="phone-screen">
|
|
306
|
+
<div class="chatgpt-header"><span class="model-name">ChatGPT</span><span class="dots">···</span></div>
|
|
307
|
+
<div class="msg user">Hmm, actually more of a city break. What've you got?</div>
|
|
308
|
+
<div class="tool-call"><span class="icon">A</span><span><span class="label">discover_getaways</span><br><span class="mono-tool">vibe=city · month=June · travelers=2</span></span></div>
|
|
309
|
+
<div class="msg assistant">Switching to a city vibe —</div>
|
|
310
|
+
<div class="wcard">
|
|
311
|
+
<div class="wcard-head">
|
|
312
|
+
<span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span>
|
|
313
|
+
<span class="wc-title">Acme Getaways</span><span class="wc-chip">Discover</span>
|
|
314
|
+
</div>
|
|
315
|
+
<div class="wcard-body">
|
|
316
|
+
<div class="dest-track">
|
|
317
|
+
<div class="dcard active">
|
|
318
|
+
<div class="dcard-head"><span class="dcard-name">Harbor City</span><span class="dcard-price">from $980</span></div>
|
|
319
|
+
<div class="dcard-region">Pacific rim · best Sep–Nov</div>
|
|
320
|
+
<div class="dcard-why">Waterfront nightlife and day-trip islands a short ferry away.</div>
|
|
321
|
+
<span class="dcard-btn">Shortlist</span>
|
|
322
|
+
</div>
|
|
323
|
+
<div class="dcard">
|
|
324
|
+
<div class="dcard-head"><span class="dcard-name">Old Quarter</span><span class="dcard-price">from $640</span></div>
|
|
325
|
+
<div class="dcard-region">Central Europe · best Apr–Oct</div>
|
|
326
|
+
<div class="dcard-why">Dense museum district and food halls, all reachable on foot.</div>
|
|
327
|
+
<span class="dcard-btn">Shortlist</span>
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
<div class="note why"><strong>Harbor City</strong> is the city fit — best Sep–Nov, so June is lively shoulder season. Month & party size carried over, so you're not re-asked.</div>
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
334
|
+
</div>
|
|
335
|
+
</div>
|
|
336
|
+
|
|
337
|
+
<div class="step-arrow">→</div>
|
|
338
|
+
|
|
339
|
+
<!-- Step 4 -->
|
|
340
|
+
<div class="phone-step">
|
|
341
|
+
<div class="step-label">4 · Handoff<small>the funnel boundary</small></div>
|
|
342
|
+
<div class="phone">
|
|
343
|
+
<div class="phone-notch"></div>
|
|
344
|
+
<div class="phone-screen">
|
|
345
|
+
<div class="chatgpt-header"><span class="model-name">ChatGPT</span><span class="dots">···</span></div>
|
|
346
|
+
<div class="msg user">Let's do Coral Bay. Book it.</div>
|
|
347
|
+
<div class="tool-call"><span class="icon">A</span><span><span class="label">create_handoff</span><br><span class="mono-tool">dest=coral_bay · month=June · pax=2</span></span></div>
|
|
348
|
+
<div class="msg assistant">Opening Acme with Coral Bay, June, two travelers pre-filled — pick exact dates and finish there.</div>
|
|
349
|
+
<div class="wcard">
|
|
350
|
+
<div class="wcard-head">
|
|
351
|
+
<span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span>
|
|
352
|
+
<span class="wc-title">Acme Getaways</span><span class="wc-sub">create_handoff</span>
|
|
353
|
+
</div>
|
|
354
|
+
<div class="wcard-body">
|
|
355
|
+
<div class="kv"><span class="k">Destination</span><span class="v">Coral Bay</span></div>
|
|
356
|
+
<div class="kv"><span class="k">Trip</span><span class="v">June · 2 travelers</span></div>
|
|
357
|
+
<div class="kv"><span class="k">Attribution</span><span class="v">src=chatgpt</span></div>
|
|
358
|
+
<div class="cta"><svg viewBox="0 0 24 24"><path d="M14 4h6v6"/><path d="m20 4-9 9"/><path d="M20 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5"/></svg>Continue on Acme</div>
|
|
359
|
+
<div class="standing">Booking and payment happen on acme.example — never inside chat.</div>
|
|
360
|
+
</div>
|
|
361
|
+
</div>
|
|
362
|
+
</div>
|
|
363
|
+
</div>
|
|
364
|
+
</div>
|
|
365
|
+
|
|
366
|
+
<div class="step-arrow">→</div>
|
|
367
|
+
|
|
368
|
+
<!-- Step 5 off-app -->
|
|
369
|
+
<div class="phone-step">
|
|
370
|
+
<div class="step-label">5 · Off-app<small>book · date · pay on Acme</small></div>
|
|
371
|
+
<div class="phone offapp">
|
|
372
|
+
<div class="phone-notch"></div>
|
|
373
|
+
<div class="phone-screen">
|
|
374
|
+
<div class="browser-header"><span class="lock">🔒</span><span class="url">book.acme.example/plan?dest=coral_bay&month=June&pax=2&src=chatgpt</span></div>
|
|
375
|
+
<div class="dest">
|
|
376
|
+
<div class="dh">Acme · Book Coral Bay</div>
|
|
377
|
+
<div class="dl">The shaped trip lands pre-filled — <strong>Coral Bay · June · 2 travelers</strong>. Traveler signs in, picks exact dates against live availability, and pays. <strong>Purchase happens here.</strong></div>
|
|
378
|
+
</div>
|
|
379
|
+
<div class="note" style="margin-top:8px;">⟵ The deep link carried <span class="mono">dest · month · pax</span> so nothing is re-typed, plus <span class="mono">src=chatgpt</span> so Acme credits this booking to the ChatGPT funnel.</div>
|
|
380
|
+
</div>
|
|
381
|
+
</div>
|
|
382
|
+
</div>
|
|
383
|
+
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
|
|
387
|
+
<!-- 1 DISCOVERY -->
|
|
388
|
+
<div class="section" id="discover">
|
|
389
|
+
<span class="section-label">Surface 1 · core</span>
|
|
390
|
+
<h2 class="section-title">Discovery — a grounded catalog, never a guess</h2>
|
|
391
|
+
<p class="section-subtitle">The opening move: turn a fuzzy feeling into four real Acme getaways, each with its own "from" price, best-months window, region, and honest reason. The model narrates which fit the stated vibe; the carousel shows the full curated catalog.</p>
|
|
392
|
+
<div class="rationale">
|
|
393
|
+
<h4>Why it's built this way</h4>
|
|
394
|
+
<p><span class="r-tag ux">UX</span> A traveler at "where should we go?" wants a few credible options with a reason each — not an infinite list. Four cards scan in seconds; one tap shortlists.</p>
|
|
395
|
+
<p><span class="r-tag acme">ACME</span> Every place, price, and reason is Acme's own catalog data returned verbatim — the app is authoritative because Acme owns all four. <span class="r-tag trust">TRUST</span> Prices are shown <strong>"from $X"</strong>, never as a quote; <code>discover_getaways</code> returns the whole catalog and never filters on the input, so switching vibe is never a dead end.</p>
|
|
396
|
+
</div>
|
|
397
|
+
<div class="phones-row">
|
|
398
|
+
<div class="phone-step">
|
|
399
|
+
<div class="step-label">Budget-first intent</div>
|
|
400
|
+
<div class="phone"><div class="phone-notch"></div><div class="phone-screen">
|
|
401
|
+
<div class="chatgpt-header"><span class="model-name">ChatGPT</span><span class="dots">···</span></div>
|
|
402
|
+
<div class="msg user">Honestly, what's the cheapest you'd actually recommend for two?</div>
|
|
403
|
+
<div class="tool-call"><span class="icon">A</span><span><span class="label">discover_getaways</span></span></div>
|
|
404
|
+
<div class="wcard"><div class="wcard-head"><span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span><span class="wc-title">Acme Getaways</span><span class="wc-chip">Discover</span></div><div class="wcard-body">
|
|
405
|
+
<div class="dest-track">
|
|
406
|
+
<div class="dcard active"><div class="dcard-head"><span class="dcard-name">Old Quarter</span><span class="dcard-price">from $640</span></div><div class="dcard-region">Central Europe · best Apr–Oct</div><div class="dcard-why">Dense museum district and food halls, all reachable on foot.</div><span class="dcard-btn">Shortlist</span></div>
|
|
407
|
+
<div class="dcard"><div class="dcard-head"><span class="dcard-name">Coral Bay</span><span class="dcard-price">from $890</span></div><div class="dcard-region">Adriatic coast · best May–Sep</div><div class="dcard-why">Calm swimming coves and a walkable old town.</div><span class="dcard-btn">Shortlist</span></div>
|
|
408
|
+
</div>
|
|
409
|
+
<div class="note why"><strong>Old Quarter</strong> starts lowest at from $640 — the value pick without feeling like a compromise.</div>
|
|
410
|
+
</div></div>
|
|
411
|
+
</div></div>
|
|
412
|
+
</div>
|
|
413
|
+
<div class="step-arrow">→</div>
|
|
414
|
+
<div class="phone-step">
|
|
415
|
+
<div class="step-label">Season-first intent</div>
|
|
416
|
+
<div class="phone"><div class="phone-notch"></div><div class="phone-screen">
|
|
417
|
+
<div class="chatgpt-header"><span class="model-name">ChatGPT</span><span class="dots">···</span></div>
|
|
418
|
+
<div class="msg user">We've got a week in December — where's actually good then?</div>
|
|
419
|
+
<div class="tool-call"><span class="icon">A</span><span><span class="label">discover_getaways</span><span class="mono-tool"> month=December</span></span></div>
|
|
420
|
+
<div class="wcard"><div class="wcard-head"><span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span><span class="wc-title">Acme Getaways</span><span class="wc-chip">Discover</span></div><div class="wcard-body">
|
|
421
|
+
<div class="dest-track">
|
|
422
|
+
<div class="dcard active"><div class="dcard-head"><span class="dcard-name">Monte Alto</span><span class="dcard-price">from $1,120</span></div><div class="dcard-region">Northern Alps · best Dec–Mar</div><div class="dcard-why">Ski-in village with beginner slopes and long groomed runs.</div><span class="dcard-btn">Shortlist</span></div>
|
|
423
|
+
</div>
|
|
424
|
+
<div class="note why"><strong>Monte Alto</strong> is the one whose window is <strong>Dec–Mar</strong> — the in-season pick. Exact December availability is Acme's to confirm.</div>
|
|
425
|
+
</div></div>
|
|
426
|
+
</div></div>
|
|
427
|
+
</div>
|
|
428
|
+
<div class="step-arrow">→</div>
|
|
429
|
+
<div class="phone-step">
|
|
430
|
+
<div class="step-label">Fullscreen browse (same component)</div>
|
|
431
|
+
<div class="phone"><div class="phone-notch"></div><div class="phone-screen">
|
|
432
|
+
<div class="chatgpt-header"><span class="model-name">ChatGPT</span><span class="dots">···</span></div>
|
|
433
|
+
<div class="msg user">Just show me everything.</div>
|
|
434
|
+
<div class="tool-call"><span class="icon">A</span><span><span class="label">discover_getaways</span></span></div>
|
|
435
|
+
<div class="wcard"><div class="wcard-head"><span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span><span class="wc-title">Acme Getaways</span><span class="wc-chip">Fullscreen</span></div><div class="wcard-body">
|
|
436
|
+
<div class="dest-track">
|
|
437
|
+
<div class="dcard"><div class="dcard-head"><span class="dcard-name">Coral Bay</span><span class="dcard-price">from $890</span></div><div class="dcard-region">Adriatic coast · May–Sep · beach</div></div>
|
|
438
|
+
<div class="dcard"><div class="dcard-head"><span class="dcard-name">Monte Alto</span><span class="dcard-price">from $1,120</span></div><div class="dcard-region">Northern Alps · Dec–Mar · mountains</div></div>
|
|
439
|
+
<div class="dcard"><div class="dcard-head"><span class="dcard-name">Old Quarter</span><span class="dcard-price">from $640</span></div><div class="dcard-region">Central Europe · Apr–Oct · culture</div></div>
|
|
440
|
+
<div class="dcard"><div class="dcard-head"><span class="dcard-name">Harbor City</span><span class="dcard-price">from $980</span></div><div class="dcard-region">Pacific rim · Sep–Nov · city</div></div>
|
|
441
|
+
</div>
|
|
442
|
+
<div class="standing">Same component, roomier layout — displayMode="fullscreen".</div>
|
|
443
|
+
</div></div>
|
|
444
|
+
</div></div>
|
|
445
|
+
</div>
|
|
446
|
+
</div>
|
|
447
|
+
</div>
|
|
448
|
+
|
|
449
|
+
<!-- 2 SHORTLIST -->
|
|
450
|
+
<div class="section" id="shortlist">
|
|
451
|
+
<span class="section-label">Surface 2</span>
|
|
452
|
+
<h2 class="section-title">Shortlist & re-shape — the deliberation loop</h2>
|
|
453
|
+
<p class="section-subtitle">Shortlisting is the "I like this one" gesture — a local widget-state write, not a booking. Changing the vibe, month, or party size re-runs discovery and re-renders the carousel, so the traveler can think out loud without losing context.</p>
|
|
454
|
+
<div class="rationale">
|
|
455
|
+
<h4>Why it's built this way</h4>
|
|
456
|
+
<p><span class="r-tag ux">UX</span> The loop rewards exploration: shortlist, switch vibe, compare, shortlist again. The values you didn't change persist, so a vibe switch never re-asks month or party size.</p>
|
|
457
|
+
<p><span class="r-tag ui">UI</span> One action per card (Shortlist toggle) and one shell CTA (Continue on Acme) — well inside the ≤2-actions-per-card rule; the carousel is a single track with no nested scroll. <span class="r-tag trust">TRUST</span> Shortlisting writes nothing off-app: <code>shortlist_getaway</code> is a non-destructive local action, not an account or a cart.</p>
|
|
458
|
+
</div>
|
|
459
|
+
<div class="phones-row">
|
|
460
|
+
<div class="phone-step">
|
|
461
|
+
<div class="step-label">Before — nothing held yet</div>
|
|
462
|
+
<div class="phone"><div class="phone-notch"></div><div class="phone-screen">
|
|
463
|
+
<div class="chatgpt-header"><span class="model-name">ChatGPT</span><span class="dots">···</span></div>
|
|
464
|
+
<div class="wcard"><div class="wcard-head"><span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span><span class="wc-title">Acme Getaways</span><span class="wc-chip">Discover</span></div><div class="wcard-body">
|
|
465
|
+
<div class="wc-status">Pick a getaway to continue.</div>
|
|
466
|
+
<div class="dest-track">
|
|
467
|
+
<div class="dcard"><div class="dcard-head"><span class="dcard-name">Coral Bay</span><span class="dcard-price">from $890</span></div><div class="dcard-region">Adriatic coast · best May–Sep</div><span class="dcard-btn">Shortlist</span></div>
|
|
468
|
+
<div class="dcard"><div class="dcard-head"><span class="dcard-name">Harbor City</span><span class="dcard-price">from $980</span></div><div class="dcard-region">Pacific rim · best Sep–Nov</div><span class="dcard-btn">Shortlist</span></div>
|
|
469
|
+
</div>
|
|
470
|
+
<div class="cta disabled">Continue on Acme</div>
|
|
471
|
+
</div></div>
|
|
472
|
+
</div></div>
|
|
473
|
+
</div>
|
|
474
|
+
<div class="step-arrow">→</div>
|
|
475
|
+
<div class="phone-step">
|
|
476
|
+
<div class="step-label">After — Coral Bay held</div>
|
|
477
|
+
<div class="phone"><div class="phone-notch"></div><div class="phone-screen">
|
|
478
|
+
<div class="chatgpt-header"><span class="model-name">ChatGPT</span><span class="dots">···</span></div>
|
|
479
|
+
<div class="tool-call"><span class="icon">A</span><span><span class="label">shortlist_getaway</span><span class="mono-tool"> "Coral Bay"</span></span></div>
|
|
480
|
+
<div class="wcard"><div class="wcard-head"><span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span><span class="wc-title">Acme Getaways</span><span class="wc-chip">Discover</span></div><div class="wcard-body">
|
|
481
|
+
<div class="wc-status" style="color:#067e7c;">Shortlisted Coral Bay.</div>
|
|
482
|
+
<div class="dest-track">
|
|
483
|
+
<div class="dcard active"><div class="dcard-head"><span class="dcard-name">Coral Bay</span><span class="dcard-price">from $890</span></div><div class="dcard-region">Adriatic coast · best May–Sep</div><span class="dcard-btn on">✓ Shortlisted</span></div>
|
|
484
|
+
<div class="dcard"><div class="dcard-head"><span class="dcard-name">Harbor City</span><span class="dcard-price">from $980</span></div><div class="dcard-region">Pacific rim · best Sep–Nov</div><span class="dcard-btn">Shortlist</span></div>
|
|
485
|
+
</div>
|
|
486
|
+
<div class="cta"><svg viewBox="0 0 24 24"><path d="M14 4h6v6"/><path d="m20 4-9 9"/><path d="M20 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5"/></svg>Continue on Acme · Coral Bay</div>
|
|
487
|
+
</div></div>
|
|
488
|
+
</div></div>
|
|
489
|
+
</div>
|
|
490
|
+
</div>
|
|
491
|
+
</div>
|
|
492
|
+
|
|
493
|
+
<!-- 3 HANDOFF -->
|
|
494
|
+
<div class="section" id="handoff">
|
|
495
|
+
<span class="section-label">Surface 3 · the funnel boundary</span>
|
|
496
|
+
<h2 class="section-title">The single, signed, attributable handoff</h2>
|
|
497
|
+
<p class="section-subtitle">One deliberate exit — no second track. <strong>Continue on Acme</strong> calls <code>create_handoff</code>, which builds a signed deep link carrying the shaped trip and the <span class="mono">src=chatgpt</span> attribution, then opens Acme's booking flow. Dates, inventory, and payment are Acme's, off-app by design.</p>
|
|
498
|
+
<div class="rationale">
|
|
499
|
+
<h4>Why it's built this way</h4>
|
|
500
|
+
<p><span class="r-tag acme">ACME</span> Acme earns on completed bookings; the app's job is to send pre-shaped, attributable demand. The deep link carries <code>dest · month · pax</code> so nothing is re-typed, plus <code>src=chatgpt</code> so Acme can measure and pay for the funnel.</p>
|
|
501
|
+
<p><span class="r-tag ui">UI</span> Every value is already URL-safe (id slug · month enum · integer), so the tool substitutes them directly — it never URL-encodes or transforms an input. <span class="r-tag trust">TRUST</span> The domain is declared in <code>handoff.allowedDomains</code>, so ChatGPT opens it without a safe-link warning; zero credentials cross the boundary.</p>
|
|
502
|
+
</div>
|
|
503
|
+
<div class="phones-row">
|
|
504
|
+
<div class="phone-step">
|
|
505
|
+
<div class="step-label">In-app — the handoff card</div>
|
|
506
|
+
<div class="phone"><div class="phone-notch"></div><div class="phone-screen">
|
|
507
|
+
<div class="chatgpt-header"><span class="model-name">ChatGPT</span><span class="dots">···</span></div>
|
|
508
|
+
<div class="tool-call"><span class="icon">A</span><span><span class="label">create_handoff</span><br><span class="mono-tool">dest=coral_bay · month=June · pax=2</span></span></div>
|
|
509
|
+
<div class="wcard"><div class="wcard-head"><span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span><span class="wc-title">Acme Getaways</span><span class="wc-sub">create_handoff</span></div><div class="wcard-body">
|
|
510
|
+
<div class="kv"><span class="k">Destination</span><span class="v">Coral Bay</span></div>
|
|
511
|
+
<div class="kv"><span class="k">Trip</span><span class="v">June · 2 travelers</span></div>
|
|
512
|
+
<div class="kv"><span class="k">Summary</span><span class="v">Coral Bay · June · 2</span></div>
|
|
513
|
+
<div class="cta"><svg viewBox="0 0 24 24"><path d="M14 4h6v6"/><path d="m20 4-9 9"/><path d="M20 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5"/></svg>Continue on Acme</div>
|
|
514
|
+
<div class="standing">Booking and payment happen on acme.example — never inside chat.</div>
|
|
515
|
+
</div></div>
|
|
516
|
+
</div></div>
|
|
517
|
+
</div>
|
|
518
|
+
<div class="step-arrow">→</div>
|
|
519
|
+
<div class="phone-step">
|
|
520
|
+
<div class="step-label">Off-app — Acme booking flow</div>
|
|
521
|
+
<div class="phone offapp"><div class="phone-notch"></div><div class="phone-screen">
|
|
522
|
+
<div class="browser-header"><span class="lock">🔒</span><span class="url">book.acme.example/plan?dest=coral_bay&month=June&pax=2&src=chatgpt</span></div>
|
|
523
|
+
<div class="dest">
|
|
524
|
+
<div class="dh">Acme · Plan your Coral Bay trip</div>
|
|
525
|
+
<div class="dl">Pre-filled from the handoff: <strong>Coral Bay · June · 2 travelers</strong>. Sign in, choose exact dates against live availability, review the dated price, and pay. <strong>The transaction lives here.</strong></div>
|
|
526
|
+
</div>
|
|
527
|
+
<div class="note" style="margin-top:8px;">The <span class="mono">src=chatgpt</span> tag credits this session — and any booking that follows — to the ChatGPT funnel. It carries no PII.</div>
|
|
528
|
+
</div></div>
|
|
529
|
+
</div>
|
|
530
|
+
</div>
|
|
531
|
+
</div>
|
|
532
|
+
|
|
533
|
+
<!-- WIDGET GALLERY -->
|
|
534
|
+
<div class="section" id="gallery">
|
|
535
|
+
<span class="section-label">Reference</span>
|
|
536
|
+
<h2 class="section-title">Widget gallery</h2>
|
|
537
|
+
<p class="section-subtitle">The app ships <strong>one</strong> widget — <span class="mono">DiscoveryCarousel</span> — shown here at rest and in its key states. Apps SDK compliant: system fonts, monochrome outlined icons, neutral surface, Acme teal reserved for the primary CTA and the "Shortlisted" state only.</p>
|
|
538
|
+
<div class="gallery">
|
|
539
|
+
|
|
540
|
+
<div class="spec-frame">
|
|
541
|
+
<div class="sf-name">DiscoveryCarousel ★ <span>· at rest</span></div>
|
|
542
|
+
<div class="wcard"><div class="wcard-head"><span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span><span class="wc-title">Acme Getaways</span><span class="wc-chip">Discover</span></div><div class="wcard-body">
|
|
543
|
+
<div class="dest-track">
|
|
544
|
+
<div class="dcard"><div class="dcard-head"><span class="dcard-name">Coral Bay</span><span class="dcard-price">from $890</span></div><div class="dcard-region">Adriatic coast · best May–Sep</div><div class="dcard-why">Calm swimming coves and a walkable old town.</div><span class="dcard-btn">Shortlist</span></div>
|
|
545
|
+
</div>
|
|
546
|
+
<div class="cta disabled">Continue on Acme</div>
|
|
547
|
+
<div class="standing">Booking and payment happen on acme.example.</div>
|
|
548
|
+
</div></div>
|
|
549
|
+
</div>
|
|
550
|
+
|
|
551
|
+
<div class="spec-frame">
|
|
552
|
+
<div class="sf-name">DiscoveryCarousel <span>· shortlisted state</span></div>
|
|
553
|
+
<div class="wcard"><div class="wcard-head"><span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span><span class="wc-title">Acme Getaways</span><span class="wc-chip">Discover</span></div><div class="wcard-body">
|
|
554
|
+
<div class="wc-status" style="color:#067e7c;">Shortlisted Harbor City.</div>
|
|
555
|
+
<div class="dest-track">
|
|
556
|
+
<div class="dcard active"><div class="dcard-head"><span class="dcard-name">Harbor City</span><span class="dcard-price">from $980</span></div><div class="dcard-region">Pacific rim · best Sep–Nov</div><span class="dcard-btn on">✓ Shortlisted</span></div>
|
|
557
|
+
</div>
|
|
558
|
+
<div class="cta"><svg viewBox="0 0 24 24"><path d="M14 4h6v6"/><path d="m20 4-9 9"/><path d="M20 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5"/></svg>Continue on Acme · Harbor City</div>
|
|
559
|
+
</div></div>
|
|
560
|
+
</div>
|
|
561
|
+
|
|
562
|
+
<div class="spec-frame">
|
|
563
|
+
<div class="sf-name">DiscoveryCarousel <span>· pending handoff</span></div>
|
|
564
|
+
<div class="wcard"><div class="wcard-head"><span class="wc-logo"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5 5-2Z"/></svg></span><span class="wc-title">Acme Getaways</span><span class="wc-chip">Discover</span></div><div class="wcard-body">
|
|
565
|
+
<div class="dest-track">
|
|
566
|
+
<div class="dcard active"><div class="dcard-head"><span class="dcard-name">Monte Alto</span><span class="dcard-price">from $1,120</span></div><div class="dcard-region">Northern Alps · best Dec–Mar</div><span class="dcard-btn on">✓ Shortlisted</span></div>
|
|
567
|
+
</div>
|
|
568
|
+
<div class="cta disabled">Opening Acme…</div>
|
|
569
|
+
<div class="standing">Booking and payment happen on acme.example.</div>
|
|
570
|
+
</div></div>
|
|
571
|
+
</div>
|
|
572
|
+
|
|
573
|
+
</div>
|
|
574
|
+
</div>
|
|
575
|
+
|
|
576
|
+
<!-- MCP TOOLS APPENDIX -->
|
|
577
|
+
<div class="section" id="tools">
|
|
578
|
+
<span class="section-label">Technical appendix</span>
|
|
579
|
+
<h2 class="section-title">MCP Tools & Call Sequence</h2>
|
|
580
|
+
<p class="section-subtitle">Every tool that appears in a wireframe, grouped by journey phase, with the intent behind each call. Server: <span class="mono">acme_discovery</span>. Three tools, one widget.</p>
|
|
581
|
+
|
|
582
|
+
<div class="api-panel">
|
|
583
|
+
<h4>Discover & Shortlist (Steps 1–3)</h4>
|
|
584
|
+
<div class="ap-sub">The in-chat loop — grounded, account-free, transaction-free.</div>
|
|
585
|
+
<div class="api-step">
|
|
586
|
+
<div class="an">1</div>
|
|
587
|
+
<div class="ac">
|
|
588
|
+
<div class="tool">discover_getaways<span class="kind">toolWithWidget</span></div>
|
|
589
|
+
<div class="api-note">In <code>{ vibe, month, travelers }</code> → out <code>{ status, vibe, month, travelers, options[] }</code> and renders <code>DiscoveryCarousel</code>. Returns the <strong>full curated catalog verbatim</strong> (4 destinations); the model narrates fit. Host status: "Finding getaways…" → "Getaways ready". <code>read-only</code>.</div>
|
|
590
|
+
</div>
|
|
591
|
+
</div>
|
|
592
|
+
<div class="api-step">
|
|
593
|
+
<div class="an">2</div>
|
|
594
|
+
<div class="ac">
|
|
595
|
+
<div class="tool">shortlist_getaway<span class="kind">toolForWidget</span></div>
|
|
596
|
+
<div class="api-note">In <code>{ destination, note }</code> → out <code>{ status, destination, note }</code>. Called from inside the carousel when a card's <strong>Shortlist</strong> is tapped; updates widget view-state. <code>local-action</code>, non-destructive — not a booking.</div>
|
|
597
|
+
</div>
|
|
598
|
+
</div>
|
|
599
|
+
<div class="api-step">
|
|
600
|
+
<div class="an">3</div>
|
|
601
|
+
<div class="ac">
|
|
602
|
+
<div class="tool">discover_getaways<span class="kind">re-invoke</span></div>
|
|
603
|
+
<div class="api-note">A natural-language vibe/month/party change re-invokes discovery with the updated input; unchanged values persist so the traveler isn't re-asked. The carousel re-renders in place.</div>
|
|
604
|
+
</div>
|
|
605
|
+
</div>
|
|
606
|
+
</div>
|
|
607
|
+
|
|
608
|
+
<div class="api-panel">
|
|
609
|
+
<h4>Handoff (Step 4 → off-app)</h4>
|
|
610
|
+
<div class="ap-sub">The single deliberate exit — signed, attributable, credential-free.</div>
|
|
611
|
+
<div class="api-step">
|
|
612
|
+
<div class="an">4</div>
|
|
613
|
+
<div class="ac">
|
|
614
|
+
<div class="tool">create_handoff<span class="kind">tool · open-link</span></div>
|
|
615
|
+
<div class="api-note">In <code>{ destination, destinationName, month, travelers }</code> → out <code>{ status, destination, summary, handoffUrl }</code>. Builds <code>https://book.acme.example/plan?dest={destination}&month={month}&pax={travelers}&src=chatgpt</code> by direct substitution of already-URL-safe values. The widget calls it, then opens <code>handoffUrl</code>. Domain declared in <code>handoff.allowedDomains</code> (<code>book.acme.example</code>, <code>acme.example</code>) so the compiler derives ChatGPT's redirect domains. <code>open-action</code>.</div>
|
|
616
|
+
</div>
|
|
617
|
+
</div>
|
|
618
|
+
</div>
|
|
619
|
+
</div>
|
|
620
|
+
|
|
621
|
+
<!-- COMPLIANCE AUDIT -->
|
|
622
|
+
<div class="section" id="audit">
|
|
623
|
+
<span class="section-label">Submission evidence</span>
|
|
624
|
+
<h2 class="section-title">OpenAI Apps SDK Compliance Audit</h2>
|
|
625
|
+
<p class="section-subtitle">Each row cites concrete app behavior, not aspiration. Reference: the OpenAI Apps SDK UX Principles + UI Guidelines. Verify against the built app with <span class="mono">noodle check --target chatgpt</span> before submission.</p>
|
|
626
|
+
|
|
627
|
+
<table class="audit-table">
|
|
628
|
+
<tr><th>OpenAI Requirement</th><th>How the Acme Getaways app addresses it</th><th>Status</th></tr>
|
|
629
|
+
<tr><td class="req">Conversational value</td><td>A traveler expresses a fuzzy feeling in natural language ("warm, walkable, June, two of us"); the model maps it to <code>vibe · month · travelers</code> and returns grounded options — something no tap-driven form does as fluidly.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
630
|
+
<tr><td class="req">Beyond base ChatGPT</td><td>Acme's own curated catalog (places, "from" prices, best-months, reasons) and a signed, attributable handoff — knowledge and an action base ChatGPT cannot provide.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
631
|
+
<tr><td class="req">Atomic, model-friendly actions</td><td>Three self-contained tools with explicit Zod input/output schemas: <code>discover_getaways</code>, <code>shortlist_getaway</code>, <code>create_handoff</code>. No ambiguity; all inputs fillable from language.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
632
|
+
<tr><td class="req">Helpful UI only</td><td>The carousel earns its widget: visual scanning of four options with price/season/reason, plus a shortlist gesture. No payment or checkout widget is built — booking is off-app by design.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
633
|
+
<tr><td class="req">In-chat task completion</td><td>The task — discover, shortlist, and shape a getaway — completes in chat; the booking is an intentional handoff, not an unfinished flow.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
634
|
+
<tr><td class="req">Performance & responsiveness</td><td>Static curated data and string-substitution handoff — no live inventory call and no AI in the tool path; carousel renders in one round-trip.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
635
|
+
<tr><td class="req">Discoverability</td><td>Broad natural triggers ("beach trip in June", "cheapest getaway for two", "somewhere good in December"). Golden-prompt set + app-description keywords are a launch workstream.</td><td><span class="pass flag">PLAN</span></td></tr>
|
|
636
|
+
<tr><td class="req">Platform fit</td><td>Rich prompts, multi-turn deliberation (re-shape on vibe/month change), lightweight per-session memory (trip shape + shortlist). No multimodality claimed where it isn't real.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
637
|
+
</table>
|
|
638
|
+
|
|
639
|
+
<div class="audit-sub">UI Guidelines Compliance</div>
|
|
640
|
+
<table class="audit-table">
|
|
641
|
+
<tr><th>Guideline</th><th>How the app addresses it</th><th>Status</th></tr>
|
|
642
|
+
<tr><td class="req">Design tokens (no vendor lock)</td><td>Styling driven by Noodle Seed server <code>branding</code> tokens (accent <code>#0EA5A4</code>, surface, radius, density) via CSS cascade layers — no app-specific global CSS.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
643
|
+
<tr><td class="req">Accent restraint</td><td>Acme teal appears only on the primary <strong>Continue on Acme</strong> CTA, the compass logo mark, and the active "Shortlisted" state. Everything else is neutral system surface.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
644
|
+
<tr><td class="req">System fonts</td><td>System font stack throughout the widget; no custom web font shipped to the host.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
645
|
+
<tr><td class="req">Monochrome outlined icons</td><td>Compass (header) and external-link (CTA) are single-stroke outlined SVGs, no fills.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
646
|
+
<tr><td class="req">WCAG AA contrast</td><td>Text/surface pairs meet AA in light and dark; the widget reads <code>theme</code> from <code>useLayout()</code> and applies <code>surfaceDark</code> (<code>#0B1B1B</code>).</td><td><span class="pass ok">PASS</span></td></tr>
|
|
647
|
+
<tr><td class="req">≤2 actions on inline cards</td><td>Each destination card has one action (Shortlist toggle); the shell has one primary CTA. Never more than two.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
648
|
+
<tr><td class="req">No nested scroll</td><td>The carousel is a single scroll surface; no scroll-within-scroll region.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
649
|
+
<tr><td class="req">Correct display-mode usage</td><td>Inline carousel for discovery; the same component in fullscreen for full-catalog browse. No PiP (no live session), no in-chat checkout.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
650
|
+
</table>
|
|
651
|
+
|
|
652
|
+
<div class="audit-sub">Domain Guardrail Rows (travel-specific)</div>
|
|
653
|
+
<table class="audit-table">
|
|
654
|
+
<tr><th>Guardrail</th><th>How the app enforces it</th><th>Status</th></tr>
|
|
655
|
+
<tr><td class="req">Never invent catalog data</td><td>Only the four curated destinations exist; every place, price, best-month, and reason is returned verbatim from Acme's catalog — the model narrates, never fabricates.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
656
|
+
<tr><td class="req">"From" pricing, never a quote</td><td>Prices always render as "from $X"; the dated, party-sized price is computed only on Acme's booking flow.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
657
|
+
<tr><td class="req">Honest funnel boundary</td><td>The standing note "Booking and payment happen on acme.example — never inside chat." is always visible; the CTA always reads "Continue on Acme". No availability is asserted in chat.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
658
|
+
<tr><td class="req">Credential-free handoff</td><td>The deep link carries only <code>dest · month · pax · src</code> — no PII, no token; the traveler authenticates and pays on Acme.</td><td><span class="pass ok">PASS</span></td></tr>
|
|
659
|
+
</table>
|
|
660
|
+
</div>
|
|
661
|
+
|
|
662
|
+
</div>
|
|
663
|
+
|
|
664
|
+
<div class="footer">
|
|
665
|
+
Acme Getaways × ChatGPT — Discovery Top-of-Funnel Wireframes · Noodle Seed · v1 · 2026<br>
|
|
666
|
+
Acme Getaways is a fictional brand; catalog, prices & best-months are the app's own curated data, internally consistent with <span class="mono">src/server.ts</span>. Verify Apps SDK compliance with <span class="mono">noodle check --target chatgpt</span> at build time.
|
|
667
|
+
</div>
|
|
668
|
+
|
|
669
|
+
</body>
|
|
670
|
+
</html>
|