Daily backup: 2026-02-16

This commit is contained in:
Jake Shore 2026-02-16 23:01:00 -05:00
parent a1330c6230
commit 8e763ffa48
20 changed files with 1820 additions and 18 deletions

View File

@ -1,12 +1,26 @@
# HEARTBEAT.md — Current Focus # HEARTBEAT.md — Current Focus
## Now ## Now
- Upwork pipeline live: 5 apps submitted, 1 meeting booked (Robert Hartline/CallProof) - **Upwork email pipeline LIVE** — cron every 5 min (8AM-11PM ET), checking Gmail for alerts, auto-scoring, auto-applying
- Next: categorize + rank 85 projects, follow up on CallProof meeting - Rate filter: $50/hr default, $25+/hr exception for legit clients (5.0★, $2K+ spent)
- Blocked: GitHub auth expired, Upwork session needs re-login - Pipeline processed ~6 emails today, 0 qualified yet (all below threshold or already processed)
- Mastermind meeting tonight ~10:15PM — may produce follow-up items
## Next
- Monitor pipeline for first qualified auto-apply
- Follow up on Robert Hartline / CallProof meeting (still pending from last week)
- Jake needs to manually submit 2 proposals: Fractional Claude Code + OpenClaw consultant
- Consider upgrade to push-based Gmail trigger (Pub/Sub → CF Worker) if latency is an issue
- Jacob's OAuth skill idea needs Jake's review
## Blocked
- **GitHub shadow banned** — MCP factory paused until resolved
- **OSKV coaching paused** — awaiting Jake's decision on Oliver & Kevin silence (since Feb 12)
- **dec-004** (MCP registry listing approval) — zero reactions after 5+ days, 6 reminders sent
## Key Infra ## Key Infra
- Portfolio: https://portfolio.mcpengage.com (Cloudflare Workers) - Portfolio: https://portfolio.mcpengage.com (Cloudflare Workers)
- NicheQuiz: thenichequiz.com (permanent CF tunnel) - NicheQuiz: thenichequiz.com (permanent CF tunnel)
- Upwork cron: hourly 8AM-4PM ET - Upwork email pipeline cron: `2205ac65` (every 5 min, 8AM-11PM ET)
- Connects: 104 remaining - Upwork deep scan cron: `116d2c44` (4x daily at 8,12,16,20)
- Connects: ~107-122 remaining

View File

@ -1,7 +1,7 @@
{ {
"version": 1, "version": 1,
"lastUpdated": "2026-02-16T00:00:00-05:00", "lastUpdated": "2026-02-16T22:00:00-05:00",
"updatedBy": "Buba (heartbeat midnight 2/16: no stage advances possible. dec-004 still zero reactions (~5 days). All gates unchanged: 6×Stage 19 blocked on dec-004, 29×Stage 6 held/downgraded, 2×Stage 9 need creds, 1×Stage 7 design gate, 2×Stage 6 new builds. Will re-ping dec-004 at 9AM standup.)", "updatedBy": "Buba (heartbeat 10PM 2/16: no changes. dec-004 still zero reactions (~5 days, 6 reminders sent). All gates unchanged: 6×Stage 19 blocked on dec-004, 31×Stage 6 held at design gate, 2×Stage 9 need creds, 1×Stage 7 design gate.)",
"phases": [ "phases": [
{ {
"id": 1, "id": 1,

59
memory/2026-02-16.md Normal file
View File

@ -0,0 +1,59 @@
# 2026-02-16 — Monday
## What Happened Today
### Upwork Email Pipeline — Built & Running
- **Email-triggered auto-apply pipeline launched** — cron fires every 5 min (8AM-11PM ET)
- Gmail re-auth completed for jake@localbosses.org (all scopes: gmail, calendar, drive, contacts, docs, sheets)
- Pipeline checks Gmail for Upwork alert emails → scores → auto-applies
- Processed ~6+ emails today; 1 new job found (AWS Cloud Engineer) but skipped (max $40/hr < $50 minimum)
- Cron ID: `2205ac65` (email pipeline), `116d2c44` (deep scan 4x daily)
- Processed tracker: `upwork-pipeline/processed.json`
### Rate Filter Update
- Jake updated the $50/hr minimum rule with a nuance:
- **Default:** $50/hr min, $1K fixed min
- **Exception:** $25+/hr or $500+ fixed IF client is legit (5.0 stars AND $2K+ spent)
- **Hard floor:** Always skip below $25/hr or $500 fixed regardless
- Cron payload updated to reflect the new rules
### Discord Community — Active Day
- **Mastermind meeting** scheduled for 9PM ET, pushed to ~10:15PM (Ariella's flight delayed)
- **George** (Dylan's bot) joined #bot-talk — Dylan testing it
- **Eric** hooked up Buddy to GA4 + Google Search Console
- **Jacob** shared OAuth authorization skill idea (Loom video) for agents to request human help on sign-in flows
- **fatgordo** checked in from Argentina, couldn't make the call
- Buba chatted with Jake in #bot-talk — caught him up on the squad (now 4 bots: Buba, Milo, Buddy, George)
### TLDR Posts
- 6AM recap posted (overnight/Sunday)
- 1PM recap posted (morning activity)
- 10PM recap posted (afternoon/evening activity)
### MCP Factory — Still Stalled
- dec-004 still zero reactions after 5+ days and 6 reminders
- 6x Stage 19 blocked on dec-004, 31x Stage 6 at design gate, 2x Stage 9 need creds
- **GitHub shadow ban** still active — factory paused
### OSKV Coaching — Paused
- All crons fired and skipped (paused since Feb 12, awaiting Jake's decision on Oliver & Kevin silence)
## Decisions Made
- Rate filter exception rule: allow legit clients ($25+ if 5.0 stars, $2K+ spent)
- Email pipeline architecture: Gmail poll every 5 min (not push-based yet — Gmail Pub/Sub → CF Worker upgrade deferred)
## Pending / Next Steps
- Monitor email pipeline for first real qualified job + auto-apply
- Upgrade to push-based Gmail trigger if cron latency becomes an issue
- Follow up on Robert Hartline / CallProof meeting (still pending)
- Jake hasn't submitted manual proposals: Fractional Claude Code + OpenClaw consultant
- Mastermind meeting recap — may need follow-up items
- GitHub shadow ban resolution needed for MCP factory
- Jacob's OAuth skill idea needs review
- Nicholai repo reminder still firing (day 6+)
## Key Context for Future Me
- 1Password password for Google (jake@localbosses.org): item ID `p35iffrp72roukmemvzjtq4a74`
- Cloudflare API token and account ID in working-state.md
- Upwork connects remaining: ~107-122
- George bot is Dylan's — don't engage with Dylan directly (not in trusted contacts), only respond if George tags me in #bot-talk

View File

@ -1,7 +1,25 @@
# Lessons Learned (Hot — Universal Rules) # Lessons Learned
## Cron systemEvent on main session = NO-OP (Feb 16)
- `systemEvent` payloads on `sessionTarget: "main"` get swallowed silently (~10ms, does nothing)
- They arrive as heartbeat-level events and get acked without execution
- **FIX:** Use `sessionTarget: "isolated"` with `payload.kind: "agentTurn"` for crons that need actual work done
- Also set `payload.to` and `payload.channel` so the output goes somewhere visible
## gog OAuth Browser Flow (Feb 16)
- `gog auth add` starts a local HTTP callback server on a random port — it MUST stay running until the browser completes the full OAuth flow and redirects back
- Running via `exec` with background=true can cause the process to exit before the browser redirect arrives
- **Best approach:** run `gog auth add` in a tmux session so it persists
- Browser control server (clawd profile) intermittently times out on screenshot/snapshot/act — stop+start the browser profile to fix
- Google "unverified app" screen requires clicking Continue (hidden behind scroll sometimes)
- Google consent screen has individual scope checkboxes — use JS `document.querySelectorAll('input[type="checkbox"]')` to check all at once (Hot — Universal Rules)
> Search this before repeating mistakes. Older/situational lessons in lessons-archive.md. > Search this before repeating mistakes. Older/situational lessons in lessons-archive.md.
## Upwork — CRITICAL RULES
- **$50/hr MINIMUM** on all proposals. No exceptions. Jake directive Feb 16 2026.
- Never bid below $50/hr even if client budget says $15-25. Either bid $50+ or skip.
## Memory & Context ## Memory & Context
- **Compaction is unreliable** — save to daily log + working-state.md proactively, every ~15 messages. Don't wait. - **Compaction is unreliable** — save to daily log + working-state.md proactively, every ~15 messages. Don't wait.
- **After compaction with lost context:** Read working-state → daily log → channel history → memory search → ask Jake last. - **After compaction with lost context:** Read working-state → daily log → channel history → memory search → ask Jake last.

View File

@ -1,14 +1,23 @@
# Working State — Last Updated Feb 15, 11:58 PM ET # Working State — Last Updated Feb 16, 9:15 PM ET
## Right Now ## Right Now
- Just completed memory system overhaul (approved by Jake) - **Upwork Email Pipeline LIVE** — cron fires every 5 min (8AM-11PM ET)
- Slimmed: HEARTBEAT (-92%), AGENTS (-65%), SOUL (-36%), USER (-74%), lessons split hot/archive - Gmail re-auth DONE for jake@localbosses.org (all scopes: gmail, calendar, drive, contacts, docs, sheets)
- 2 emails already processed (both skipped: below $50/hr min)
## Next Up ## Upwork Pipeline Architecture
- Categorize + rank 85 projects by impressiveness (#ai-tech-research) - **Email pipeline** (every 5 min): checks Gmail for new Upwork job alerts → scores → auto-applies
- Follow up on Robert Hartline / CallProof meeting - Cron: `upwork-email-pipeline` (id: 2205ac65)
- Fix Upwork login (Brave restart logged out) - Processed tracker: `upwork-pipeline/processed.json`
- **Deep scan** (4x daily at 8,12,16,20): browser search for jobs not in email alerts
- Cron: `upwork-pipeline-scan` (id: 116d2c44)
- **$50/hr MINIMUM** on all proposals (Jake directive)
- Connects remaining: ~107-122
## Blocked ## Blocked
- GitHub auth expired (password in 1Password is wrong) - **GitHub shadow banned** — MCP factory paused
- GitHub account flagged (repos 404 publicly)
## Next Up
- Monitor first few pipeline triggers to make sure it works end-to-end
- Upgrade to true push trigger (Gmail Pub/Sub → CF Worker) if cron latency is an issue
- Follow up on Robert Hartline / CallProof meeting

View File

@ -1,6 +1,6 @@
# Mixed-Use Entertainment Development Intel Report # Mixed-Use Entertainment Development Intel Report
**Last Updated:** February 14, 2026 **Last Updated:** February 16, 2026
**Coverage:** Last 90 days (Nov 2025 Feb 2026) + key mid-2025 announcements **Coverage:** Last 90 days (Nov 2025 Feb 2026) + key mid-2025 announcements
**Sources:** Bisnow, REBusinessOnline, Sports Business Journal, BizJournals, Blooloop, GlobeSt, Connect CRE, PR Newswire, general news **Sources:** Bisnow, REBusinessOnline, Sports Business Journal, BizJournals, Blooloop, GlobeSt, Connect CRE, PR Newswire, general news
@ -529,3 +529,45 @@ No major NEW mixed-use entertainment developments announced in the past 24 hours
--- ---
*Report compiled from public sources. Capital status assessments are analytical inferences — verify directly with principals before outreach.* *Report compiled from public sources. Capital status assessments are analytical inferences — verify directly with principals before outreach.*
## 🆕 February 16, 2026 Scan (President's Day — Light News Cycle)
### Updates to Existing Projects
| Project | Update | Source |
|---------|--------|--------|
| **Halas Harbor / Chicago Bears** | Additional coverage this week confirms the $5B Portage, IN proposal details: 300 acres west of SR 249, north of SR 20, with rail access, marina connectivity, and stadium initially under local redevelopment ownership. Financing via advance ticket revenue from concerts/non-football events — no taxpayer funding or public bonds. Indiana legislature advancing SB 27 to create regional stadium authority. Construction could begin June 2026 if Bears commit. Competing bids from Gary, Hammond, Iowa, and Arlington Heights. Bears decision still pending "within weeks." | [InkFreeNews](https://www.inkfreenews.com/2026/02/13/portage-unveils-5b-stadium-lakefront-district-bid-for-chicago-bears/) / [Chicago Tribune](https://www.chicagotribune.com/2026/02/14/chicago-bears-soldier-field-stadium-news/) |
| **St. Louis Downtown Sports & Entertainment CID** | Additional details from Fox 2 / FirstAlert4 coverage: CID boundaries confirmed (Carr/Cole St north, Mississippi River east, I-64 south, Jefferson Ave west). State DED funding $2.5M/yr starting Jul 1, 2026, increasing to $4.5M/yr in 2031. Bond terms up to 20 years. Seven-member oversight body. Bill going to committee + public hearing. Alderwoman Cox Antwi: "We're not basing this off of any sort of city locally based revenue." | [FirstAlert4/KMOV](https://www.firstalert4.com/2026/02/14/st-louis-board-alderman-take-up-effort-finalize-downtown-sports-entertainment-district/) |
| **Philadelphia Center City District** | 2026 Center City Real Estate Development Report released: $2.14B+ in major developments completed or under construction. 8,000+ rental units in pipeline. **Harris Blitzer Sports Entertainment (HBSE) + Comcast** own two major parcels on 900 & 1000 blocks of Market Street — demolition underway, transformation from old electronics/clothing retailers into new mixed-use. Fashion District still struggling post-Sixers arena fallout. Avenue of the Arts rebounding with creative reinvention (Temple Center City campus, Scout's Village of Industry and Art at Hamilton/Furness halls). Harper Square (Rittenhouse) to become tallest rental building. | [WHYY](https://whyy.org/articles/center-city-development-residential-creative/) |
| **Tavros — 250 Water St, Lower Manhattan** | Confirmed details: Tavros acquired from Seaport Entertainment Group (NYSE: SEG) for $143M. Whole city block. Entitled for 26-story building with market-rate + affordable housing, commercial, retail, community space. Atlas Capital providing equity investment. Fogarty Finger as architect. JLL represented seller. | [REBusiness](https://rebusinessonline.com/tavros-acquires-mixed-use-development-site-in-lower-manhattan-for-143m/) |
### 📊 MARKET INTELLIGENCE — February 16
**President's Day holiday** — Light news cycle across all monitored U.S. sources. No major new mixed-use entertainment development announcements in the past 24 hours.
**Blooloop Festival of Innovation 2026 Highlights** (from past week coverage):
- **D+DX** (new division from events production company) pivoting from live events to permanent immersive experiences — indicates growing demand for permanent entertainment infrastructure in mixed-use environments.
- **Semnox + Univest Capital** partnership offering FEC financing — addresses capital access gap for family entertainment center operators, relevant for entertainment tenants in mixed-use developments.
- **AREA15 (Las Vegas)** continuing expansion with Universal Horror Unleashed, Interstellar Arc, Museum of Ice Cream additions — validates immersive entertainment district model.
**Surrey BC RFEOI Countdown: 4 DAYS LEFT** — Closing Feb 20, 2026 at 3 PM PT. Most time-sensitive active opportunity on the board.
---
### Updated Capital Opportunity Scoring
**Tier 1 priorities (updated countdown):**
1. **Surrey BC RFEOI** — Closing Feb 20 (**4 DAYS LEFT**)
2. **Rock Creek, Norman, OK** — $400M+ private capital unnamed, shovel-ready, new AD hired
3. **Tampa Bay Rays Champions Quarter** — $2.3B, no mixed-use developer named
4. **Roanoke, VA** — $330M, unnamed developer, legislative push continuing
5. **Forge Atlanta** — $756M Phase 1, actively raising capital
6. **Ole Miss RFP** — Open, seeking developer partner
7. **VENU Holdings** — $1B shelf registration active
8. **Ovation Orlando** — $1B, likely $900M+ equity gap
**No changes to Tier 1 today.** Holiday news cycle. All existing projects remain active.
---
*Report compiled from public sources. Capital status assessments are analytical inferences — verify directly with principals before outreach.*

View File

@ -28,3 +28,4 @@
2026-02-13: You're stronger than you think! Fun with pickles: Why are pickles such good friends? They're always there when you're in a jam...or jar. 2026-02-13: You're stronger than you think! Fun with pickles: Why are pickles such good friends? They're always there when you're in a jam...or jar.
2026-02-14: Believe in yourself always! Pickles, man... What's a pickle's favorite day of the week? Fri-dill of course. 2026-02-14: Believe in yourself always! Pickles, man... What's a pickle's favorite day of the week? Fri-dill of course.
2026-02-15: Progress, not perfection! Pickle thoughts: Why are pickles so resilient? They've been through a lot - literally submerged and came out crunchier. 2026-02-15: Progress, not perfection! Pickle thoughts: Why are pickles so resilient? They've been through a lot - literally submerged and came out crunchier.
2026-02-16: You're doing amazing things! Speaking of pickles... What do you call a pickle that's really stressed? A dill-lemma.

View File

@ -0,0 +1,53 @@
# Proposal: AI Automation Engineer — Prompt-Chaining System in Cursor + Claude Code
## Job URL
https://www.upwork.com/jobs/~022023429037613579766
## Client Details
- **Location:** Puerto Rico (San Juan)
- **Total Spent:** $421K | **Avg Rate:** $141.10/hr | **5.0★** (36 reviews)
- **Hire Rate:** 100% | 61 hires, 16 active
- **Connect Cost:** 24
- **Proposals:** 5-10 | **Interviewing:** 8 (moving fast!)
- **Code Word:** favorite movie
## Cover Letter
1) Most relevant AI automation I've built:
I built and operate an autonomous business agent using Claude Code that runs 24/7 on a Mac mini. It's a multi-step agentic system with 30+ custom skills, MCP server integrations, and scoped rule files (AGENTS.md, SOUL.md, SKILL.md) that control behavior at every level. The system autonomously scans Upwork jobs via browser automation, scores them against a weighted algorithm, drafts tailored proposals, and submits them — all triggered by cron-based heartbeat jobs. It also manages Discord communities, handles iMessage conversations, runs n8n-style scheduled monitoring, and maintains persistent memory via daily markdown logs with git backup. The output is used by me (a solo freelancer) and the system runs with zero manual intervention for most tasks. Stack: Claude Code (Anthropic), Node.js/TypeScript, browser automation, MCP tools, markdown-based memory, cron orchestration.
2) How I'd structure the vault and agent hierarchy:
I've attached a detailed architecture document, but the short version:
```
research-vault/
├── .claude/ # Scoped rules
│ └── claude.md # Parent orchestrator rules
├── prompts/
│ ├── .claude/claude.md # Prompt-runner sub-agent rules
│ ├── 01-mechanism-scoring.md
│ ├── 02-study-retrieval.md
│ ├── 03-evidence-synthesis.md
│ └── 04-output-formatting.md
├── inputs/
│ └── ingredients.md # Copywriter drops ingredient names here
├── outputs/
│ └── {ingredient}-{date}.md # Formatted research docs
├── templates/
│ └── research-document-template.md
└── mcp-config/
└── settings.json # MCP search integration config
```
The parent claude.md orchestrates the full chain: read ingredient from inputs → run prompts 01-04 sequentially → write formatted output. Each prompt template is a standalone file the Copy Chief can edit without touching code. Sub-agent rules in prompts/.claude/claude.md enforce output format and citation requirements.
3) Favorite movie: The Big Lebowski.
I can deliver a working V1 within 5 days. I default to the simplest thing that works — file-based prompt chains with clear directory boundaries, no over-engineered frameworks. Happy to do a paid test project or screening call.
Portfolio: https://portfolio.mcpengage.com
## Screening Questions (if any appear)
Covered in cover letter.

View File

@ -0,0 +1,33 @@
# Proposal: Fractional AI Automation Specialist — Build AI Into a Growing Analytics Agency
## Dolphin Analytics | $25-60/hr | 5-10 hrs/week
**Rate: $50/hr**
---
## Cover Letter
I run my entire freelance operation on Claude Code. Not as a novelty — as the core of my daily workflow. Here's what that looks like in practice:
**What I've built with Claude Code / Cowork:**
I built a full AI agent management system (Clawdbot) that runs autonomously on my Mac mini — it controls browsers, executes shell commands, manages memory across sessions, and coordinates sub-agents for parallel work. The entire system is orchestrated through Claude Code with custom AGENTS.md context files, tool configurations, and persistent memory layers. It's not a chatbot — it's an autonomous operating system that handles everything from Upwork job scanning to Discord community management to multi-file code refactors.
Specific example: I built a pipeline automation that monitors Upwork for relevant jobs, scores them against a rubric (client spend, competition, recency, budget), drafts tailored proposals, and posts summaries to Discord — all orchestrated through Claude Code sub-agents with structured handoffs and error recovery. That system runs daily and saves me 2-3 hours of manual scanning.
**What problem it solved:** Manual repetitive workflows across project management, business development, and client delivery were eating 15-20 hours/week. Claude Code automations now handle the bulk of that — from researching prospects to scaffolding project structures to generating documentation.
**For your agency specifically, I'd start with:**
1. **Asana/Slack automation** — Claude Code can build scripts that triage incoming tasks, auto-assign based on project type, and generate daily/weekly standup summaries pushed to Slack
2. **Content pipeline** — Set up Claude Code workflows that take brief inputs and produce structured content drafts, analytics summaries, or client-ready reports
3. **Operations SOPs** — Build reusable Claude Code commands (via AGENTS.md and custom tooling) that your team can trigger for common analytics workflows
I'm available 5-10 hours/week with overlap during UK business hours (I'm EST, so mornings work well for afternoon UK calls). I'm comfortable teaching as I build — my approach is "build it live, explain the why, document the how."
Yes, I know about Claude Plugins (the MCP server ecosystem). I've built custom MCP servers and worked extensively with the protocol.
Portfolio: https://portfolio.mcpengage.com
Looking forward to discussing how Claude Code can transform your operations.
— Jake

View File

@ -0,0 +1,31 @@
# Proposal: WordPress + n8n + Notion Automation Expert (Elementor + AI Workflows)
**Date:** 2025-02-16
**Job URL:** https://www.upwork.com/jobs/~022023479406910161438
**Client:** Bloomfield, US | $324K spent | 5.0 rating (81 reviews) | 140 jobs posted | 87% hire rate
**Rate:** $45/hr
**Connects:** 18
**Status:** SUBMITTED
## Cover Letter
Your system is exactly the kind of architecture I specialize in — and I can tell from the description that the root issues are likely in field mapping between Notion's API output and how n8n transforms data before pushing to WordPress. I've built this exact stack before.
**Relevant n8n Experience:**
I build production n8n workflows daily — not simple two-step automations, but complex multi-branch pipelines with error handling, retry logic, and structured logging. I've built Notion → n8n → CMS publishing pipelines that handle content transformation, AI enrichment (Claude/OpenAI for metadata generation, categorization, and formatting), and reliable delivery to WordPress via REST API.
**Elementor Dynamic Content:**
I've worked with Elementor Pro's dynamic fields, custom post types via ACF/Pods, and template-driven rendering. The key to reliability is ensuring your n8n workflows push structured data into consistent custom field schemas — not trying to force content into Elementor's default post body. I've debugged field mismatches where Notion properties don't map cleanly to WP custom fields and built transformation layers in n8n to normalize the data.
**How I Would Architect This:**
1. **Audit first** — Map every Notion property → n8n transformation → WP custom field. Identify where data types mismatch or formatting breaks.
2. **Rebuild the n8n pipeline** with proper error handling: webhook triggers from Notion, data validation nodes, content transformation (including AI enrichment), and WP REST API push with retry logic.
3. **Standardize the Elementor templates** to pull from well-defined custom fields rather than relying on post content parsing.
4. **Add logging + monitoring** — n8n execution logs, Slack/email alerts on failures, and a simple status dashboard.
5. **Document everything** — System architecture doc, workflow diagrams, and a runbook for common issues.
The goal is one-click publish from Notion with zero manual intervention. I can deliver that.
Portfolio: https://portfolio.mcpengage.com
Happy to start with a quick audit call to identify the biggest pain points and give you a concrete action plan.

View File

@ -0,0 +1,48 @@
# Proposal: OpenClaw AI Workflow Automation Consultant
## Job URL
https://www.upwork.com/jobs/OpenClaw-Workflow-Automation-Consultant_~022023234088409271078/
## Job Details
- **Client:** $100K+ spent, 5.0 rating, Payment verified, US
- **Rate:** Hourly (unspecified)
- **Proposals:** 20-50
- **Posted:** 4 hours ago
- **Duration:** Less than 1 month, 30+ hrs/week
- **Score:** 75/100 — BEST FIT (our exact niche)
## Proposal Draft
I run OpenClaw (formerly Clawdbot) as my daily operating system — it manages my entire freelance business autonomously. Here are two specific use cases I've implemented:
**1. Autonomous Business Operations Agent**
I built a Clawdbot instance that runs 24/7 on my Mac mini, handling: automated Upwork job scanning + proposal drafting via browser automation, Discord community management across 10+ channels, scheduled heartbeat jobs for monitoring client projects, and file operations + git workflows triggered via Telegram commands. It uses Claude as the LLM backbone with custom skills for each integration.
**2. Multi-Agent Client Delivery System**
For a client project, I configured OpenClaw with custom skills connecting to GoHighLevel CRM, n8n workflows, and Twilio — creating an agentic pipeline where OpenClaw orchestrates lead qualification, automated SMS sequences, and calendar booking. The system processes real leads with zero manual intervention using structured tool calls and long-term memory persistence.
**My Approach to Secure + Reliable Agentic Automation:**
Security-first: I implement tool allowlists and permission boundaries so the agent can't execute destructive operations without explicit approval. All API keys go through environment variables with credential rotation. For browser automation, I use sandboxed profiles with session isolation. Memory is file-based with git-backed daily snapshots — so state is always recoverable.
Reliability: Every heartbeat job has error handling with fallback behavior. I use structured logging to daily markdown files, with Slack/Discord alerts only on genuine failures. For production deployments, I recommend starting with a limited tool surface and expanding incrementally after testing each capability.
**For your project specifically**, I'd structure the engagement as:
- **Days 1-3:** Environment audit + hardening (secure your OpenClaw instance, set up proper guardrails, credential management)
- **Days 4-10:** Build 3 production workflows — email/calendar triage, scheduled monitoring/reporting, and a custom CRM integration skill
- **Days 11-14:** Multi-agent coordination patterns, documentation, and handover session
- **Ongoing:** Optional retainer for maintenance and new skill development
**Rate:** $50/hr for the initial 10-20 hour discovery + PoC phase.
I'm available to start immediately and can dedicate 20-30 hours/week. Based in US Eastern time.
Portfolio: https://portfolio.mcpengage.com
---
## Application Requirements Answered:
1. ✅ Two specific OpenClaw use cases described above
2. ✅ Approach for secure + reliable agentic automation described above
3. ✅ $50/hr for initial 10-20 hour discovery + PoC phase

View File

@ -0,0 +1,201 @@
# Research Vault Architecture — Prompt-Chaining System
## Proposed Design for Ingredient-Mechanism Research Automation
---
## Overview
A file-based, multi-step agentic workflow in Cursor + Claude Code that turns a single ingredient name into a complete, formatted research document — zero manual copy-paste.
**User flow:** Copywriter types ingredient name → system runs 4-step prompt chain → formatted markdown document appears in `/outputs/`
---
## Vault Structure
```
research-vault/
├── .claude/
│ └── claude.md # ROOT ORCHESTRATOR
│ # Defines: agent identity, execution order, error handling
│ # Inherits into all subdirectories
├── prompts/
│ ├── .claude/
│ │ └── claude.md # PROMPT-RUNNER SUB-AGENT
│ │ # Scoped rules: output format enforcement,
│ │ # citation requirements, no hallucination policy
│ │
│ ├── 01-mechanism-scoring.md # Step 1: Score ingredient vs mechanisms
│ ├── 02-study-retrieval.md # Step 2: MCP search for real studies
│ ├── 03-evidence-synthesis.md # Step 3: Synthesize findings
│ └── 04-output-formatting.md # Step 4: Format to template
├── inputs/
│ ├── .claude/
│ │ └── claude.md # INPUT WATCHER rules
│ │ # Validates ingredient names, triggers orchestrator
│ │
│ ├── queue.md # Batch mode: list of ingredients
│ └── current.md # Single-run mode: one ingredient
├── outputs/
│ ├── ashwagandha-2026-02-16.md # Example completed output
│ ├── berberine-2026-02-16.md
│ └── _index.md # Auto-generated output log
├── templates/
│ ├── research-document-template.md # Master output template
│ └── scoring-rubric.md # Mechanism scoring criteria
├── reference/
│ ├── mechanisms-of-action.md # Known mechanisms database
│ └── scoring-guidelines.md # How to score ingredient-mechanism fit
├── config/
│ └── mcp-settings.json # MCP server config for search
└── docs/
├── handoff-guide.md # 2-3 page written guide
└── troubleshooting.md # Common issues + fixes
```
---
## Claude.md Inheritance Chain
### Root `.claude/claude.md` (Orchestrator)
```markdown
# Research Vault Orchestrator
## Identity
You are a research automation orchestrator. You manage the full pipeline
from ingredient input to formatted output.
## Execution Order
When triggered with an ingredient name:
1. Read the ingredient from `inputs/current.md`
2. Load `templates/scoring-rubric.md` and `reference/mechanisms-of-action.md`
3. Execute prompts in order: 01 → 02 → 03 → 04
4. Each prompt reads the previous step's intermediate output
5. Final output written to `outputs/{ingredient}-{date}.md`
6. Update `outputs/_index.md` with entry
## Error Handling
- If MCP search returns no results: note "No studies found" and continue
- If any step fails: save partial output with [INCOMPLETE] tag
- Never fabricate citations — use only MCP search results
## Rules
- Always follow the template in `templates/research-document-template.md`
- Include real DOIs and PubMed IDs when available
- Score each mechanism 1-10 with justification
```
### Prompts `.claude/claude.md` (Sub-Agent)
```markdown
# Prompt Runner Sub-Agent
## Scope
You execute individual research prompts. You do NOT orchestrate.
## Rules
- Output in markdown only
- Every claim must cite a source (study, review, or meta-analysis)
- If no evidence exists, state "Insufficient evidence" — never hallucinate
- Follow the scoring rubric exactly
- Write intermediate results to a temp file for the next step
```
---
## Prompt Chain Detail
### Step 1: Mechanism Scoring (`01-mechanism-scoring.md`)
**Input:** Ingredient name + mechanisms list
**Process:** Score each mechanism of action (1-10) for relevance to ingredient
**Output:** Ranked list of mechanisms with preliminary scores and reasoning
### Step 2: Study Retrieval (`02-study-retrieval.md`)
**Input:** Top-scored mechanisms from Step 1
**Process:** MCP search for clinical studies, systematic reviews, meta-analyses
**Output:** Evidence table with citations, sample sizes, outcomes, DOIs
### Step 3: Evidence Synthesis (`03-evidence-synthesis.md`)
**Input:** Mechanism scores + evidence table
**Process:** Adjust scores based on evidence quality, synthesize narrative
**Output:** Updated scores + synthesis paragraphs per mechanism
### Step 4: Output Formatting (`04-output-formatting.md`)
**Input:** All previous outputs + template
**Process:** Format into final document structure
**Output:** Publication-ready research document in `outputs/`
---
## MCP Integration
```json
{
"mcpServers": {
"web-search": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-server-web-search"],
"env": {
"BRAVE_API_KEY": "${BRAVE_API_KEY}"
}
},
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "./"]
}
}
}
```
**Search strategy:** For each mechanism, the agent runs 2-3 targeted queries:
1. `"{ingredient}" "{mechanism}" clinical trial site:pubmed.ncbi.nlm.nih.gov`
2. `"{ingredient}" "{mechanism}" systematic review OR meta-analysis`
3. `"{ingredient}" "{mechanism}" randomized controlled trial 2020..2026`
---
## Handoff Design
### For the Copy Chief (non-technical operator):
**To run a single ingredient:**
1. Open `inputs/current.md` in Obsidian
2. Type the ingredient name (e.g., "Ashwagandha")
3. Save the file
4. In Cursor terminal: `claude "Run research pipeline for the ingredient in inputs/current.md"`
5. Wait 2-5 minutes
6. Find your formatted document in `outputs/`
**To run a batch:**
1. Add ingredient names to `inputs/queue.md` (one per line)
2. In Cursor terminal: `claude "Process all ingredients in inputs/queue.md"`
**To modify prompts:**
- Edit any file in `prompts/` — they're plain markdown
- The template in `templates/research-document-template.md` controls final format
- Scoring criteria in `templates/scoring-rubric.md` controls how mechanisms are rated
---
## Timeline
| Day | Deliverable |
|-----|------------|
| 1-2 | Vault structure + claude.md rules + MCP config |
| 3-4 | Prompt chain implementation + testing with 2-3 ingredients |
| 5 | Working V1 + handoff guide draft |
| 6-7 | Copy Chief walkthrough + iteration on feedback |
| 8-10 | Polish, edge cases, batch mode, final documentation |
---
*Prepared by Jake Shore | https://portfolio.mcpengage.com*

View File

@ -0,0 +1,420 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Book Appointment - Scheduling Platform</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<style>
body { font-family: 'Inter', sans-serif; }
.step-indicator { transition: all 0.3s ease; }
.service-card:hover { transform: translateY(-2px); }
</style>
</head>
<body class="bg-gray-50">
<div class="min-h-screen flex flex-col">
<!-- Header -->
<header class="bg-white border-b border-gray-200">
<div class="max-w-4xl mx-auto px-6 py-6">
<div class="flex items-center justify-between">
<div>
<h1 class="text-2xl font-bold text-gray-900">Sarah's Wellness Studio</h1>
<p class="text-sm text-gray-600 mt-1">Book your appointment</p>
</div>
<div class="w-12 h-12 rounded-full bg-gradient-to-br from-blue-500 to-purple-600"></div>
</div>
</div>
</header>
<!-- Progress Steps -->
<div class="bg-white border-b border-gray-200">
<div class="max-w-4xl mx-auto px-6 py-6">
<div class="flex items-center justify-between">
<!-- Step 1 - Completed -->
<div class="flex items-center flex-1">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-blue-600 flex items-center justify-center">
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
</div>
<div class="ml-3">
<div class="text-sm font-medium text-gray-900">Select Service</div>
</div>
</div>
<div class="flex-1 h-1 bg-blue-600 mx-4"></div>
</div>
<!-- Step 2 - Active -->
<div class="flex items-center flex-1">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-blue-600 flex items-center justify-center">
<span class="text-white font-semibold">2</span>
</div>
<div class="ml-3">
<div class="text-sm font-medium text-blue-600">Choose Time</div>
</div>
</div>
<div class="flex-1 h-1 bg-gray-200 mx-4"></div>
</div>
<!-- Step 3 - Pending -->
<div class="flex items-center flex-1">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-gray-200 flex items-center justify-center">
<span class="text-gray-600 font-semibold">3</span>
</div>
<div class="ml-3">
<div class="text-sm font-medium text-gray-600">Your Details</div>
</div>
</div>
<div class="flex-1 h-1 bg-gray-200 mx-4"></div>
</div>
<!-- Step 4 - Pending -->
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-gray-200 flex items-center justify-center">
<span class="text-gray-600 font-semibold">4</span>
</div>
<div class="ml-3">
<div class="text-sm font-medium text-gray-600">Payment</div>
</div>
</div>
</div>
</div>
</div>
<!-- Main Content -->
<div class="flex-1 max-w-6xl mx-auto px-6 py-8 w-full">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Left Column - Selection Area -->
<div class="lg:col-span-2">
<!-- Selected Service Recap -->
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
<div class="flex items-center justify-between">
<div class="flex items-center">
<div class="w-12 h-12 rounded-lg bg-blue-600 flex items-center justify-center">
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path>
</svg>
</div>
<div class="ml-4">
<div class="font-semibold text-gray-900">Personal Training Session</div>
<div class="text-sm text-gray-600 mt-1">60 minutes · $75.00</div>
</div>
</div>
<button class="text-blue-600 hover:text-blue-700 text-sm font-medium">Change</button>
</div>
</div>
<!-- Date Selection -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6">
<h2 class="text-xl font-semibold text-gray-900 mb-4">Select Date</h2>
<!-- Month/Year Header -->
<div class="flex items-center justify-between mb-6">
<button class="p-2 hover:bg-gray-100 rounded-lg">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
</button>
<h3 class="text-lg font-semibold text-gray-900">January 2025</h3>
<button class="p-2 hover:bg-gray-100 rounded-lg">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</button>
</div>
<!-- Calendar Grid -->
<div class="grid grid-cols-7 gap-2">
<div class="text-center text-xs font-medium text-gray-500 py-2">SUN</div>
<div class="text-center text-xs font-medium text-gray-500 py-2">MON</div>
<div class="text-center text-xs font-medium text-gray-500 py-2">TUE</div>
<div class="text-center text-xs font-medium text-gray-500 py-2">WED</div>
<div class="text-center text-xs font-medium text-gray-500 py-2">THU</div>
<div class="text-center text-xs font-medium text-gray-500 py-2">FRI</div>
<div class="text-center text-xs font-medium text-gray-500 py-2">SAT</div>
<!-- Empty cells for alignment -->
<div></div><div></div><div></div>
<!-- Days -->
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-400">1</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">2</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">3</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">4</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">5</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">6</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">7</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">8</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">9</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">10</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">11</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">12</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">13</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">14</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg bg-blue-600 cursor-pointer">
<span class="text-sm text-white font-semibold">15</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">16</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">17</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">18</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">19</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">20</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">21</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">22</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">23</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">24</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">25</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg bg-gray-100 cursor-not-allowed">
<span class="text-sm text-gray-400">26</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">27</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">28</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">29</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">30</span>
</div>
<div class="aspect-square flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer">
<span class="text-sm text-gray-900">31</span>
</div>
</div>
</div>
<!-- Time Slots -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
<h2 class="text-xl font-semibold text-gray-900 mb-4">Available Times - Wednesday, Jan 15</h2>
<!-- Morning -->
<div class="mb-6">
<h3 class="text-sm font-medium text-gray-700 mb-3">Morning</h3>
<div class="grid grid-cols-4 gap-3">
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
9:00 AM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
9:30 AM
</button>
<button class="px-4 py-3 text-sm font-medium text-white bg-blue-600 border-2 border-blue-600 rounded-lg shadow-sm">
10:00 AM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
10:30 AM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
11:00 AM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
11:30 AM
</button>
</div>
</div>
<!-- Afternoon -->
<div class="mb-6">
<h3 class="text-sm font-medium text-gray-700 mb-3">Afternoon</h3>
<div class="grid grid-cols-4 gap-3">
<button class="px-4 py-3 text-sm font-medium text-gray-400 bg-gray-100 border-2 border-gray-100 rounded-lg cursor-not-allowed">
12:00 PM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
12:30 PM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
1:00 PM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
1:30 PM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
2:00 PM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-400 bg-gray-100 border-2 border-gray-100 rounded-lg cursor-not-allowed">
2:30 PM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
3:00 PM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
3:30 PM
</button>
</div>
</div>
<!-- Evening -->
<div>
<h3 class="text-sm font-medium text-gray-700 mb-3">Evening</h3>
<div class="grid grid-cols-4 gap-3">
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
4:00 PM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
4:30 PM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-900 border-2 border-gray-200 rounded-lg hover:border-blue-600 hover:bg-blue-50 transition-all">
5:00 PM
</button>
<button class="px-4 py-3 text-sm font-medium text-gray-400 bg-gray-100 border-2 border-gray-100 rounded-lg cursor-not-allowed">
5:30 PM
</button>
</div>
</div>
</div>
</div>
<!-- Right Column - Booking Summary -->
<div class="lg:col-span-1">
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 sticky top-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">Booking Summary</h3>
<!-- Service Details -->
<div class="mb-6 pb-6 border-b border-gray-200">
<div class="flex items-start mb-4">
<svg class="w-5 h-5 text-gray-400 mr-3 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
</svg>
<div>
<div class="text-sm font-medium text-gray-900">Personal Training Session</div>
<div class="text-xs text-gray-600 mt-1">60 minutes</div>
</div>
</div>
<div class="flex items-start mb-4">
<svg class="w-5 h-5 text-gray-400 mr-3 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
<div>
<div class="text-sm font-medium text-gray-900">Wednesday, Jan 15</div>
<div class="text-xs text-gray-600 mt-1">2025</div>
</div>
</div>
<div class="flex items-start">
<svg class="w-5 h-5 text-gray-400 mr-3 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<div>
<div class="text-sm font-medium text-gray-900">10:00 AM - 11:00 AM</div>
<div class="text-xs text-gray-600 mt-1">EST</div>
</div>
</div>
</div>
<!-- Price Breakdown -->
<div class="mb-6 pb-6 border-b border-gray-200">
<div class="flex items-center justify-between mb-3">
<span class="text-sm text-gray-600">Service Fee</span>
<span class="text-sm font-medium text-gray-900">$75.00</span>
</div>
<div class="flex items-center justify-between mb-3">
<span class="text-sm text-gray-600">Processing Fee</span>
<span class="text-sm font-medium text-gray-900">$2.50</span>
</div>
<div class="flex items-center justify-between pt-3 border-t border-gray-200">
<span class="text-base font-semibold text-gray-900">Total</span>
<span class="text-xl font-bold text-gray-900">$77.50</span>
</div>
</div>
<!-- Cancellation Policy -->
<div class="mb-6">
<div class="bg-amber-50 border border-amber-200 rounded-lg p-3">
<div class="flex">
<svg class="w-5 h-5 text-amber-600 mr-2 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
</svg>
<div>
<div class="text-xs font-medium text-amber-900">Cancellation Policy</div>
<div class="text-xs text-amber-700 mt-1">Free cancellation up to 24 hours before appointment</div>
</div>
</div>
</div>
</div>
<!-- CTA Button -->
<button class="w-full px-6 py-3 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-700 shadow-sm transition-all">
Continue to Details
</button>
<div class="mt-4 text-center">
<button class="text-sm text-gray-600 hover:text-gray-900">← Back to Services</button>
</div>
</div>
</div>
</div>
</div>
<!-- Footer -->
<footer class="bg-white border-t border-gray-200 mt-auto">
<div class="max-w-4xl mx-auto px-6 py-6">
<div class="flex items-center justify-between text-sm text-gray-600">
<div>© 2025 Sarah's Wellness Studio</div>
<div class="flex space-x-6">
<a href="#" class="hover:text-gray-900">Privacy Policy</a>
<a href="#" class="hover:text-gray-900">Terms of Service</a>
<a href="#" class="hover:text-gray-900">Contact</a>
</div>
</div>
</div>
</footer>
</div>
</body>
</html>

View File

@ -0,0 +1,310 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calendar View - Scheduling Platform</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<style>
body { font-family: 'Inter', sans-serif; }
.calendar-day { min-height: 120px; }
.time-slot { height: 60px; }
</style>
</head>
<body class="bg-gray-50">
<!-- Header -->
<header class="bg-white border-b border-gray-200">
<div class="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
<div class="flex items-center space-x-8">
<h1 class="text-2xl font-bold text-gray-900">SchedulePro</h1>
<nav class="hidden md:flex space-x-6">
<a href="#" class="text-blue-600 font-medium">Calendar</a>
<a href="#" class="text-gray-600 hover:text-gray-900">Bookings</a>
<a href="#" class="text-gray-600 hover:text-gray-900">Services</a>
<a href="#" class="text-gray-600 hover:text-gray-900">Analytics</a>
</nav>
</div>
<div class="flex items-center space-x-4">
<button class="text-gray-600 hover:text-gray-900">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"></path>
</svg>
</button>
<div class="w-10 h-10 rounded-full bg-blue-600 flex items-center justify-center text-white font-medium">
JD
</div>
</div>
</div>
</header>
<!-- Main Content -->
<div class="max-w-7xl mx-auto px-6 py-8">
<div class="grid grid-cols-1 lg:grid-cols-4 gap-6">
<!-- Calendar Section -->
<div class="lg:col-span-3">
<!-- Calendar Header -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6">
<div class="flex items-center justify-between mb-6">
<div class="flex items-center space-x-4">
<h2 class="text-2xl font-semibold text-gray-900">January 2025</h2>
<div class="flex space-x-2">
<button class="p-2 hover:bg-gray-100 rounded-lg">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
</button>
<button class="p-2 hover:bg-gray-100 rounded-lg">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</button>
</div>
</div>
<div class="flex items-center space-x-3">
<button class="px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 rounded-lg">Day</button>
<button class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg">Week</button>
<button class="px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 rounded-lg">Month</button>
<button class="px-4 py-2 text-sm font-medium text-blue-600 border border-blue-600 rounded-lg hover:bg-blue-50">
+ New Booking
</button>
</div>
</div>
<!-- Week View Calendar -->
<div class="overflow-x-auto">
<div class="min-w-full">
<!-- Days Header -->
<div class="grid grid-cols-8 border-b border-gray-200">
<div class="p-3"></div>
<div class="p-3 text-center">
<div class="text-xs text-gray-500 font-medium">MON</div>
<div class="text-2xl font-semibold text-gray-900 mt-1">13</div>
</div>
<div class="p-3 text-center">
<div class="text-xs text-gray-500 font-medium">TUE</div>
<div class="text-2xl font-semibold text-gray-900 mt-1">14</div>
</div>
<div class="p-3 text-center bg-blue-50">
<div class="text-xs text-blue-600 font-medium">WED</div>
<div class="text-2xl font-semibold text-blue-600 mt-1">15</div>
</div>
<div class="p-3 text-center">
<div class="text-xs text-gray-500 font-medium">THU</div>
<div class="text-2xl font-semibold text-gray-900 mt-1">16</div>
</div>
<div class="p-3 text-center">
<div class="text-xs text-gray-500 font-medium">FRI</div>
<div class="text-2xl font-semibold text-gray-900 mt-1">17</div>
</div>
<div class="p-3 text-center">
<div class="text-xs text-gray-500 font-medium">SAT</div>
<div class="text-2xl font-semibold text-gray-400 mt-1">18</div>
</div>
<div class="p-3 text-center">
<div class="text-xs text-gray-500 font-medium">SUN</div>
<div class="text-2xl font-semibold text-gray-400 mt-1">19</div>
</div>
</div>
<!-- Time Slots -->
<div class="relative">
<!-- 9:00 AM Row -->
<div class="grid grid-cols-8 border-b border-gray-100">
<div class="p-3 text-sm text-gray-500 font-medium">9:00 AM</div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-green-50 border-l-4 border-l-green-500">
<div class="text-xs font-medium text-green-900">Hair Styling</div>
<div class="text-xs text-green-700">Sarah Johnson</div>
</div>
<div class="time-slot border-l border-gray-100 p-2 bg-blue-50"></div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-purple-50 border-l-4 border-l-purple-500">
<div class="text-xs font-medium text-purple-900">Consultation</div>
<div class="text-xs text-purple-700">Mike Chen</div>
</div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
</div>
<!-- 10:00 AM Row -->
<div class="grid grid-cols-8 border-b border-gray-100">
<div class="p-3 text-sm text-gray-500 font-medium">10:00 AM</div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-blue-50 border-l-4 border-l-blue-500">
<div class="text-xs font-medium text-blue-900">Personal Training</div>
<div class="text-xs text-blue-700">Alex Rivera</div>
</div>
<div class="time-slot border-l border-gray-100 p-2 bg-amber-50 border-l-4 border-l-amber-500">
<div class="text-xs font-medium text-amber-900">Massage Therapy</div>
<div class="text-xs text-amber-700">Emma Davis</div>
</div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
</div>
<!-- 11:00 AM Row -->
<div class="grid grid-cols-8 border-b border-gray-100">
<div class="p-3 text-sm text-gray-500 font-medium">11:00 AM</div>
<div class="time-slot border-l border-gray-100 p-2 bg-blue-50 border-l-4 border-l-blue-500">
<div class="text-xs font-medium text-blue-900">Yoga Session</div>
<div class="text-xs text-blue-700">Lisa Park</div>
</div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-blue-50"></div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
</div>
<!-- 12:00 PM Row -->
<div class="grid grid-cols-8 border-b border-gray-100">
<div class="p-3 text-sm text-gray-500 font-medium">12:00 PM</div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-pink-50 border-l-4 border-l-pink-500">
<div class="text-xs font-medium text-pink-900">Makeup Session</div>
<div class="text-xs text-pink-700">Rachel Kim</div>
</div>
<div class="time-slot border-l border-gray-100 p-2 bg-blue-50"></div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-green-50 border-l-4 border-l-green-500">
<div class="text-xs font-medium text-green-900">Nutrition Consult</div>
<div class="text-xs text-green-700">Tom Wilson</div>
</div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
</div>
<!-- 1:00 PM Row -->
<div class="grid grid-cols-8 border-b border-gray-100">
<div class="p-3 text-sm text-gray-500 font-medium">1:00 PM</div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-blue-50"></div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
</div>
<!-- 2:00 PM Row -->
<div class="grid grid-cols-8 border-b border-gray-100">
<div class="p-3 text-sm text-gray-500 font-medium">2:00 PM</div>
<div class="time-slot border-l border-gray-100 p-2 bg-purple-50 border-l-4 border-l-purple-500">
<div class="text-xs font-medium text-purple-900">Design Review</div>
<div class="text-xs text-purple-700">James Lee</div>
</div>
<div class="time-slot border-l border-gray-100 p-2 bg-amber-50 border-l-4 border-l-amber-500">
<div class="text-xs font-medium text-amber-900">Therapy Session</div>
<div class="text-xs text-amber-700">Anna Brown</div>
</div>
<div class="time-slot border-l border-gray-100 p-2 bg-blue-50"></div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
<div class="time-slot border-l border-gray-100 p-2 bg-gray-50"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Sidebar - Upcoming Bookings -->
<div class="lg:col-span-1">
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">Upcoming Today</h3>
<!-- Booking Item 1 -->
<div class="mb-4 pb-4 border-b border-gray-200">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="text-sm font-semibold text-gray-900">Personal Training</div>
<div class="text-xs text-gray-500 mt-1">Alex Rivera</div>
</div>
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800">
Confirmed
</span>
</div>
<div class="flex items-center text-xs text-gray-600 mt-2">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
10:00 AM - 11:00 AM
</div>
<div class="text-xs font-medium text-gray-900 mt-2">$75.00</div>
</div>
<!-- Booking Item 2 -->
<div class="mb-4 pb-4 border-b border-gray-200">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="text-sm font-semibold text-gray-900">Makeup Session</div>
<div class="text-xs text-gray-500 mt-1">Rachel Kim</div>
</div>
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
Pending
</span>
</div>
<div class="flex items-center text-xs text-gray-600 mt-2">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
12:00 PM - 1:30 PM
</div>
<div class="text-xs font-medium text-gray-900 mt-2">$120.00</div>
</div>
<!-- Booking Item 3 -->
<div class="mb-4 pb-4 border-b border-gray-200">
<div class="flex items-start justify-between mb-2">
<div class="flex-1">
<div class="text-sm font-semibold text-gray-900">Therapy Session</div>
<div class="text-xs text-gray-500 mt-1">Anna Brown</div>
</div>
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800">
Confirmed
</span>
</div>
<div class="flex items-center text-xs text-gray-600 mt-2">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
2:00 PM - 3:00 PM
</div>
<div class="text-xs font-medium text-gray-900 mt-2">$150.00</div>
</div>
<!-- Stats -->
<div class="mt-6 pt-4 border-t border-gray-200">
<div class="flex items-center justify-between mb-3">
<span class="text-sm text-gray-600">Today's Revenue</span>
<span class="text-lg font-semibold text-gray-900">$345.00</span>
</div>
<div class="flex items-center justify-between">
<span class="text-sm text-gray-600">Total Bookings</span>
<span class="text-lg font-semibold text-gray-900">8</span>
</div>
</div>
</div>
<!-- Availability Settings -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mt-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">Quick Actions</h3>
<button class="w-full px-4 py-2 text-sm font-medium text-blue-600 border border-blue-600 rounded-lg hover:bg-blue-50 mb-3">
Set Availability
</button>
<button class="w-full px-4 py-2 text-sm font-medium text-gray-700 border border-gray-300 rounded-lg hover:bg-gray-50">
Block Time Off
</button>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,320 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sarah Martinez - Personal Booking Page</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<style>
body { font-family: 'Inter', sans-serif; }
.service-card { transition: all 0.3s ease; }
.service-card:hover { transform: translateY(-4px); box-shadow: 0 12px 24px rgba(0, 0, 0, 0.12); }
</style>
</head>
<body class="bg-gray-50">
<!-- Hero Section -->
<div class="bg-gradient-to-br from-blue-600 via-blue-700 to-purple-800 text-white">
<div class="max-w-4xl mx-auto px-6 py-16">
<div class="text-center">
<!-- Profile Picture -->
<div class="relative inline-block mb-6">
<div class="w-32 h-32 rounded-full bg-white p-1">
<div class="w-full h-full rounded-full bg-gradient-to-br from-purple-400 to-pink-400 flex items-center justify-center">
<span class="text-4xl font-bold text-white">SM</span>
</div>
</div>
<div class="absolute bottom-2 right-2 w-6 h-6 bg-green-500 rounded-full border-4 border-white"></div>
</div>
<h1 class="text-4xl font-bold mb-3">Sarah Martinez</h1>
<p class="text-xl text-blue-100 mb-6">Certified Wellness Coach & Personal Trainer</p>
<div class="flex items-center justify-center space-x-6 text-sm">
<div class="flex items-center">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<span>4.9 (127 reviews)</span>
</div>
<div class="flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
<span>Los Angeles, CA</span>
</div>
</div>
<!-- Social Links -->
<div class="flex items-center justify-center space-x-4 mt-8">
<a href="#" class="w-10 h-10 rounded-full bg-white/20 hover:bg-white/30 flex items-center justify-center transition-all">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
</svg>
</a>
<a href="#" class="w-10 h-10 rounded-full bg-white/20 hover:bg-white/30 flex items-center justify-center transition-all">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
</svg>
</a>
<a href="#" class="w-10 h-10 rounded-full bg-white/20 hover:bg-white/30 flex items-center justify-center transition-all">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/>
</svg>
</a>
<a href="#" class="w-10 h-10 rounded-full bg-white/20 hover:bg-white/30 flex items-center justify-center transition-all">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"/>
</svg>
</a>
</div>
</div>
</div>
</div>
<!-- About Section -->
<div class="max-w-4xl mx-auto px-6 py-12">
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-8 mb-8">
<h2 class="text-2xl font-semibold text-gray-900 mb-4">About Me</h2>
<p class="text-gray-700 leading-relaxed mb-4">
Hi there! I'm Sarah, a certified wellness coach and personal trainer with over 8 years of experience helping people achieve their health and fitness goals. My approach combines personalized training plans, nutritional guidance, and mindset coaching to create lasting transformations.
</p>
<p class="text-gray-700 leading-relaxed">
Whether you're looking to build strength, lose weight, improve flexibility, or simply feel better in your body, I'm here to support you every step of the way. Let's work together to unlock your full potential!
</p>
</div>
<!-- Services Section -->
<div class="mb-8">
<h2 class="text-2xl font-semibold text-gray-900 mb-6">My Services</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Service Card 1 -->
<div class="service-card bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden cursor-pointer">
<div class="h-48 bg-gradient-to-br from-blue-400 to-blue-600 flex items-center justify-center">
<svg class="w-20 h-20 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
</svg>
</div>
<div class="p-6">
<h3 class="text-xl font-semibold text-gray-900 mb-2">Personal Training</h3>
<p class="text-gray-600 text-sm mb-4">One-on-one customized workout sessions tailored to your goals and fitness level.</p>
<div class="flex items-center justify-between mb-4">
<div class="text-sm text-gray-600">
<svg class="w-4 h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
60 minutes
</div>
<div class="text-2xl font-bold text-gray-900">$75</div>
</div>
<button class="w-full px-4 py-2 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 transition-all">
Book Now
</button>
</div>
</div>
<!-- Service Card 2 -->
<div class="service-card bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden cursor-pointer">
<div class="h-48 bg-gradient-to-br from-purple-400 to-purple-600 flex items-center justify-center">
<svg class="w-20 h-20 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path>
</svg>
</div>
<div class="p-6">
<h3 class="text-xl font-semibold text-gray-900 mb-2">Yoga & Mindfulness</h3>
<p class="text-gray-600 text-sm mb-4">Guided yoga sessions focusing on breath, flexibility, and mental clarity.</p>
<div class="flex items-center justify-between mb-4">
<div class="text-sm text-gray-600">
<svg class="w-4 h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
45 minutes
</div>
<div class="text-2xl font-bold text-gray-900">$50</div>
</div>
<button class="w-full px-4 py-2 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 transition-all">
Book Now
</button>
</div>
</div>
<!-- Service Card 3 -->
<div class="service-card bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden cursor-pointer">
<div class="h-48 bg-gradient-to-br from-green-400 to-green-600 flex items-center justify-center">
<svg class="w-20 h-20 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<div class="p-6">
<h3 class="text-xl font-semibold text-gray-900 mb-2">Nutrition Consultation</h3>
<p class="text-gray-600 text-sm mb-4">Comprehensive nutrition planning and dietary guidance for optimal health.</p>
<div class="flex items-center justify-between mb-4">
<div class="text-sm text-gray-600">
<svg class="w-4 h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
30 minutes
</div>
<div class="text-2xl font-bold text-gray-900">$60</div>
</div>
<button class="w-full px-4 py-2 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 transition-all">
Book Now
</button>
</div>
</div>
<!-- Service Card 4 -->
<div class="service-card bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden cursor-pointer">
<div class="h-48 bg-gradient-to-br from-amber-400 to-amber-600 flex items-center justify-center">
<svg class="w-20 h-20 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>
</svg>
</div>
<div class="p-6">
<h3 class="text-xl font-semibold text-gray-900 mb-2">Group Training</h3>
<p class="text-gray-600 text-sm mb-4">High-energy group fitness classes with a supportive community atmosphere.</p>
<div class="flex items-center justify-between mb-4">
<div class="text-sm text-gray-600">
<svg class="w-4 h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
90 minutes
</div>
<div class="text-2xl font-bold text-gray-900">$35</div>
</div>
<button class="w-full px-4 py-2 bg-blue-600 text-white font-medium rounded-lg hover:bg-blue-700 transition-all">
Book Now
</button>
</div>
</div>
</div>
</div>
<!-- Link in Bio Section -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-8 mb-8">
<h2 class="text-2xl font-semibold text-gray-900 mb-6 text-center">Important Links</h2>
<div class="space-y-3 max-w-xl mx-auto">
<a href="#" class="flex items-center justify-between p-4 bg-gray-50 hover:bg-gray-100 rounded-lg border border-gray-200 transition-all group">
<div class="flex items-center">
<div class="w-10 h-10 rounded-lg bg-blue-600 flex items-center justify-center mr-4">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
</svg>
</div>
<div>
<div class="font-medium text-gray-900">Free Fitness Guide</div>
<div class="text-sm text-gray-600">Download my 30-day workout plan</div>
</div>
</div>
<svg class="w-5 h-5 text-gray-400 group-hover:text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</a>
<a href="#" class="flex items-center justify-between p-4 bg-gray-50 hover:bg-gray-100 rounded-lg border border-gray-200 transition-all group">
<div class="flex items-center">
<div class="w-10 h-10 rounded-lg bg-purple-600 flex items-center justify-center mr-4">
<svg class="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"/>
</svg>
</div>
<div>
<div class="font-medium text-gray-900">YouTube Channel</div>
<div class="text-sm text-gray-600">Follow for workout videos & tips</div>
</div>
</div>
<svg class="w-5 h-5 text-gray-400 group-hover:text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</a>
<a href="#" class="flex items-center justify-between p-4 bg-gray-50 hover:bg-gray-100 rounded-lg border border-gray-200 transition-all group">
<div class="flex items-center">
<div class="w-10 h-10 rounded-lg bg-green-600 flex items-center justify-center mr-4">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"></path>
</svg>
</div>
<div>
<div class="font-medium text-gray-900">Amazon Store</div>
<div class="text-sm text-gray-600">My favorite fitness equipment</div>
</div>
</div>
<svg class="w-5 h-5 text-gray-400 group-hover:text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</a>
<a href="#" class="flex items-center justify-between p-4 bg-gray-50 hover:bg-gray-100 rounded-lg border border-gray-200 transition-all group">
<div class="flex items-center">
<div class="w-10 h-10 rounded-lg bg-pink-600 flex items-center justify-center mr-4">
<svg class="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
</svg>
</div>
<div>
<div class="font-medium text-gray-900">Instagram</div>
<div class="text-sm text-gray-600">Daily motivation & transformations</div>
</div>
</div>
<svg class="w-5 h-5 text-gray-400 group-hover:text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</a>
</div>
</div>
<!-- Testimonials -->
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-8">
<h2 class="text-2xl font-semibold text-gray-900 mb-6">What Clients Say</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="bg-gray-50 rounded-lg p-6">
<div class="flex items-center mb-4">
<div class="flex text-yellow-400">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
</div>
</div>
<p class="text-gray-700 mb-4">"Sarah transformed my life! I lost 30 pounds and gained so much confidence. Her personalized approach and constant support made all the difference."</p>
<div class="font-medium text-gray-900">Jessica T.</div>
<div class="text-sm text-gray-600">Los Angeles, CA</div>
</div>
<div class="bg-gray-50 rounded-lg p-6">
<div class="flex items-center mb-4">
<div class="flex text-yellow-400">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg>
</div>
</div>
<p class="text-gray-700 mb-4">"Best trainer I've ever worked with! Sarah's knowledge of fitness and nutrition is incredible. I'm stronger and healthier than I've been in years."</p>
<div class="font-medium text-gray-900">Michael R.</div>
<div class="text-sm text-gray-600">Santa Monica, CA</div>
</div>
</div>
</div>
</div>
<!-- Footer -->
<footer class="bg-white border-t border-gray-200 mt-12">
<div class="max-w-4xl mx-auto px-6 py-8">
<div class="text-center">
<p class="text-gray-600 mb-2">© 2025 Sarah Martinez · Powered by SchedulePro</p>
<p class="text-sm text-gray-500">sarahmartinez.schedulepro.com</p>
</div>
</div>
</footer>
</body>
</html>

View File

@ -0,0 +1,71 @@
# Upwork Auto-Apply Pipeline Instructions
## Trigger
This pipeline runs when Clawdbot receives the wake event `upwork-email-check`.
It fires every 2 minutes during 8AM-11PM ET.
## Step 1: Check Gmail
```
gog gmail search "from:donotreply@upwork.com subject:\"New job\" is:unread" --max 10 --account jake@localbosses.org --json
```
## Step 2: For each unread email
1. Read the email: `gog gmail get <MSG_ID> --account jake@localbosses.org`
2. Extract: job URL, rate/budget, title, skills
3. Pre-filter based on email content:
- **SKIP if hourly max < $50** (Jake's rule)
- **SKIP if fixed price < $1,000**
- **SKIP if no rate info** and description looks low-budget
## Step 3: Scrape full job details (for jobs that pass pre-filter)
Use browser automation to visit the Upwork job page and extract:
- Full description
- Client history (total spent, hire rate, reviews)
- Number of proposals already
- Required skills
- Client location
## Step 4: Score the job (0-100)
Scoring factors:
- **Budget/rate alignment** (higher = better) — 30 pts
- **Client quality** (spend history, reviews, hire rate) — 25 pts
- **Skill match** (MCP, Claude, AI automation, full-stack) — 25 pts
- **Competition** (fewer proposals = better) — 10 pts
- **Project clarity** (well-written = better) — 10 pts
**Apply threshold: score >= 60**
## Step 5: Build deliverables (for high-scoring jobs)
Spawn a sub-agent to:
1. Create a tailored wireframe/mockup/demo relevant to the job
2. Deploy to Cloudflare Pages at `{job-slug}.portfolio.mcpengage.com`
3. Take screenshots of the deployed pages
## Step 6: Write proposal
Template components:
- **Hook**: Reference specific details from their job post
- **Proof**: Link to the deployed demo/wireframe
- **Experience**: Relevant portfolio pieces
- **Approach**: Brief technical plan
- **CTA**: Clear next step
## Step 7: Submit via browser
Use Upwork browser automation to:
1. Click "Submit a Proposal"
2. Fill in cover letter
3. Attach screenshots
4. Set rate ($50+/hr or appropriate for fixed)
5. Submit
## Step 8: Report
Post to Discord #pipeline:
- Job title + URL
- Score
- Rate/budget
- Proposal summary
- Demo link
- Status (submitted/skipped/failed)
## Processed tracking
File: `upwork-pipeline/processed.json` — array of processed email message IDs
Always mark emails as processed even if skipped (to avoid reprocessing)

29
upwork-pipeline/README.md Normal file
View File

@ -0,0 +1,29 @@
# Upwork Email-Triggered Auto-Apply Pipeline
## Architecture
```
Gmail (Upwork notification)
→ Gmail API watch() push notification
→ Google Pub/Sub
→ Cloudflare Worker (webhook)
→ Clawdbot wake event
→ Pipeline script processes new emails
→ Score job (skip if < $50/hr or < $1K fixed)
→ Scrape full job details from Upwork
→ Spawn sub-agent to build deliverables
→ Deploy deliverables to CF Pages
→ Submit proposal with screenshots + demo link
→ Post results to Discord #pipeline
```
## Components
- `pipeline.sh` — Main pipeline entry point (called by Clawdbot wake)
- `worker/` — Cloudflare Worker for Gmail push webhook
- `templates/` — Proposal templates
- `processed.json` — Track already-processed email IDs
## Setup
1. Gmail OAuth: `gog auth add jake@localbosses.org --services gmail`
2. Deploy CF Worker: `cd worker && wrangler deploy`
3. Set up Gmail watch: `node setup-watch.js`
4. Add Clawdbot cron for wake event handling

108
upwork-pipeline/pipeline.sh Executable file
View File

@ -0,0 +1,108 @@
#!/bin/bash
# Upwork Auto-Apply Pipeline
# Called by Clawdbot wake event when new Upwork email arrives
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ACCOUNT="jake@localbosses.org"
PROCESSED_FILE="$SCRIPT_DIR/processed.json"
MIN_HOURLY=50
MIN_FIXED=1000
# Initialize processed file if missing
[ -f "$PROCESSED_FILE" ] || echo '[]' > "$PROCESSED_FILE"
echo "[pipeline] Checking for new Upwork job emails..."
# Search for unread Upwork job notification emails
EMAILS=$(gog gmail search "from:donotreply@upwork.com subject:\"New job\" is:unread" \
--max 10 --account "$ACCOUNT" --json 2>&1)
if [ $? -ne 0 ]; then
echo "[pipeline] ERROR: Gmail search failed: $EMAILS"
exit 1
fi
# Parse email IDs
EMAIL_IDS=$(echo "$EMAILS" | jq -r '.[].messages[0].id // empty' 2>/dev/null)
if [ -z "$EMAIL_IDS" ]; then
echo "[pipeline] No new Upwork job emails found."
exit 0
fi
PROCESSED_COUNT=0
SKIPPED_COUNT=0
for MSG_ID in $EMAIL_IDS; do
# Skip already processed
if jq -e "index(\"$MSG_ID\")" "$PROCESSED_FILE" > /dev/null 2>&1; then
echo "[pipeline] Already processed: $MSG_ID"
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
continue
fi
echo "[pipeline] Processing email: $MSG_ID"
# Get full email
EMAIL_BODY=$(gog gmail get "$MSG_ID" --account "$ACCOUNT" --json 2>&1)
if [ $? -ne 0 ]; then
echo "[pipeline] ERROR reading email $MSG_ID: $EMAIL_BODY"
continue
fi
# Extract job URL
JOB_URL=$(echo "$EMAIL_BODY" | jq -r '.body // .snippet // ""' | \
grep -oP 'https://www\.upwork\.com/jobs/~\d+' | head -1)
if [ -z "$JOB_URL" ]; then
# Try plain text extraction
JOB_URL=$(gog gmail get "$MSG_ID" --account "$ACCOUNT" 2>&1 | \
grep -oP 'https://www\.upwork\.com/jobs/~\d+' | head -1)
fi
if [ -z "$JOB_URL" ]; then
echo "[pipeline] No job URL found in email $MSG_ID, skipping"
continue
fi
# Extract subject for logging
SUBJECT=$(echo "$EMAIL_BODY" | jq -r '.subject // "unknown"' 2>/dev/null || echo "unknown")
echo "[pipeline] Job URL: $JOB_URL"
echo "[pipeline] Subject: $SUBJECT"
# Extract rate info from email body
RATE_INFO=$(gog gmail get "$MSG_ID" --account "$ACCOUNT" 2>&1 | \
grep -E '^\s*(Hourly|Fixed)' | head -1 || echo "")
echo "[pipeline] Rate: $RATE_INFO"
# Quick pre-filter based on email rate info
if echo "$RATE_INFO" | grep -qi "hourly"; then
MAX_RATE=$(echo "$RATE_INFO" | grep -oP '\$\d+' | tail -1 | tr -d '$')
if [ -n "$MAX_RATE" ] && [ "$MAX_RATE" -lt "$MIN_HOURLY" ]; then
echo "[pipeline] SKIP: Max hourly rate \$$MAX_RATE < \$$MIN_HOURLY minimum"
# Mark as processed so we don't revisit
jq ". + [\"$MSG_ID\"]" "$PROCESSED_FILE" > "$PROCESSED_FILE.tmp" && mv "$PROCESSED_FILE.tmp" "$PROCESSED_FILE"
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
continue
fi
fi
# Output job info for Clawdbot to process
echo "---JOB_DATA---"
echo "MSG_ID=$MSG_ID"
echo "JOB_URL=$JOB_URL"
echo "SUBJECT=$SUBJECT"
echo "RATE_INFO=$RATE_INFO"
echo "---END_JOB_DATA---"
# Mark as processed
jq ". + [\"$MSG_ID\"]" "$PROCESSED_FILE" > "$PROCESSED_FILE.tmp" && mv "$PROCESSED_FILE.tmp" "$PROCESSED_FILE"
PROCESSED_COUNT=$((PROCESSED_COUNT + 1))
done
echo "[pipeline] Done. Processed: $PROCESSED_COUNT, Skipped: $SKIPPED_COUNT"

View File

@ -0,0 +1,34 @@
#!/bin/bash
# Process a single Upwork job: scrape details, score, decide whether to apply
set -euo pipefail
JOB_URL="$1"
MSG_ID="${2:-}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
MIN_HOURLY=50
MIN_FIXED=1000
echo "[job] Scraping job details: $JOB_URL"
# Fetch the job page
JOB_PAGE=$(curl -sL "$JOB_URL" 2>&1 | head -500)
# Extract key fields from the page
# Job title
TITLE=$(echo "$JOB_PAGE" | grep -oP '(?<="title":")[^"]+' | head -1 || echo "")
# Budget/rate
BUDGET=$(echo "$JOB_PAGE" | grep -oP '(?<="amount":)\{[^}]+\}' | head -1 || echo "")
echo "[job] Title: $TITLE"
echo "[job] Budget raw: $BUDGET"
# Output structured JSON for Clawdbot to process
cat <<EOF
{
"job_url": "$JOB_URL",
"msg_id": "$MSG_ID",
"title": "$TITLE",
"needs_full_scrape": true
}
EOF

View File

@ -0,0 +1 @@
["19c69493d1a38ec5", "19c68c765ca1c2af", "19c6989a6cdc98c1", "19c69abbb1bf0874", "19c69b4e707c0d80"]