Skip to content

Commit 4cce460

Browse files
Brandon CharlesonBrandon Charleson
authored andcommitted
feat: add Instantly.ai v2 API plugin with 20 actions
- Lead operations: create, get, list, update, delete, update status, add to campaign - Campaign operations: create, get, list, update, delete, activate, pause - Account operations: list, get, pause, resume, enable/disable warmup - Custom Instantly logo - Integration credentials and test connection
1 parent f7b3f88 commit 4cce460

26 files changed

+2689
-0
lines changed

docs/neon-setup-guide.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Neon Database Setup Guide
2+
3+
This guide documents how we set up Neon.tech PostgreSQL for the Workflow Builder project.
4+
5+
## What is Neon?
6+
7+
Neon is a serverless PostgreSQL database that offers:
8+
- Free tier with 0.5 GB storage
9+
- Auto-suspend after 5 minutes of inactivity (saves costs)
10+
- Instant database branching (like git for databases)
11+
- Connection pooling built-in
12+
13+
## Step-by-Step Setup
14+
15+
### 1. Create a Neon Account
16+
17+
1. Go to [https://console.neon.tech/](https://console.neon.tech/)
18+
2. Sign up using GitHub, Google, or email
19+
3. After signing in, you'll land on your dashboard
20+
21+
### 2. Create a New Project
22+
23+
When you first sign up, Neon automatically creates a project for you. If you need a new one:
24+
25+
1. Click "New Project" in the dashboard
26+
2. Choose a project name (e.g., "workflow-builder")
27+
3. Select a region closest to you (e.g., "US East")
28+
4. Click "Create Project"
29+
30+
### 3. Get Your Connection String
31+
32+
1. From your project dashboard, click the "Connect" button (top right)
33+
2. A dialog appears with connection details
34+
3. Make sure "Connection pooling" is enabled (toggle should be ON)
35+
4. Click "Show password" to reveal the full connection string
36+
5. Copy the connection string - it looks like:
37+
```
38+
postgresql://username:password@ep-xxx-xxx.region.aws.neon.tech/neondb?sslmode=require
39+
```
40+
41+
### 4. Configure Environment Variables
42+
43+
Create a `.env.local` file in your project root (this file is gitignored):
44+
45+
```env
46+
# Database - Neon PostgreSQL
47+
DATABASE_URL=postgresql://your-connection-string-here
48+
49+
# Authentication (generate with: openssl rand -base64 32)
50+
BETTER_AUTH_SECRET=your-generated-secret
51+
52+
# Credentials Encryption (generate with: openssl rand -hex 32)
53+
INTEGRATION_ENCRYPTION_KEY=your-64-char-hex-string
54+
55+
# App URLs
56+
BETTER_AUTH_URL=http://localhost:3000
57+
NEXT_PUBLIC_APP_URL=http://localhost:3000
58+
```
59+
60+
Also copy to `.env` for Drizzle migrations:
61+
```bash
62+
cp .env.local .env
63+
```
64+
65+
### 5. Push Database Schema
66+
67+
Run the following command to create all tables:
68+
69+
```bash
70+
pnpm db:push
71+
```
72+
73+
This uses Drizzle ORM to push the schema defined in `lib/db/schema.ts` to your database.
74+
75+
### 6. Start the Development Server
76+
77+
```bash
78+
pnpm dev
79+
```
80+
81+
Visit [http://localhost:3000](http://localhost:3000) - you should see the workflow builder!
82+
83+
## How the Database Works in This Project
84+
85+
### Technology Stack
86+
87+
- **Drizzle ORM**: Type-safe database toolkit for TypeScript
88+
- **PostgreSQL**: The database engine (hosted on Neon)
89+
- **Better Auth**: Authentication library that stores users/sessions in the database
90+
91+
### Database Schema
92+
93+
The schema is defined in `lib/db/schema.ts` and includes:
94+
95+
| Table | Purpose |
96+
|-------|---------|
97+
| `user` | User accounts (email, name, password hash) |
98+
| `session` | Active login sessions |
99+
| `account` | OAuth provider connections |
100+
| `verification` | Email verification tokens |
101+
| `workflows` | Workflow definitions (nodes, edges, config) |
102+
| `workflow_executions` | Workflow run history |
103+
| `workflow_execution_logs` | Detailed step-by-step logs |
104+
| `api_keys` | User API keys for programmatic access |
105+
106+
### Database Commands
107+
108+
```bash
109+
# Push schema changes to database (no migration files)
110+
pnpm db:push
111+
112+
# Generate migration files (for production)
113+
pnpm db:generate
114+
115+
# Open Drizzle Studio (visual database browser)
116+
pnpm db:studio
117+
```
118+
119+
### Connection Flow
120+
121+
1. App reads `DATABASE_URL` from environment
122+
2. `lib/db/index.ts` creates a connection pool using `postgres` driver
123+
3. Drizzle ORM wraps the connection for type-safe queries
124+
4. API routes and server components use `db` to query data
125+
126+
## Troubleshooting
127+
128+
### "database does not exist" Error
129+
130+
Make sure your `DATABASE_URL` points to the correct database name (usually `neondb`).
131+
132+
### Connection Timeout
133+
134+
Neon auto-suspends after 5 min idle. First request after suspend has ~500ms cold start. This is normal.
135+
136+
### Schema Push Fails
137+
138+
1. Check `DATABASE_URL` is set correctly in both `.env` and `.env.local`
139+
2. Ensure your Neon project is active (not suspended)
140+
3. Try running `pnpm db:push` again
141+
142+
## Security Notes
143+
144+
- Never commit `.env` or `.env.local` files
145+
- These files are already in `.gitignore`
146+
- Rotate `BETTER_AUTH_SECRET` and `INTEGRATION_ENCRYPTION_KEY` if exposed
147+
- Neon connection strings include passwords - keep them secret!
148+
149+
## Useful Links
150+
151+
- [Neon Documentation](https://neon.tech/docs)
152+
- [Drizzle ORM Docs](https://orm.drizzle.team/)
153+
- [Better Auth Docs](https://better-auth.com/)
154+

plugins/instantly/credentials.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export type InstantlyCredentials = {
2+
INSTANTLY_API_KEY?: string;
3+
};
4+

plugins/instantly/icon.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* eslint-disable @next/next/no-img-element */
2+
export function InstantlyIcon({ className }: { className?: string }) {
3+
return (
4+
<img
5+
alt="Instantly"
6+
className={className}
7+
src="/instantly-logo.png"
8+
/>
9+
);
10+
}
11+

0 commit comments

Comments
 (0)