Skip to content

Commit bd627aa

Browse files
authored
Merge pull request #15 from jaredzwick/hir-121/personalize-endpoint
hir-121: AI personalization helper endpoint
2 parents d34dc89 + 3e74dc2 commit bd627aa

14 files changed

Lines changed: 1401 additions & 39 deletions

File tree

.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,9 @@ GMAIL_WEBHOOK_SECRET=YOUR_WEBHOOK_SECRET_HERE
3939
# Silent-reply follow-up: days between prospect reply and the auto follow-up.
4040
# Pulled at runtime so we can tune in prod without a deploy.
4141
REPLY_FOLLOWUP_OFFSET_DAYS=3
42+
43+
# AI personalization (POST /api/personalize). When unset the endpoint returns
44+
# 503 and the "Personalize with AI" button surfaces a clean error to the user.
45+
ANTHROPIC_API_KEY=YOUR_ANTHROPIC_API_KEY_HERE
46+
# Optional override — defaults to claude-haiku-4-5-20251001 (low cost, fast).
47+
# ANTHROPIC_PERSONALIZE_MODEL=claude-haiku-4-5-20251001

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,46 @@ and follow-up. Each is plaintext, under ~120 words, with a single CTA and
4949
deliverability notes. See [`templates/README.md`](templates/README.md) for
5050
how to load one into a campaign.
5151

52+
# AI Personalization
53+
54+
Templates give you a starting point. Personalization is what turns a
55+
starting point into a draft worth sending. Coldflow ships an opt-in helper
56+
endpoint that takes a contact and a template and returns a personalized
57+
variant — filling any remaining `{{vars}}` and adding 1–2 light touches
58+
that acknowledge the recipient's role and reference their company
59+
specifically.
60+
61+
**UI:** open `/dashboard/campaigns/new`, pick a template, then click
62+
**Personalize with AI**. Provide a contact (name, company, role) and
63+
review the line-by-line diff before applying.
64+
65+
**API:** `POST /api/personalize`
66+
67+
```
68+
{
69+
"template_id": "sales_founder_direct",
70+
"contact": {
71+
"name": "Alex Chen",
72+
"company": "Acme Robotics",
73+
"role": "VP of Engineering",
74+
"product_name": "Coldflow",
75+
"sender_name": "Jared"
76+
}
77+
}
78+
```
79+
80+
Any extra string fields on `contact` become optional context — variables
81+
like `{{product_name}}` are filled deterministically server-side before
82+
the LLM is asked to add personalization touches. The response includes
83+
`personalized_subject`, `personalized_body`, `used_variables`, and the
84+
SDK `usage` object so you can track spend. Authenticated callers are
85+
limited to one request every two seconds.
86+
87+
**Setup:** add `ANTHROPIC_API_KEY=…` to your `.env` (see `.env.example`).
88+
Without a key the endpoint returns 503 and the UI shows a clean error.
89+
Default model is `claude-haiku-4-5-20251001`; override with
90+
`ANTHROPIC_PERSONALIZE_MODEL`.
91+
5292
# Move the needle TO-DO list:
5393

5494
- [ ] Integration with GHL / N8N

next.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ const nextConfig = {
3737
async headers() { return [ { source: '/(.*)', headers: [ { key: 'Cross-Origin-Opener-Policy', value: 'same-origin', }, ], }, ]; },
3838
reactStrictMode: true,
3939
redirects,
40+
// /api/personalize reads templates/*.md at request time. On Vercel
41+
// serverless the function dir, not the repo root, is `process.cwd()`,
42+
// so the markdown pack must be explicitly traced into the bundle.
43+
outputFileTracingIncludes: {
44+
'/api/personalize': ['./templates/**/*.md'],
45+
},
4046
}
4147

4248
export default withPayload(withNextra(nextConfig), { devBundleServerPackages: false })

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"db:studio": "pnpm --filter db db:studio"
2525
},
2626
"dependencies": {
27+
"@anthropic-ai/sdk": "^0.92.0",
2728
"@payloadcms/admin-bar": "3.64.0",
2829
"@payloadcms/db-postgres": "3.64.0",
2930
"@payloadcms/live-preview-react": "3.64.0",
@@ -67,6 +68,7 @@
6768
"sharp": "0.34.2",
6869
"tailwind-merge": "^2.3.0",
6970
"tailwindcss-animate": "^1.0.7",
71+
"yaml": "^2.8.4",
7072
"zod": "^4.1.13"
7173
},
7274
"devDependencies": {

pnpm-lock.yaml

Lines changed: 67 additions & 32 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)