Revue alternative for your personal blog - MailChimp

Last year, I wrote an article (in Chinese) about how to create a newsletter with Next.js and Revue. But unfortunately, Revue was shut down by Elon Musk in this early year.

After trying SubstckConvertKitmailerlite and MailChimp, MailChimp won for me because:

  • The free plan, which is appropriate for a personal startup, allows up to 500 contacts and 2,500 monthly sends.
  • Even if you're on the free plan, it offers APIs. If you already have a personal website, you won't need another one to store your newsletters.

Setting up MailChimp#

After creating a free account,you'll need to fetch your API key。And other values you'll need to grab:

  • The API server region. Log into your Mailchimp account and look at the URL in your browser. You'll see something like; the us19 part is the server region.
  • The Audience ID for the mailing list.

Add Secrets to Environment Variables#

Let's keep your secrets in environment variables without hardcoding them and revealing them in the public. If you are using Next.js and deploying with Vercel,you can:


Don't forget to add .env.local to your .gitignore. We don't want to commit our secrets.

Creating The Request for Subscription#

We can create an API route at pages/api/subscribe.js to add a member to our list.

import type { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { email } = req.body;

  res.setHeader('Access-Control-Allow-Origin', '*');

  if (!email) {
    return res.status(400).json({
      error: 'Email is required'

  const revRes = await fetch(
      method: 'POST',
      headers: {
        Authorization: `anystring ${process.env.MAILCHIMP_API_KEY}`,
        'Content-Type': 'application/json'
      body: JSON.stringify({
        email_address: email,
        status: 'subscribed',
        tags: ['xxx'] // If you wanna add some tags

  const data = await revRes.json();

  if (data.status >= 400) {
    return res.status(500).json({
      error: data?.detail ?? 'Something went wrong'

  return res.status(200).json({ error: '' });

Creating A Subscribe Component#

We need a component to send a request to our API, for gathering user's email.

import Image from 'next/image';
import React, { FormEvent, useRef, useState } from 'react';

const LoadingSVG = () => {
  return (
        viewBox="0 0 19 17"
        className="fill-white dark:fill-white"
        <circle className="loadingCircle" cx="2.2" cy="10" r="1.6" />
        <circle className="loadingCircle" cx="9.5" cy="10" r="1.6" />
        <circle className="loadingCircle" cx="16.8" cy="10" r="1.6" />

const Subscribe = () => {
  const inputEl = useRef<HTMLInputElement>(null);
  const [errMsg, setErrMsg] = useState('');
  const [loading, setLoading] = useState(false);

  const subscribe = async (e: FormEvent) => {

    const res = await fetch('/api/subscribe', {
      body: JSON.stringify({
        email: inputEl?.current?.value
      headers: {
        'Content-Type': 'application/json'
      method: 'POST'

    const json = await res.json();
    const { error } = json;

    if (error) {

    if (inputEl?.current?.value) {
      inputEl.current.value = '';

    setErrMsg('Success! 🎉 You are now subscribed to the newsletter.');

  return (
    <div className="w-full p-4 mt-10 fontOutfit">
      <div className="flex justify-between items-center">
            className="w-8 h-8 rounded-full overflow-hidden"

        <div className="max-w-[55ch]">
          <p className="font-medium text-sm">Have a weekly visit of</p>
          <p className="font-bold text-2xl bg-gradient-to-r from-subscribleRight to-subscrible bg-clip-text text-transparent">
            Howl&apos;s Moving Castle
          <p className="font-light mt-4">
            Get emails from me about web development, tech, and early access to new articles. I will
            only send emails when new content is posted.
          <p className="font-bold">Subscribe Now!</p>
        <form className="relative mt-4 border rounded" onSubmit={subscribe}>
            className="px-4 py-2 block w-full border-gray-300 rounded-md bg-white dark:bg-bg text-gray-900 dark:text-gray-100 pr-32 outline-none"
            placeholder="Your e-mail address"
            className="bg-gradient-to-r from-subscribleRight to-subscrible flex items-center justify-center absolute right-1 top-1 px-4 py-1 font-medium bg-subscrible text-white rounded w-28 h-9">
            {loading ? <LoadingSVG /> : 'SUBSCRIBE'}
        {errMsg && <div className="mt-4 text-gray-500 text-sm">{errMsg}</div>}

export default Subscribe;

We end up with a scene that like the one below:

Cheese 🧀#

We can embed Mailchimp's campaigns into our individual websites. Dive into the entire souce code for my blog is open source.


Have a weekly visit of

Howl's Moving Castle

Get emails from me about web development, tech, and early access to new articles. I will only send emails when new content is posted.

Subscribe Now!