Next.js

Integrate Stack0 with Next.js App Router using Route Handlers and Server Actions.

Installation

Terminal
npm install @stack0/sdk

Environment Variables

.env.local
STACK0_API_KEY=sk_live_your_api_key

Create a Shared Client

Create a shared Stack0 client that can be imported across your app:

lib/stack0.ts
import { Stack0 } from '@stack0/sdk'
export const stack0 = new Stack0({
apiKey: process.env.STACK0_API_KEY!
})

Route Handler

Create an API route to handle email sending:

app/api/send-email/route.ts
import { stack0 } from '@/lib/stack0'
import { NextResponse } from 'next/server'
export async function POST(request: Request) {
const { to, subject, html } = await request.json()
try {
const result = await stack0.mail.send({
from: 'noreply@yourdomain.com',
to,
subject,
html,
})
return NextResponse.json(result)
} catch (error) {
return NextResponse.json(
{ error: 'Failed to send email' },
{ status: 500 }
)
}
}

Server Action

Use Server Actions for a more streamlined approach:

app/actions/email.ts
'use server'
import { stack0 } from '@/lib/stack0'
export async function sendWelcomeEmail(email: string, name: string) {
return await stack0.mail.send({
from: 'welcome@yourdomain.com',
to: email,
subject: `Welcome, ${name}!`,
html: `
<h1>Welcome to our platform, ${name}!</h1>
<p>We're excited to have you on board.</p>
`,
})
}
export async function sendContactForm(data: {
name: string
email: string
message: string
}) {
return await stack0.mail.send({
from: 'contact@yourdomain.com',
to: 'team@yourdomain.com',
subject: `Contact Form: ${data.name}`,
replyTo: data.email,
html: `
<h2>New Contact Form Submission</h2>
<p><strong>From:</strong> ${data.name} (${data.email})</p>
<p><strong>Message:</strong></p>
<p>${data.message}</p>
`,
})
}

Using in a Component

Call the Server Action from a client component:

components/contact-form.tsx
'use client'
import { sendContactForm } from '@/app/actions/email'
import { useState } from 'react'
export function ContactForm() {
const [status, setStatus] = useState<'idle' | 'sending' | 'sent'>('idle')
async function handleSubmit(formData: FormData) {
setStatus('sending')
await sendContactForm({
name: formData.get('name') as string,
email: formData.get('email') as string,
message: formData.get('message') as string,
})
setStatus('sent')
}
return (
<form action={handleSubmit}>
<input name="name" placeholder="Name" required />
<input name="email" type="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" required />
<button type="submit" disabled={status === 'sending'}>
{status === 'sending' ? 'Sending...' : 'Send'}
</button>
{status === 'sent' && <p>Message sent!</p>}
</form>
)
}

File Uploads with CDN

Handle file uploads using the CDN product:

app/api/upload/route.ts
import { stack0 } from '@/lib/stack0'
import { NextResponse } from 'next/server'
export async function POST(request: Request) {
const { filename, mimeType, size } = await request.json()
// Get a presigned upload URL
const { uploadUrl, assetId, cdnUrl } = await stack0.cdn.getUploadUrl({
filename,
mimeType,
size,
})
return NextResponse.json({ uploadUrl, assetId, cdnUrl })
}
export async function PUT(request: Request) {
const { assetId } = await request.json()
// Confirm the upload is complete
await stack0.cdn.confirmUpload({ assetId })
return NextResponse.json({ success: true })
}