@nordsym/apiclaw 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/AGENTS.md +74 -0
  2. package/HEARTBEAT.md +4 -0
  3. package/IDENTITY.md +22 -0
  4. package/README.md +197 -202
  5. package/SOUL.md +36 -0
  6. package/STATUS.md +237 -0
  7. package/TOOLS.md +36 -0
  8. package/USER.md +17 -0
  9. package/{backend/convex → convex}/_generated/api.d.ts +6 -6
  10. package/convex/credits.ts +211 -0
  11. package/convex/http.ts +490 -0
  12. package/convex/providers.ts +516 -0
  13. package/convex/purchases.ts +183 -0
  14. package/convex/schema.ts +180 -0
  15. package/convex.json +3 -0
  16. package/dist/credentials.d.ts +19 -0
  17. package/dist/credentials.d.ts.map +1 -0
  18. package/dist/credentials.js +158 -0
  19. package/dist/credentials.js.map +1 -0
  20. package/dist/credits.d.ts +14 -11
  21. package/dist/credits.d.ts.map +1 -1
  22. package/dist/credits.js +151 -99
  23. package/dist/credits.js.map +1 -1
  24. package/dist/discovery.d.ts +7 -16
  25. package/dist/discovery.d.ts.map +1 -1
  26. package/dist/discovery.js +33 -40
  27. package/dist/discovery.js.map +1 -1
  28. package/dist/execute.d.ts +19 -0
  29. package/dist/execute.d.ts.map +1 -0
  30. package/dist/execute.js +285 -0
  31. package/dist/execute.js.map +1 -0
  32. package/dist/index.js +106 -30
  33. package/dist/index.js.map +1 -1
  34. package/dist/proxy.d.ts +6 -0
  35. package/dist/proxy.d.ts.map +1 -0
  36. package/dist/proxy.js +19 -0
  37. package/dist/proxy.js.map +1 -0
  38. package/dist/registry/apis.json +95362 -202
  39. package/dist/registry/apis_expanded.json +100853 -0
  40. package/dist/stripe.d.ts +68 -0
  41. package/dist/stripe.d.ts.map +1 -0
  42. package/dist/stripe.js +196 -0
  43. package/dist/stripe.js.map +1 -0
  44. package/dist/test.d.ts +3 -2
  45. package/dist/test.d.ts.map +1 -1
  46. package/dist/test.js +105 -75
  47. package/dist/test.js.map +1 -1
  48. package/dist/types.d.ts +0 -28
  49. package/dist/types.d.ts.map +1 -1
  50. package/dist/webhook.d.ts +2 -0
  51. package/dist/webhook.d.ts.map +1 -0
  52. package/dist/webhook.js +90 -0
  53. package/dist/webhook.js.map +1 -0
  54. package/landing/DESIGN.md +343 -0
  55. package/landing/package-lock.json +1190 -40
  56. package/landing/package.json +5 -2
  57. package/landing/public/android-chrome-192x192.png +0 -0
  58. package/landing/public/android-chrome-512x512.png +0 -0
  59. package/landing/public/apple-touch-icon.png +0 -0
  60. package/landing/public/demo.gif +0 -0
  61. package/landing/public/demo.mp4 +0 -0
  62. package/landing/public/favicon-16x16.png +0 -0
  63. package/landing/public/favicon-32x32.png +0 -0
  64. package/landing/public/favicon.ico +0 -0
  65. package/landing/public/favicon.svg +3 -0
  66. package/landing/public/icon.svg +47 -0
  67. package/landing/public/logo-mono.svg +37 -0
  68. package/landing/public/logo-simple.svg +45 -0
  69. package/landing/public/logo.svg +84 -0
  70. package/landing/public/og-image.png +0 -0
  71. package/landing/public/og-template.html +184 -0
  72. package/landing/public/site.webmanifest +31 -0
  73. package/landing/scripts/generate-assets.js +284 -0
  74. package/landing/scripts/generate-pngs.js +48 -0
  75. package/landing/scripts/generate-stats.js +42 -0
  76. package/landing/src/app/admin/page.tsx +348 -0
  77. package/landing/src/app/api/auth/magic-link/route.ts +73 -0
  78. package/landing/src/app/api/auth/session/route.ts +38 -0
  79. package/landing/src/app/api/auth/verify/route.ts +43 -0
  80. package/landing/src/app/api/og/route.tsx +74 -0
  81. package/landing/src/app/globals.css +439 -100
  82. package/landing/src/app/layout.tsx +37 -9
  83. package/landing/src/app/page.tsx +640 -552
  84. package/landing/src/app/providers/dashboard/login/page.tsx +176 -0
  85. package/landing/src/app/providers/dashboard/page.tsx +589 -0
  86. package/landing/src/app/providers/dashboard/verify/page.tsx +106 -0
  87. package/landing/src/app/providers/layout.tsx +14 -0
  88. package/landing/src/app/providers/page.tsx +402 -0
  89. package/landing/src/app/providers/register/page.tsx +670 -0
  90. package/landing/src/components/ProviderDashboard.tsx +794 -0
  91. package/landing/src/hooks/useDashboardData.ts +99 -0
  92. package/landing/src/lib/apis.json +116054 -0
  93. package/landing/src/lib/convex-client.ts +106 -0
  94. package/landing/src/lib/mock-data.ts +285 -0
  95. package/landing/src/lib/stats.json +6 -0
  96. package/landing/tailwind.config.ts +12 -11
  97. package/landing/tsconfig.tsbuildinfo +1 -0
  98. package/package.json +21 -20
  99. package/scripts/SYMBOT-FIX.md +238 -0
  100. package/scripts/demo-simulation.py +177 -0
  101. package/scripts/expand-more.py +502 -0
  102. package/scripts/expand-registry.py +434 -0
  103. package/scripts/history-sanitizer.ts +272 -0
  104. package/scripts/mass-scrape.py +1308 -0
  105. package/scripts/sync-and-deploy.sh +36 -0
  106. package/src/credentials.ts +177 -0
  107. package/src/credits.ts +190 -122
  108. package/src/discovery.ts +45 -58
  109. package/src/execute.ts +350 -0
  110. package/src/index.ts +113 -31
  111. package/src/proxy.ts +24 -0
  112. package/src/registry/apis.json +95362 -202
  113. package/src/registry/apis_expanded.json +100853 -0
  114. package/src/stripe.ts +243 -0
  115. package/src/test.ts +127 -89
  116. package/src/types.ts +0 -34
  117. package/src/webhook.ts +107 -0
  118. package/.github/ISSUE_TEMPLATE/add-api.yml +0 -123
  119. package/BRIEFING.md +0 -30
  120. package/backend/convex/apiKeys.ts +0 -75
  121. package/backend/convex/purchases.ts +0 -74
  122. package/backend/convex/schema.ts +0 -45
  123. package/backend/convex/transactions.ts +0 -57
  124. package/backend/convex/users.ts +0 -94
  125. package/backend/package-lock.json +0 -521
  126. package/backend/package.json +0 -15
  127. package/dist/registry/parse_apis.py +0 -146
  128. package/dist/revenuecat.d.ts +0 -61
  129. package/dist/revenuecat.d.ts.map +0 -1
  130. package/dist/revenuecat.js +0 -166
  131. package/dist/revenuecat.js.map +0 -1
  132. package/dist/webhooks/revenuecat.d.ts +0 -48
  133. package/dist/webhooks/revenuecat.d.ts.map +0 -1
  134. package/dist/webhooks/revenuecat.js +0 -119
  135. package/dist/webhooks/revenuecat.js.map +0 -1
  136. package/docs/revenuecat-setup.md +0 -89
  137. package/landing/src/app/api/keys/route.ts +0 -71
  138. package/landing/src/app/api/log/route.ts +0 -37
  139. package/landing/src/app/api/stats/route.ts +0 -37
  140. package/landing/src/app/page.tsx.bak +0 -567
  141. package/landing/src/components/AddKeyModal.tsx +0 -159
  142. package/newsletter-template.html +0 -71
  143. package/outreach/OUTREACH-SYSTEM.md +0 -211
  144. package/outreach/email-template.html +0 -179
  145. package/outreach/targets.md +0 -133
  146. package/src/registry/parse_apis.py +0 -146
  147. package/src/revenuecat.ts +0 -239
  148. package/src/webhooks/revenuecat.ts +0 -187
  149. /package/{backend/convex → convex}/README.md +0 -0
  150. /package/{backend/convex → convex}/_generated/api.js +0 -0
  151. /package/{backend/convex → convex}/_generated/dataModel.d.ts +0 -0
  152. /package/{backend/convex → convex}/_generated/server.d.ts +0 -0
  153. /package/{backend/convex → convex}/_generated/server.js +0 -0
  154. /package/{backend/convex → convex}/tsconfig.json +0 -0
@@ -0,0 +1,176 @@
1
+ "use client";
2
+
3
+ import { useState, useEffect } from "react";
4
+ import { Mail, Loader2, Check, ArrowRight, Sun, Moon } from "lucide-react";
5
+ import Link from "next/link";
6
+ import { useRouter } from "next/navigation";
7
+
8
+ export default function LoginPage() {
9
+ const router = useRouter();
10
+ const [isDark, setIsDark] = useState(false);
11
+ const [email, setEmail] = useState("");
12
+ const [isLoading, setIsLoading] = useState(false);
13
+ const [isSent, setIsSent] = useState(false);
14
+ const [error, setError] = useState<string | null>(null);
15
+
16
+ useEffect(() => {
17
+ // Check if already logged in
18
+ const sessionToken = localStorage.getItem("apiclaw_session");
19
+ if (sessionToken) {
20
+ router.push("/providers/dashboard");
21
+ return;
22
+ }
23
+
24
+ const saved = localStorage.getItem("theme");
25
+ const prefersDark = saved ? saved === "dark" : true;
26
+ setIsDark(prefersDark);
27
+ document.documentElement.classList.toggle("dark", prefersDark);
28
+ }, [router]);
29
+
30
+ const toggleTheme = () => {
31
+ const newTheme = !isDark;
32
+ setIsDark(newTheme);
33
+ document.documentElement.classList.toggle("dark", newTheme);
34
+ localStorage.setItem("theme", newTheme ? "dark" : "light");
35
+ };
36
+
37
+ const handleSubmit = async (e: React.FormEvent) => {
38
+ e.preventDefault();
39
+ setIsLoading(true);
40
+ setError(null);
41
+
42
+ try {
43
+ const response = await fetch("/api/auth/magic-link", {
44
+ method: "POST",
45
+ headers: { "Content-Type": "application/json" },
46
+ body: JSON.stringify({ email }),
47
+ });
48
+
49
+ if (!response.ok) {
50
+ const data = await response.json();
51
+ throw new Error(data.error || "Failed to send magic link");
52
+ }
53
+
54
+ setIsSent(true);
55
+ } catch (err) {
56
+ setError(err instanceof Error ? err.message : "Something went wrong");
57
+ } finally {
58
+ setIsLoading(false);
59
+ }
60
+ };
61
+
62
+ if (isSent) {
63
+ return (
64
+ <main className="min-h-screen flex items-center justify-center px-6">
65
+ <div className="max-w-md w-full text-center">
66
+ <div className="w-20 h-20 rounded-full bg-accent/20 flex items-center justify-center mx-auto mb-8">
67
+ <Check className="w-10 h-10 text-accent" />
68
+ </div>
69
+ <h1 className="text-3xl font-bold mb-4">Check Your Email</h1>
70
+ <p className="text-text-secondary mb-2">
71
+ We&apos;ve sent a magic link to:
72
+ </p>
73
+ <p className="font-semibold text-lg mb-8">{email}</p>
74
+ <p className="text-sm text-text-muted">
75
+ Click the link in the email to sign in. The link expires in 15 minutes.
76
+ </p>
77
+ <button
78
+ onClick={() => setIsSent(false)}
79
+ className="mt-8 text-accent hover:underline"
80
+ >
81
+ Use a different email
82
+ </button>
83
+ </div>
84
+ </main>
85
+ );
86
+ }
87
+
88
+ return (
89
+ <main className="min-h-screen">
90
+ {/* Header */}
91
+ <header className="fixed top-0 w-full z-50 bg-background/90 backdrop-blur-xl border-b border-border-subtle">
92
+ <div className="max-w-6xl mx-auto px-6 py-4 flex items-center justify-between">
93
+ <Link href="/" className="flex items-center gap-3">
94
+ <div className="w-9 h-9 rounded-xl bg-accent/20 flex items-center justify-center text-xl">
95
+ 🦞
96
+ </div>
97
+ <span className="font-bold text-lg tracking-tight">APIClaw</span>
98
+ </Link>
99
+ <button
100
+ onClick={toggleTheme}
101
+ className="p-2 rounded-lg hover:bg-[var(--surface)] transition"
102
+ aria-label="Toggle theme"
103
+ >
104
+ {isDark ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
105
+ </button>
106
+ </div>
107
+ </header>
108
+
109
+ <div className="pt-32 pb-24 px-6">
110
+ <div className="max-w-md mx-auto">
111
+ <div className="text-center mb-8">
112
+ <h1 className="text-3xl font-bold mb-2">Provider Dashboard</h1>
113
+ <p className="text-text-secondary">
114
+ Sign in to manage your APIs and view analytics
115
+ </p>
116
+ </div>
117
+
118
+ <div className="rounded-2xl bg-surface-elevated border border-border p-8">
119
+ <form onSubmit={handleSubmit} className="space-y-6">
120
+ <div>
121
+ <label className="block text-sm font-medium mb-2">Email</label>
122
+ <div className="relative">
123
+ <Mail className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-text-muted" />
124
+ <input
125
+ type="email"
126
+ value={email}
127
+ onChange={(e) => {
128
+ setEmail(e.target.value);
129
+ setError(null);
130
+ }}
131
+ placeholder="you@company.com"
132
+ required
133
+ className="w-full pl-12 pr-4 py-3 rounded-xl bg-surface border border-border focus:border-accent focus:outline-none transition"
134
+ />
135
+ </div>
136
+ </div>
137
+
138
+ {error && (
139
+ <div className="p-3 rounded-lg bg-red-500/10 border border-red-500/30 text-red-500 text-sm">
140
+ {error}
141
+ </div>
142
+ )}
143
+
144
+ <button
145
+ type="submit"
146
+ disabled={isLoading || !email}
147
+ className="btn-primary w-full justify-center disabled:opacity-50"
148
+ >
149
+ {isLoading ? (
150
+ <>
151
+ <Loader2 className="w-5 h-5 animate-spin" />
152
+ Sending...
153
+ </>
154
+ ) : (
155
+ <>
156
+ Send Magic Link
157
+ <ArrowRight className="w-5 h-5" />
158
+ </>
159
+ )}
160
+ </button>
161
+ </form>
162
+
163
+ <div className="mt-6 pt-6 border-t border-border text-center">
164
+ <p className="text-sm text-text-muted">
165
+ Don&apos;t have APIs listed?{" "}
166
+ <Link href="/providers/register" className="text-accent hover:underline">
167
+ Register as a provider
168
+ </Link>
169
+ </p>
170
+ </div>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ </main>
175
+ );
176
+ }