Chyanne Robbins

← Selected Work

Technical Implementation · Deployed

The Commons

A custom membership inquiry workflow connecting a website, serverless API, and CRM.

Project Properties

Project Type
Independent concept and technical implementation
Technologies
Eleventy, JavaScript, Node.js, Vercel, Cloudflare Turnstile, HubSpot
Status
Live demonstration
View live project ↗ (opens in a new tab)
The Commons homepage: a navigation bar with About, Membership, and an Explore Membership button above a sunset photo of people beneath woven umbrellas, with the headline “A social club for creative people in Fort Lauderdale.”
The Commons homepage, as deployed on Vercel.

Overview

The Commons is a fictional creative members' club developed as an independent technical implementation project.

While the business itself is conceptual, the website and its supporting inquiry workflow are functional. Visitors can submit an inquiry through a custom form, which is validated and processed through a serverless API before being recorded in HubSpot.

I developed the project to explore how a custom website can connect with the systems a business uses to manage information and communicate with prospective customers.

The Problem

A membership-based business needs more than a website that presents its offerings. It also needs a reliable way to collect inquiries, organize information, and manage incoming interest.

For this concept, I focused on connecting the visitor-facing experience to a CRM while accounting for data validation, consent, spam prevention, and potential submission failures.

The goal was to implement a working inquiry-to-CRM workflow rather than build a form that only demonstrated the intended experience visually.

System Overview

The solution connects four primary components:

Website: A custom Eleventy site containing the membership inquiry form.

Vercel API: A Node.js serverless function that validates incoming data and processes submissions.

Cloudflare Turnstile: A verification service used to help prevent automated submissions.

HubSpot CRM: The destination where accepted inquiries are recorded and organized.

When a visitor submits the form, the browser sends their information and verification token to the backend. The API validates the information, verifies the token with Cloudflare, checks the authorized hostname, and sends the accepted inquiry to HubSpot.

The website then communicates the result to the visitor.

The Commons membership inquiry architectureFour systems. 01, Browser — The Commons website: the visitor completes and submits the inquiry form, sending the form data and a verification token to 02, Vercel API — the serverless backend, which receives and validates the request. The API sends the token to 03, Cloudflare Turnstile — the verification service — which returns the verification result to the API. Only after successful validation and verification does the API submit the accepted inquiry to 04, HubSpot CRM, which records it and returns a submission result to the API. The API then returns a success or error response to the browser. Cloudflare Turnstile and HubSpot never communicate directly.01BrowserThe Commons websiteVisitor completes and submits the inquiry form.Form data+ tokenSuccessor error02Vercel APIServerless backendReceives and validates the request, coordinatesverification, and submits accepted inquiries.VerifytokenResultAcceptedinquiryResult03CloudflareTurnstileVerification serviceVerifies the tokenand returns theresult to Vercel.04HubSpot CRMCustomer relationshipmanagementRecords the acceptedinquiry.RequestResponse
How a membership inquiry moves through the system. Cloudflare Turnstile only verifies the token; the Vercel API is the only component that sends data to HubSpot.

I chose a serverless approach for this relatively small workflow, avoiding the need to maintain a separate application server.

The integration includes server-side field validation, required processing consent, a honeypot field, and Cloudflare Turnstile verification.

The backend also uses environment variables to manage configuration, restricts accepted Turnstile hostnames, and handles failures without silently bypassing verification.

Vercel's firewall provides an additional layer of rate limiting.

Together, these decisions support a lightweight implementation while addressing practical concerns that arise when a public-facing form connects to a business system.

const cloudflareResponse = await fetch(
  "https://challenges.cloudflare.com/turnstile/v0/siteverify",
  {
    method: "POST",
    body: new URLSearchParams({
      secret,
      response: turnstileToken
    })
  }
);

// …

if (verification.success !== true) {
  // Cloudflare's reason codes only; never the token or secret.
  console.warn(
    "Turnstile verification failed:",
    verification["error-codes"],
    "hostname:",
    verification.hostname
  );
  return response.status(403).json({
    error: "Verification failed. Please try again."
  });
}

// The token must have been issued on one of our own hostnames.
const tokenHostname =
  typeof verification.hostname === "string"
    ? verification.hostname.toLowerCase()
    : "";

if (!allowedHostnames.includes(tokenHostname)) {
  console.warn("Turnstile hostname not allowed:", tokenHostname || "(none)");
  return response.status(403).json({
    error: "Verification failed. Please try again."
  });
}

// Only after successful verification do we contact HubSpot.
Abridged excerpt from the project's serverless API: the Turnstile token is verified with Cloudflare, tokens issued for unapproved hostnames are rejected, and only then does the request continue to HubSpot. “// …” marks omitted lines.

Two issues were particularly useful in developing my understanding of technical integrations.

Runtime configuration

During Turnstile integration, the local Vercel server continued using an older testing secret even after I updated the environment file.

The problem wasn't the API's verification logic. It was the environment inherited by the running development process.

Tracing that behavior helped me understand the distinction between source code, local configuration files, and the variables actually available to an application at runtime.

Validation across systems

After deployment, certain inquiries failed even though they passed the website's validation and Turnstile verification.

The backend returned an error because HubSpot was rejecting the submission. I added privacy-conscious diagnostic logging to capture HubSpot's error type and affected field without recording submitted personal information.

The logs revealed a REQUIRED_FIELD error for lastname.

The website collected one full-name field and permitted single-word names, but the HubSpot form required a last name. Making that CRM field optional resolved the mismatch.

The experience reinforced an important lesson: a workflow can appear correctly implemented within one system and still fail because another system applies different rules.


The final implementation was deployed publicly through Vercel.

I verified that an inquiry submitted through the live website was accepted and recorded in HubSpot. The implementation also underwent syntax and build checks, targeted failure-path testing, and a comparison of the committed source against the deployed version.

01 Website form

The Commons membership inquiry form, with fields for full name, email, membership interest, and an optional message, followed by a privacy notice, a consent checkbox, a Cloudflare Turnstile verification widget, and a Submit interest button.
View full size ↗

02 HubSpot record

HubSpot form submission for the fictional test contact Portfolio Verification, submitted October 21, 2026 at 12:28 AM EDT using the API. Contact record fields: First Name, Portfolio; Last Name, Verification; Email, portfolio.verification@example.com; Membership interest, Undecided; Message, “Final production integration test.” Other values: Process consent, I consent.
View full size ↗
The deployed inquiry form, including the consent checkbox and Turnstile verification, alongside a production test submission recorded in HubSpot through the API, with its mapped fields and processing consent.

The result is a working demonstration of how a custom digital experience can connect to a CRM through a backend integration.

The implementation provides a foundation for future extensions, including inquiry management tools, automated follow-ups, and more developed administrative workflows.


I directed the implementation, configured external services, made integration and workflow decisions, participated in troubleshooting, and verified the final system.

I used ChatGPT to support technical learning, planning, and debugging, and Claude Code to assist with code implementation, testing, review, and deployment.

AI-assisted development was part of the workflow, while I remained responsible for understanding the system, evaluating results, and making implementation decisions.


The Commons is a portfolio demonstration, not an operating membership club.

The current implementation focuses on collecting and recording inquiries. It does not include automated follow-up communications, a membership management platform, or an internal operations dashboard.

Potential next steps include extending the CRM workflow, creating internal tools for reviewing inquiries, and improving operational processes around data retention and ongoing maintenance.