@ucptools/validator 1.0.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.
Files changed (121) hide show
  1. package/CLAUDE.md +109 -0
  2. package/CONTRIBUTING.md +113 -0
  3. package/LICENSE +21 -0
  4. package/README.md +203 -0
  5. package/api/analyze-feed.js +140 -0
  6. package/api/badge.js +185 -0
  7. package/api/benchmark.js +177 -0
  8. package/api/directory-stats.ts +29 -0
  9. package/api/directory.ts +73 -0
  10. package/api/generate-compliance.js +143 -0
  11. package/api/generate-schema.js +457 -0
  12. package/api/generate.js +132 -0
  13. package/api/security-scan.js +133 -0
  14. package/api/simulate.js +187 -0
  15. package/api/tsconfig.json +10 -0
  16. package/api/validate.js +1351 -0
  17. package/apify-actor/.actor/actor.json +68 -0
  18. package/apify-actor/.actor/input_schema.json +32 -0
  19. package/apify-actor/APIFY-STORE-LISTING.md +412 -0
  20. package/apify-actor/Dockerfile +8 -0
  21. package/apify-actor/README.md +166 -0
  22. package/apify-actor/main.ts +111 -0
  23. package/apify-actor/package.json +17 -0
  24. package/apify-actor/src/main.js +199 -0
  25. package/docs/BRAND-IDENTITY.md +238 -0
  26. package/docs/BRAND-STYLE-GUIDE.md +356 -0
  27. package/drizzle/0000_black_king_cobra.sql +39 -0
  28. package/drizzle/meta/0000_snapshot.json +309 -0
  29. package/drizzle/meta/_journal.json +13 -0
  30. package/drizzle.config.ts +10 -0
  31. package/examples/full-profile.json +70 -0
  32. package/examples/minimal-profile.json +23 -0
  33. package/package.json +69 -0
  34. package/public/.well-known/ucp +25 -0
  35. package/public/android-chrome-192x192.png +0 -0
  36. package/public/android-chrome-512x512.png +0 -0
  37. package/public/apple-touch-icon.png +0 -0
  38. package/public/brand.css +321 -0
  39. package/public/directory.html +701 -0
  40. package/public/favicon-16x16.png +0 -0
  41. package/public/favicon-32x32.png +0 -0
  42. package/public/favicon.ico +0 -0
  43. package/public/guides/bigcommerce.html +743 -0
  44. package/public/guides/fastucp.html +838 -0
  45. package/public/guides/magento.html +779 -0
  46. package/public/guides/shopify.html +726 -0
  47. package/public/guides/squarespace.html +749 -0
  48. package/public/guides/wix.html +747 -0
  49. package/public/guides/woocommerce.html +733 -0
  50. package/public/index.html +3835 -0
  51. package/public/learn.html +396 -0
  52. package/public/logo.jpeg +0 -0
  53. package/public/og-image-icon.png +0 -0
  54. package/public/og-image.png +0 -0
  55. package/public/robots.txt +6 -0
  56. package/public/site.webmanifest +31 -0
  57. package/public/sitemap.xml +69 -0
  58. package/public/social/linkedin-banner-1128x191.png +0 -0
  59. package/public/social/temp.PNG +0 -0
  60. package/public/social/x-header-1500x500.png +0 -0
  61. package/public/verify.html +410 -0
  62. package/scripts/generate-favicons.js +44 -0
  63. package/scripts/generate-ico.js +23 -0
  64. package/scripts/generate-og-image.js +45 -0
  65. package/scripts/reset-db.ts +77 -0
  66. package/scripts/seed-db.ts +71 -0
  67. package/scripts/setup-benchmark-db.js +70 -0
  68. package/src/api/server.ts +266 -0
  69. package/src/cli/index.ts +302 -0
  70. package/src/compliance/compliance-generator.ts +452 -0
  71. package/src/compliance/index.ts +28 -0
  72. package/src/compliance/templates.ts +338 -0
  73. package/src/compliance/types.ts +170 -0
  74. package/src/db/index.ts +28 -0
  75. package/src/db/schema.ts +84 -0
  76. package/src/feed-analyzer/feed-analyzer.ts +726 -0
  77. package/src/feed-analyzer/index.ts +34 -0
  78. package/src/feed-analyzer/types.ts +354 -0
  79. package/src/generator/index.ts +7 -0
  80. package/src/generator/key-generator.ts +124 -0
  81. package/src/generator/profile-builder.ts +402 -0
  82. package/src/hosting/artifacts-generator.ts +679 -0
  83. package/src/hosting/index.ts +6 -0
  84. package/src/index.ts +105 -0
  85. package/src/security/index.ts +15 -0
  86. package/src/security/security-scanner.ts +604 -0
  87. package/src/security/types.ts +55 -0
  88. package/src/services/directory.ts +434 -0
  89. package/src/simulator/agent-simulator.ts +941 -0
  90. package/src/simulator/index.ts +7 -0
  91. package/src/simulator/types.ts +170 -0
  92. package/src/types/generator.ts +140 -0
  93. package/src/types/index.ts +7 -0
  94. package/src/types/ucp-profile.ts +140 -0
  95. package/src/types/validation.ts +89 -0
  96. package/src/validator/index.ts +194 -0
  97. package/src/validator/network-validator.ts +417 -0
  98. package/src/validator/rules-validator.ts +297 -0
  99. package/src/validator/sdk-validator.ts +330 -0
  100. package/src/validator/structural-validator.ts +476 -0
  101. package/tests/fixtures/non-compliant-profile.json +25 -0
  102. package/tests/fixtures/official-sample-profile.json +75 -0
  103. package/tests/integration/benchmark.test.ts +207 -0
  104. package/tests/integration/database.test.ts +163 -0
  105. package/tests/integration/directory-api.test.ts +268 -0
  106. package/tests/integration/simulate-api.test.ts +230 -0
  107. package/tests/integration/validate-api.test.ts +269 -0
  108. package/tests/setup.ts +15 -0
  109. package/tests/unit/agent-simulator.test.ts +575 -0
  110. package/tests/unit/compliance-generator.test.ts +374 -0
  111. package/tests/unit/directory-service.test.ts +272 -0
  112. package/tests/unit/feed-analyzer.test.ts +517 -0
  113. package/tests/unit/lint-suggestions.test.ts +423 -0
  114. package/tests/unit/official-samples.test.ts +211 -0
  115. package/tests/unit/pdf-report.test.ts +390 -0
  116. package/tests/unit/sdk-validator.test.ts +531 -0
  117. package/tests/unit/security-scanner.test.ts +410 -0
  118. package/tests/unit/validation.test.ts +390 -0
  119. package/tsconfig.json +20 -0
  120. package/vercel.json +34 -0
  121. package/vitest.config.ts +22 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * UCP Profile Validator - Apify Actor
3
+ * Validates any domain's UCP Business Profile at /.well-known/ucp
4
+ *
5
+ * Free tier: validation + report
6
+ * Paid tier: generation + monitoring
7
+ */
8
+
9
+ import { Actor } from 'apify';
10
+ import { validateRemote, validateQuick } from '../src/validator/index.js';
11
+
12
+ interface Input {
13
+ domain: string;
14
+ mode?: 'quick' | 'full';
15
+ includeRecommendations?: boolean;
16
+ }
17
+
18
+ interface Output {
19
+ domain: string;
20
+ profileUrl: string;
21
+ valid: boolean;
22
+ score: number;
23
+ grade: 'A' | 'B' | 'C' | 'D' | 'F';
24
+ ucpVersion?: string;
25
+ errors: number;
26
+ warnings: number;
27
+ issues: Array<{
28
+ severity: string;
29
+ code: string;
30
+ message: string;
31
+ hint?: string;
32
+ }>;
33
+ recommendations?: string[];
34
+ checkedAt: string;
35
+ // CTA for monetization
36
+ upgradeUrl: string;
37
+ }
38
+
39
+ await Actor.init();
40
+
41
+ const input = await Actor.getInput<Input>();
42
+
43
+ if (!input?.domain) {
44
+ throw new Error('Missing required input: domain');
45
+ }
46
+
47
+ const domain = input.domain.replace(/^https?:\/\//, '').replace(/\/$/, '');
48
+
49
+ console.log(`Validating UCP profile for: ${domain}`);
50
+
51
+ const report = await validateRemote(domain, {
52
+ mode: input.mode === 'quick' ? 'rules' : 'full',
53
+ });
54
+
55
+ const profileUrl = report.profile_url || `https://${domain}/.well-known/ucp`;
56
+
57
+ // Calculate score (0-100)
58
+ const errorWeight = 20;
59
+ const warnWeight = 5;
60
+ const errors = report.issues.filter(i => i.severity === 'error').length;
61
+ const warnings = report.issues.filter(i => i.severity === 'warn').length;
62
+ const score = Math.max(0, 100 - (errors * errorWeight) - (warnings * warnWeight));
63
+
64
+ // Calculate grade
65
+ const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : score >= 60 ? 'D' : 'F';
66
+
67
+ // Generate recommendations
68
+ const recommendations: string[] = [];
69
+ if (errors > 0) {
70
+ recommendations.push('Fix all errors before going live with UCP-enabled agents');
71
+ }
72
+ if (!report.ucp_version) {
73
+ recommendations.push('Ensure your profile is accessible at /.well-known/ucp');
74
+ }
75
+ if (report.issues.some(i => i.code === 'UCP_MISSING_SIGNING_KEYS')) {
76
+ recommendations.push('Add signing_keys if you plan to use Order capability with webhooks');
77
+ }
78
+ if (report.issues.some(i => i.code === 'UCP_ENDPOINT_NOT_HTTPS')) {
79
+ recommendations.push('All endpoints must use HTTPS for security');
80
+ }
81
+ if (score === 100) {
82
+ recommendations.push('Your profile is fully compliant! Consider adding more capabilities.');
83
+ }
84
+
85
+ const output: Output = {
86
+ domain,
87
+ profileUrl,
88
+ valid: report.ok,
89
+ score,
90
+ grade,
91
+ ucpVersion: report.ucp_version,
92
+ errors,
93
+ warnings,
94
+ issues: report.issues.map(i => ({
95
+ severity: i.severity,
96
+ code: i.code,
97
+ message: i.message,
98
+ hint: i.hint,
99
+ })),
100
+ recommendations: input.includeRecommendations !== false ? recommendations : undefined,
101
+ checkedAt: report.validated_at,
102
+ upgradeUrl: 'https://ucp.tools/generate?ref=apify',
103
+ };
104
+
105
+ console.log(`\nValidation complete: ${grade} (${score}/100)`);
106
+ console.log(`Errors: ${errors}, Warnings: ${warnings}`);
107
+
108
+ await Actor.pushData(output);
109
+ await Actor.setValue('OUTPUT', output);
110
+
111
+ await Actor.exit();
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "ucp-profile-validator-actor",
3
+ "version": "1.0.0",
4
+ "description": "Apify Actor: Validate UCP Business Profiles",
5
+ "type": "module",
6
+ "main": "src/main.js",
7
+ "scripts": {
8
+ "start": "node src/main.js",
9
+ "test": "echo \"No tests yet\""
10
+ },
11
+ "dependencies": {
12
+ "apify": "^3.1.0"
13
+ },
14
+ "engines": {
15
+ "node": ">=18"
16
+ }
17
+ }
@@ -0,0 +1,199 @@
1
+ /**
2
+ * UCP Profile Validator - Apify Actor
3
+ * Validates any domain's UCP Business Profile at /.well-known/ucp
4
+ */
5
+
6
+ import { Actor } from 'apify';
7
+
8
+ const VERSION_REGEX = /^\d{4}-\d{2}-\d{2}$/;
9
+
10
+ async function fetchProfile(domain) {
11
+ // Try both /.well-known/ucp and /.well-known/ucp.json
12
+ const urls = [
13
+ `https://${domain}/.well-known/ucp`,
14
+ `https://${domain}/.well-known/ucp.json`,
15
+ ];
16
+
17
+ for (const url of urls) {
18
+ try {
19
+ const res = await fetch(url, {
20
+ headers: { 'Accept': 'application/json', 'User-Agent': 'UCP-Validator-Apify/1.0' },
21
+ signal: AbortSignal.timeout(15000),
22
+ });
23
+
24
+ if (!res.ok) continue;
25
+
26
+ const text = await res.text();
27
+ // Check if response looks like JSON (not HTML)
28
+ if (text.trim().startsWith('<')) continue;
29
+
30
+ const profile = JSON.parse(text);
31
+ return { profile, profileUrl: url };
32
+ } catch (e) {
33
+ // Try next URL
34
+ continue;
35
+ }
36
+ }
37
+
38
+ return { profile: null, error: 'No UCP profile found at /.well-known/ucp or /.well-known/ucp.json' };
39
+ }
40
+
41
+ function validateProfile(profile) {
42
+ const issues = [];
43
+
44
+ if (!profile || typeof profile !== 'object') {
45
+ issues.push({ severity: 'error', code: 'UCP_MISSING_ROOT', path: '$', message: 'Profile must be a JSON object' });
46
+ return issues;
47
+ }
48
+
49
+ if (!profile.ucp || typeof profile.ucp !== 'object') {
50
+ issues.push({ severity: 'error', code: 'UCP_MISSING_ROOT', path: '$.ucp', message: 'Missing required "ucp" object' });
51
+ return issues;
52
+ }
53
+
54
+ const ucp = profile.ucp;
55
+
56
+ // Version validation
57
+ if (!ucp.version) {
58
+ issues.push({ severity: 'error', code: 'UCP_MISSING_VERSION', path: '$.ucp.version', message: 'Missing version field' });
59
+ } else if (!VERSION_REGEX.test(ucp.version)) {
60
+ issues.push({ severity: 'error', code: 'UCP_INVALID_VERSION', path: '$.ucp.version', message: `Invalid version: ${ucp.version}`, hint: 'Use YYYY-MM-DD format' });
61
+ }
62
+
63
+ // Services validation
64
+ if (!ucp.services || typeof ucp.services !== 'object') {
65
+ issues.push({ severity: 'error', code: 'UCP_MISSING_SERVICES', path: '$.ucp.services', message: 'Missing services' });
66
+ } else {
67
+ for (const [name, svc] of Object.entries(ucp.services)) {
68
+ if (!svc.version) issues.push({ severity: 'error', code: 'UCP_INVALID_SERVICE', path: `$.ucp.services["${name}"].version`, message: `Service "${name}" missing version` });
69
+ if (!svc.spec) issues.push({ severity: 'error', code: 'UCP_INVALID_SERVICE', path: `$.ucp.services["${name}"].spec`, message: `Service "${name}" missing spec` });
70
+ if (!svc.rest && !svc.mcp && !svc.a2a && !svc.embedded) {
71
+ issues.push({ severity: 'warn', code: 'UCP_NO_TRANSPORT', path: `$.ucp.services["${name}"]`, message: `Service "${name}" has no transport bindings` });
72
+ }
73
+ if (svc.rest?.endpoint) {
74
+ if (!svc.rest.endpoint.startsWith('https://')) {
75
+ issues.push({ severity: 'error', code: 'UCP_ENDPOINT_NOT_HTTPS', path: `$.ucp.services["${name}"].rest.endpoint`, message: 'Endpoint must use HTTPS' });
76
+ }
77
+ if (svc.rest.endpoint.endsWith('/')) {
78
+ issues.push({ severity: 'warn', code: 'UCP_TRAILING_SLASH', path: `$.ucp.services["${name}"].rest.endpoint`, message: 'Remove trailing slash' });
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ // Capabilities validation
85
+ if (!ucp.capabilities || !Array.isArray(ucp.capabilities)) {
86
+ issues.push({ severity: 'error', code: 'UCP_MISSING_CAPABILITIES', path: '$.ucp.capabilities', message: 'Missing capabilities array' });
87
+ } else {
88
+ const capNames = new Set(ucp.capabilities.map(c => c.name));
89
+ ucp.capabilities.forEach((cap, i) => {
90
+ const path = `$.ucp.capabilities[${i}]`;
91
+ if (!cap.name) issues.push({ severity: 'error', code: 'UCP_INVALID_CAP', path: `${path}.name`, message: 'Missing name' });
92
+ if (!cap.version) issues.push({ severity: 'error', code: 'UCP_INVALID_CAP', path: `${path}.version`, message: 'Missing version' });
93
+ if (!cap.spec) issues.push({ severity: 'error', code: 'UCP_INVALID_CAP', path: `${path}.spec`, message: 'Missing spec' });
94
+ if (!cap.schema) issues.push({ severity: 'error', code: 'UCP_INVALID_CAP', path: `${path}.schema`, message: 'Missing schema' });
95
+
96
+ // Namespace checks
97
+ if (cap.name?.startsWith('dev.ucp.')) {
98
+ if (cap.spec && !cap.spec.startsWith('https://ucp.dev/')) {
99
+ issues.push({ severity: 'error', code: 'UCP_NS_MISMATCH', path: `${path}.spec`, message: 'dev.ucp.* spec must be on ucp.dev' });
100
+ }
101
+ if (cap.schema && !cap.schema.startsWith('https://ucp.dev/')) {
102
+ issues.push({ severity: 'error', code: 'UCP_NS_MISMATCH', path: `${path}.schema`, message: 'dev.ucp.* schema must be on ucp.dev' });
103
+ }
104
+ }
105
+
106
+ // Extension checks
107
+ if (cap.extends && !capNames.has(cap.extends)) {
108
+ issues.push({ severity: 'error', code: 'UCP_ORPHAN_EXT', path: `${path}.extends`, message: `Parent "${cap.extends}" not found` });
109
+ }
110
+ });
111
+
112
+ // Signing keys check
113
+ const hasOrder = ucp.capabilities.some(c => c.name === 'dev.ucp.shopping.order');
114
+ if (hasOrder && (!profile.signing_keys || profile.signing_keys.length === 0)) {
115
+ issues.push({ severity: 'error', code: 'UCP_MISSING_KEYS', path: '$.signing_keys', message: 'Order requires signing_keys' });
116
+ }
117
+ }
118
+
119
+ return issues;
120
+ }
121
+
122
+ await Actor.init();
123
+
124
+ const input = await Actor.getInput();
125
+
126
+ if (!input?.domain) {
127
+ throw new Error('Missing required input: domain');
128
+ }
129
+
130
+ const domain = input.domain.replace(/^https?:\/\//, '').replace(/\/$/, '');
131
+
132
+ console.log(`🔍 Validating UCP profile for: ${domain}`);
133
+
134
+ const { profile, profileUrl: foundProfileUrl, error } = await fetchProfile(domain);
135
+ const profileUrl = foundProfileUrl || `https://${domain}/.well-known/ucp`;
136
+
137
+ let issues = [];
138
+ let ucpVersion = null;
139
+
140
+ if (error || !profile) {
141
+ issues.push({
142
+ severity: 'error',
143
+ code: 'UCP_FETCH_FAILED',
144
+ path: '$.well-known/ucp',
145
+ message: error || 'Failed to fetch profile',
146
+ });
147
+ } else {
148
+ issues = validateProfile(profile);
149
+ ucpVersion = profile?.ucp?.version;
150
+ }
151
+
152
+ // Calculate score
153
+ const errors = issues.filter(i => i.severity === 'error').length;
154
+ const warnings = issues.filter(i => i.severity === 'warn').length;
155
+ const score = Math.max(0, 100 - (errors * 20) - (warnings * 5));
156
+ const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : score >= 60 ? 'D' : 'F';
157
+
158
+ // Recommendations
159
+ const recommendations = [];
160
+ if (errors > 0) recommendations.push('Fix all errors before deploying');
161
+ if (!ucpVersion) recommendations.push('Ensure profile is accessible at /.well-known/ucp');
162
+ if (issues.some(i => i.code === 'UCP_MISSING_KEYS')) recommendations.push('Add signing_keys for Order capability');
163
+ if (score === 100) recommendations.push('Profile is fully compliant!');
164
+
165
+ const output = {
166
+ domain,
167
+ profileUrl,
168
+ valid: errors === 0,
169
+ score,
170
+ grade,
171
+ ucpVersion,
172
+ errors,
173
+ warnings,
174
+ issues: issues.map(i => ({
175
+ severity: i.severity,
176
+ code: i.code,
177
+ message: i.message,
178
+ hint: i.hint,
179
+ })),
180
+ recommendations: input.includeRecommendations !== false ? recommendations : undefined,
181
+ checkedAt: new Date().toISOString(),
182
+ generatorUrl: 'https://ucptools.dev/generate',
183
+ };
184
+
185
+ console.log(`\n📊 Result: ${grade} (${score}/100)`);
186
+ console.log(` Errors: ${errors}, Warnings: ${warnings}`);
187
+ if (errors === 0) {
188
+ console.log('✅ Profile is valid!');
189
+ } else {
190
+ console.log('❌ Profile has issues that need to be fixed');
191
+ }
192
+
193
+ // Push result to dataset
194
+ // Note: Using PPE with synthetic 'apify-default-dataset-item' event
195
+ // This automatically charges users per result - no manual Actor.charge() needed
196
+ await Actor.pushData(output);
197
+ await Actor.setValue('OUTPUT', output);
198
+
199
+ await Actor.exit();
@@ -0,0 +1,238 @@
1
+ # UCP.tools - Brand Identity Guide
2
+
3
+ ## Brand Overview
4
+
5
+ **UCP.tools** is an independent developer tool that helps merchants prepare for AI-powered commerce by validating and generating Universal Commerce Protocol (UCP) business profiles.
6
+
7
+ ---
8
+
9
+ ## Brand Name & Variations
10
+
11
+ | Context | Usage |
12
+ |---------|-------|
13
+ | **Primary** | UCP.tools |
14
+ | **Domain** | ucptools.dev (or ucptools.io as fallback) |
15
+ | **Apify Actor** | UCP Profile Validator |
16
+ | **npm package** | ucp-profile-tools |
17
+ | **GitHub** | ucp-tools |
18
+ | **Tagline** | "Get ready for AI commerce" |
19
+ | **Short tagline** | "Validate. Generate. Ship." |
20
+
21
+ ---
22
+
23
+ ## Brand Voice & Personality
24
+
25
+ ### Tone
26
+ - **Developer-first**: Technical but approachable
27
+ - **Direct**: No fluff, get to the point
28
+ - **Helpful**: Focus on solving problems
29
+ - **Independent**: Not affiliated with any platform
30
+
31
+ ### Language Style
32
+ - Use "you/your" not "users/merchants"
33
+ - Active voice: "Validate your profile" not "Profiles can be validated"
34
+ - Confident: "Fix issues instantly" not "May help fix issues"
35
+ - No corporate jargon: "Check" not "Leverage our validation capabilities"
36
+
37
+ ### Example Copy
38
+
39
+ **Good:**
40
+ > "Your UCP profile has 2 errors. Here's how to fix them."
41
+
42
+ **Bad:**
43
+ > "Our comprehensive validation engine has detected potential compliance issues in your Universal Commerce Protocol business profile configuration."
44
+
45
+ ---
46
+
47
+ ## Visual Identity
48
+
49
+ ### Colors
50
+
51
+ | Name | Hex | Usage |
52
+ |------|-----|-------|
53
+ | **Primary Blue** | `#2563eb` | Buttons, links, accents |
54
+ | **Primary Dark** | `#1d4ed8` | Hover states |
55
+ | **Success Green** | `#16a34a` | Valid, success states |
56
+ | **Warning Amber** | `#ca8a04` | Warnings |
57
+ | **Error Red** | `#dc2626` | Errors, invalid states |
58
+ | **Background** | `#f8fafc` | Page background |
59
+ | **Card White** | `#ffffff` | Cards, panels |
60
+ | **Text Dark** | `#1e293b` | Primary text |
61
+ | **Text Muted** | `#64748b` | Secondary text |
62
+ | **Border** | `#e2e8f0` | Borders, dividers |
63
+
64
+ ### Typography
65
+
66
+ - **Headings**: System font stack (SF Pro, Segoe UI, Roboto)
67
+ - **Body**: Same system font stack
68
+ - **Code**: Monospace (SF Mono, Consolas, Monaco)
69
+ - **Font weights**: 400 (normal), 500 (medium), 600 (semibold), 700 (bold)
70
+
71
+ ### Logo Concepts
72
+
73
+ **Text Logo:**
74
+ ```
75
+ UCP.tools
76
+ ```
77
+ - "UCP" in Primary Blue (#2563eb), bold
78
+ - ".tools" in Text Muted (#64748b), normal weight
79
+
80
+ **Icon Concepts:**
81
+ - Checkmark inside a document/file icon
82
+ - Shield with checkmark (security/validation)
83
+ - Interconnected nodes (protocol/commerce)
84
+
85
+ ### Grade Badges (Validation Scores)
86
+
87
+ | Grade | Background | Text Color |
88
+ |-------|------------|------------|
89
+ | A | `#dcfce7` | `#16a34a` |
90
+ | B | `#dbeafe` | `#2563eb` |
91
+ | C | `#fef9c3` | `#ca8a04` |
92
+ | D | `#fed7aa` | `#ea580c` |
93
+ | F | `#fee2e2` | `#dc2626` |
94
+
95
+ ---
96
+
97
+ ## Messaging Framework
98
+
99
+ ### Elevator Pitch (10 seconds)
100
+ > "UCP.tools validates and generates UCP business profiles so your store is ready for AI shopping agents."
101
+
102
+ ### Short Description (30 seconds)
103
+ > "UCP.tools is a free validator and generator for Universal Commerce Protocol profiles. Check if your /.well-known/ucp endpoint is correct, generate compliant profiles, and get ready for AI-powered commerce - in seconds."
104
+
105
+ ### Full Description (Product Hunt / Apify Store)
106
+ > "The Universal Commerce Protocol (UCP) lets AI agents discover and transact with online stores. But getting your profile right is tricky - wrong namespaces, missing fields, and endpoint issues break agent compatibility.
107
+ >
108
+ > UCP.tools fixes that:
109
+ > - **Validate** any domain's UCP profile instantly
110
+ > - **Generate** compliant profiles with a simple wizard
111
+ > - **Get actionable fixes** for every issue found
112
+ > - **Score your readiness** with A-F grades
113
+ >
114
+ > Free to use. No signup required. Built by developers, for developers."
115
+
116
+ ### Key Messages
117
+
118
+ 1. **Problem**: "AI agents can't discover your store if your UCP profile is broken"
119
+ 2. **Solution**: "Validate and fix your profile in seconds"
120
+ 3. **Proof**: "Checks all UCP spec rules: namespaces, endpoints, signing keys"
121
+ 4. **CTA**: "Check your profile free at ucptools.dev"
122
+
123
+ ---
124
+
125
+ ## Target Audience
126
+
127
+ ### Primary: Developers & Technical Founders
128
+ - Building on headless commerce (Medusa, Saleor, custom)
129
+ - Care about standards compliance
130
+ - Comfortable with JSON/APIs
131
+ - Value speed and accuracy
132
+
133
+ ### Secondary: E-commerce Agencies
134
+ - Managing multiple client stores
135
+ - Need bulk validation
136
+ - Want white-label reports
137
+
138
+ ### Tertiary: Non-technical Merchants
139
+ - Shopify/WooCommerce store owners
140
+ - Need simple "is it working?" check
141
+ - May upgrade to managed service
142
+
143
+ ---
144
+
145
+ ## Competitive Positioning
146
+
147
+ ### We Are
148
+ - Free and instant
149
+ - Developer-focused
150
+ - Independent (not affiliated with Google/Shopify)
151
+ - Self-serve first
152
+
153
+ ### We Are Not
154
+ - Enterprise sales motion
155
+ - Full UCP implementation service
156
+ - Platform-specific (works with any backend)
157
+
158
+ ### Differentiators
159
+ | Feature | UCP.tools | UCP Ready | WellKnown | UCP Playground |
160
+ |---------|-----------|-----------|-----------|----------------|
161
+ | Free validation | ✅ Unlimited | Limited | ❌ | Demo only |
162
+ | Profile generation | ✅ | ❌ | ❌ | ❌ |
163
+ | CLI/API access | ✅ | ❌ | ❌ | ❌ |
164
+ | No signup | ✅ | ? | ❌ | ✅ |
165
+
166
+ ---
167
+
168
+ ## Content Guidelines
169
+
170
+ ### Headlines
171
+ - Lead with benefit: "Validate Your UCP Profile" not "UCP Validation Tool"
172
+ - Use numbers: "Fix 12 common UCP errors" not "Fix UCP errors"
173
+ - Create urgency: "AI agents are coming. Is your store ready?"
174
+
175
+ ### Call-to-Actions
176
+ - Primary: "Validate Now" / "Check Your Profile"
177
+ - Secondary: "Generate Profile" / "Download JSON"
178
+ - Tertiary: "See Pricing" / "Get Pro"
179
+
180
+ ### Error Messages
181
+ - Be specific: "Endpoint must use HTTPS" not "Invalid endpoint"
182
+ - Be helpful: Include "hint" with fix suggestion
183
+ - Be human: "Oops, we couldn't reach your profile" not "Error 404"
184
+
185
+ ---
186
+
187
+ ## Social Media Templates
188
+
189
+ ### Twitter/X Bio
190
+ > Free UCP profile validator & generator. Get your store ready for AI commerce agents. ⚡ Instant results, no signup.
191
+
192
+ ### Product Hunt Tagline
193
+ > Validate and generate UCP profiles for AI-powered commerce
194
+
195
+ ### GitHub Description
196
+ > Free, open-source UCP (Universal Commerce Protocol) profile validator and generator. CLI + API + Web UI.
197
+
198
+ ---
199
+
200
+ ## Legal & Disclaimers
201
+
202
+ ### Standard Disclaimer
203
+ > "UCP.tools is an independent project and is not affiliated with, endorsed by, or sponsored by Google, Shopify, or the Universal Commerce Protocol working group."
204
+
205
+ ### Open Source Notice
206
+ > "UCP.tools is open source under the MIT license. The UCP specification is maintained by the UCP working group."
207
+
208
+ ---
209
+
210
+ ## Asset Checklist for Launch
211
+
212
+ - [ ] Logo (SVG, PNG @1x, @2x)
213
+ - [ ] Favicon (16x16, 32x32, apple-touch-icon)
214
+ - [ ] Open Graph image (1200x630)
215
+ - [ ] Twitter card image (1200x600)
216
+ - [ ] Product Hunt thumbnail (240x240)
217
+ - [ ] Apify Actor icon (256x256)
218
+ - [ ] Screenshots (web UI, CLI output, validation report)
219
+
220
+ ---
221
+
222
+ ## GPT Prompt for Brand-Consistent Content
223
+
224
+ When generating content for UCP.tools, use this context:
225
+
226
+ ```
227
+ You are writing for UCP.tools, a free developer tool that validates and generates Universal Commerce Protocol (UCP) business profiles.
228
+
229
+ Brand voice: Developer-first, direct, helpful, independent
230
+ Target audience: Developers building e-commerce, technical founders, agencies
231
+ Key differentiator: Free, instant, no signup, generates profiles (not just validates)
232
+
233
+ Avoid: Corporate jargon, "leverage", "utilize", "comprehensive solution"
234
+ Use: "Check", "fix", "validate", "generate", "your profile", "instant"
235
+
236
+ Colors: Blue (#2563eb), Green for success, Red for errors
237
+ Tagline: "Get ready for AI commerce"
238
+ ```