@nordsym/apiclaw 1.3.7 → 1.3.9

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 (203) hide show
  1. package/README.md +436 -200
  2. package/convex/_generated/api.d.ts +4 -0
  3. package/convex/agents.ts +403 -0
  4. package/convex/directCall.ts +80 -0
  5. package/convex/earnProgress.ts +753 -0
  6. package/convex/logs.ts +17 -0
  7. package/convex/providerKeys.ts +82 -2
  8. package/convex/schema.ts +71 -2
  9. package/convex/workspaces.ts +84 -2
  10. package/dist/adapters/base.d.ts +112 -0
  11. package/dist/adapters/base.d.ts.map +1 -0
  12. package/dist/adapters/base.js +247 -0
  13. package/dist/adapters/base.js.map +1 -0
  14. package/dist/adapters/claude-desktop.d.ts +12 -0
  15. package/dist/adapters/claude-desktop.d.ts.map +1 -0
  16. package/dist/adapters/claude-desktop.js +36 -0
  17. package/dist/adapters/claude-desktop.js.map +1 -0
  18. package/dist/adapters/cline.d.ts +20 -0
  19. package/dist/adapters/cline.d.ts.map +1 -0
  20. package/dist/adapters/cline.js +77 -0
  21. package/dist/adapters/cline.js.map +1 -0
  22. package/dist/adapters/continue.d.ts +26 -0
  23. package/dist/adapters/continue.d.ts.map +1 -0
  24. package/dist/adapters/continue.js +68 -0
  25. package/dist/adapters/continue.js.map +1 -0
  26. package/dist/adapters/cursor.d.ts +12 -0
  27. package/dist/adapters/cursor.d.ts.map +1 -0
  28. package/dist/adapters/cursor.js +38 -0
  29. package/dist/adapters/cursor.js.map +1 -0
  30. package/dist/adapters/custom.d.ts +47 -0
  31. package/dist/adapters/custom.d.ts.map +1 -0
  32. package/dist/adapters/custom.js +146 -0
  33. package/dist/adapters/custom.js.map +1 -0
  34. package/dist/adapters/detect.d.ts +69 -0
  35. package/dist/adapters/detect.d.ts.map +1 -0
  36. package/dist/adapters/detect.js +158 -0
  37. package/dist/adapters/detect.js.map +1 -0
  38. package/dist/adapters/index.d.ts +21 -0
  39. package/dist/adapters/index.d.ts.map +1 -0
  40. package/dist/adapters/index.js +23 -0
  41. package/dist/adapters/index.js.map +1 -0
  42. package/dist/adapters/windsurf.d.ts +12 -0
  43. package/dist/adapters/windsurf.d.ts.map +1 -0
  44. package/dist/adapters/windsurf.js +39 -0
  45. package/dist/adapters/windsurf.js.map +1 -0
  46. package/dist/bin.d.ts +9 -0
  47. package/dist/bin.d.ts.map +1 -0
  48. package/dist/bin.js +19 -0
  49. package/dist/bin.js.map +1 -0
  50. package/dist/cli/commands/doctor.d.ts +34 -0
  51. package/dist/cli/commands/doctor.d.ts.map +1 -0
  52. package/dist/cli/commands/doctor.js +312 -0
  53. package/dist/cli/commands/doctor.js.map +1 -0
  54. package/dist/cli/commands/index.d.ts +9 -0
  55. package/dist/cli/commands/index.d.ts.map +1 -0
  56. package/dist/cli/commands/index.js +9 -0
  57. package/dist/cli/commands/index.js.map +1 -0
  58. package/dist/cli/commands/mcp-install.d.ts +14 -0
  59. package/dist/cli/commands/mcp-install.d.ts.map +1 -0
  60. package/dist/cli/commands/mcp-install.js +246 -0
  61. package/dist/cli/commands/mcp-install.js.map +1 -0
  62. package/dist/cli/commands/restore.d.ts +50 -0
  63. package/dist/cli/commands/restore.d.ts.map +1 -0
  64. package/dist/cli/commands/restore.js +260 -0
  65. package/dist/cli/commands/restore.js.map +1 -0
  66. package/dist/cli/commands/setup.d.ts +19 -0
  67. package/dist/cli/commands/setup.d.ts.map +1 -0
  68. package/dist/cli/commands/setup.js +206 -0
  69. package/dist/cli/commands/setup.js.map +1 -0
  70. package/dist/cli/commands/uninstall.d.ts +37 -0
  71. package/dist/cli/commands/uninstall.d.ts.map +1 -0
  72. package/dist/cli/commands/uninstall.js +189 -0
  73. package/dist/cli/commands/uninstall.js.map +1 -0
  74. package/dist/cli/index.d.ts +7 -0
  75. package/dist/cli/index.d.ts.map +1 -0
  76. package/dist/cli/index.js +105 -0
  77. package/dist/cli/index.js.map +1 -0
  78. package/dist/discovery.d.ts +6 -2
  79. package/dist/discovery.d.ts.map +1 -1
  80. package/dist/discovery.js +296 -2
  81. package/dist/discovery.js.map +1 -1
  82. package/dist/enterprise/env.d.ts +56 -0
  83. package/dist/enterprise/env.d.ts.map +1 -0
  84. package/dist/enterprise/env.js +124 -0
  85. package/dist/enterprise/env.js.map +1 -0
  86. package/dist/enterprise/index.d.ts +7 -0
  87. package/dist/enterprise/index.d.ts.map +1 -0
  88. package/dist/enterprise/index.js +7 -0
  89. package/dist/enterprise/index.js.map +1 -0
  90. package/dist/enterprise/script-generator.d.ts +32 -0
  91. package/dist/enterprise/script-generator.d.ts.map +1 -0
  92. package/dist/enterprise/script-generator.js +461 -0
  93. package/dist/enterprise/script-generator.js.map +1 -0
  94. package/dist/execute.d.ts +21 -0
  95. package/dist/execute.d.ts.map +1 -1
  96. package/dist/execute.js +231 -0
  97. package/dist/execute.js.map +1 -1
  98. package/dist/index.js +79 -7
  99. package/dist/index.js.map +1 -1
  100. package/dist/stripe.d.ts +1 -1
  101. package/dist/stripe.js +1 -1
  102. package/dist/stripe.js.map +1 -1
  103. package/dist/types.d.ts +29 -0
  104. package/dist/types.d.ts.map +1 -1
  105. package/dist/ui/colors.d.ts +111 -0
  106. package/dist/ui/colors.d.ts.map +1 -0
  107. package/dist/ui/colors.js +185 -0
  108. package/dist/ui/colors.js.map +1 -0
  109. package/dist/ui/errors.d.ts +69 -0
  110. package/dist/ui/errors.d.ts.map +1 -0
  111. package/dist/ui/errors.js +334 -0
  112. package/dist/ui/errors.js.map +1 -0
  113. package/dist/ui/index.d.ts +10 -0
  114. package/dist/ui/index.d.ts.map +1 -0
  115. package/dist/ui/index.js +14 -0
  116. package/dist/ui/index.js.map +1 -0
  117. package/dist/ui/prompts.d.ts +88 -0
  118. package/dist/ui/prompts.d.ts.map +1 -0
  119. package/dist/ui/prompts.js +295 -0
  120. package/dist/ui/prompts.js.map +1 -0
  121. package/dist/ui/spinner.d.ts +112 -0
  122. package/dist/ui/spinner.d.ts.map +1 -0
  123. package/dist/ui/spinner.js +229 -0
  124. package/dist/ui/spinner.js.map +1 -0
  125. package/dist/utils/backup.d.ts +48 -0
  126. package/dist/utils/backup.d.ts.map +1 -0
  127. package/dist/utils/backup.js +182 -0
  128. package/dist/utils/backup.js.map +1 -0
  129. package/dist/utils/config.d.ts +80 -0
  130. package/dist/utils/config.d.ts.map +1 -0
  131. package/dist/utils/config.js +221 -0
  132. package/dist/utils/config.js.map +1 -0
  133. package/dist/utils/os.d.ts +45 -0
  134. package/dist/utils/os.d.ts.map +1 -0
  135. package/dist/utils/os.js +106 -0
  136. package/dist/utils/os.js.map +1 -0
  137. package/dist/utils/paths.d.ts +38 -0
  138. package/dist/utils/paths.d.ts.map +1 -0
  139. package/dist/utils/paths.js +160 -0
  140. package/dist/utils/paths.js.map +1 -0
  141. package/docs/PRD-BILLING.md +226 -0
  142. package/docs/PRD-EARN-SYSTEM.md +261 -0
  143. package/docs/PRD-MCP-AUTO-SETUP.md +623 -0
  144. package/docs/enterprise-deployment.md +728 -0
  145. package/landing/next.config.mjs +14 -0
  146. package/landing/public/book/index.html +24 -5
  147. package/landing/public/demo-product.jpg +0 -0
  148. package/landing/public/stats.json +4 -2
  149. package/landing/scripts/generate-stats.js +13 -0
  150. package/landing/src/app/api/og/route.tsx +1 -3
  151. package/landing/src/app/api/workspace-auth/magic-link/route.ts +6 -3
  152. package/landing/src/app/auth/verify/page.tsx +11 -4
  153. package/landing/src/app/docs/page.tsx +1 -1
  154. package/landing/src/app/join/page.tsx +49 -0
  155. package/landing/src/app/layout.tsx +1 -1
  156. package/landing/src/app/login/page.tsx +7 -1
  157. package/landing/src/app/page.tsx +50 -38
  158. package/landing/src/app/providers/register/page.tsx +1 -1
  159. package/landing/src/app/workspace/page.tsx +484 -806
  160. package/landing/src/components/CheckoutButton.tsx +1 -1
  161. package/landing/src/components/EarnCreditsTab.tsx +842 -0
  162. package/landing/src/components/HeroTabs.tsx +2 -2
  163. package/landing/src/components/demo/PhoneDemo.tsx +423 -0
  164. package/landing/src/components/demo/index.ts +1 -0
  165. package/landing/src/lib/stats.json +3 -1
  166. package/landing/tailwind.config.ts +10 -0
  167. package/package.json +9 -2
  168. package/src/adapters/base.ts +363 -0
  169. package/src/adapters/claude-desktop.ts +41 -0
  170. package/src/adapters/cline.ts +88 -0
  171. package/src/adapters/continue.ts +91 -0
  172. package/src/adapters/cursor.ts +43 -0
  173. package/src/adapters/custom.ts +188 -0
  174. package/src/adapters/detect.ts +202 -0
  175. package/src/adapters/index.ts +47 -0
  176. package/src/adapters/windsurf.ts +44 -0
  177. package/src/bin.ts +19 -0
  178. package/src/cli/commands/doctor.ts +367 -0
  179. package/src/cli/commands/index.ts +9 -0
  180. package/src/cli/commands/mcp-install.ts +291 -0
  181. package/src/cli/commands/restore.ts +333 -0
  182. package/src/cli/commands/setup.ts +276 -0
  183. package/src/cli/commands/uninstall.ts +240 -0
  184. package/src/cli/index.ts +116 -0
  185. package/src/discovery.ts +328 -3
  186. package/src/enterprise/env.ts +156 -0
  187. package/src/enterprise/index.ts +7 -0
  188. package/src/enterprise/script-generator.ts +481 -0
  189. package/src/execute.ts +256 -0
  190. package/src/index.ts +85 -7
  191. package/src/stripe.ts +1 -1
  192. package/src/types.ts +32 -0
  193. package/src/ui/colors.ts +219 -0
  194. package/src/ui/errors.ts +394 -0
  195. package/src/ui/index.ts +17 -0
  196. package/src/ui/prompts.ts +390 -0
  197. package/src/ui/spinner.ts +325 -0
  198. package/src/utils/backup.ts +224 -0
  199. package/src/utils/config.ts +315 -0
  200. package/src/utils/os.ts +124 -0
  201. package/src/utils/paths.ts +203 -0
  202. package/STATUS.md +0 -160
  203. package/landing/tsconfig.tsbuildinfo +0 -1
@@ -1,6 +1,20 @@
1
1
  /** @type {import('next').NextConfig} */
2
2
  const nextConfig = {
3
3
  output: 'standalone',
4
+ async redirects() {
5
+ return [
6
+ {
7
+ source: '/docs',
8
+ destination: '/workspace?tab=docs',
9
+ permanent: false,
10
+ },
11
+ {
12
+ source: '/faq',
13
+ destination: '/#faq',
14
+ permanent: false,
15
+ },
16
+ ];
17
+ },
4
18
  };
5
19
 
6
20
  export default nextConfig;
@@ -231,12 +231,8 @@
231
231
 
232
232
  <div class="form-group">
233
233
  <label>Preferred Day</label>
234
- <select name="day" required>
234
+ <select name="day" required id="day-select">
235
235
  <option value="">Select a day</option>
236
- <option value="tuesday">Tuesday (Feb 25)</option>
237
- <option value="wednesday">Wednesday (Feb 26)</option>
238
- <option value="thursday">Thursday (Feb 27)</option>
239
- <option value="friday">Friday (Feb 28)</option>
240
236
  </select>
241
237
  </div>
242
238
 
@@ -300,6 +296,29 @@
300
296
  }
301
297
  });
302
298
 
299
+ // Generate dynamic weekday options (next 5 weekdays)
300
+ const daySelect = document.getElementById('day-select');
301
+ const dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
302
+ const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
303
+
304
+ let date = new Date();
305
+ let addedDays = 0;
306
+
307
+ while (addedDays < 5) {
308
+ date.setDate(date.getDate() + 1);
309
+ const dayOfWeek = date.getDay();
310
+ if (dayOfWeek !== 0 && dayOfWeek !== 6) { // Skip weekends
311
+ const dayName = dayNames[dayOfWeek];
312
+ const monthName = monthNames[date.getMonth()];
313
+ const dateNum = date.getDate();
314
+ const option = document.createElement('option');
315
+ option.value = `${dayName.toLowerCase()}-${date.toISOString().split('T')[0]}`;
316
+ option.textContent = `${dayName} (${monthName} ${dateNum})`;
317
+ daySelect.appendChild(option);
318
+ addedDays++;
319
+ }
320
+ }
321
+
303
322
  // Time slot selection
304
323
  document.querySelectorAll('.time-slot').forEach(slot => {
305
324
  slot.addEventListener('click', () => {
Binary file
@@ -1,8 +1,10 @@
1
1
  {
2
2
  "apiCount": 22392,
3
+ "openApiCount": 996,
4
+ "directCallCount": 10,
3
5
  "categoryCount": 14,
4
- "lastUpdated": "2026-02-27T12:05:00.000Z",
5
- "generatedAt": "2026-02-27T12:05:00.000Z",
6
+ "lastUpdated": "2026-02-28T21:45:00.000Z",
7
+ "generatedAt": "2026-02-28T21:45:00.000Z",
6
8
  "categoryBreakdown": {
7
9
  "Utilities": 7069,
8
10
  "Analytics": 2600,
@@ -88,8 +88,19 @@ try {
88
88
  });
89
89
  const uniqueCategories = Object.keys(categoryBreakdown);
90
90
 
91
+ // Count open APIs (no auth required) - case insensitive
92
+ const openApiCount = registry.apis.filter(api =>
93
+ !api.auth || api.auth === '' || api.auth.toLowerCase() === 'none'
94
+ ).length;
95
+
96
+ // Direct call providers (hardcoded for now, update when adding new providers)
97
+ // Groq, Deepgram, Mistral, Cohere, Together, Stability, AssemblyAI, Serper, OpenAI, Anthropic, ElevenLabs, Replicate, Brave, Resend, Twilio, 46elks, Stripe, SendGrid
98
+ const directCallCount = 18;
99
+
91
100
  const stats = {
92
101
  apiCount: registry.count,
102
+ openApiCount: openApiCount,
103
+ directCallCount: directCallCount,
93
104
  categoryCount: uniqueCategories.length,
94
105
  lastUpdated: registry.lastUpdated || new Date().toISOString().split('T')[0],
95
106
  generatedAt: new Date().toISOString(),
@@ -109,6 +120,8 @@ try {
109
120
  // Write fallback stats
110
121
  const fallback = {
111
122
  apiCount: 22392,
123
+ openApiCount: 996,
124
+ directCallCount: 18,
112
125
  categoryCount: 14,
113
126
  lastUpdated: new Date().toISOString().split('T')[0],
114
127
  generatedAt: new Date().toISOString(),
@@ -60,11 +60,9 @@ export async function GET() {
60
60
  >
61
61
  <span>{statsData.apiCount.toLocaleString()}+ APIs</span>
62
62
  <span>•</span>
63
- <span>{statsData.categoryCount} Categories</span>
63
+ <span>{statsData.directCallCount} Direct Call</span>
64
64
  <span>•</span>
65
65
  <span>MCP Native</span>
66
- <span>•</span>
67
- <span>Direct Call</span>
68
66
  </div>
69
67
  <div
70
68
  style={{
@@ -4,7 +4,7 @@ const CONVEX_URL = process.env.NEXT_PUBLIC_CONVEX_URL || "https://adventurous-av
4
4
 
5
5
  export async function POST(req: NextRequest) {
6
6
  try {
7
- const { email, fingerprint } = await req.json();
7
+ const { email, fingerprint, referralCode } = await req.json();
8
8
 
9
9
  if (!email || !email.includes("@")) {
10
10
  return NextResponse.json({ error: "Valid email required" }, { status: 400 });
@@ -33,8 +33,11 @@ export async function POST(req: NextRequest) {
33
33
  throw new Error("Failed to get token from Convex");
34
34
  }
35
35
 
36
- // Send magic link email via n8n
37
- const magicLinkUrl = `${process.env.NEXT_PUBLIC_APP_URL || "https://apiclaw.nordsym.com"}/dashboard/verify?token=${token}`;
36
+ // Build magic link URL with optional referral code
37
+ let magicLinkUrl = `${process.env.NEXT_PUBLIC_APP_URL || "https://apiclaw.nordsym.com"}/auth/verify?token=${token}`;
38
+ if (referralCode) {
39
+ magicLinkUrl += `&ref=${encodeURIComponent(referralCode)}`;
40
+ }
38
41
 
39
42
  await fetch("https://nordsym.app.n8n.cloud/webhook/symbot-gmail", {
40
43
  method: "POST",
@@ -23,6 +23,7 @@ interface VerifyResult {
23
23
  function VerifyContent() {
24
24
  const searchParams = useSearchParams();
25
25
  const token = searchParams.get("token");
26
+ const referralCode = searchParams.get("ref"); // Referral code from signup URL
26
27
 
27
28
  const [status, setStatus] = useState<"loading" | "success" | "error">("loading");
28
29
  const [error, setError] = useState<string>("");
@@ -43,17 +44,23 @@ function VerifyContent() {
43
44
  return;
44
45
  }
45
46
 
46
- verifyToken(token);
47
- }, [token]);
47
+ verifyToken(token, referralCode || undefined);
48
+ }, [token, referralCode]);
48
49
 
49
- async function verifyToken(token: string) {
50
+ async function verifyToken(token: string, refCode?: string) {
50
51
  try {
52
+ // Build args with optional referral code
53
+ const args: { token: string; referralCode?: string } = { token };
54
+ if (refCode) {
55
+ args.referralCode = refCode;
56
+ }
57
+
51
58
  const response = await fetch(`${CONVEX_URL}/api/mutation`, {
52
59
  method: "POST",
53
60
  headers: { "Content-Type": "application/json" },
54
61
  body: JSON.stringify({
55
62
  path: "workspaces:verifyMagicLink",
56
- args: { token },
63
+ args,
57
64
  }),
58
65
  });
59
66
 
@@ -311,7 +311,7 @@ export default function DocsPage() {
311
311
  </li>
312
312
  <li>
313
313
  <strong>Email:</strong>{' '}
314
- <a href="mailto:symbot@nordsym.com" className="text-[var(--accent)] hover:underline">symbot@nordsym.com</a>
314
+ <a href="mailto:support_apiclaw@nordsym.com" className="text-[var(--accent)] hover:underline">support_apiclaw@nordsym.com</a>
315
315
  </li>
316
316
  </ul>
317
317
  </div>
@@ -0,0 +1,49 @@
1
+ "use client";
2
+
3
+ import { useEffect } from "react";
4
+ import { useSearchParams, useRouter } from "next/navigation";
5
+ import { Suspense } from "react";
6
+
7
+ function JoinContent() {
8
+ const searchParams = useSearchParams();
9
+ const router = useRouter();
10
+ const refCode = searchParams.get("ref");
11
+
12
+ useEffect(() => {
13
+ // Store referral code in localStorage for use during signup
14
+ if (refCode) {
15
+ localStorage.setItem("apiclaw_referral_code", refCode);
16
+ }
17
+
18
+ // Redirect to login page
19
+ router.push("/login");
20
+ }, [refCode, router]);
21
+
22
+ return (
23
+ <div className="min-h-screen bg-[var(--background)] flex items-center justify-center p-4">
24
+ <div className="text-center">
25
+ <span className="text-6xl animate-bounce">🦞</span>
26
+ <p className="mt-4 text-[var(--text-secondary)]">
27
+ {refCode ? "Processing your invite..." : "Redirecting to login..."}
28
+ </p>
29
+ </div>
30
+ </div>
31
+ );
32
+ }
33
+
34
+ export default function JoinPage() {
35
+ return (
36
+ <Suspense
37
+ fallback={
38
+ <div className="min-h-screen bg-[var(--background)] flex items-center justify-center">
39
+ <div className="text-center">
40
+ <span className="text-6xl">🦞</span>
41
+ <p className="mt-4 text-[var(--text-secondary)]">Loading...</p>
42
+ </div>
43
+ </div>
44
+ }
45
+ >
46
+ <JoinContent />
47
+ </Suspense>
48
+ );
49
+ }
@@ -24,7 +24,7 @@ export const metadata: Metadata = {
24
24
  locale: "en_US",
25
25
  images: [
26
26
  {
27
- url: "/api/og?v=2",
27
+ url: "/api/og?v=4",
28
28
  width: 1200,
29
29
  height: 630,
30
30
  alt: "APIClaw - The API layer for AI agents",
@@ -48,10 +48,13 @@ export default function LoginPage() {
48
48
  setError(null);
49
49
 
50
50
  try {
51
+ // Check for stored referral code (from /join page)
52
+ const referralCode = localStorage.getItem("apiclaw_referral_code");
53
+
51
54
  const response = await fetch("/api/workspace-auth/magic-link", {
52
55
  method: "POST",
53
56
  headers: { "Content-Type": "application/json" },
54
- body: JSON.stringify({ email }),
57
+ body: JSON.stringify({ email, referralCode }),
55
58
  });
56
59
 
57
60
  if (!response.ok) {
@@ -59,6 +62,9 @@ export default function LoginPage() {
59
62
  throw new Error(data.error || "Failed to send magic link");
60
63
  }
61
64
 
65
+ // Clear referral code after sending (it will be in the email link)
66
+ localStorage.removeItem("apiclaw_referral_code");
67
+
62
68
  setIsSent(true);
63
69
  } catch (err) {
64
70
  setError(err instanceof Error ? err.message : "Something went wrong");
@@ -10,11 +10,12 @@ import {
10
10
  import statsData from "@/lib/stats.json";
11
11
  import { useState, useEffect, useRef } from "react";
12
12
  import { HeroTabs } from "@/components/HeroTabs";
13
+ import { PhoneDemo } from "@/components/demo";
13
14
 
14
15
  const stats = [
15
16
  { number: statsData.apiCount.toLocaleString(), label: "APIs Indexed", live: true },
16
- { number: "865", label: "Open APIs", live: true },
17
- { number: "11", label: "Direct Call", live: true },
17
+ { number: statsData.openApiCount.toLocaleString(), label: "Open APIs", live: true },
18
+ { number: statsData.directCallCount.toString(), label: "Direct Call", live: true },
18
19
  { number: statsData.categoryCount.toString(), label: "Categories", live: false },
19
20
  ];
20
21
 
@@ -128,7 +129,7 @@ const providerBenefits = [
128
129
  ];
129
130
 
130
131
  const terminalLines = [
131
- { type: "prompt", text: "npx @nordsym/apiclaw" },
132
+ { type: "prompt", text: "npx @nordsym/apiclaw mcp-install" },
132
133
  { type: "output", text: "", delay: 500 },
133
134
  { type: "output", text: "🦞 APIClaw v1.2.2", delay: 100 },
134
135
  { type: "output", text: "", delay: 50 },
@@ -177,27 +178,37 @@ export default function Home() {
177
178
  { name: "Firecrawl", desc: "Web scraping to LLM-ready markdown", category: "Search" },
178
179
  { name: "E2B", desc: "Secure cloud sandboxes for code execution", category: "AI & LLM" },
179
180
  { name: "GitHub", desc: "Repos, issues, PRs, and more", category: "Other" },
180
- { name: "CoinGecko", desc: "Crypto prices and market data", category: "Crypto" },
181
181
  ];
182
182
 
183
183
  const copyToClipboard = () => {
184
- navigator.clipboard.writeText('npx @nordsym/apiclaw');
184
+ navigator.clipboard.writeText('npx @nordsym/apiclaw mcp-install');
185
185
  setShowCopied(true);
186
186
  setTimeout(() => setShowCopied(false), 2000);
187
187
  };
188
188
 
189
189
  const copyContextToClipboard = () => {
190
- const context = `APIClaw is the API layer for AI agents. It's an MCP server with ${statsData.apiCount.toLocaleString()}+ APIs.
190
+ const context = `APIClaw Direct Call Execution Layer for AI Agents
191
191
 
192
- Your agent can use these tools:
193
- • discover_apis - Search APIs by capability (not keywords)
194
- • get_api_details - Get full specs, pricing, and metadata
195
- • call_api - Direct Call: use APIs without managing keys
196
- • list_connected - See 11 available providers (Replicate, OpenRouter, ElevenLabs, etc.)
192
+ You have access to APIClaw, an MCP server that lets you execute API calls WITHOUT managing keys.
197
193
 
198
- Install: npx @nordsym/apiclaw
199
- Docs: https://apiclaw.nordsym.com/docs
200
- Website: https://apiclaw.nordsym.com`;
194
+ Direct Call = Zero-Config Execution:
195
+ No API key management needed
196
+ APIClaw handles auth, headers, signatures
197
+ • Execute immediately on ${statsData.directCallCount} providers
198
+
199
+ Available Providers:
200
+ Replicate (AI models), ElevenLabs (voice), OpenRouter (LLMs), Resend (email), 46elks (SMS), Brave Search, Firecrawl, E2B, GitHub
201
+
202
+ Your Tools:
203
+ • list_connected - See providers ready for instant execution
204
+ • call_api(provider, action, params) - Execute directly. Auth handled by APIClaw — omit/leave auth fields empty
205
+ • discover_apis - Search ${statsData.apiCount.toLocaleString()}+ APIs by capability
206
+ • get_api_details - Full specs if you need them
207
+
208
+ You have authority to act. Use call_api directly.
209
+
210
+ Install: npx @nordsym/apiclaw mcp-install
211
+ Docs: https://apiclaw.nordsym.com/docs`;
201
212
  navigator.clipboard.writeText(context);
202
213
  setShowContextCopied(true);
203
214
  setTimeout(() => setShowContextCopied(false), 2500);
@@ -279,8 +290,13 @@ Website: https://apiclaw.nordsym.com`;
279
290
 
280
291
  return (
281
292
  <main className="min-h-screen overflow-x-hidden">
293
+ {/* Early Access Banner */}
294
+ <div className="fixed top-0 w-full z-[60] bg-accent text-background text-center py-2 px-4 text-sm font-medium">
295
+ 🦞 <span className="font-bold">Early Access</span> — Join the first wave of agents
296
+ </div>
297
+
282
298
  {/* Header */}
283
- <header className="fixed top-0 w-full z-50 bg-background/80 backdrop-blur-xl border-b border-border-subtle">
299
+ <header className="fixed top-9 w-full z-50 bg-background/80 backdrop-blur-xl border-b border-border-subtle">
284
300
  <div className="max-w-6xl mx-auto px-4 sm:px-6 py-3 sm:py-4 flex items-center justify-between">
285
301
  <div className="flex items-center gap-2 sm:gap-3">
286
302
  <div className="w-8 h-8 sm:w-10 sm:h-10 rounded-xl bg-accent/20 flex items-center justify-center text-xl sm:text-2xl logo-float">
@@ -309,18 +325,6 @@ Website: https://apiclaw.nordsym.com`;
309
325
  >
310
326
  For API Providers
311
327
  </a>
312
- <a
313
- href="/docs"
314
- className="transition hover:text-text-primary"
315
- >
316
- Docs
317
- </a>
318
- <a
319
- href="/earn"
320
- className="transition hover:text-text-primary"
321
- >
322
- Earn
323
- </a>
324
328
  <a
325
329
  href="#faq"
326
330
  className={`transition ${activeSection === "faq" ? "text-accent font-medium" : "hover:text-text-primary"}`}
@@ -410,13 +414,6 @@ Website: https://apiclaw.nordsym.com`;
410
414
  >
411
415
  For API Providers
412
416
  </a>
413
- <a
414
- href="/docs"
415
- onClick={() => setMobileMenuOpen(false)}
416
- className="py-2 text-text-muted hover:text-text-primary transition"
417
- >
418
- Docs
419
- </a>
420
417
  <a
421
418
  href="#faq"
422
419
  onClick={() => setMobileMenuOpen(false)}
@@ -449,7 +446,7 @@ Website: https://apiclaw.nordsym.com`;
449
446
  </header>
450
447
 
451
448
  {/* Hero */}
452
- <section className="relative pt-32 pb-20 px-6 bg-grid">
449
+ <section className="relative pt-44 pb-20 px-6 bg-grid">
453
450
  <div className="hero-glow" />
454
451
 
455
452
  <div className="max-w-6xl mx-auto relative z-10">
@@ -539,6 +536,21 @@ Website: https://apiclaw.nordsym.com`;
539
536
  </div>
540
537
  </section>
541
538
 
539
+ {/* Phone Demo - With vs Without APIClaw */}
540
+ <section className="py-20 px-6">
541
+ <div className="max-w-5xl mx-auto">
542
+ <div className="text-center mb-12">
543
+ <h2 className="text-3xl md:text-4xl font-bold mb-4">
544
+ See the Difference
545
+ </h2>
546
+ <p className="text-text-muted text-lg max-w-2xl mx-auto">
547
+ Toggle to compare what happens when your AI agent has APIClaw — versus doing it the old way.
548
+ </p>
549
+ </div>
550
+ <PhoneDemo />
551
+ </div>
552
+ </section>
553
+
542
554
  {/* Direct Call Modal */}
543
555
  {showDirectCallModal && (
544
556
  <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/80 backdrop-blur-sm" onClick={() => setShowDirectCallModal(false)}>
@@ -971,7 +983,7 @@ Website: https://apiclaw.nordsym.com`;
971
983
  </li>
972
984
  <li className="flex items-start gap-3 text-text-secondary text-sm sm:text-base">
973
985
  <Check className="w-5 h-5 text-accent flex-shrink-0 mt-0.5" />
974
- 10+ providers (AI Models, Scraping, Code, Search)
986
+ 18 providers (AI Models, Scraping, Code, Search)
975
987
  </li>
976
988
  <li className="flex items-start gap-3 text-text-secondary text-sm sm:text-base">
977
989
  <Check className="w-5 h-5 text-accent flex-shrink-0 mt-0.5" />
@@ -1044,7 +1056,7 @@ Website: https://apiclaw.nordsym.com`;
1044
1056
  },
1045
1057
  {
1046
1058
  q: "How does Direct Call work?",
1047
- a: "Direct Call lets your agent use APIs without managing API keys. APIClaw handles authentication — your agent just calls the API through us. Currently available for 10+ providers including Replicate (1000+ ML models), OpenRouter (100+ LLMs), Firecrawl (web scraping), E2B (code sandbox), and more."
1059
+ a: "Direct Call lets your agent use APIs without managing API keys. APIClaw handles authentication — your agent just calls the API through us. Currently available for 18 providers including Replicate (1000+ ML models), OpenRouter (100+ LLMs), Firecrawl (web scraping), E2B (code sandbox), and more."
1048
1060
  },
1049
1061
  {
1050
1062
  q: "How are API credentials secured?",
@@ -1166,7 +1178,7 @@ Website: https://apiclaw.nordsym.com`;
1166
1178
 
1167
1179
  {/* Telegram Chat Bubble */}
1168
1180
  <a
1169
- href="https://t.me/Symbot_apiclaw_bot"
1181
+ href="https://t.me/Symbot_nordsym_bot?start=apiclaw"
1170
1182
  target="_blank"
1171
1183
  rel="noopener noreferrer"
1172
1184
  className="fixed bottom-6 right-6 z-50 group"
@@ -731,7 +731,7 @@ export default function RegisterPage() {
731
731
  {/* Help text */}
732
732
  <p className="text-center text-text-muted text-sm mt-6">
733
733
  Questions?{' '}
734
- <a href="mailto:gustav@nordsym.com" className="text-accent hover:underline">
734
+ <a href="mailto:support_apiclaw@nordsym.com" className="text-accent hover:underline">
735
735
  Contact us
736
736
  </a>
737
737
  {' '}or check the{' '}