8
Fullstack

Subscribe Newsletter

A comprehensive, full-stack newsletter management system with subscriber management, campaign creation, email automation, and admin dashboard integration for Next.js applications.

Newsletter Subscription System

A powerful, enterprise-grade newsletter management system that combines elegant user interfaces with robust backend functionality. Features automated email campaigns, subscriber management, unsubscribe handling, and comprehensive admin controls with real-time analytics.

Newsletter Subscription System
Loading component registry...

The component includes complete database models for subscribers, campaigns, and recipient tracking. All email templates and unsubscribe flows are pre-configured and ready to use.

Features

Rich Email Campaigns

HTML email support with professional templates.

Secure Unsubscribe Flow

Token-based unsubscribe with confirmation.

Real-time Analytics

Track opens, clicks, and subscriber engagement.

Batch Email Processing

Efficient bulk email sending with rate limiting.

Admin Dashboard

Comprehensive management interface.

Installation

Install the Component

Install the newsletter system using the AxionJS CLI:

Terminal
npx axionjs-ui add subscribe-newsletter

Configure Environment Variables

Configure your email server settings in .env:

DATABASE_URL="postgresql://username:password@localhost:5432/database_name"
EMAIL_SERVER_HOST="smtp.gmail.com"
EMAIL_SERVER_PORT="587"
EMAIL_SERVER_USER="your-email@gmail.com"
EMAIL_SERVER_PASSWORD="your-app-password"
ADMIN_EMAIL="admin@yoursite.com"
EMAIL_FROM="Your Site <noreply@yoursite.com>"
SITE_NAME="Your Site Name"
NEXT_PUBLIC_APP_URL="https://yoursite.com"
NEWSLETTER_SECRET="your-secure-secret"

Database Setup

Set up the database schema with Prisma. Add this to your schema.prisma file:

schema.prisma
model NewsletterSubscriber {
  id             String                        @id @default(cuid())
  email          String                        @unique
  name           String?
  status         String                        @default("ACTIVE")
  token          String?                       @unique
  tokenCreatedAt DateTime?                     @default(now())
  createdAt      DateTime                      @default(now())
  updatedAt      DateTime                      @updatedAt
  campaigns      NewsletterCampaignRecipient[]
}
 
model NewsletterCampaign {
  id         String                        @id @default(cuid())
  subject    String
  content    String                        @db.Text
  sentAt     DateTime?
  createdAt  DateTime                      @default(now())
  updatedAt  DateTime                      @updatedAt
  recipients NewsletterCampaignRecipient[]
}
 
model NewsletterCampaignRecipient {
  id           String    @id @default(cuid())
  campaignId   String
  subscriberId String
  status       String    @default("PENDING")
  sentAt       DateTime?
  openedAt     DateTime?
  clickedAt    DateTime?
 
  campaign   NewsletterCampaign   @relation(fields: [campaignId], references: [id], onDelete: Cascade)
  subscriber NewsletterSubscriber @relation(fields: [subscriberId], references: [id], onDelete: Cascade)
 
  @@unique([campaignId, subscriberId])
}

Run Database Migrations

Apply the schema changes to your database:

Terminal
npx prisma db push

Make sure to configure your email provider settings before testing. Use app-specific passwords for Gmail.

Libraries Used

This component leverages several modern libraries and frameworks:

  • Next.js 14+: App Router with Server Actions
  • React Hook Form: Form state management and validation
  • Zod: Schema validation for both client and server
  • Prisma: Database ORM for PostgreSQL
  • Nodemailer: Email sending functionality
  • Lucide React: Modern icon library
  • date-fns: Date formatting utilities
  • Tailwind CSS: Utility-first CSS framework

Usage

Add the newsletter subscription form to any page:

app/page.tsx
import NewsletterSubscription from "@/components/newsletter-subscription";
 
export default function HomePage() {
  return (
    <div className="min-h-screen">
      {/* Your page content */}
      
      <NewsletterSubscription />
    </div>
  );
}

The component automatically handles:

  • Form validation and submission
  • Duplicate email detection
  • Confirmation email sending
  • Success/error state management
  • Responsive design

Subscription Management

The system intelligently handles various subscription scenarios:

actions/subscribe-newsletter-actions.ts
// Smart duplicate handling
const existingSubscriber = await db.newsletterSubscriber.findUnique({
  where: { email },
});
 
if (existingSubscriber) {
  if (existingSubscriber.status === "ACTIVE") {
    return {
      success: false,
      message: "This email is already subscribed to our newsletter.",
    };
  } else {
    // Reactivate unsubscribed users
    await db.newsletterSubscriber.update({
      where: { email },
      data: {
        status: "ACTIVE",
        token: generateSecureToken(),
        tokenCreatedAt: new Date(),
      },
    });
  }
}

Features include:

  • Duplicate Prevention: Prevents multiple subscriptions with same email
  • Secure Tokens: Cryptographically secure unsubscribe tokens
  • Status Tracking: Active, unsubscribed, and pending states

Server Actions

actions/subscribe-newsletter-actions.ts
export async function subscribeToNewsletter(
  prevState: SubscribeFormState,
  formData: FormData,
): Promise<SubscribeFormState> {
  // Validate form data
  const validatedFields = subscribeFormSchema.safeParse({
    email: formData.get("email"),
    name: formData.get("name") || "",
  });
 
  if (!validatedFields.success) {
    return {
      success: false,
      errors: validatedFields.error.flatten().fieldErrors,
      message: "Please check the form for errors.",
    };
  }
 
  const { email, name } = validatedFields.data;
  const token = generateSecureToken();
 
  try {
    await db.newsletterSubscriber.create({
      data: {
        email,
        name: name || null,
        status: "ACTIVE",
        token: token,
        tokenCreatedAt: new Date(),
      },
    });
 
    await sendConfirmationEmail(email, name || "", token);
    revalidatePath("/admin/newsletter");
 
    return {
      success: true,
      message: "Thank you for subscribing to our newsletter!",
    };
  } catch (error) {
    console.error("Error subscribing to newsletter:", error);
    return {
      success: false,
      message: "Failed to subscribe. Please try again later.",
    };
  }
}

Features:

  • Zod validation for type safety
  • Secure token generation
  • Automatic confirmation emails
  • Error handling and user feedback

API Reference

Server Actions

PropTypeDefault
subscribeToNewsletter
(prevState: SubscribeFormState, formData: FormData) => Promise<SubscribeFormState>
-
createAndSendCampaign
(prevState: CampaignFormState, formData: FormData) => Promise<CampaignFormState>
-
unsubscribeByToken
(token: string) => Promise<{ success: boolean; message: string }>
-
getAllSubscribers
() => Promise<NewsletterSubscriber[]>
-
getAllCampaigns
() => Promise<NewsletterCampaign[]>
-
deleteSubscriber
(id: string) => Promise<{ success: boolean; error?: string }>
-
verifyUnsubscribeToken
(token: string) => Promise<string | null>
-

Conclusion

This newsletter subscription provides a complete solution for managing email campaigns, subscribers, and analytics. With its robust backend, elegant UI components, and seamless integration with Next.js, it empowers developers to build powerful newsletter features quickly and efficiently.

On this page