Changeset 2e247e4 in Klonkt for src/server.js


Ignore:
Timestamp:
06/19/2026 12:00:48 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
91094a4
Parents:
255e3d3
Message:

Newsletter / mailing list (premium feature #1) + SMTP wiring

Email infrastructure reuses src/config/mailer.js (env SMTP_*, graceful: without
SMTP no sending, sign-ups still work via single opt-in).

  • DB: subscribers table (per-site, status pending/confirmed/unsub, token) + newsletters table (send history). Idempotent in initializeDatabase.
  • SubscriberService: addSubscriber (double opt-in if SMTP, otherwise single), confirm, unsubscribe, confirmedFor, counts. Email validation + dedupe per (site, email).
  • routes/newsletter.js (public, premium-gated; unsubscribe always works): GET/POST /nieuwsbrief, /nieuwsbrief/bevestigen/:token, /nieuwsbrief/uitschrijven/:token. Confirm/unsub links absolute via PUBLIC_BASE_URL + siteUrlBase.
  • routes/admin-newsletter.js (site admin + premium): GET /admin/newsletter (compose + counts + history + shareable signup link + SMTP warning), POST /admin/newsletter/send (to confirmed subscribers, unsubscribe link per email, history written).
  • views: pages/newsletter.ejs (multi-state) + pages/admin-newsletter.ejs.
  • admin dashboard: premium links Newsletter + Press kit added.

Feature #2 (download-for-email) and #8 (notify) reuse subscribers. node --check
passed; local test suite missing better-sqlite3 (runs on the VPS).

Co-Authored-By: Claude <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/server.js

    r255e3d3 r2e247e4  
    5353import circleRoutes from './routes/circle.js';
    5454import epkRoutes from './routes/epk.js';
     55import newsletterRoutes from './routes/newsletter.js';
     56import adminNewsletterRoutes from './routes/admin-newsletter.js';
    5557
    5658if (!process.env.SESSION_SECRET) {
     
    252254app.use('/admin/patreon', adminPatreonRoutes);
    253255app.use('/admin/stats', adminStatsRoutes);
     256app.use('/admin/newsletter', adminNewsletterRoutes);
    254257app.use('/admin', adminRoutes);
    255258app.use('/prutter', prutterRoutes);
     
    267270app.use('/', circleRoutes); // /cirkel-feed (solo/hub: next() -> postsRoutes)
    268271app.use('/', epkRoutes); // /pers perskit (premium; niet-premium: next() -> 404)
     272app.use('/', newsletterRoutes); // /nieuwsbrief in/uitschrijven (premium; niet-premium: next())
    269273app.use('/', postsRoutes);
    270274
Note: See TracChangeset for help on using the changeset viewer.