Skip to content
All projects

CRM · Full-stack web platform · AI automation

Easy Control

From web form to signed contract: AI qualifies, the CEO approves and WhatsApp follow-ups run on their own, with every send monitored.

Client
Bolsa Atleta USA
Role
Full-stack Software Engineer
Year
2026
Technologies
  • Next.js
  • React
  • TypeScript
  • Node.js
  • PostgreSQL (Supabase)
  • Google Cloud
  • Gemini API
  • GitHub Actions

Context

Bolsa Atleta USA advises Brazilian athletes seeking sports scholarships at schools and universities in the United States. The project covers the complete system: the public website with its assessment form, and Easy Control, the internal CRM and operations platform the CEO and the team use for sales, contracts and family follow-up. I built it as the sole engineer, AI-assisted (Claude Code), and it is in production.

Challenge

Leads from paid campaigns arrive at any hour and lose interest quickly. Most athletes are minors and the decision involves a large investment, so every automated message requires control over eligibility, timing and recipient. The system had to automate the sales funnel without removing human approval, and continuously monitor delivery, including silent failures from external providers.

Results

Cloud Functions in production
27
screens in Easy Control
60+
pull requests merged in 2026
410+
CI guard test files
41

Key deliverables

  1. 01Architected and built the public website and multi-step form with Next.js, React and TypeScript, with internationalization in Portuguese, English and Spanish and campaign attribution (UTM, source and device) stored on every lead in PostgreSQL (Supabase).
  2. 02Integrated Gemini into lead qualification with a versioned prompt, an auditable 0–100 financial score, five classification states and an adversarial second pass, keeping human approval before the first outbound outreach to each form lead.
  3. 03Built Easy Control with Next.js, React and Supabase, a platform with more than 60 screens (kanban pipeline with editable stages, executive War Room and approval queue), with role-based access control (RBAC) and PostgreSQL Row Level Security.
  4. 04Designed the Easy Control component library and design system with React, TypeScript and Tailwind CSS (color, typography, radius and shadow tokens, typed variants with class-variance-authority, drag-and-drop domain components, and light and dark themes), applied across every screen.
  5. 05Built the serverless backend with 27 Node.js 20 Cloud Functions on Google Cloud (AI qualification, WhatsApp cadence via Z-API, conversation flow engine, calendar, billing and data syncs), with idempotent sending and two independent sending safeguards in the flow engine.
  6. 06Implemented observability with 23 automated health checks (Cloud Function + Cloud Scheduler), WhatsApp and email alerts and a dead-man's switch on GitHub Actions, plus CI/CD with 41 guard test files that block merges on regressions.
  1. The funnel on mobile

    The funnel starts on the public website, in Portuguese, English and Spanish. The mobile-first form captures the investment range that feeds the AI score, and the approved lead gets the meeting invitation and confirmation on WhatsApp. The conversation was recreated with fictitious data.

    • bolsaatletausa.com home page on mobile: the Bolsa Atleta USA logo, the headline “Educação Esportiva Inteligente” (Smart Sports Education), an “Acompanhamento ativo em cada etapa” (Active support at every step) pill, copy about journeys from high school to university and a burgundy “Iniciar avaliação estratégica” (Start strategic assessment) button.
      bolsaatletausa.com home page on mobile: the Bolsa Atleta USA logo, the headline “Educação Esportiva Inteligente” (Smart Sports Education), an “Acompanhamento ativo em cada etapa” (Active support at every step) pill, copy about journeys from high school to university and a burgundy “Iniciar avaliação estratégica” (Start strategic assessment) button.
    • The form's “Estrutura Estratégica” (Strategic structure) step on mobile: copy about the yearly investment in US dollars, the question of how much the family is prepared to invest and five ranges from US$ 15,000 to US$ 70,000 as cards, one selected; footer “Etapa 2 de 2, 75% completo” (Stage 2 of 2, 75% complete).
      The form's “Estrutura Estratégica” (Strategic structure) step on mobile: copy about the yearly investment in US dollars, the question of how much the family is prepared to invest and five ranges from US$ 15,000 to US$ 70,000 as cards, one selected; footer “Etapa 2 de 2, 75% completo” (Stage 2 of 2, 75% complete).
    • Bolsa Atleta USA WhatsApp conversation with a parent: a message saying the athlete's profile was selected, with a link to book the Individual Strategy Meeting, the family's reply, the automatic meeting confirmation with date, time and a Google Meet link, and the family's final reply confirming attendance.
      Bolsa Atleta USA WhatsApp conversation with a parent: a message saying the athlete's profile was selected, with a link to book the Individual Strategy Meeting, the family's reply, the automatic meeting confirmation with date, time and a Google Meet link, and the family's final reply confirming attendance.
  2. Human approval

    The approval dossier brings together Gemini's auditable score and reasoning so the CEO can decide. Recreated screen with fictitious data.

    Lead approval window over the pipeline: on the left the queue sorted by score, on the right the athlete dossier with the AI pre-qualification — financial score 82, profession tier A, high sports priority, reinforcement and alert signals — plus Reject and Approve lead buttons.
    Lead approval window over the pipeline: on the left the queue sorted by score, on the right the athlete dossier with the AI pre-qualification — financial score 82, profession tier A, high sports priority, reinforcement and alert signals — plus Reject and Approve lead buttons.
  3. Pipeline with editable stages

    The kanban pipeline has editable stages, and its first column is the human approval queue. Recreated screen with fictitious data.

    Easy Control sales pipeline kanban: an orange column of leads awaiting approval, followed by Lead, Meeting booked, Meeting and Diagnosis, with athlete cards showing value, plan, next action and priority and AI-qualification badges; above, pipeline indicators and filters by temperature, plan and overdue actions.
    Easy Control sales pipeline kanban: an orange column of leads awaiting approval, followed by Lead, Meeting booked, Meeting and Diagnosis, with athlete cards showing value, plan, next action and priority and AI-qualification badges; above, pipeline indicators and filters by temperature, plan and overdue actions.
  4. War Room

    The War Room brings revenue, funnel, cash and editable goals together on a single screen. Recreated screen with fictitious data.

    Easy Control executive War Room, with the brand logo at the top of the sidebar: monthly revenue with a 12-month area chart and goal progress, cards for total pipeline, conversion and active families, yearly strategic goals and six shortcuts to goal, funnel, cash, risk, positioning and family experience.
    Easy Control executive War Room, with the brand logo at the top of the sidebar: monthly revenue with a 12-month area chart and goal progress, cards for total pipeline, conversion and active families, yearly strategic goals and six shortcuts to goal, funnel, cash, risk, positioning and family experience.
  5. Conversation flows

    The conversation flow engine is channel-agnostic, measures lead capture and runs live on WhatsApp. Recreated screen with fictitious data.

    Easy Control WhatsApp conversation flow builder: a keyword-message trigger, chained blocks for message, multiple-choice question, AI classification, funnel capture and human handoff, each showing how many contacts arrived and moved on; alongside, the capture funnel, the sending safeguards with Instagram pending approval and the AI flow assistant.
    Easy Control WhatsApp conversation flow builder: a keyword-message trigger, chained blocks for message, multiple-choice question, AI classification, funnel capture and human handoff, each showing how many contacts arrived and moved on; alongside, the capture funnel, the sending safeguards with Instagram pending approval and the AI flow assistant.
  6. Observability

    The observability monitor runs automated checks every 30 minutes and confirms actual message delivery. Recreated screen with fictitious data.

    Easy Control observability queue monitor: overall status All operational, indicators for WhatsApp connection, qualifications and confirmed deliveries, five operational automations, six queue checks marked OK and the flow from form to meeting.
    Easy Control observability queue monitor: overall status All operational, indicators for WhatsApp connection, qualifications and confirmed deliveries, five operational automations, six queue checks marked OK and the flow from form to meeting.
  7. Design system foundations

    Light and dark theme tokens feed primitives with typed variants, reused across more than 60 screens.

    Easy Control design system sheet, foundations and primitives, with the brand symbol, a block split into three green stages, beside the title: ten color tokens as light and dark pairs with hex values (primary and ec-stage-2 in the brand's forest and pine greens, which turn mint and light jade in the dark theme, gradient, text, surfaces and status colors); Inter type scale; 6 to 20 px radii, four shadow levels and the liquid glass material over brand color blobs; buttons in primary, secondary, ghost, brand and destructive variants across default, hover and disabled states, sizes and keyboard focus; tone badges, HOT, WARM, COLD, INVALID and INCOMPLETE classifications, plans, priorities and percentage deltas; switches, segmented and underline tabs, text inputs and a page header.
    Easy Control design system sheet, foundations and primitives, with the brand symbol, a block split into three green stages, beside the title: ten color tokens as light and dark pairs with hex values (primary and ec-stage-2 in the brand's forest and pine greens, which turn mint and light jade in the dark theme, gradient, text, surfaces and status colors); Inter type scale; 6 to 20 px radii, four shadow levels and the liquid glass material over brand color blobs; buttons in primary, secondary, ghost, brand and destructive variants across default, hover and disabled states, sizes and keyboard focus; tone badges, HOT, WARM, COLD, INVALID and INCOMPLETE classifications, plans, priorities and percentage deltas; switches, segmented and underline tabs, text inputs and a page header.
  8. Card anatomy

    The kanban card is built from primitives and composes the column and the board, with every state coming from the component's own classes.

    Easy Control anatomy and composition sheet: the kanban deal card enlarged with six numbered markers (stage stripe, athlete and guardian, plan, value and time in stage, next action and badges) linked to the component's typed props and its JSX signature; beside it, the composition chain Badge, DealCard, PipelineColumn and PipelineBoard; below, the same card in default, hover, dragging, incomplete with overdue action and off-timing states.
    Easy Control anatomy and composition sheet: the kanban deal card enlarged with six numbered markers (stage stripe, athlete and guardian, plan, value and time in stage, next action and badges) linked to the component's typed props and its JSX signature; beside it, the composition chain Badge, DealCard, PipelineColumn and PipelineBoard; below, the same card in default, hover, dragging, incomplete with overdue action and off-timing states.
  9. Domain components

    Domain components cover loading, dragging, empty and error states, and switch themes through tokens alone.

    Easy Control domain components sheet with states the screens do not show: a kanban column highlighted as a drop target with a card being dragged, a loading skeleton, an empty approval column and a hidden column during reordering; KPI cards with an inverted delta; the pre-qualification dossier in its WARM variant with score 58; a paused automation; condition and wait flow blocks; OK, Warning and Failure health checks; a lead-approved toast; and, on a dark panel, the same components with the dark theme tokens.
    Easy Control domain components sheet with states the screens do not show: a kanban column highlighted as a drop target with a card being dragged, a loading skeleton, an empty approval column and a hidden column during reordering; KPI cards with an inverted delta; the pre-qualification dossier in its WARM variant with score 58; a paused automation; condition and wait flow blocks; OK, Warning and Failure health checks; a lead-approved toast; and, on a dark panel, the same components with the dark theme tokens.
  10. Architecture

    The board follows the lead journey from 1 to 10: from the Next.js form to PostgreSQL on Supabase, from the 27 Cloud Functions on Google Cloud to the CEO's approval and confirmed WhatsApp delivery, with the watcher outside Google Cloud and the decisions and trade-offs alongside.

    Easy Control architecture board in the style of a Miro board, from form to contract, with the figures 27 Cloud Functions in production, 17 Cloud Scheduler jobs, 131 versioned migrations, more than 200 RLS policies, 23 health checks every 30 min and 41 guard test files. Eight zones: Clients and channels (the athlete's family, WhatsApp, Instagram awaiting Meta's review and the CEO and team with 4 roles); Front-end on Vercel (the public website in three languages, the multi-step form, the short link, Easy Control on the App Router with Server Components, the WhatsApp inbox, tracking and the Turborepo monorepo with pnpm); Data on Supabase (PostgREST, Database Webhooks, PostgreSQL as the CRM's single source of truth, Supabase Auth, Storage, SQL functions and triggers and the settings with fail-closed gates); Google Cloud in the us-central1 region, with the 17 Cloud Scheduler jobs and their crons, the WhatsApp queues, the automation and flow engines, observability and the edge, webhook and API functions; external APIs (Gemini 2.5 Flash, Resend with Brevo as fallback, Sheets, Calendar, Drive, Gmail, Z-API, Marketing API and Instagram); CI/CD on GitHub Actions, with the CI that blocks the merge, develop to UAT, main to production and the dead-man's switch; Security, fail-closed by default; and Decisions and trade-offs on sticky notes. The lead journey, numbered 1 to 10, goes from the form to the PostgREST upsert, the database webhook that triggers 3 functions, Gemini's score, the CEO's approval, the queue with CAS, delivery through Z-API, the Calendar push, the mirror of each message and the heartbeat read by the watcher on GitHub Actions. Dashed blue lines mark asynchronous steps, and red ones, failure and fallback.
    Easy Control architecture board in the style of a Miro board, from form to contract, with the figures 27 Cloud Functions in production, 17 Cloud Scheduler jobs, 131 versioned migrations, more than 200 RLS policies, 23 health checks every 30 min and 41 guard test files. Eight zones: Clients and channels (the athlete's family, WhatsApp, Instagram awaiting Meta's review and the CEO and team with 4 roles); Front-end on Vercel (the public website in three languages, the multi-step form, the short link, Easy Control on the App Router with Server Components, the WhatsApp inbox, tracking and the Turborepo monorepo with pnpm); Data on Supabase (PostgREST, Database Webhooks, PostgreSQL as the CRM's single source of truth, Supabase Auth, Storage, SQL functions and triggers and the settings with fail-closed gates); Google Cloud in the us-central1 region, with the 17 Cloud Scheduler jobs and their crons, the WhatsApp queues, the automation and flow engines, observability and the edge, webhook and API functions; external APIs (Gemini 2.5 Flash, Resend with Brevo as fallback, Sheets, Calendar, Drive, Gmail, Z-API, Marketing API and Instagram); CI/CD on GitHub Actions, with the CI that blocks the merge, develop to UAT, main to production and the dead-man's switch; Security, fail-closed by default; and Decisions and trade-offs on sticky notes. The lead journey, numbered 1 to 10, goes from the form to the PostgREST upsert, the database webhook that triggers 3 functions, Gemini's score, the CEO's approval, the queue with CAS, delivery through Z-API, the Calendar push, the mirror of each message and the heartbeat read by the watcher on GitHub Actions. Dashed blue lines mark asynchronous steps, and red ones, failure and fallback.

Features and the pains they solve

Every feature was born from a real operational problem.

  1. 01

    AI lead qualification

    Pain
    With a two-person operation, every meeting counts. The biggest cost was hours of meetings with mid-profile leads, plus forms filled in with random data.
    Solution
    Every new form triggers a Cloud Function that sends the sanitized data to Gemini (versioned prompt, temperature 0) and gets back a 0 to 100 financial score based on profession tier. A code-level gate stops junk data from ever coming out HOT or WARM, and the middle band gets an adversarial second pass.

    Impact: 0 to 100 score · 5 classifications

  2. 02

    Human approval queue

    Pain
    In the fully automated version, a HOT or WARM lead got its first WhatsApp message without any human review: the AI alone decided who was invited.
    Solution
    HOT and WARM leads come in as pending in the first pipeline column, with the AI dossier, and the CEO is notified right away. Only approval creates the deal and unlocks outreach; requalification never overrides that decision, and anything pending for more than 24 hours raises an alert.

    Impact: 100% of first WhatsApps need approval

  3. 03

    WhatsApp cadence

    Pain
    Campaign leads lose interest fast, so follow-ups have to go out at the right time and only to the right people: a single missing eligibility filter is enough for a message to reach someone out of profile or at the wrong moment.
    Solution
    Hourly schedulers send the first message and two follow-ups through Z‑API, filtering by class, timing and approval, and stop once the lead books a meeting. Each send is claimed with an atomic compare-and-set (CAS) before it goes out, and a CI guard test blocks the merge if any filter disappears.

    Impact: Default: 22 h, 48 h and 7 days

  4. 04

    Observability

    Pain
    A WhatsApp provider can answer 200 OK without delivering anything: without monitoring real delivery, the connection drops, the queues look up to date and nobody notices.
    Solution
    Every 30 minutes, a Cloud Function looks for positive signs of life, such as the connection state and the copy of each message WhatsApp echoes back as proof of delivery. Alerts go out on WhatsApp and by email, and a dead-man's switch on GitHub Actions fires if the monitor itself stops.

    Impact: Up to 23 checks every 30 min

  5. 05

    Meeting detection via Calendar

    Pain
    Meetings booked by leads could fail to reach the CRM, with no error or log, when the phone number came in a format the parser didn't recognize (like the area code in parentheses glued to the digits). And if Google's push failed, there was no second chance.
    Solution
    A Google Calendar push notification matches the event to the lead (email or last 10 digits of the phone), confirms the meeting to the lead with the Meet link, notifies the CEO and moves the deal to Meeting booked. An hourly sweep recovers anything the push missed.

    Impact: Push + hourly sweep

  6. 06

    Pipeline with editable stages

    Pain
    The CEO's sales process had 9 stages that didn't match the stages stored in the database, and renaming one would have required a database migration plus changes scattered across the code.
    Solution
    A drag-and-drop kanban whose column labels and order come from configuration, not from the database enum. Clicking a column lets the CEO edit its name, automations and AI agents, and create columns of their own.

    Impact: 9 stages + up to 6 custom columns

  7. 07

    War Room

    Pain
    Leads landed in a Google spreadsheet, and there was no single view of revenue, funnel and cash.
    Solution
    An executive dashboard that brings together MRR, ARR, total pipeline, average ticket and conversion, with shortcuts to the goal, funnel, cash, risk, positioning and family analyses, all computed from the CRM's own data.

    Impact: 6 executive panels

  8. 08

    Conversation flows

    Pain
    The conversation automation tool used before measured sends, not results: plenty of activity, but hardly any captured contact, email or phone number.
    Solution
    An in-house, channel-agnostic engine, live on WhatsApp and ready for Instagram (pending Meta's app review), with chained questions and a capture block that validates email and phone before saving. Every step goes to an append-only trail that measures capture block by block.

    Impact: 2 independent sending safeguards

  9. 09

    No-code automations

    Pain
    Operational rules, like a task for a stalled negotiation or a reminder for an upcoming installment, couldn't be set up without code.
    Solution
    A visual trigger, conditions and actions builder where the CEO sets up the rule. A Cloud Function runs the rules every hour with compare-and-set, retries with backoff and a 45–60 s pause between WhatsApp sends, and every new automation is monitored from the moment it is created.

    Impact: 14 triggers and 7 action types

  10. 10

    Meeting transcripts

    Pain
    The Google Meet transcript sat in a document attached to the event, outside the lead's history in the CRM.
    Solution
    A Cloud Function finds the document on the Calendar event, exports the text through the Drive API, optionally summarizes it with Gemini and stores it all on the deal, also on demand from the Meeting tab.

    Impact: Every 2 h, no duplicates

  11. 11

    Assessment form

    Pain
    Leads come from paid campaigns on mobile, some from outside Brazil, and the assessment is long. A form tied to Brazilian phone numbers and postal codes would shut those families out, and closing the tab halfway would lose the answers.
    Solution
    A 12-step mobile-first form in 2 stages, in Portuguese, English and Spanish, with international phone numbers, a country-aware address step and a draft saved on the device. Every submission stores UTMs, landing page, CTA and device alongside the lead.

    Impact: 12 steps in 3 languages

  12. 12

    Meta Ads spend and CAC

    Pain
    Marketing spend was entered by hand, per channel and per month, with no link to the campaigns that brought in each lead.
    Solution
    A daily sync with the Marketing API stores spend per campaign per day and matches the campaign ID with each lead's utm_id, computing CAC per lead, per qualified lead and per customer.

    Impact: CAC at 3 funnel stages