SKILL: Add PI Events to Cloudflare D1
Trigger
Use this skill when Alex says:
- "Add an event to the site"
- "Add this event to D1"
- "Update PI events"
- "Add [event name] on [date] to babenchuk.com"
- Sends a CSV or list of events to add
Context
- Database:
mb-events(Cloudflare D1) - Env vars: load from
~/.env/.env— use$CF_API_TOKEN,$CF_ACCOUNT_ID,$CF_ZONE_BABENCHUK_COM - Repo:
/Users/viki/Projects/projects/marketing-bull/babenchuk-com/ - Live site: https://babenchuk.com/#events
Schema
CREATE TABLE events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
address TEXT,
date_start TEXT, -- ISO format: "2026-06-06T08:00:00" or "2026-06-06"
date_end TEXT, -- ISO format or NULL
location TEXT, -- venue name/description
rsvp_contact TEXT, -- phone/email to RSVP
rsvp_to TEXT, -- person/org name to RSVP to
register_url TEXT, -- registration/info URL
tags TEXT, -- comma-separated: "PI,networking,Miller"
created_at TEXT DEFAULT (datetime('now'))
);
Steps
1. Load credentials
source ~/.env/.env
# Provides: $CF_API_TOKEN, $CF_ACCOUNT_ID
2. Build the INSERT SQL
Parse the event data Alex provides. Convert dates to ISO 8601:
- "March 14, 2026 6:00 PM (EDT)" →
2026-03-14T18:00:00 - "June 6, 2026" →
2026-06-06 - Date ranges: set
date_start+date_end
Escape single quotes in text fields by doubling them: O'Brien → O''Brien
INSERT INTO events (name, address, date_start, date_end, location, rsvp_contact, rsvp_to, register_url, tags)
VALUES ('Event Name', NULL, '2026-06-06T08:00:00', '2026-06-06T18:00:00', 'Venue, City FL', 'contact@example.com', 'Organizer Name', 'https://register-url.com', 'PI,conference');
3. Execute against D1 (remote)
source ~/.env/.env
cd /Users/viki/Projects/projects/marketing-bull/babenchuk-com
CLOUDFLARE_API_TOKEN="$CF_API_TOKEN" \
CLOUDFLARE_ACCOUNT_ID="$CF_ACCOUNT_ID" \
npx wrangler d1 execute mb-events --remote \
--command "INSERT INTO events (name, address, date_start, date_end, location, rsvp_contact, rsvp_to, register_url, tags) VALUES ('...', ...);"
For multiple events at once, use a SQL file:
CLOUDFLARE_API_TOKEN="$CF_API_TOKEN" \
CLOUDFLARE_ACCOUNT_ID="$CF_ACCOUNT_ID" \
npx wrangler d1 execute mb-events --remote --file=/tmp/new-events.sql
4. Verify insertion
CLOUDFLARE_API_TOKEN="$CF_API_TOKEN" \
CLOUDFLARE_ACCOUNT_ID="$CF_ACCOUNT_ID" \
npx wrangler d1 execute mb-events --remote \
--command "SELECT id, name, date_start FROM events ORDER BY date_start DESC LIMIT 5;"
Or hit the live API:
curl -s "https://babenchuk-com.pages.dev/api/events?all=true" | jq '[.events[] | {id, name, date: .date}]'
5. No redeploy needed
D1 is a live database. Events appear on the site immediately — no wrangler deploy required.
Useful Queries
List all upcoming events:
source ~/.env/.env
CLOUDFLARE_API_TOKEN="$CF_API_TOKEN" CLOUDFLARE_ACCOUNT_ID="$CF_ACCOUNT_ID" \
npx wrangler d1 execute mb-events --remote --command "SELECT id, name, date_start FROM events WHERE date_start >= date('now') ORDER BY date_start ASC;"
Delete an event by ID:
CLOUDFLARE_API_TOKEN="$CF_API_TOKEN" CLOUDFLARE_ACCOUNT_ID="$CF_ACCOUNT_ID" \
npx wrangler d1 execute mb-events --remote --command "DELETE FROM events WHERE id = 42;"
Update an event:
CLOUDFLARE_API_TOKEN="$CF_API_TOKEN" CLOUDFLARE_ACCOUNT_ID="$CF_ACCOUNT_ID" \
npx wrangler d1 execute mb-events --remote --command "UPDATE events SET register_url = 'https://new-url.com' WHERE id = 42;"
Bulk insert from CSV: Convert CSV to SQL INSERTs manually or ask Viki to parse and generate the SQL.
Tag Conventions
Use consistent comma-separated tags (no spaces after commas):
PI— general PI networkingMiller— Andrew Miller eventsPT Now— PT Now eventsconference— multi-day summitsattorney— attorney-focusedmedical— medical professional eventsbar association— FL bar eventsnetworking— general networkingMRI— MRI/imaging provider eventsCLE— continuing legal education
Notes
date_startanddate_endmust be ISO 8601 strings — the frontend parses them withnew Date()- NULL is fine for optional fields (address, location, rsvp_contact, rsvp_to, register_url)
- Tags field is plain text — frontend splits on commas
- No redeploy needed after DB changes — site fetches live from D1 on every page load