惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
爱范儿
爱范儿
V
Visual Studio Blog
Engineering at Meta
Engineering at Meta
B
Blog
云风的 BLOG
云风的 BLOG
G
Google Developers Blog
MongoDB | Blog
MongoDB | Blog
博客园 - Franky
U
Unit 42
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
WordPress大学
WordPress大学
D
DataBreaches.Net
B
Blog RSS Feed
小众软件
小众软件
人人都是产品经理
人人都是产品经理
I
InfoQ
P
Proofpoint News Feed
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
J
Java Code Geeks
The GitHub Blog
The GitHub Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I built a client's booking site in an afternoon (AI for t...
FavCRM · 2026-06-03 · via DEV Community

Syndicated from the FavCRM blog. The old quote was two weeks. With an agent on the UI and a headless backend, it's an afternoon.

A client needs a booking site. The old quote was two weeks: a calendar, a database, an availability engine, payments, a customer table.

With an AI agent building the frontend and FavCRM as the headless backend, the real work is an afternoon. Here is the whole job, start to finish.

The scenario

A small clinic. Three services, one practitioner, online booking with deposit. You are the agency; you have an AI agent in your editor and a terminal.

The plan:

  1. Register the clinic's FavCRM workspace
  2. Configure services and availability
  3. Wire one server route that talks to FavCRM
  4. Let the agent build the booking UI against that route
  5. Test a real booking end to end

Step 1 — Register the workspace (~5 min)

The favcrm CLI registers a workspace and issues an API key. No dashboard.

favcrm signup request --email clinic@example.com \
  --organisation-name "Bright Smile Clinic"
favcrm signup verify --request-id <id> --code <6-digit-code>

Enter fullscreen mode Exit fullscreen mode

The verify step prints a fav_mcp_* key. Put it where your build can read it — never in the repo:

export FAVCRM_API_KEY=fav_mcp_...

Enter fullscreen mode Exit fullscreen mode

Step 2 — Configure services and availability (~30 min)

Hand the brief to your agent and let it call the tools. Inspect a schema first:

favcrm tool describe create_service

Enter fullscreen mode Exit fullscreen mode

Then create each service:

favcrm tool call create_service '{
  "name": "New Patient Exam",
  "durationMinutes": 45,
  "price": "80.00"
}'
favcrm tool call create_service '{
  "name": "Cleaning",
  "durationMinutes": 30,
  "price": "60.00"
}'

Enter fullscreen mode Exit fullscreen mode

Set when the practitioner works, so availability is real:

favcrm tool call set_staff_availability '{
  "weekday": "mon",
  "start": "09:00",
  "end": "17:00"
}'

Enter fullscreen mode Exit fullscreen mode

Repeat per weekday. At this point the backend is done — services, hours, an availability engine that knows about clashes. You wrote no schema.

Step 3 — One server route (~30 min)

The browser must never hold the API key. Put it in one server route that proxies two operations: read slots, create a booking. FavCRM's MCP endpoint speaks JSON-RPC over HTTP, so a route handler can call it directly.

// app/api/booking/route.js  (Next.js route handler)
const MCP = 'https://api.favcrm.io/mcp';

async function callTool(name, args) {
  const res = await fetch(MCP, {
    method: 'POST',
    headers: {
      'content-type': 'application/json',
      authorization: `Bearer ${process.env.FAVCRM_API_KEY}`,
    },
    body: JSON.stringify({
      jsonrpc: '2.0',
      id: 1,
      method: 'tools/call',
      params: { name, arguments: args },
    }),
  });
  if (!res.ok) throw new Error(`FavCRM ${res.status}`);
  return res.json();
}

export async function GET(req) {
  const { searchParams } = new URL(req.url);
  const slots = await callTool('get_available_slots', {
    serviceId: searchParams.get('serviceId'),
    date: searchParams.get('date'),
  });
  return Response.json(slots);
}

export async function POST(req) {
  const body = await req.json();
  const booking = await callTool('create_booking', {
    serviceId: body.serviceId,
    start: body.start,
    customer: { name: body.name, email: body.email },
  });
  return Response.json(booking);
}

Enter fullscreen mode Exit fullscreen mode

That is the entire backend you write — a proxy. create_booking clash-checks, persists the row, and upserts the customer. Your route does no business logic.

Step 4 — The booking UI (~1–2 hrs)

This is where the agent earns its keep. Prompt it:

Build a booking page. Fetch services, let the visitor pick one and a date,
GET /api/booking for open slots, POST /api/booking to confirm.
Show a success state with the booking time.

Enter fullscreen mode Exit fullscreen mode

The agent produces the React. It is calling your route, your route is calling FavCRM. The UI is yours to style for the clinic's brand — the parts that are tedious and error-prone (availability, persistence, clashes) are not your code.

Step 5 — Test a real booking

Run the flow in the browser, then confirm it landed:

favcrm tool call list_bookings '{}'

Enter fullscreen mode Exit fullscreen mode

The booking is there. So is the patient — create_booking upserted a crm_accounts record with their details and history. When they book again, it attaches to the same record.

To take the deposit, add one more proxied call:

favcrm tool describe create_invoice

Enter fullscreen mode Exit fullscreen mode

What shipped, and what you skipped

The clinic has a branded booking site, real bookings, a patient list that fills itself, and Stripe deposits.

You skipped: the database, the migrations, the availability algorithm, the double-booking bug you would have shipped and fixed in week two, the customer table, the Stripe webhook reconciliation.

You wrote: a service config, one proxy route, and a UI.

That is what a headless CRM is for. The free tier covers a build like this end to end — point your agent at it and run the afternoon yourself.

New to the category? Start with what an agentic CRM is.