@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.
- package/README.md +436 -200
- package/convex/_generated/api.d.ts +4 -0
- package/convex/agents.ts +403 -0
- package/convex/directCall.ts +80 -0
- package/convex/earnProgress.ts +753 -0
- package/convex/logs.ts +17 -0
- package/convex/providerKeys.ts +82 -2
- package/convex/schema.ts +71 -2
- package/convex/workspaces.ts +84 -2
- package/dist/adapters/base.d.ts +112 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +247 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/claude-desktop.d.ts +12 -0
- package/dist/adapters/claude-desktop.d.ts.map +1 -0
- package/dist/adapters/claude-desktop.js +36 -0
- package/dist/adapters/claude-desktop.js.map +1 -0
- package/dist/adapters/cline.d.ts +20 -0
- package/dist/adapters/cline.d.ts.map +1 -0
- package/dist/adapters/cline.js +77 -0
- package/dist/adapters/cline.js.map +1 -0
- package/dist/adapters/continue.d.ts +26 -0
- package/dist/adapters/continue.d.ts.map +1 -0
- package/dist/adapters/continue.js +68 -0
- package/dist/adapters/continue.js.map +1 -0
- package/dist/adapters/cursor.d.ts +12 -0
- package/dist/adapters/cursor.d.ts.map +1 -0
- package/dist/adapters/cursor.js +38 -0
- package/dist/adapters/cursor.js.map +1 -0
- package/dist/adapters/custom.d.ts +47 -0
- package/dist/adapters/custom.d.ts.map +1 -0
- package/dist/adapters/custom.js +146 -0
- package/dist/adapters/custom.js.map +1 -0
- package/dist/adapters/detect.d.ts +69 -0
- package/dist/adapters/detect.d.ts.map +1 -0
- package/dist/adapters/detect.js +158 -0
- package/dist/adapters/detect.js.map +1 -0
- package/dist/adapters/index.d.ts +21 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +23 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/windsurf.d.ts +12 -0
- package/dist/adapters/windsurf.d.ts.map +1 -0
- package/dist/adapters/windsurf.js +39 -0
- package/dist/adapters/windsurf.js.map +1 -0
- package/dist/bin.d.ts +9 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +19 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +34 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +312 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/index.d.ts +9 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +9 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/mcp-install.d.ts +14 -0
- package/dist/cli/commands/mcp-install.d.ts.map +1 -0
- package/dist/cli/commands/mcp-install.js +246 -0
- package/dist/cli/commands/mcp-install.js.map +1 -0
- package/dist/cli/commands/restore.d.ts +50 -0
- package/dist/cli/commands/restore.d.ts.map +1 -0
- package/dist/cli/commands/restore.js +260 -0
- package/dist/cli/commands/restore.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +19 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +206 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +37 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -0
- package/dist/cli/commands/uninstall.js +189 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +105 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/discovery.d.ts +6 -2
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +296 -2
- package/dist/discovery.js.map +1 -1
- package/dist/enterprise/env.d.ts +56 -0
- package/dist/enterprise/env.d.ts.map +1 -0
- package/dist/enterprise/env.js +124 -0
- package/dist/enterprise/env.js.map +1 -0
- package/dist/enterprise/index.d.ts +7 -0
- package/dist/enterprise/index.d.ts.map +1 -0
- package/dist/enterprise/index.js +7 -0
- package/dist/enterprise/index.js.map +1 -0
- package/dist/enterprise/script-generator.d.ts +32 -0
- package/dist/enterprise/script-generator.d.ts.map +1 -0
- package/dist/enterprise/script-generator.js +461 -0
- package/dist/enterprise/script-generator.js.map +1 -0
- package/dist/execute.d.ts +21 -0
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +231 -0
- package/dist/execute.js.map +1 -1
- package/dist/index.js +79 -7
- package/dist/index.js.map +1 -1
- package/dist/stripe.d.ts +1 -1
- package/dist/stripe.js +1 -1
- package/dist/stripe.js.map +1 -1
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/colors.d.ts +111 -0
- package/dist/ui/colors.d.ts.map +1 -0
- package/dist/ui/colors.js +185 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/ui/errors.d.ts +69 -0
- package/dist/ui/errors.d.ts.map +1 -0
- package/dist/ui/errors.js +334 -0
- package/dist/ui/errors.js.map +1 -0
- package/dist/ui/index.d.ts +10 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +14 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/prompts.d.ts +88 -0
- package/dist/ui/prompts.d.ts.map +1 -0
- package/dist/ui/prompts.js +295 -0
- package/dist/ui/prompts.js.map +1 -0
- package/dist/ui/spinner.d.ts +112 -0
- package/dist/ui/spinner.d.ts.map +1 -0
- package/dist/ui/spinner.js +229 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/utils/backup.d.ts +48 -0
- package/dist/utils/backup.d.ts.map +1 -0
- package/dist/utils/backup.js +182 -0
- package/dist/utils/backup.js.map +1 -0
- package/dist/utils/config.d.ts +80 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +221 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/os.d.ts +45 -0
- package/dist/utils/os.d.ts.map +1 -0
- package/dist/utils/os.js +106 -0
- package/dist/utils/os.js.map +1 -0
- package/dist/utils/paths.d.ts +38 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +160 -0
- package/dist/utils/paths.js.map +1 -0
- package/docs/PRD-BILLING.md +226 -0
- package/docs/PRD-EARN-SYSTEM.md +261 -0
- package/docs/PRD-MCP-AUTO-SETUP.md +623 -0
- package/docs/enterprise-deployment.md +728 -0
- package/landing/next.config.mjs +14 -0
- package/landing/public/book/index.html +24 -5
- package/landing/public/demo-product.jpg +0 -0
- package/landing/public/stats.json +4 -2
- package/landing/scripts/generate-stats.js +13 -0
- package/landing/src/app/api/og/route.tsx +1 -3
- package/landing/src/app/api/workspace-auth/magic-link/route.ts +6 -3
- package/landing/src/app/auth/verify/page.tsx +11 -4
- package/landing/src/app/docs/page.tsx +1 -1
- package/landing/src/app/join/page.tsx +49 -0
- package/landing/src/app/layout.tsx +1 -1
- package/landing/src/app/login/page.tsx +7 -1
- package/landing/src/app/page.tsx +50 -38
- package/landing/src/app/providers/register/page.tsx +1 -1
- package/landing/src/app/workspace/page.tsx +484 -806
- package/landing/src/components/CheckoutButton.tsx +1 -1
- package/landing/src/components/EarnCreditsTab.tsx +842 -0
- package/landing/src/components/HeroTabs.tsx +2 -2
- package/landing/src/components/demo/PhoneDemo.tsx +423 -0
- package/landing/src/components/demo/index.ts +1 -0
- package/landing/src/lib/stats.json +3 -1
- package/landing/tailwind.config.ts +10 -0
- package/package.json +9 -2
- package/src/adapters/base.ts +363 -0
- package/src/adapters/claude-desktop.ts +41 -0
- package/src/adapters/cline.ts +88 -0
- package/src/adapters/continue.ts +91 -0
- package/src/adapters/cursor.ts +43 -0
- package/src/adapters/custom.ts +188 -0
- package/src/adapters/detect.ts +202 -0
- package/src/adapters/index.ts +47 -0
- package/src/adapters/windsurf.ts +44 -0
- package/src/bin.ts +19 -0
- package/src/cli/commands/doctor.ts +367 -0
- package/src/cli/commands/index.ts +9 -0
- package/src/cli/commands/mcp-install.ts +291 -0
- package/src/cli/commands/restore.ts +333 -0
- package/src/cli/commands/setup.ts +276 -0
- package/src/cli/commands/uninstall.ts +240 -0
- package/src/cli/index.ts +116 -0
- package/src/discovery.ts +328 -3
- package/src/enterprise/env.ts +156 -0
- package/src/enterprise/index.ts +7 -0
- package/src/enterprise/script-generator.ts +481 -0
- package/src/execute.ts +256 -0
- package/src/index.ts +85 -7
- package/src/stripe.ts +1 -1
- package/src/types.ts +32 -0
- package/src/ui/colors.ts +219 -0
- package/src/ui/errors.ts +394 -0
- package/src/ui/index.ts +17 -0
- package/src/ui/prompts.ts +390 -0
- package/src/ui/spinner.ts +325 -0
- package/src/utils/backup.ts +224 -0
- package/src/utils/config.ts +315 -0
- package/src/utils/os.ts +124 -0
- package/src/utils/paths.ts +203 -0
- package/STATUS.md +0 -160
- package/landing/tsconfig.tsbuildinfo +0 -1
package/landing/next.config.mjs
CHANGED
|
@@ -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-
|
|
5
|
-
"generatedAt": "2026-02-
|
|
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.
|
|
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
|
-
//
|
|
37
|
-
|
|
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
|
|
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:
|
|
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
|
+
}
|
|
@@ -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");
|
package/landing/src/app/page.tsx
CHANGED
|
@@ -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:
|
|
17
|
-
{ number:
|
|
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
|
|
190
|
+
const context = `APIClaw – Direct Call Execution Layer for AI Agents
|
|
191
191
|
|
|
192
|
-
|
|
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
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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
|
|
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/
|
|
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:
|
|
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{' '}
|