agentsclimarketplace

Formcarry

Skill hicay/claude-code-skills/formcarry

Public repository for Claude Code Agent Skills

Install
npx -y skills add hicay/claude-code-skills --skill formcarry

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Build and deploy forms without a backend using Formcarry as the form endpoint. Use this skill when the user mentions "formcarry," "form backend," "form endpoint," "contact form," "no backend form," "form without server," "collect form submissions," "form API," "HTML form submission," "form handling," "lead capture form," "feedback form," "survey form," "registration form," or wants to add a working form to any website, landing page, or app without building server-side code. Covers HTML forms, AJAX submissions (React, Vue, Fetch, Axios), file uploads, spam protection, webhooks, auto-responders, field validation, Stripe payments, and the Formcarry REST API.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

10.6 KB, as published. Nobody here has run it

Formcarry — Forms Without a Backend

Formcarry is a form backend that collects submissions from HTML or JavaScript forms with minimal configuration. No server code needed. Setup takes ~3 minutes.

Endpoint format: https://formcarry.com/s/{FORM_ID}

Before Building

  1. Does the user have a Formcarry account? If not, they need one at formcarry.com
  2. What type of form? Contact, feedback, registration, payment, file upload
  3. Submission method? HTML (page redirect) or AJAX (no reload)
  4. Framework? Plain HTML, React, Vue, Next.js, Astro, or other
  5. Features needed? File uploads, spam protection, auto-responder, webhooks, payments

Quick Start — 3 Steps

Step 1: Create form in Formcarry dashboard

Dashboard → Create Form → Copy endpoint URL from Setup tab.

Step 2: Point your form to the endpoint

<form action="https://formcarry.com/s/{FORM_ID}" method="POST">
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <textarea name="message"></textarea>
  <button type="submit">Send</button>
</form>

Step 3: Submit and check dashboard

Submissions appear in Formcarry dashboard. Email notifications sent to form owner.

Critical rule: Every <input>, <textarea>, and <select> MUST have a name attribute. Without it, data won't be collected.


Submission Methods

Method 1: HTML Form (Page Redirect)

Simplest approach. Form submits, user redirects to thank-you page.

<form action="https://formcarry.com/s/{FORM_ID}" method="POST">
  <input type="text" name="name" placeholder="Name" required>
  <input type="email" name="email" placeholder="Email" required>
  <textarea name="message" placeholder="Message"></textarea>
  <button type="submit">Send</button>
</form>

Method 2: Fetch API (No Reload)

form.addEventListener("submit", async (e) => {
  e.preventDefault();

  const data = Object.fromEntries(new FormData(form));

  const response = await fetch("https://formcarry.com/s/{FORM_ID}", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Accept": "application/json",
    },
    body: JSON.stringify(data),
  });

  const result = await response.json();

  if (result.code === 200) {
    // Success
  } else {
    // Error: result.message
  }
});

Method 3: React

const [status, setStatus] = useState<"idle" | "sending" | "sent" | "error">("idle");

async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
  e.preventDefault();
  setStatus("sending");

  const data = Object.fromEntries(new FormData(e.currentTarget));

  try {
    const res = await fetch("https://formcarry.com/s/{FORM_ID}", {
      method: "POST",
      headers: { "Content-Type": "application/json", "Accept": "application/json" },
      body: JSON.stringify(data),
    });

    const result = await res.json();
    setStatus(result.code === 200 ? "sent" : "error");
  } catch {
    setStatus("error");
  }
}

For complete code examples (Vue, Axios, jQuery, XMLHttpRequest, file uploads), see references/code-examples.md.


Special Hidden Fields

Control behavior with hidden inputs:

FieldPurposeExample
_nextRedirect URL after submit<input type="hidden" name="_next" value="https://site.com/thanks">
_gotchaHoneypot spam trap<input type="hidden" name="_gotcha">

Note: Dashboard thank-you page URL overrides _next. Leave dashboard field empty to use _next.


Spam Protection

Three layers, use together for best results:

1. Built-in (automatic)

Formcarry's algorithm detects spam automatically. Spam is flagged, not deleted.

2. Honeypot field

<input type="hidden" name="_gotcha">

Bots fill hidden fields. Humans don't. Submissions with _gotcha filled are flagged as spam.

3. Google reCAPTCHA

Configure reCAPTCHA secret key in dashboard or via API (googleRecaptcha parameter).

Plan note: Free plan counts spam toward submission limit. Paid plans don't.


File Uploads

Requirement: enctype="multipart/form-data" on the form tag. Limit: 10MB per file. Paid plans only.

<form action="https://formcarry.com/s/{FORM_ID}" method="POST" enctype="multipart/form-data">
  <input type="text" name="name">
  <input type="file" name="attachment">
  <button type="submit">Send</button>
</form>

Multiple files: add multiple attribute or use multiple <input type="file"> elements.

AJAX file uploads: Use FormData object, do NOT set Content-Type header (browser sets it automatically with boundary).

const formData = new FormData(formElement);

const res = await fetch("https://formcarry.com/s/{FORM_ID}", {
  method: "POST",
  headers: { "Accept": "application/json" },
  body: formData, // NOT JSON.stringify — send FormData directly
});

Field Validations

Configure in dashboard. Six validators:

ValidatorRule
requiredField cannot be empty
numberMust be a number
emailMust be valid email
urlMust be valid URL
containsMust contain specified value
notContainsMust NOT contain specified value

Error response (HTTP 422):

{
  "code": 422,
  "status": "error",
  "title": "Validation Failed",
  "errors": {
    "email": { "message": "email is not a valid email", "rule": "email" }
  }
}

Handle validation errors by highlighting fields:

if (result.code === 422) {
  Object.keys(result.errors).forEach(field => {
    document.querySelector(`[name="${field}"]`).classList.add("error");
  });
}

Email Notifications

Self notifications (to form owner)

Enabled by default. Configure email, subject, and template in dashboard.

Auto-response (to submitter)

Enable in dashboard. Requires an email field in the form. Sends confirmation to the person who submitted.

Custom email templates

Available on Growth/Premium plans. Use Mustache-style variables:

Hi {{name}},

Thanks for reaching out about {{subject}}.

{{#phone}}
We'll also call you at {{phone}}.
{{/phone}}

{{#fallback}}company | your company{{/fallback}}

Variables: {{fieldName}} — maps to form field name attributes. Conditionals: {{#field}}...{{/field}} — renders only if field has value. Fallbacks: {{#fallback}}field | default text{{/fallback}} — default when empty. Iteration: {{#fields}}{{key}}: {{value}}{{/fields}} — loop through all fields.


Webhooks

Configure webhook URL in dashboard or via API. Formcarry POSTs submission data to your URL in real-time.

Use cases: Slack notifications, CRM updates, database sync, custom processing.


Stripe Payments

Collect payments alongside form submissions. Configure Stripe integration in dashboard.


REST API

For programmatic form management and submission retrieval.

Authentication: Pass api_key header in every request. Find key in dashboard → Integrations.

For complete API reference (create/delete forms, list/filter submissions, pagination), see references/api-reference.md.


Pricing Quick Reference

PlanPriceFormsSubmissions/moFile StorageTeam
Baby (Free)$0150Yes1
Starter$5/moUnlimited5001GB3
Basic$15/moUnlimited2,0002GB5
Premium$80/moUnlimited30,00030GB20
EnterpriseCustomUnlimitedUnlimitedUnlimitedUnlimited

Common Patterns

Contact form with spam protection

<form action="https://formcarry.com/s/{FORM_ID}" method="POST">
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <textarea name="message" required></textarea>
  <input type="hidden" name="_gotcha">
  <input type="hidden" name="_next" value="https://site.com/thanks">
  <button type="submit">Send Message</button>
</form>

Newsletter signup (minimal)

<form action="https://formcarry.com/s/{FORM_ID}" method="POST">
  <input type="email" name="email" placeholder="[email protected]" required>
  <button type="submit">Subscribe</button>
</form>

Multi-step with JS (collect, then submit)

Collect data across steps in a JS object, then submit all at once via Fetch.

React hook pattern

function useFormcarry(formId: string) {
  const [status, setStatus] = useState<"idle" | "sending" | "sent" | "error">("idle");
  const [errors, setErrors] = useState<Record<string, string>>({});

  async function submit(data: Record<string, string>) {
    setStatus("sending");
    setErrors({});

    try {
      const res = await fetch(`https://formcarry.com/s/${formId}`, {
        method: "POST",
        headers: { "Content-Type": "application/json", "Accept": "application/json" },
        body: JSON.stringify(data),
      });

      const result = await res.json();

      if (result.code === 200) {
        setStatus("sent");
      } else if (result.code === 422) {
        setErrors(Object.fromEntries(
          Object.entries(result.errors).map(([k, v]: any) => [k, v.message])
        ));
        setStatus("error");
      } else {
        setStatus("error");
      }
    } catch {
      setStatus("error");
    }
  }

  return { status, errors, submit };
}

Troubleshooting

ProblemCauseFix
Fields show as emptyMissing name attributeAdd name to every input
CORS errorMissing Accept headerAdd Accept: application/json
File upload failsMissing enctypeAdd enctype="multipart/form-data"
File upload fails (AJAX)Setting Content-Type manuallyDon't set Content-Type, send FormData directly
_next redirect not workingDashboard has custom thank-you URLClear dashboard thank-you page field
Spam not filteredNo protection configuredAdd _gotcha hidden field + enable reCAPTCHA
422 errorField validation failedCheck result.errors for specific field issues

Gives 0 of the 12 instructions most apis services skills give

Counted across 424 of the 426 authors here whose files we hold, read 2026-08-06

  • use plural nouns for resource namesin 41 of 424, across 32 files
  • use cursor-based pagination for large datasetsin 35 of 424, across 20 files
  • include rate limit headers in responsesin 25 of 424, across 13 files
  • Use kebab-case for multi-word resourcesin 23 of 424, across 13 files
  • version APIs in the URL pathin 19 of 424, across 9 files
  • use semantic HTTP status codesin 18 of 424, across 8 files
  • verify webhook signaturesin 18 of 424, across 11 files
  • use query parameters for filteringin 17 of 424, across 6 files
  • use async database operationsin 14 of 424, across 7 files
  • wrap successful responses in a data fieldin 13 of 424, across 3 files
  • prefix sorting parameters with a hyphen for descending orderin 13 of 424, across 3 files
  • set appropriate HTTP status codesin 13 of 424, across 6 files

Said here and by no other author read

  • Point forms to the Formcarry endpoint.
  • Add a name attribute to every field.
  • Send an Accept header for AJAX submissions.
  • Set the correct enctype for file uploads.
  • Send FormData directly for AJAX file uploads.
  • Add hidden _gotcha fields for spam protection.

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.