// Waitlist API endpoint using PostgreSQL
// Simple interest signups with email confirmation via Resend
const { Pool } = require('pg');
const { Resend } = require('resend');
// Initialize PostgreSQL connection pool
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false
});
// Initialize Resend
const resend = new Resend(process.env.RESEND_API_KEY);
const welcomeEmail = (signup) => ({
subject: 'Welcome to Valley of the Commons',
html: `
Welcome to the Valley!
Dear ${signup.name},
Thank you for your interest in Valley of the Commons - a four-week pop-up village in the Austrian Alps (August 24 - September 20, 2026).
You've been added to our community list. We'll keep you updated on:
- Application opening and deadlines
- Event announcements and updates
- Ways to get involved
${signup.involvement ? `
Your interests:
${signup.involvement}
` : ''}
Apply Now
See you in the valley,
The Valley of the Commons Team
You received this email because you signed up at votc.jeffemmett.com.
Unsubscribe
`
});
async function logEmail(recipientEmail, recipientName, emailType, subject, resendId, metadata = {}) {
try {
await pool.query(
`INSERT INTO email_log (recipient_email, recipient_name, email_type, subject, resend_id, metadata)
VALUES ($1, $2, $3, $4, $5, $6)`,
[recipientEmail, recipientName, emailType, subject, resendId, JSON.stringify(metadata)]
);
} catch (error) {
console.error('Failed to log email:', error);
}
}
module.exports = async function handler(req, res) {
// CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') {
return res.status(200).end();
}
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const { email, name, involvement } = req.body;
// Validate email
if (!email || !email.includes('@')) {
return res.status(400).json({ error: 'Valid email is required' });
}
// Validate name
if (!name || name.trim() === '') {
return res.status(400).json({ error: 'Name is required' });
}
// Validate involvement
if (!involvement || involvement.trim() === '') {
return res.status(400).json({ error: 'Please describe your desired involvement' });
}
const emailLower = email.toLowerCase().trim();
const nameTrimmed = name.trim();
const involvementTrimmed = involvement.trim();
// Check if email already exists
const existing = await pool.query(
'SELECT id FROM waitlist WHERE email = $1',
[emailLower]
);
if (existing.rows.length > 0) {
// Update existing entry
await pool.query(
'UPDATE waitlist SET name = $1, involvement = $2 WHERE email = $3',
[nameTrimmed, involvementTrimmed, emailLower]
);
return res.status(200).json({
success: true,
message: 'Your information has been updated!'
});
}
// Insert new signup
const result = await pool.query(
`INSERT INTO waitlist (email, name, involvement) VALUES ($1, $2, $3) RETURNING id`,
[emailLower, nameTrimmed, involvementTrimmed]
);
const signup = {
id: result.rows[0].id,
email: emailLower,
name: nameTrimmed,
involvement: involvementTrimmed
};
// Send welcome email
if (process.env.RESEND_API_KEY) {
try {
const email = welcomeEmail(signup);
const { data: emailData } = await resend.emails.send({
from: process.env.EMAIL_FROM || 'Valley of the Commons ',
to: signup.email,
subject: email.subject,
html: email.html
});
await logEmail(signup.email, signup.name, 'waitlist_welcome', email.subject, emailData?.id);
} catch (emailError) {
console.error('Failed to send welcome email:', emailError);
// Don't fail the request if email fails
}
}
return res.status(200).json({
success: true,
message: 'Successfully joined the waitlist!'
});
} catch (error) {
console.error('Waitlist error:', error);
return res.status(500).json({ error: 'Failed to join waitlist. Please try again later.' });
}
};