Back to DevLog

Building a Classified Newsletter System: From Admin Panel to Auto-Send

3 min read

Had an intense session upgrading the EpsteinScan newsletter system today. What started as fixing a few template bugs turned into a complete overhaul of the admin experience.

The Admin Auth Journey

First tackled the admin panel authentication. I wanted something that matched the whole "classified dossier" vibe of the project, so I built out a proper login page with "AUTHORIZED PERSONNEL ONLY" stamps and "TOP SECRET" watermarks. The newsletter admin panel now has four main sections: subscriber stats, transmission log, manual transmit controls, and scheduled operations overview.

SendGrid Template Hell (and Victory)

This was probably the most frustrating part. SendGrid's dynamic templates are powerful but finicky. I went through multiple iterations:

  1. Started with basic {{subject}} and {{body}} variables
  2. Evolved to a full classified briefing design with DECLASSIFIED banners and amber/gold color schemes
  3. Hit a major roadblock with HTML escaping - turns out I needed triple braces {{{CONTENT}}} instead of double to prevent Handlebars from mangling the HTML
  4. Had to add inline styles everywhere because email clients are notorious for ignoring CSS blocks

The final template uses variables like {{BRIEFING_NUMBER}}, {{DATE}}, {{SUBJECT}}, and {{{CONTENT}}} to create a cohesive intelligence briefing aesthetic.

Smart Send Controls

Built two types of send buttons:

  • Test Preview: Sends to a single test email for end-to-end validation
  • Send Live: Triggers the actual newsletter to all subscribers via background process

Both use fetch() calls instead of form submissions, with proper loading spinners and styled status messages. The test sends are marked as preview-only so they don't increment briefing numbers or trigger the duplicate send guard.

Scheduling Overhaul

Made some key frequency changes:

  • Newsletter cadence: weekly Tuesdays → twice weekly Monday & Thursday at 9 AM CT
  • Send guard reduced from 144 hours to 60 hours (makes sense with the new schedule)
  • Source monitoring: every 6 hours → twice daily at 8 AM and 6 PM
  • Added nightly cleanup at 3 AM to purge old monitoring data

The twice-weekly schedule should keep subscribers more engaged while the 60-hour guard prevents accidental duplicates.

Briefing Number Logic

Implemented a proper briefing numbering system that counts non-preview newsletter sends. Seeded the database with three historical briefing records (#001-#003) so the next live send will be #004. The system automatically calculates the next briefing number and shows "Next Transmission" info in the admin dashboard.

AI Content Formatting

Updated the content generation prompt to mandate inline-styled HTML. Every heading gets <h2 style="color:#c8952e;..."> and paragraphs get <p style="color:#d4d4d4;..."> to ensure consistent rendering across email clients that strip CSS.

What's Next

The system is now running with 28 subscribers and ready for the next auto-send on Monday. After purging 514 stale monitor items, we're down to 544 active ones. The whole flow from content generation to subscriber delivery is now smooth and properly themed.

Sometimes the best coding sessions are the ones where you solve the immediate problem but end up rebuilding half the system in the process. The newsletter admin panel went from basic functionality to a proper command center that actually feels fun to use.

Share this post