@stackverify/forms 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,319 @@
1
+ # StackVerify Forms
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@stackverify/forms)](https://www.npmjs.com/package/@stackverify/forms)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@stackverify/forms)](https://www.npmjs.com/package/@stackverify/forms)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-3178C6?logo=typescript\&logoColor=white)](https://www.typescriptlang.org/)
6
+ [![License](https://img.shields.io/npm/l/@stackverify/forms)](LICENSE)
7
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@stackverify/forms)](https://bundlephobia.com/package/@stackverify/forms)
8
+
9
+ A lightweight JavaScript and TypeScript SDK for submitting forms to StackVerify.
10
+
11
+ Collect submissions from any website or application without building your own backend. Every submission is securely stored, delivered to your StackVerify dashboard, and can trigger email notifications, webhooks, WhatsApp workflows, and future automations.
12
+
13
+ ---
14
+
15
+ ## Why StackVerify Forms?
16
+
17
+ Building and maintaining infrastructure for a simple contact form shouldn't slow down your product.
18
+
19
+ StackVerify Forms gives you:
20
+
21
+ * Instant form endpoints
22
+ * Submission storage
23
+ * Dashboard for managing responses
24
+ * Email notifications
25
+ * Webhook support
26
+ * WhatsApp automation
27
+ * TypeScript support
28
+ * Framework-agnostic SDK
29
+ * Zero runtime dependencies
30
+
31
+ Instead of building APIs, databases, and notification systems, simply submit your data and let StackVerify handle the rest.
32
+
33
+ ---
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ npm install @stackverify/forms
39
+ ```
40
+
41
+ ```bash
42
+ yarn add @stackverify/forms
43
+ ```
44
+
45
+ ```bash
46
+ pnpm add @stackverify/forms
47
+ ```
48
+
49
+ ---
50
+
51
+ # Quick Start
52
+
53
+ Create a form from your StackVerify dashboard.
54
+
55
+ You'll receive a unique Form ID.
56
+
57
+ ```ts
58
+ import { submitForm } from "@stackverify/forms";
59
+
60
+ await submitForm({
61
+ formId: "frm_xxxxxxxxx",
62
+ data: {
63
+ name: "Jane Doe",
64
+ email: "jane@example.com",
65
+ company: "Acme Inc.",
66
+ message: "I'd like to schedule a demo."
67
+ }
68
+ });
69
+ ```
70
+
71
+ Your submission is immediately available inside your StackVerify dashboard.
72
+
73
+ ---
74
+
75
+ # React
76
+
77
+ ```tsx
78
+ import { submitForm } from "@stackverify/forms";
79
+
80
+ export default function ContactForm() {
81
+
82
+ async function handleSubmit(e) {
83
+ e.preventDefault();
84
+
85
+ const data = Object.fromEntries(
86
+ new FormData(e.target)
87
+ );
88
+
89
+ await submitForm({
90
+ formId: "frm_xxxxxxxxx",
91
+ data
92
+ });
93
+ }
94
+
95
+ return (
96
+ <form onSubmit={handleSubmit}>
97
+ <input name="name" />
98
+ <input name="email" />
99
+ <textarea name="message" />
100
+ <button>Send</button>
101
+ </form>
102
+ );
103
+ }
104
+ ```
105
+
106
+ ---
107
+
108
+ # Next.js
109
+
110
+ ```ts
111
+ import { submitForm } from "@stackverify/forms";
112
+
113
+ await submitForm({
114
+ formId: process.env.NEXT_PUBLIC_FORM_ID!,
115
+ data: {
116
+ email,
117
+ message
118
+ }
119
+ });
120
+ ```
121
+
122
+ ---
123
+
124
+ # Vue
125
+
126
+ ```ts
127
+ import { submitForm } from "@stackverify/forms";
128
+
129
+ await submitForm({
130
+ formId: "frm_xxxxxxxxx",
131
+ data: {
132
+ name,
133
+ email
134
+ }
135
+ });
136
+ ```
137
+
138
+ ---
139
+
140
+ # Svelte
141
+
142
+ ```ts
143
+ import { submitForm } from "@stackverify/forms";
144
+
145
+ await submitForm({
146
+ formId: "frm_xxxxxxxxx",
147
+ data
148
+ });
149
+ ```
150
+
151
+ ---
152
+
153
+ # Node.js
154
+
155
+ ```ts
156
+ import { submitForm } from "@stackverify/forms";
157
+
158
+ await submitForm({
159
+ formId: "frm_xxxxxxxxx",
160
+ data: {
161
+ userId: 123,
162
+ event: "signup"
163
+ }
164
+ });
165
+ ```
166
+
167
+ ---
168
+
169
+ # Vanilla JavaScript
170
+
171
+ ```js
172
+ import { submitForm } from "@stackverify/forms";
173
+
174
+ submitForm({
175
+ formId: "frm_xxxxxxxxx",
176
+ data: {
177
+ email: "john@example.com"
178
+ }
179
+ });
180
+ ```
181
+
182
+ ---
183
+
184
+ # HTML
185
+
186
+ Every form automatically includes a public endpoint.
187
+
188
+ ```html
189
+ <form action="https://stackverify.site/api/f/YOUR_FORM_ID" method="POST">
190
+
191
+ <input
192
+ name="name"
193
+ required>
194
+
195
+ <input
196
+ type="email"
197
+ name="email"
198
+ required>
199
+
200
+ <button type="submit">
201
+ Submit
202
+ </button>
203
+
204
+ </form>
205
+ ```
206
+
207
+ No backend required.
208
+
209
+ ---
210
+
211
+ # API
212
+
213
+ ```ts
214
+ submitForm({
215
+ formId,
216
+ data,
217
+ timeout,
218
+ baseUrl,
219
+ fetch
220
+ });
221
+ ```
222
+
223
+ | Option | Type | Description |
224
+ | ------- | ------------------- | --------------------------- |
225
+ | formId | string | StackVerify Form ID |
226
+ | data | Record<string, any> | Form data |
227
+ | timeout | number | Request timeout |
228
+ | baseUrl | string | Custom API URL |
229
+ | fetch | Fetch | Custom fetch implementation |
230
+
231
+ ---
232
+
233
+ # TypeScript
234
+
235
+ Built-in TypeScript definitions are included.
236
+
237
+ ```ts
238
+ import type { SubmitOptions } from "@stackverify/forms";
239
+ ```
240
+
241
+ ---
242
+
243
+ # Supported Frameworks
244
+
245
+ | Frontend | Backend |
246
+ | ------------------ | ------------------ |
247
+ | React | Node.js |
248
+ | Next.js | Express |
249
+ | Vue | Bun |
250
+ | Nuxt | Deno |
251
+ | Angular | Fastify |
252
+ | Svelte | NestJS |
253
+ | SvelteKit | Cloudflare Workers |
254
+ | Astro | |
255
+ | Remix | |
256
+ | SolidJS | |
257
+ | Vite | |
258
+ | Vanilla JavaScript | |
259
+
260
+ ---
261
+
262
+ # Typical Workflow
263
+
264
+ ```
265
+ Application
266
+
267
+
268
+ StackVerify Forms SDK
269
+
270
+
271
+ StackVerify API
272
+
273
+ ├── Stores submissions
274
+ ├── Dashboard
275
+ ├── Email notifications
276
+ ├── Webhooks
277
+ └── Automation
278
+ ```
279
+
280
+ ---
281
+
282
+ # Use Cases
283
+
284
+ * Contact forms
285
+ * Newsletter subscriptions
286
+ * Lead generation
287
+ * Landing pages
288
+ * SaaS onboarding
289
+ * Product orders
290
+ * Event registration
291
+ * Customer feedback
292
+ * Internal business tools
293
+ * Booking requests
294
+ * Waitlists
295
+
296
+ ---
297
+
298
+ # Why Use the SDK?
299
+
300
+ You could send requests manually using `fetch`.
301
+
302
+ The SDK provides:
303
+
304
+ * Consistent API
305
+ * TypeScript support
306
+ * Validation
307
+ * Better error handling
308
+ * Cleaner code
309
+ * Future compatibility as StackVerify evolves
310
+
311
+ ---
312
+
313
+ # License
314
+
315
+ MIT
316
+
317
+ ---
318
+
319
+ Built for developers who want to ship forms, not infrastructure.
package/dist/index.cjs ADDED
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ StackVerifyError: () => StackVerifyError,
24
+ submitForm: () => submitForm
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/utils.ts
29
+ function toFormEncoded(data) {
30
+ const body = new URLSearchParams();
31
+ Object.entries(data).forEach(([k, v]) => {
32
+ if (v !== void 0 && v !== null) {
33
+ body.append(k, String(v));
34
+ }
35
+ });
36
+ return body;
37
+ }
38
+
39
+ // src/errors.ts
40
+ var StackVerifyError = class extends Error {
41
+ constructor(message, options) {
42
+ super(message, { cause: options?.cause });
43
+ this.name = "StackVerifyError";
44
+ this.status = options?.status;
45
+ this.code = options?.code;
46
+ this.details = options?.details;
47
+ }
48
+ };
49
+
50
+ // src/submitForm.ts
51
+ async function submitForm({
52
+ formId,
53
+ data,
54
+ baseUrl = "https://stackverify.site",
55
+ timeout = 1e4,
56
+ fetch: fetchImpl = fetch
57
+ }) {
58
+ const controller = new AbortController();
59
+ const timer = setTimeout(() => {
60
+ controller.abort();
61
+ }, timeout);
62
+ try {
63
+ const response = await fetchImpl(
64
+ `${baseUrl}/api/f/${formId}`,
65
+ {
66
+ method: "POST",
67
+ headers: {
68
+ "Content-Type": "application/x-www-form-urlencoded"
69
+ },
70
+ body: toFormEncoded(data),
71
+ signal: controller.signal
72
+ }
73
+ );
74
+ clearTimeout(timer);
75
+ const text = await response.text();
76
+ let dataResponse;
77
+ try {
78
+ dataResponse = JSON.parse(text);
79
+ } catch {
80
+ dataResponse = text;
81
+ }
82
+ if (!response.ok) {
83
+ throw new StackVerifyError(
84
+ dataResponse?.message || `Submission failed (${response.status})`
85
+ );
86
+ }
87
+ return dataResponse;
88
+ } catch (err) {
89
+ clearTimeout(timer);
90
+ if (err.name === "AbortError") {
91
+ throw new StackVerifyError("Request timeout");
92
+ }
93
+ throw err;
94
+ }
95
+ }
96
+ // Annotate the CommonJS export names for ESM import in node:
97
+ 0 && (module.exports = {
98
+ StackVerifyError,
99
+ submitForm
100
+ });
@@ -0,0 +1,28 @@
1
+ interface SubmitFormOptions {
2
+ formId: string;
3
+ data: Record<string, any>;
4
+ baseUrl?: string;
5
+ timeout?: number;
6
+ fetch?: typeof fetch;
7
+ }
8
+ declare function submitForm({ formId, data, baseUrl, timeout, fetch: fetchImpl }: SubmitFormOptions): Promise<any>;
9
+
10
+ declare class StackVerifyError extends Error {
11
+ status?: number;
12
+ code?: string;
13
+ details?: any;
14
+ constructor(message: string, options?: {
15
+ status?: number;
16
+ code?: string;
17
+ details?: any;
18
+ cause?: unknown;
19
+ });
20
+ }
21
+
22
+ interface SubmitOptions {
23
+ baseUrl?: string;
24
+ timeout?: number;
25
+ fetch?: typeof fetch;
26
+ }
27
+
28
+ export { StackVerifyError, type SubmitOptions, submitForm };
@@ -0,0 +1,28 @@
1
+ interface SubmitFormOptions {
2
+ formId: string;
3
+ data: Record<string, any>;
4
+ baseUrl?: string;
5
+ timeout?: number;
6
+ fetch?: typeof fetch;
7
+ }
8
+ declare function submitForm({ formId, data, baseUrl, timeout, fetch: fetchImpl }: SubmitFormOptions): Promise<any>;
9
+
10
+ declare class StackVerifyError extends Error {
11
+ status?: number;
12
+ code?: string;
13
+ details?: any;
14
+ constructor(message: string, options?: {
15
+ status?: number;
16
+ code?: string;
17
+ details?: any;
18
+ cause?: unknown;
19
+ });
20
+ }
21
+
22
+ interface SubmitOptions {
23
+ baseUrl?: string;
24
+ timeout?: number;
25
+ fetch?: typeof fetch;
26
+ }
27
+
28
+ export { StackVerifyError, type SubmitOptions, submitForm };
package/dist/index.js ADDED
@@ -0,0 +1,72 @@
1
+ // src/utils.ts
2
+ function toFormEncoded(data) {
3
+ const body = new URLSearchParams();
4
+ Object.entries(data).forEach(([k, v]) => {
5
+ if (v !== void 0 && v !== null) {
6
+ body.append(k, String(v));
7
+ }
8
+ });
9
+ return body;
10
+ }
11
+
12
+ // src/errors.ts
13
+ var StackVerifyError = class extends Error {
14
+ constructor(message, options) {
15
+ super(message, { cause: options?.cause });
16
+ this.name = "StackVerifyError";
17
+ this.status = options?.status;
18
+ this.code = options?.code;
19
+ this.details = options?.details;
20
+ }
21
+ };
22
+
23
+ // src/submitForm.ts
24
+ async function submitForm({
25
+ formId,
26
+ data,
27
+ baseUrl = "https://stackverify.site",
28
+ timeout = 1e4,
29
+ fetch: fetchImpl = fetch
30
+ }) {
31
+ const controller = new AbortController();
32
+ const timer = setTimeout(() => {
33
+ controller.abort();
34
+ }, timeout);
35
+ try {
36
+ const response = await fetchImpl(
37
+ `${baseUrl}/api/f/${formId}`,
38
+ {
39
+ method: "POST",
40
+ headers: {
41
+ "Content-Type": "application/x-www-form-urlencoded"
42
+ },
43
+ body: toFormEncoded(data),
44
+ signal: controller.signal
45
+ }
46
+ );
47
+ clearTimeout(timer);
48
+ const text = await response.text();
49
+ let dataResponse;
50
+ try {
51
+ dataResponse = JSON.parse(text);
52
+ } catch {
53
+ dataResponse = text;
54
+ }
55
+ if (!response.ok) {
56
+ throw new StackVerifyError(
57
+ dataResponse?.message || `Submission failed (${response.status})`
58
+ );
59
+ }
60
+ return dataResponse;
61
+ } catch (err) {
62
+ clearTimeout(timer);
63
+ if (err.name === "AbortError") {
64
+ throw new StackVerifyError("Request timeout");
65
+ }
66
+ throw err;
67
+ }
68
+ }
69
+ export {
70
+ StackVerifyError,
71
+ submitForm
72
+ };
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@stackverify/forms",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "API-first form, lead & order collection SDK. Works on Vercel, React, Next.js, and any frontend framework. No backend required.",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "keywords": [
20
+ "forms",
21
+ "leads",
22
+ "orders",
23
+ "api",
24
+ "serverless",
25
+ "vercel",
26
+ "frontend",
27
+ "no-backend",
28
+ "saas",
29
+ "webhooks"
30
+ ],
31
+ "author": "StackVerify",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/stackmorgan/stackmorgan-forms"
36
+ },
37
+ "homepage": "https://stackverify.site/forms",
38
+ "bugs": {
39
+ "url": "https://stackverify.site/contact"
40
+ },
41
+ "scripts": {
42
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean"
43
+ },
44
+ "devDependencies": {
45
+ "tsup": "^8.5.1",
46
+ "typescript": "^5.9.3"
47
+ },
48
+ "dependencies": {
49
+ "@stackverify/forms": "file:stackverify-forms-1.0.0.tgz"
50
+ }
51
+ }