@nordsym/apiclaw 1.2.0 → 1.2.2

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 (46) hide show
  1. package/.env.prod +1 -0
  2. package/README.md +5 -5
  3. package/STATUS.md +7 -7
  4. package/convex/http.ts +33 -1
  5. package/data/combined-02-25.json +5602 -0
  6. package/data/night-batch-02-25.json +2732 -0
  7. package/data/night-expansion-02-25.json +2872 -0
  8. package/dist/credentials.d.ts.map +1 -1
  9. package/dist/credentials.js +15 -0
  10. package/dist/credentials.js.map +1 -1
  11. package/dist/execute.d.ts +1 -1
  12. package/dist/execute.d.ts.map +1 -1
  13. package/dist/execute.js +77 -1
  14. package/dist/execute.js.map +1 -1
  15. package/dist/index.js +9 -7
  16. package/dist/index.js.map +1 -1
  17. package/dist/proxy.d.ts.map +1 -1
  18. package/dist/proxy.js +1 -1
  19. package/dist/proxy.js.map +1 -1
  20. package/dist/registry/apis.json +44476 -174
  21. package/landing/src/app/api/auth/magic-link/route.ts +8 -1
  22. package/landing/src/app/api/auth/verify/route.ts +7 -4
  23. package/landing/src/app/docs/page.tsx +83 -82
  24. package/landing/src/app/earn/page.tsx +8 -8
  25. package/landing/src/app/page.tsx +208 -15
  26. package/landing/src/app/providers/page.tsx +6 -5
  27. package/landing/src/app/providers/register/page.tsx +1 -1
  28. package/landing/src/lib/convex-client.ts +6 -2
  29. package/landing/src/lib/stats.json +1 -1
  30. package/package.json +3 -2
  31. package/scripts/merge-to-registry.py +77 -0
  32. package/scripts/night-batch-02-24.py +391 -0
  33. package/scripts/night-batch-02-25.py +479 -0
  34. package/scripts/night-batch-03-24-b2.py +387 -0
  35. package/scripts/night-batch-03-24-b3.py +284 -0
  36. package/scripts/night-batch-03-24.py +447 -0
  37. package/scripts/night-batch-06-24-b2.py +695 -0
  38. package/scripts/night-batch-06-24-b3.py +696 -0
  39. package/scripts/night-batch-06-24.py +825 -0
  40. package/scripts/night-expansion-02-24-02.py +708 -0
  41. package/scripts/night-expansion-02-25.py +668 -0
  42. package/src/credentials.ts +16 -0
  43. package/src/execute.ts +87 -1
  44. package/src/index.ts +9 -7
  45. package/src/proxy.ts +1 -1
  46. package/src/registry/apis.json +44476 -174
@@ -24,7 +24,14 @@ export async function POST(req: NextRequest) {
24
24
  throw new Error("Failed to create magic link");
25
25
  }
26
26
 
27
- const { token } = await response.json();
27
+ const result = await response.json();
28
+
29
+ // Convex wraps response in { status: "success", value: {...} }
30
+ const token = result.value?.token || result.token;
31
+
32
+ if (!token) {
33
+ throw new Error("Failed to get token from Convex");
34
+ }
28
35
 
29
36
  // Send magic link email via n8n
30
37
  const magicLinkUrl = `${process.env.NEXT_PUBLIC_APP_URL || "https://apiclaw.nordsym.com"}/providers/dashboard/verify?token=${token}`;
@@ -25,16 +25,19 @@ export async function POST(req: NextRequest) {
25
25
  }
26
26
 
27
27
  const result = await response.json();
28
+
29
+ // Convex wraps response in { status: "success", value: {...} }
30
+ const data = result.value || result;
28
31
 
29
- if (!result.success) {
30
- return NextResponse.json({ error: result.error || "Invalid token" }, { status: 400 });
32
+ if (!data.success) {
33
+ return NextResponse.json({ error: data.error || "Invalid token" }, { status: 400 });
31
34
  }
32
35
 
33
36
  // Return session token
34
37
  return NextResponse.json({
35
38
  success: true,
36
- sessionToken: result.sessionToken,
37
- provider: result.provider,
39
+ sessionToken: data.sessionToken,
40
+ provider: data.provider,
38
41
  });
39
42
  } catch (error) {
40
43
  console.error("Verify error:", error);
@@ -5,12 +5,12 @@ import { useState, useEffect } from 'react';
5
5
  import { Sun, Moon } from 'lucide-react';
6
6
 
7
7
  export default function DocsPage() {
8
- const [theme, setTheme] = useState<'light' | 'dark'>('dark');
8
+ const [theme, setTheme] = useState<'light' | 'dark'>('light');
9
9
 
10
10
  useEffect(() => {
11
11
  const savedTheme = localStorage.getItem('apiclaw-theme') as 'light' | 'dark' | null;
12
- const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
13
- const initialTheme = savedTheme || systemTheme;
12
+ // Default to light for docs
13
+ const initialTheme = savedTheme || 'light';
14
14
  setTheme(initialTheme);
15
15
  document.documentElement.classList.toggle('dark', initialTheme === 'dark');
16
16
  }, []);
@@ -33,14 +33,14 @@ export default function DocsPage() {
33
33
  APIClaw
34
34
  </span>
35
35
  </Link>
36
- <nav className="flex items-center gap-6">
37
- <Link href="/" className="text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors">Home</Link>
38
- <Link href="/providers" className="text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors">Providers</Link>
39
- <Link href="/earn" className="text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors">Earn Credits</Link>
36
+ <nav className="flex items-center gap-4 md:gap-6">
37
+ <Link href="/" className="hidden sm:block text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors text-sm md:text-base">Home</Link>
38
+ <Link href="/providers" className="hidden md:block text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors text-sm md:text-base">Providers</Link>
39
+ <Link href="/earn" className="hidden md:block text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors text-sm md:text-base">Earn Credits</Link>
40
40
  <a
41
41
  href="https://github.com/nordsym/apiclaw"
42
42
  target="_blank"
43
- className="text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors"
43
+ className="text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors text-sm md:text-base"
44
44
  >
45
45
  GitHub
46
46
  </a>
@@ -112,6 +112,67 @@ export default function DocsPage() {
112
112
  </div>
113
113
  </section>
114
114
 
115
+
116
+ {/* Examples */}
117
+ <section className="mb-16">
118
+ <h2 className="text-2xl font-bold mb-6 flex items-center gap-3">
119
+ <span className="text-[var(--accent)]">💡</span> Examples
120
+ </h2>
121
+
122
+ <div className="space-y-6">
123
+ <div className="bg-[var(--surface)] border border-[var(--border)] rounded-xl p-6">
124
+ <h3 className="text-lg font-semibold mb-4">Send an SMS</h3>
125
+ <pre className="bg-[var(--surface-elevated)] border border-[var(--border)] rounded-lg p-4 overflow-x-auto">
126
+ <code className="text-sm">
127
+ <span className="text-[var(--text-muted)]">// Find SMS providers for Sweden</span>{'\n'}
128
+ <span className="text-purple-600 dark:text-purple-400">discover_apis</span>({'{ '}<span className="text-sky-600 dark:text-sky-400">query</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;send SMS Sweden&quot;</span>{' }'}){'\n\n'}
129
+ <span className="text-[var(--text-muted)]">// Send via direct-call</span>{'\n'}
130
+ <span className="text-purple-600 dark:text-purple-400">call_api</span>({'{\n'}
131
+ {" "}<span className="text-sky-600 dark:text-sky-400">provider</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;46elks&quot;</span>,{'\n'}
132
+ {" "}<span className="text-sky-600 dark:text-sky-400">endpoint</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;sms&quot;</span>,{'\n'}
133
+ {" "}<span className="text-sky-600 dark:text-sky-400">params</span>: {'{\n'}
134
+ {" "}<span className="text-sky-600 dark:text-sky-400">to</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;+46701234567&quot;</span>,{'\n'}
135
+ {" "}<span className="text-sky-600 dark:text-sky-400">message</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;Hello from APIClaw!&quot;</span>{'\n'}
136
+ {" }"}{'\n'}
137
+ {'}'})
138
+ </code>
139
+ </pre>
140
+ </div>
141
+
142
+ <div className="bg-[var(--surface)] border border-[var(--border)] rounded-xl p-6">
143
+ <h3 className="text-lg font-semibold mb-4">Search the web</h3>
144
+ <pre className="bg-[var(--surface-elevated)] border border-[var(--border)] rounded-lg p-4 overflow-x-auto">
145
+ <code className="text-sm">
146
+ <span className="text-purple-600 dark:text-purple-400">call_api</span>({'{\n'}
147
+ {" "}<span className="text-sky-600 dark:text-sky-400">provider</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;brave_search&quot;</span>,{'\n'}
148
+ {" "}<span className="text-sky-600 dark:text-sky-400">endpoint</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;search&quot;</span>,{'\n'}
149
+ {" "}<span className="text-sky-600 dark:text-sky-400">params</span>: {'{ '}<span className="text-sky-600 dark:text-sky-400">query</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;best MCP servers 2026&quot;</span>{' }'}{'\n'}
150
+ {'}'})
151
+ </code>
152
+ </pre>
153
+ </div>
154
+
155
+ <div className="bg-[var(--surface)] border border-[var(--border)] rounded-xl p-6">
156
+ <h3 className="text-lg font-semibold mb-4">Generate speech</h3>
157
+ <pre className="bg-[var(--surface-elevated)] border border-[var(--border)] rounded-lg p-4 overflow-x-auto">
158
+ <code className="text-sm">
159
+ <span className="text-purple-600 dark:text-purple-400">call_api</span>({'{\n'}
160
+ {" "}<span className="text-sky-600 dark:text-sky-400">provider</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;elevenlabs&quot;</span>,{'\n'}
161
+ {" "}<span className="text-sky-600 dark:text-sky-400">endpoint</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;tts&quot;</span>,{'\n'}
162
+ {" "}<span className="text-sky-600 dark:text-sky-400">params</span>: {'{\n'}
163
+ {" "}<span className="text-sky-600 dark:text-sky-400">text</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;Hello, I am an AI agent!&quot;</span>,{'\n'}
164
+ {" "}<span className="text-sky-600 dark:text-sky-400">voice</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;adam&quot;</span>{'\n'}
165
+ {" }"}{'\n'}
166
+ {'}'})
167
+ </code>
168
+ </pre>
169
+ </div>
170
+ </div>
171
+ </section>
172
+
173
+ {/* For Providers */}
174
+ <section className="mb-16">
175
+
115
176
  {/* Tools Reference */}
116
177
  <section className="mb-16">
117
178
  <h2 className="text-2xl font-bold mb-6 flex items-center gap-3">
@@ -143,10 +204,10 @@ export default function DocsPage() {
143
204
  <div className="mt-4 text-sm text-[var(--text-muted)]">
144
205
  <strong className="text-[var(--text-primary)]">Parameters:</strong>
145
206
  <ul className="list-disc list-inside mt-2 space-y-1">
146
- <li><code className="text-[var(--accent)]">query</code> Natural language description</li>
147
- <li><code className="text-[var(--accent)]">category</code> Filter: communication, search, ai</li>
148
- <li><code className="text-[var(--accent)]">max_results</code> Number of results (default: 5)</li>
149
- <li><code className="text-[var(--accent)]">region</code> Filter by region (e.g., &quot;sweden&quot;)</li>
207
+ <li><code className="text-[var(--accent)]">query</code> - Natural language description</li>
208
+ <li><code className="text-[var(--accent)]">category</code> - Filter: communication, search, ai</li>
209
+ <li><code className="text-[var(--accent)]">max_results</code> - Number of results (default: 5)</li>
210
+ <li><code className="text-[var(--accent)]">region</code> - Filter by region (e.g., &quot;sweden&quot;)</li>
150
211
  </ul>
151
212
  </div>
152
213
  </div>
@@ -167,19 +228,19 @@ export default function DocsPage() {
167
228
  {/* get_connected_providers */}
168
229
  <div className="bg-[var(--surface)] border border-[var(--border)] rounded-xl p-6">
169
230
  <h3 className="text-lg font-mono text-[var(--accent)] mb-2">get_connected_providers</h3>
170
- <p className="text-[var(--text-secondary)] mb-4">List all instant-connect providers (no API key needed).</p>
231
+ <p className="text-[var(--text-secondary)] mb-4">List all direct-call providers (no API key needed).</p>
171
232
  <pre className="bg-[var(--surface-elevated)] border border-[var(--border)] rounded-lg p-4 overflow-x-auto">
172
233
  <code className="text-sm text-[var(--text-primary)]">get_connected_providers()</code>
173
234
  </pre>
174
235
  <div className="mt-4 text-sm text-[var(--text-muted)]">
175
236
  <strong className="text-[var(--text-primary)]">Currently available:</strong>
176
237
  <ul className="list-disc list-inside mt-2 space-y-1">
177
- <li><code className="text-[var(--accent)]">brave_search</code> Web search</li>
178
- <li><code className="text-[var(--accent)]">46elks</code> SMS (Sweden)</li>
179
- <li><code className="text-[var(--accent)]">twilio</code> SMS (Global)</li>
180
- <li><code className="text-[var(--accent)]">resend</code> Email</li>
181
- <li><code className="text-[var(--accent)]">openrouter</code> LLM routing</li>
182
- <li><code className="text-[var(--accent)]">elevenlabs</code> Text-to-speech</li>
238
+ <li><code className="text-[var(--accent)]">brave_search</code> - Web search</li>
239
+ <li><code className="text-[var(--accent)]">46elks</code> - SMS (Sweden)</li>
240
+ <li><code className="text-[var(--accent)]">twilio</code> - SMS (Global)</li>
241
+ <li><code className="text-[var(--accent)]">resend</code> - Email</li>
242
+ <li><code className="text-[var(--accent)]">openrouter</code> - LLM routing</li>
243
+ <li><code className="text-[var(--accent)]">elevenlabs</code> - Text-to-speech</li>
183
244
  </ul>
184
245
  </div>
185
246
  </div>
@@ -187,7 +248,7 @@ export default function DocsPage() {
187
248
  {/* call_api */}
188
249
  <div className="bg-[var(--surface)] border border-[var(--border)] rounded-xl p-6">
189
250
  <h3 className="text-lg font-mono text-[var(--accent)] mb-2">call_api</h3>
190
- <p className="text-[var(--text-secondary)] mb-4">Execute an API call through an instant-connect provider.</p>
251
+ <p className="text-[var(--text-secondary)] mb-4">Execute an API call through an direct-call provider.</p>
191
252
  <pre className="bg-[var(--surface-elevated)] border border-[var(--border)] rounded-lg p-4 overflow-x-auto">
192
253
  <code className="text-sm">
193
254
  <span className="text-purple-600 dark:text-purple-400">call_api</span>({'{\n'}
@@ -209,66 +270,6 @@ export default function DocsPage() {
209
270
  </div>
210
271
  </div>
211
272
  </section>
212
-
213
- {/* Examples */}
214
- <section className="mb-16">
215
- <h2 className="text-2xl font-bold mb-6 flex items-center gap-3">
216
- <span className="text-[var(--accent)]">💡</span> Examples
217
- </h2>
218
-
219
- <div className="space-y-6">
220
- <div className="bg-[var(--surface)] border border-[var(--border)] rounded-xl p-6">
221
- <h3 className="text-lg font-semibold mb-4">Send an SMS</h3>
222
- <pre className="bg-[var(--surface-elevated)] border border-[var(--border)] rounded-lg p-4 overflow-x-auto">
223
- <code className="text-sm">
224
- <span className="text-[var(--text-muted)]">// Find SMS providers for Sweden</span>{'\n'}
225
- <span className="text-purple-600 dark:text-purple-400">discover_apis</span>({'{ '}<span className="text-sky-600 dark:text-sky-400">query</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;send SMS Sweden&quot;</span>{' }'}){'\n\n'}
226
- <span className="text-[var(--text-muted)]">// Send via instant-connect</span>{'\n'}
227
- <span className="text-purple-600 dark:text-purple-400">call_api</span>({'{\n'}
228
- {" "}<span className="text-sky-600 dark:text-sky-400">provider</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;46elks&quot;</span>,{'\n'}
229
- {" "}<span className="text-sky-600 dark:text-sky-400">endpoint</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;sms&quot;</span>,{'\n'}
230
- {" "}<span className="text-sky-600 dark:text-sky-400">params</span>: {'{\n'}
231
- {" "}<span className="text-sky-600 dark:text-sky-400">to</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;+46701234567&quot;</span>,{'\n'}
232
- {" "}<span className="text-sky-600 dark:text-sky-400">message</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;Hello from APIClaw!&quot;</span>{'\n'}
233
- {" }"}{'\n'}
234
- {'}'})
235
- </code>
236
- </pre>
237
- </div>
238
-
239
- <div className="bg-[var(--surface)] border border-[var(--border)] rounded-xl p-6">
240
- <h3 className="text-lg font-semibold mb-4">Search the web</h3>
241
- <pre className="bg-[var(--surface-elevated)] border border-[var(--border)] rounded-lg p-4 overflow-x-auto">
242
- <code className="text-sm">
243
- <span className="text-purple-600 dark:text-purple-400">call_api</span>({'{\n'}
244
- {" "}<span className="text-sky-600 dark:text-sky-400">provider</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;brave_search&quot;</span>,{'\n'}
245
- {" "}<span className="text-sky-600 dark:text-sky-400">endpoint</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;search&quot;</span>,{'\n'}
246
- {" "}<span className="text-sky-600 dark:text-sky-400">params</span>: {'{ '}<span className="text-sky-600 dark:text-sky-400">query</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;best MCP servers 2026&quot;</span>{' }'}{'\n'}
247
- {'}'})
248
- </code>
249
- </pre>
250
- </div>
251
-
252
- <div className="bg-[var(--surface)] border border-[var(--border)] rounded-xl p-6">
253
- <h3 className="text-lg font-semibold mb-4">Generate speech</h3>
254
- <pre className="bg-[var(--surface-elevated)] border border-[var(--border)] rounded-lg p-4 overflow-x-auto">
255
- <code className="text-sm">
256
- <span className="text-purple-600 dark:text-purple-400">call_api</span>({'{\n'}
257
- {" "}<span className="text-sky-600 dark:text-sky-400">provider</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;elevenlabs&quot;</span>,{'\n'}
258
- {" "}<span className="text-sky-600 dark:text-sky-400">endpoint</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;tts&quot;</span>,{'\n'}
259
- {" "}<span className="text-sky-600 dark:text-sky-400">params</span>: {'{\n'}
260
- {" "}<span className="text-sky-600 dark:text-sky-400">text</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;Hello, I am an AI agent!&quot;</span>,{'\n'}
261
- {" "}<span className="text-sky-600 dark:text-sky-400">voice</span>: <span className="text-emerald-600 dark:text-emerald-400">&quot;adam&quot;</span>{'\n'}
262
- {" }"}{'\n'}
263
- {'}'})
264
- </code>
265
- </pre>
266
- </div>
267
- </div>
268
- </section>
269
-
270
- {/* For Providers */}
271
- <section className="mb-16">
272
273
  <h2 className="text-2xl font-bold mb-6 flex items-center gap-3">
273
274
  <span className="text-[var(--accent)]">🤝</span> For API Providers
274
275
  </h2>
@@ -278,8 +279,8 @@ export default function DocsPage() {
278
279
  </p>
279
280
  <ul className="list-disc list-inside text-[var(--text-secondary)] space-y-2 mb-6">
280
281
  <li>Get discovered by AI agents searching for your capabilities</li>
281
- <li>Direct Connect integration agents use your API instantly</li>
282
- <li>Analytics dashboard see how agents use your API</li>
282
+ <li>Direct Connect integration. Agents use your API instantly</li>
283
+ <li>Analytics dashboard. See how agents use your API</li>
283
284
  <li>Revenue share on premium tiers</li>
284
285
  </ul>
285
286
  <Link
@@ -73,12 +73,12 @@ export default function EarnPage() {
73
73
  const [email, setEmail] = useState('');
74
74
  const [subscribed, setSubscribed] = useState(false);
75
75
  const [totalCredits] = useState(1350); // Demo value
76
- const [theme, setTheme] = useState<'light' | 'dark'>('dark');
76
+ const [theme, setTheme] = useState<'light' | 'dark'>('light');
77
77
 
78
78
  useEffect(() => {
79
79
  const savedTheme = localStorage.getItem('apiclaw-theme') as 'light' | 'dark' | null;
80
- const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
81
- const initialTheme = savedTheme || systemTheme;
80
+ // Default to light
81
+ const initialTheme = savedTheme || 'light';
82
82
  setTheme(initialTheme);
83
83
  document.documentElement.classList.toggle('dark', initialTheme === 'dark');
84
84
  }, []);
@@ -116,14 +116,14 @@ export default function EarnPage() {
116
116
  APIClaw
117
117
  </span>
118
118
  </Link>
119
- <nav className="flex items-center gap-6">
120
- <Link href="/" className="text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors">
119
+ <nav className="flex items-center gap-4 md:gap-6">
120
+ <Link href="/" className="hidden sm:block text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors text-sm md:text-base">
121
121
  Home
122
122
  </Link>
123
- <Link href="/docs" className="text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors">
123
+ <Link href="/docs" className="text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors text-sm md:text-base">
124
124
  Docs
125
125
  </Link>
126
- <Link href="/providers" className="text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors">
126
+ <Link href="/providers" className="hidden md:block text-[var(--text-secondary)] hover:text-[var(--accent)] transition-colors text-sm md:text-base">
127
127
  Providers
128
128
  </Link>
129
129
  <button
@@ -278,7 +278,7 @@ export default function EarnPage() {
278
278
  </div>
279
279
  <h3 className="font-semibold mb-2">Use</h3>
280
280
  <p className="text-[var(--text-secondary)] text-sm">
281
- Spend credits on API calls SMS, search, AI, and more
281
+ Spend credits on API calls: SMS, search, AI, and more
282
282
  </p>
283
283
  </div>
284
284
  <div className="text-center">
@@ -29,7 +29,7 @@ const howItWorks = [
29
29
  {
30
30
  step: "1",
31
31
  title: "Agent Asks",
32
- description: "Your agent queries APIClaw for a capability—not a product name.",
32
+ description: "Your agent queries APIClaw for a capability. Not a product name.",
33
33
  icon: Search,
34
34
  codeJsx: (
35
35
  <>
@@ -63,7 +63,7 @@ const howItWorks = [
63
63
  {
64
64
  step: "3",
65
65
  title: "Agent Integrates",
66
- description: "Full specs, auth details, endpoints—everything to start building.",
66
+ description: "Full specs, auth details, endpoints. Everything to start building.",
67
67
  icon: Rocket,
68
68
  codeJsx: (
69
69
  <>
@@ -92,7 +92,7 @@ const agentBenefits = [
92
92
  {
93
93
  icon: Database,
94
94
  title: "Structured Data",
95
- description: "JSON responses with pricing, limits, regions, auth—everything an agent needs.",
95
+ description: "JSON responses with pricing, limits, regions, auth. Everything an agent needs.",
96
96
  },
97
97
  {
98
98
  icon: Shield,
@@ -137,12 +137,25 @@ const terminalLines = [
137
137
  { type: "accent", text: "→ Add to Claude Desktop: Settings → MCP → Add Server", delay: 0 },
138
138
  ];
139
139
 
140
+ const directCallProviders = [
141
+ { name: "46elks", desc: "SMS (Sweden)" },
142
+ { name: "Twilio", desc: "SMS (Global)" },
143
+ { name: "Resend", desc: "Email" },
144
+ { name: "Brave Search", desc: "Web search" },
145
+ { name: "OpenRouter", desc: "100+ LLMs" },
146
+ { name: "ElevenLabs", desc: "Text-to-speech" },
147
+ { name: "Firecrawl", desc: "Web scraping" },
148
+ { name: "GitHub", desc: "Repos & Issues" },
149
+ { name: "Replicate", desc: "1000s of ML models" },
150
+ ];
151
+
140
152
  export default function Home() {
141
153
  const [isDark, setIsDark] = useState(true);
142
154
  const [terminalOutput, setTerminalOutput] = useState<typeof terminalLines>([]);
143
155
  const [isTyping, setIsTyping] = useState(true);
144
156
  const [currentLineIndex, setCurrentLineIndex] = useState(0);
145
157
  const [activeSection, setActiveSection] = useState<string>("");
158
+ const [showProvidersModal, setShowProvidersModal] = useState(false);
146
159
  const terminalRef = useRef<HTMLDivElement>(null);
147
160
 
148
161
  // Scroll-based active section detection using Intersection Observer
@@ -289,8 +302,16 @@ export default function Home() {
289
302
  <div className="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
290
303
  {/* Left: Copy */}
291
304
  <div className="text-center lg:text-left">
292
- <div className="badge badge-live mb-6 inline-flex">
293
- <span className="flex items-center gap-2"><span className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />Live • {statsData.apiCount.toLocaleString()} APIs</span>
305
+ <div className="flex flex-wrap items-center justify-center lg:justify-start gap-3 mb-6">
306
+ <div className="badge badge-live inline-flex">
307
+ <span className="flex items-center gap-2"><span className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />Live • {statsData.apiCount.toLocaleString()} APIs</span>
308
+ </div>
309
+ <button
310
+ onClick={() => setShowProvidersModal(true)}
311
+ className="badge inline-flex bg-accent/10 border-accent/30 text-accent hover:bg-accent/20 transition-colors cursor-pointer"
312
+ >
313
+ <span className="flex items-center gap-2"><Zap className="w-3 h-3" />Direct Call: SMS, Email, Search, AI & more</span>
314
+ </button>
294
315
  </div>
295
316
 
296
317
  <h1 className="text-5xl md:text-6xl lg:text-7xl font-black mb-6 leading-[1.05] tracking-tighter">
@@ -321,15 +342,19 @@ export default function Home() {
321
342
  <span className="text-xs opacity-70">copy</span>
322
343
  </button>
323
344
  <a
324
- href="https://github.com/nordsym/apiclaw"
325
- target="_blank"
326
- rel="noopener noreferrer"
345
+ href="/docs"
327
346
  className="btn-secondary"
328
347
  >
329
- <Github className="w-5 h-5" />
330
- View on GitHub
348
+ Get Started
349
+ <ArrowRight className="w-5 h-5" />
331
350
  </a>
332
351
  </div>
352
+
353
+ {/* Social proof */}
354
+ <p className="text-sm text-text-muted mt-4 flex items-center gap-2">
355
+ <Users className="w-4 h-4" />
356
+ <span>The API layer agent builders are switching to</span>
357
+ </p>
333
358
 
334
359
  </div>
335
360
 
@@ -340,7 +365,7 @@ export default function Home() {
340
365
  <div className="terminal-dot terminal-dot-red" />
341
366
  <div className="terminal-dot terminal-dot-yellow" />
342
367
  <div className="terminal-dot terminal-dot-green" />
343
- <span className="terminal-title">apiclaw — zsh</span>
368
+ <span className="terminal-title">apiclaw</span>
344
369
  </div>
345
370
  <div className="terminal-body">
346
371
  {terminalOutput.map((line, i) => (
@@ -392,6 +417,118 @@ export default function Home() {
392
417
  </div>
393
418
  </section>
394
419
 
420
+ {/* Before/After */}
421
+ <section className="py-12 px-6">
422
+ <div className="max-w-4xl mx-auto">
423
+ <div className="grid md:grid-cols-2 gap-8">
424
+ <div className="p-6 rounded-xl border border-red-500/20 bg-red-500/5">
425
+ <div className="flex items-center gap-2 text-red-400 font-medium mb-4">
426
+ <span className="text-xl">😤</span> Without APIClaw
427
+ </div>
428
+ <ul className="space-y-3 text-text-secondary">
429
+ <li className="flex items-start gap-2">
430
+ <span className="text-red-400 mt-1">✗</span>
431
+ <span>3+ hours searching for the right API</span>
432
+ </li>
433
+ <li className="flex items-start gap-2">
434
+ <span className="text-red-400 mt-1">✗</span>
435
+ <span>Create accounts, manage API keys</span>
436
+ </li>
437
+ <li className="flex items-start gap-2">
438
+ <span className="text-red-400 mt-1">✗</span>
439
+ <span>Read docs, figure out auth, test endpoints</span>
440
+ </li>
441
+ <li className="flex items-start gap-2">
442
+ <span className="text-red-400 mt-1">✗</span>
443
+ <span>Your agent waits... and waits...</span>
444
+ </li>
445
+ </ul>
446
+ </div>
447
+ <div className="p-6 rounded-xl border border-green-500/20 bg-green-500/5">
448
+ <div className="flex items-center gap-2 text-green-400 font-medium mb-4">
449
+ <span className="text-xl">🦞</span> With APIClaw
450
+ </div>
451
+ <ul className="space-y-3 text-text-secondary">
452
+ <li className="flex items-start gap-2">
453
+ <span className="text-green-400 mt-1">✓</span>
454
+ <span><strong>∞ hours saved</strong> per integration</span>
455
+ </li>
456
+ <li className="flex items-start gap-2">
457
+ <span className="text-green-400 mt-1">✓</span>
458
+ <span>No accounts, no API keys needed</span>
459
+ </li>
460
+ <li className="flex items-start gap-2">
461
+ <span className="text-green-400 mt-1">✓</span>
462
+ <span>Direct Call: SMS, Email, AI, and more</span>
463
+ </li>
464
+ <li className="flex items-start gap-2">
465
+ <span className="text-green-400 mt-1">✓</span>
466
+ <span>Your agent ships. Today.</span>
467
+ </li>
468
+ </ul>
469
+ </div>
470
+ </div>
471
+ <p className="text-center text-sm text-text-muted mt-8">
472
+ <Rocket className="w-4 h-4 inline mr-1" />
473
+ New Direct Call providers added weekly
474
+ </p>
475
+ </div>
476
+ </section>
477
+
478
+ {/* Quick Start */}
479
+ <section className="py-16 px-6 bg-surface/50">
480
+ <div className="max-w-3xl mx-auto">
481
+ <div className="text-center mb-8">
482
+ <h2 className="text-2xl md:text-3xl font-bold flex items-center justify-center gap-3">
483
+ <Zap className="w-6 h-6 text-accent" />
484
+ Quick Start
485
+ </h2>
486
+ <p className="text-text-secondary mt-2">Get running in 30 seconds</p>
487
+ </div>
488
+
489
+ <div className="grid md:grid-cols-2 gap-6">
490
+ {/* Install */}
491
+ <div className="code-preview">
492
+ <div className="code-preview-header">
493
+ terminal
494
+ </div>
495
+ <div className="code-preview-body">
496
+ <pre className="text-sm whitespace-pre-wrap">
497
+ <span className="text-gray-500"># Run directly with npx</span>{"\n"}
498
+ <span className="text-green-400">$</span> <span className="text-blue-400">npx</span> @nordsym/apiclaw{"\n\n"}
499
+ <span className="text-gray-500"># Or install globally</span>{"\n"}
500
+ <span className="text-green-400">$</span> <span className="text-blue-400">npm</span> install -g @nordsym/apiclaw{"\n"}
501
+ <span className="text-green-400">$</span> apiclaw
502
+ </pre>
503
+ </div>
504
+ </div>
505
+
506
+ {/* MCP Config */}
507
+ <div className="code-preview">
508
+ <div className="code-preview-header">
509
+ claude_desktop_config.json
510
+ </div>
511
+ <div className="code-preview-body">
512
+ <pre className="text-sm whitespace-pre-wrap">
513
+ <span className="text-gray-500">{"{"}</span>{"\n"}
514
+ {" "}<span className="text-red-400">"mcpServers"</span>: <span className="text-gray-500">{"{"}</span>{"\n"}
515
+ {" "}<span className="text-red-400">"apiclaw"</span>: <span className="text-gray-500">{"{"}</span>{"\n"}
516
+ {" "}<span className="text-red-400">"command"</span>: <span className="text-green-400">"npx"</span>,{"\n"}
517
+ {" "}<span className="text-red-400">"args"</span>: [<span className="text-green-400">"@nordsym/apiclaw"</span>]{"\n"}
518
+ {" "}<span className="text-gray-500">{"}"}</span>{"\n"}
519
+ {" "}<span className="text-gray-500">{"}"}</span>{"\n"}
520
+ <span className="text-gray-500">{"}"}</span>
521
+ </pre>
522
+ </div>
523
+ </div>
524
+ </div>
525
+
526
+ <p className="text-center text-sm text-text-muted mt-6">
527
+ Works with Claude Desktop, Cursor, and any MCP-compatible client
528
+ </p>
529
+ </div>
530
+ </section>
531
+
395
532
  <div className="divider" />
396
533
 
397
534
  {/* How It Works */}
@@ -482,7 +619,7 @@ export default function Home() {
482
619
 
483
620
  <div className="code-preview">
484
621
  <div className="code-preview-header">
485
- agent.ts — Claude Agent Example
622
+ agent.ts
486
623
  </div>
487
624
  <div className="code-preview-body">
488
625
  <pre className="text-sm">
@@ -579,7 +716,7 @@ export default function Home() {
579
716
  </h2>
580
717
 
581
718
  <p className="text-text-secondary text-lg mb-8 leading-relaxed">
582
- AI agents are the new developers. They don't browse landing pages
719
+ AI agents are the new developers. They don't browse landing pages.
583
720
  they query capabilities. Get your API in front of them.
584
721
  </p>
585
722
 
@@ -661,9 +798,10 @@ export default function Home() {
661
798
  </div>
662
799
  <h3 className="text-2xl font-bold mb-2">Provisioning</h3>
663
800
  <p className="text-text-secondary mb-6">Agent-native credential management</p>
664
- <div className="text-5xl font-black mb-6 text-text-muted">
665
- TBD
801
+ <div className="text-3xl font-bold mb-2 text-text-muted">
802
+ Free Beta
666
803
  </div>
804
+ <p className="text-sm text-text-muted mb-4">Early adopters get extended free access</p>
667
805
  <ul className="space-y-4 mb-8">
668
806
  <li className="flex items-center gap-3 text-text-muted">
669
807
  <Check className="w-5 h-5 flex-shrink-0" />
@@ -828,6 +966,61 @@ export default function Home() {
828
966
  <span className="text-text-primary font-medium">Talk to the Clawdbot building this</span>
829
967
  </div>
830
968
  </a>
969
+
970
+ {/* Direct Call Providers Modal */}
971
+ {showProvidersModal && (
972
+ <div
973
+ className="fixed inset-0 z-[100] flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm"
974
+ onClick={() => setShowProvidersModal(false)}
975
+ >
976
+ <div
977
+ className="bg-background border border-border rounded-2xl shadow-2xl max-w-md w-full max-h-[80vh] overflow-hidden"
978
+ onClick={(e) => e.stopPropagation()}
979
+ >
980
+ <div className="p-6 border-b border-border">
981
+ <div className="flex items-center justify-between">
982
+ <h3 className="text-xl font-bold flex items-center gap-2">
983
+ <Zap className="w-5 h-5 text-accent" />
984
+ Direct Call Providers
985
+ </h3>
986
+ <button
987
+ onClick={() => setShowProvidersModal(false)}
988
+ className="p-2 hover:bg-surface rounded-lg transition-colors"
989
+ >
990
+ <span className="text-xl">×</span>
991
+ </button>
992
+ </div>
993
+ <p className="text-sm text-text-muted mt-1">No API keys needed. Call directly through APIClaw.</p>
994
+ </div>
995
+
996
+ <div className="p-4 max-h-[40vh] overflow-y-auto">
997
+ <div className="grid grid-cols-2 gap-3">
998
+ {directCallProviders.map((provider, i) => (
999
+ <div key={i} className="p-3 rounded-xl bg-surface border border-border">
1000
+ <div className="font-medium text-sm">{provider.name}</div>
1001
+ <div className="text-xs text-text-muted">{provider.desc}</div>
1002
+ </div>
1003
+ ))}
1004
+ </div>
1005
+ </div>
1006
+
1007
+ <div className="p-6 border-t border-border bg-surface/50">
1008
+ <p className="text-sm text-text-secondary mb-4 text-center">
1009
+ Want your API here? Get discovered by thousands of AI agents.
1010
+ </p>
1011
+ <a
1012
+ href="https://nordsym.github.io/NordSym-Scheduler/"
1013
+ target="_blank"
1014
+ rel="noopener noreferrer"
1015
+ className="btn-primary w-full justify-center"
1016
+ >
1017
+ <span>Book a Call</span>
1018
+ <ArrowRight className="w-4 h-4" />
1019
+ </a>
1020
+ </div>
1021
+ </div>
1022
+ </div>
1023
+ )}
831
1024
  </main>
832
1025
  );
833
1026
  }