import { useState } from “react”;
const NAVY = “#162240”;
const COASTAL_BLUE = “#6B93B2”;
const SAND = “#C8B89A”;
const CREAM = “#F5F0E8”;
const TAUPE = “#8A7060”;
const CHARCOAL = “#2C2520”;
const PLACEHOLDER_IMG = “https://necoastalcreative.com/wp-content/uploads/2026/04/print-is-back.png”;
const BANNER_IMG = “https://necoastalcreative.com/wp-content/uploads/2026/05/mark-graham-scaled.png”;
const LOGO_IMG = “https://necoastalcreative.com/wp-content/uploads/2026/05/currents-logo-transparent.png”;
const SECTIONS = [
{ id: “cover”, label: “Cover & Hero” },
{ id: “editor”, label: “Editor’s Note” },
{ id: “creative_edit”, label: “The Creative Edit” },
{ id: “spotlight”, label: “Spotlight” },
{ id: “compass”, label: “Compass” },
{ id: “podcast”, label: “Creative Confidential” },
{ id: “events”, label: “Current Events” },
{ id: “brandbox”, label: “BrandBox” },
{ id: “banners”, label: “Banner Ads” },
{ id: “connections”, label: “conNECCtions” },
{ id: “scene”, label: “Scene on the Coast” },
{ id: “shop”, label: “Coastal NECCessities” },
{ id: “footer”, label: “Footer & Socials” },
{ id: “output”, label: “⬇ Generate HTML” },
];
const defaultData = {
date: “May 23, 2025”,
cover_image: PLACEHOLDER_IMG,
hero_line1: “Island”,
hero_line2: “Girl”,
hero_caption: “Cailini Coastal founder Meg Young captures the ease and elegance of coastal living through timeless, island-inspired pieces”,
photo_credit: “Cover Photo: Meg Young outside her brand’s showcase home on Nantucket, MA · Photography by Zofia Crosby”,
banners: [
{ image: BANNER_IMG, href: “#” },
{ image: BANNER_IMG, href: “#” },
{ image: BANNER_IMG, href: “#” },
{ image: BANNER_IMG, href: “#” },
],
editor_note: “Welcome to December — the season of juggling all the things right alongside the twinkle lights. The holidays move fast, but I hope you still find a few quiet moments for yourself… even five minutes with a cup of coffee to refill your creative cup.\n\nThis week, we’re spotlighting Meg Young of Cailini Coastal, a valued BLOOM speaker and a beautiful example of coastal style done with intention.\n\nHere’s to a joyful week — and a little breathing room for you.”,
cover_story_image: PLACEHOLDER_IMG,
cover_story_kicker: “Cover Story”,
cover_story_headline: “Island Girl”,
cover_story_body: “How Meg Young built Cailini Coastal into a destination brand rooted in coastal ease and timeless New England style.”,
cover_story_link: “#”,
edit_items: [
{ image: PLACEHOLDER_IMG, label: “Shop”, title: “Item Name Here”, body: “Short description of this curated coastal find.”, link: “#”, btn_label: “Shop Now →”, btn_show: true },
{ image: PLACEHOLDER_IMG, label: “Shop”, title: “Item Name Here”, body: “Short description of this curated coastal find.”, link: “#”, btn_label: “Shop Now →”, btn_show: true },
],
spotlight_items: [
{ image: PLACEHOLDER_IMG, label: “Spotlight”, title: “Creator Name”, body: “A deeper look at what makes this coastal creative one to watch.”, link: “#”, btn_label: “Follow on Instagram →”, btn_show: true },
{ image: PLACEHOLDER_IMG, label: “Spotlight”, title: “Creator Name”, body: “A deeper look at what makes this coastal creative one to watch.”, link: “#”, btn_label: “Follow on Instagram →”, btn_show: true },
],
compass_image: PLACEHOLDER_IMG,
compass_title: “”,
compass_body: “”,
compass_link: “#”,
compass2_image: PLACEHOLDER_IMG,
compass2_title: “”,
compass2_body: “”,
compass2_link: “#”,
podcast_link: “#”,
events: [
{ image: PLACEHOLDER_IMG, title: “ELEVATE”, tag: “• New Speaker & Panel Additions •”, body: “We’re building something extraordinary — new speakers, fresh panels, and brand activations that will inspire and elevate every woman in the room.”, link: “#” },
],
brandbox_body: “We partner with incredible brands, friends, and community members to create something truly elevated. From turnkey content and styled photo shoots to curated brand activations and shared spotlights — BrandBox is your seat at the table inside one of coastal New England’s most engaged creative communities.”,
brandbox_link: “#”,
away_items: [
{ image: PLACEHOLDER_IMG, label: “Featured Stay”, title: “The Griswold Inn”, body: “Spaces are filling up — NECC readers get 30% off regular room rates.”, code: “NECC30”, link: “#” },
{ image: PLACEHOLDER_IMG, label: “Partner Deal”, title: “Partner Name”, body: “Short description of the deal available exclusively to NECC readers.”, code: “NECC__”, link: “#” },
],
connections_body: “From meet-ups and pop-ups to brand activations and creative collaborations, conNECCtions is where we share and celebrate the moments that make our community thrive.”,
connections_image: PLACEHOLDER_IMG,
connections_photos: [
{ image: PLACEHOLDER_IMG, caption: “” },
{ image: PLACEHOLDER_IMG, caption: “” },
{ image: PLACEHOLDER_IMG, caption: “” },
{ image: PLACEHOLDER_IMG, caption: “” },
],
scene_items: [
{ image: PLACEHOLDER_IMG, handle: “@newenglandsummers”, name: “Follow Eden”, platform: “instagram” },
{ image: PLACEHOLDER_IMG, handle: “@theconnecticutlife”, name: “Follow Haley”, platform: “instagram” },
{ image: PLACEHOLDER_IMG, handle: “@handle”, name: “Follow on TikTok”, platform: “tiktok” },
{ image: PLACEHOLDER_IMG, handle: “@handle”, name: “Follow on TikTok”, platform: “tiktok” },
],
shop_items: [
{ image: PLACEHOLDER_IMG, name: “Stroll Scarf”, link: “#” },
{ image: PLACEHOLDER_IMG, name: “Stroll Floral Weekender Bag”, link: “#” },
{ image: PLACEHOLDER_IMG, name: “Stroll Crewneck Sweatshirt”, link: “#” },
{ image: PLACEHOLDER_IMG, name: “Stroll Tumbler”, link: “#” },
{ image: PLACEHOLDER_IMG, name: “Brant Point Phone Cover”, link: “#” },
{ image: PLACEHOLDER_IMG, name: “Coaster Set”, link: “#” },
],
shop_link: “#”,
instagram_link: “#”,
ltk_link: “#”,
shopmy_link: “#”,
substack_link: “#”,
address: “New England Coastal Creative, LLC\n8 Wescott Court · Riverside, CT 06878”,
unsubscribe_link: “#”,
};
function generateHTML(d) {
const btn = (href, text, filled) =>
`
${text} `;
const sectionLabel = (text) =>
`
${text}
`;
const dividerTitle = (text) =>
`
`;
const banner = (i) =>
`
`;
const img43 = (src, alt=”) =>
`
`;
const editCards = d.edit_items.map(item => `
${img43(item.image, item.title)}
${item.label}
${item.title}
${item.body}
${item.btn_show && item.link ? btn(item.link, item.btn_label || “Shop Now →”, false) : ”}
`).join(”);
const spotlightCards = d.spotlight_items.map(item => `
${img43(item.image, item.title)}
${item.label}
${item.title}
${item.body}
${item.btn_show && item.link ? btn(item.link, item.btn_label || “Read Their Story →”, false) : ”}
`).join(”);
const awayCards = d.away_items.map(item => `
${item.label}
${item.title}
${item.body}
${item.code ? `
${item.code}
` : ”}
${item.link ? btn(item.link, “Learn More →”, false) : ”}
`).join(”);
const sceneCards = d.scene_items.map(item => `
${item.platform === ‘tiktok’ ? ‘🎵’ : ‘📷’} ${item.handle}
${item.name}
`).join(”);
const shopCards = d.shop_items.map(item => `
`).join(”);
const editorParas = d.editor_note.split(‘\n\n’).filter(p => p.trim()).map(p =>
`
${p}
`
).join(”);
return `
CURRENTS Weekly — ${d.date}
your source for coastal creativity, connection & community
${d.hero_line1}${d.hero_line2}
${d.hero_caption}
${d.photo_credit}
${sectionLabel(“A Note from Kim”)}
${editorParas}
${d.cover_story_kicker}
${d.cover_story_headline}
${d.cover_story_body}
${btn(d.cover_story_link, “Read It Now →”, true)}
${banner(0)}
${dividerTitle(“The Creative Edit”)}
${sectionLabel(“Shop the Shore”)}
${editCards}
${dividerTitle(“Spotlight”)}
${sectionLabel(“Behind the Creatives Shaping Our Coastal Community”)}
${spotlightCards}
${banner(1)}
${dividerTitle(“Compass”)}
${sectionLabel(“Compass”)}
Creative Brand Guidance
${d.compass_title}
${d.compass_body}
${btn(d.compass_link, “Read It on Compass →”, false)}
${d.compass2_title ? `
${sectionLabel(“Compass”)}
Creative Brand Guidance
${d.compass2_title}
${d.compass2_body}
${btn(d.compass2_link, “Read It on Compass →”, false)}
` : ”}
🎙
On Substack
Creative Confidential
Your insider’s guide to Creativity, Connection & Community — new episodes dropping weekly.
Read or Listen on Substack →
${sectionLabel(`
Current Events
`)}
${d.events.map((ev, i) => `
${ev.title}
${ev.tag ? `
${ev.tag}
` : ”}
${ev.body}
${btn(ev.link, “Grab Your Seat Now →”, true)}
`).join(”)}
${banner(2)}
• BrandBox Spotlight •
Want to See Your Brand Featured Here?
${d.brandbox_body}
Turnkey Content
We handle the creative — you get the assets
Photo Shoots
Elevated, on-brand imagery for your team
Experiences
Pop-ups, events & activations that resonate
Interested in BrandBox? Let’s build something beautiful together.
${btn(d.brandbox_link, “Connect With Us →”, true)}
${sectionLabel(“Community Moments”)}
conNECC tions
${d.connections_body}
${d.connections_photos.some(p => p.image) ? `
${d.connections_photos.filter(p => p.image).map(p => `
${p.caption ? `
${p.caption}
` : ”}
`).join(”)}
` : ”}
${awayCards}
${banner(3)}
Creative Directory
Find a Creative
Your trusted guide for finding creative partners & businesses.Add your business for FREE now through December 31st
${sectionLabel(“instaCoastal”)}
Scene on the Coast
Follow along with some of our favorite creators making waves across Instagram & TikTok
${sceneCards}
${sectionLabel(“Shop Our Creative Must-Haves for Work, Travel & Play”)}
Coastal NECC essities
${shopCards}
${btn(d.shop_link, “Shop Now →”, true)}
• instaCoastal •
@necoastalcreative — Catch up on our latest stories and posts
`;
}
const iStyle = { width:”100%”, padding:”8px 12px”, fontFamily:”‘Playfair Display’,serif”, fontSize:”14px”, border:`1px solid ${SAND}`, borderRadius:”2px”, background:”#fff”, color:CHARCOAL, marginTop:”4px”, outline:”none” };
const taStyle = { …iStyle, minHeight:”100px”, resize:”vertical”, lineHeight:”1.6″ };
const lStyle = { fontFamily:”‘Roboto Serif’,serif”, fontSize:”9px”, fontWeight:600, letterSpacing:”2px”, textTransform:”uppercase”, color:TAUPE, display:”block”, marginBottom:”2px” };
const shStyle = { fontFamily:”‘Playfair Display’,serif”, fontSize:”22px”, fontWeight:700, color:NAVY, marginBottom:”20px”, paddingBottom:”10px”, borderBottom:`2px solid ${SAND}` };
const cbStyle = { background:CREAM, border:`1px solid ${SAND}`, borderRadius:”4px”, padding:”16px”, marginBottom:”16px” };
function Field({ label, value, onChange, type=”text”, rows }) {
return (
{label}
{type === “textarea”
?
);
}
function Card({ index, label, fields, item, onChange }) {
return (
{label} {index+1}
{fields.map(f =>
onChange(f.key,v)} type={f.type||”text”} rows={f.rows} />)}
);
}
export default function NewsletterBuilder() {
const [data, setData] = useState(defaultData);
const [activeSection, setActiveSection] = useState(“cover”);
const [html, setHtml] = useState(“”);
const set = (key, value) => setData(d => ({ …d, [key]:value }));
const setArr = (arrayKey, index, field, value) => setData(d => {
const arr = […d[arrayKey]];
arr[index] = { …arr[index], [field]:value };
return { …d, [arrayKey]:arr };
});
const handleGenerate = () => {
setHtml(generateHTML(data));
setActiveSection(“output”);
};
const renderSection = () => {
if (activeSection === “output”) {
return (
Your Newsletter HTML
{html ? (
<>
✓ Ready! Click inside the box → Cmd+A / Ctrl+A to select all → Cmd+C / Ctrl+C to copy → paste into Flodesk, Mailchimp, or your email platform’s custom HTML block.
);
}
const ef = [{ key:”image”, label:”Image URL” }, { key:”label”, label:”Label” }, { key:”title”, label:”Title” }, { key:”body”, label:”Description”, type:”textarea”, rows:3 }, { key:”link”, label:”Link” }];
const JobBox = ({ job, tip }) => (
This Section’s Job
{job}
{tip}
);
switch(activeSection) {
case “cover”: return
Cover & Hero
set(“date”,v)} />
set(“cover_image”,v)} />
set(“hero_line1”,v)} />
set(“hero_line2”,v)} />
set(“hero_caption”,v)} type=”textarea” rows={3} />
set(“photo_credit”,v)} type=”textarea” rows={2} />
set(“banner_href”,v)} />
;
case “editor”: return
Editor’s Note
Separate paragraphs with a blank line (press Enter twice).
set(“editor_note”,v)} type=”textarea” rows={10} />
Cover Story CTA
set(“cover_story_image”,v)} />
set(“cover_story_kicker”,v)} />
set(“cover_story_headline”,v)} />
set(“cover_story_body”,v)} type=”textarea” rows={3} />
set(“cover_story_link”,v)} />
;
case “creative_edit”: return
The Creative Edit
{data.edit_items.map((item,i) => (
Feature {i+1}
setArr(“edit_items”,i,”image”,v)} />
setArr(“edit_items”,i,”label”,v)} />
setArr(“edit_items”,i,”title”,v)} />
setArr(“edit_items”,i,”body”,v)} type=”textarea” rows={3} />
Link URL
setArr(“edit_items”,i,”link”,e.target.value)} />
{item.btn_show &&
Try: “Shop Now →” · “Follow on Instagram →” · “Shop the Collection →” · “Learn More →” · “Shop the Sale →”
}
))}
;
case “spotlight”: return
Spotlight
{data.spotlight_items.map((item,i) => (
Creator {i+1}
setArr(“spotlight_items”,i,”image”,v)} />
setArr(“spotlight_items”,i,”label”,v)} />
setArr(“spotlight_items”,i,”title”,v)} />
setArr(“spotlight_items”,i,”body”,v)} type=”textarea” rows={3} />
Link URL (Instagram profile, TikTok, website, article…)
setArr(“spotlight_items”,i,”link”,e.target.value)} />
{item.btn_show &&
Try: “Follow on Instagram →” · “Follow on TikTok →” · “Follow Along →” · “Meet [Name] →” · “Read Their Story →”
}
))}
;
case “compass”: return
Compass
Compass Article 1
set(“compass_image”,v)} />
set(“compass_title”,v)} />
set(“compass_body”,v)} type=”textarea” rows={3} />
set(“compass_link”,v)} />
Compass Article 2
Optional — leave Title blank and this slot won’t appear in the newsletter.
set(“compass2_image”,v)} />
set(“compass2_title”,v)} />
set(“compass2_body”,v)} type=”textarea” rows={3} />
set(“compass2_link”,v)} />
;
case “podcast”: return
Creative Confidential
set(“podcast_link”,v)} />
;
case “events”: return
Current Events
Events This Week
setData(d => ({ …d, events: […d.events, { image: PLACEHOLDER_IMG, title: “”, tag: “”, body: “”, link: “#” }] }))}
style={{ padding:”6px 14px”, background:NAVY, color:”#fff”, border:”none”, cursor:”pointer”, fontFamily:”‘Roboto Serif’,serif”, fontSize:”9px”, fontWeight:600, letterSpacing:”1.5px”, textTransform:”uppercase”, borderRadius:”2px” }}>
+ Add Event
{data.events.map((ev, i) => (
Event {i+1}
{data.events.length > 1 && (
setData(d => ({ …d, events: d.events.filter((_,idx) => idx !== i) }))}
style={{ padding:”4px 10px”, background:”transparent”, color:TAUPE, border:`1px solid ${SAND}`, cursor:”pointer”, fontFamily:”‘Roboto Serif’,serif”, fontSize:”9px”, letterSpacing:”1px”, textTransform:”uppercase”, borderRadius:”2px” }}>
Remove
)}
setArr(“events”,i,”title”,v)} />
setArr(“events”,i,”image”,v)} />
setArr(“events”,i,”tag”,v)} />
setArr(“events”,i,”body”,v)} type=”textarea” rows={3} />
setArr(“events”,i,”link”,v)} />
))}
;
case “brandbox”: return
BrandBox Spotlight
set(“brandbox_body”,v)} type=”textarea” rows={5} />
set(“brandbox_link”,v)} />
;
case “banners”: return
Banner Ads
Each banner appears between newsletter sections. Upload your image to your website or CDN and paste the URL below. Each banner can link to a different destination.
{[0,1,2,3].map(i => (
Banner {i+1} — {[“After Cover Story”,”After Spotlight”,”After Current Events”,”After conNECCtions”][i]}
setArr(“banners”,i,”image”,v)} />
setArr(“banners”,i,”href”,v)} />
))}
;
case “connections”: return
conNECCtions
Drop your photos first. Feature cards are optional — add them only if you have a launch, deal, or moment worth a CTA this week.
set(“connections_body”,v)} type=”textarea” rows={3} />
set(“connections_image”,v)} />
{/* PHOTO GRID */}
Photo Grid — Up to 4 Images
Add up to 4 photos from your week — events, pop-ups, behind the scenes. Leave unused slots blank and they won’t appear.
{data.connections_photos.map((photo, i) => (
Photo {i+1}
setArr(“connections_photos”,i,”image”,v||PLACEHOLDER_IMG)} />
setArr(“connections_photos”,i,”caption”,v)} />
))}
{/* FEATURE CARDS */}
Feature Cards — Launches · Pop-Ups · Deals · Recaps
setData(d => ({ …d, away_items: […d.away_items, { image: PLACEHOLDER_IMG, label: “New Launch”, title: “”, body: “”, code: “”, link: “#” }] }))}
style={{ padding:”6px 14px”, background:NAVY, color:”#fff”, border:”none”, cursor:”pointer”, fontFamily:”‘Roboto Serif’,serif”, fontSize:”9px”, fontWeight:600, letterSpacing:”1.5px”, textTransform:”uppercase”, borderRadius:”2px”, whiteSpace:”nowrap” }}>
+ Add Card
{data.away_items.map((item,i) => (
Feature {i+1}
{data.away_items.length > 1 && (
setData(d => ({ …d, away_items: d.away_items.filter((_,idx) => idx !== i) }))}
style={{ padding:”4px 10px”, background:”transparent”, color:TAUPE, border:`1px solid ${SAND}`, cursor:”pointer”, fontFamily:”‘Roboto Serif’,serif”, fontSize:”9px”, letterSpacing:”1px”, textTransform:”uppercase”, borderRadius:”2px” }}>
Remove
)}
setArr(“away_items”,i,”image”,v)} />
setArr(“away_items”,i,”label”,v)} />
setArr(“away_items”,i,”title”,v)} />
setArr(“away_items”,i,”body”,v)} type=”textarea” rows={3} />
setArr(“away_items”,i,”code”,v)} />
setArr(“away_items”,i,”link”,v)} />
))}
;
case “scene”: return
Scene on the Coast
For Platform field type instagram or tiktok .
{data.scene_items.map((item,i) =>
setArr(“scene_items”,i,f,v)} />)}
;
case “shop”: return
Coastal NECCessities
set(“shop_link”,v)} />
{data.shop_items.map((item,i) => setArr(“shop_items”,i,f,v)} />)}
;
case “footer”: return
Footer & Social Links
set(“instagram_link”,v)} />
set(“ltk_link”,v)} />
set(“shopmy_link”,v)} />
set(“substack_link”,v)} />
set(“address”,v)} type=”textarea” rows={2} />
set(“unsubscribe_link”,v)} />
;
default: return null;
}
};
return (
CURRENTS
Newsletter Builder
{SECTIONS.map(s => (
setActiveSection(s.id)} style={{
display:”block”, width:”100%”, textAlign:”left”, padding:”10px 20px”,
fontFamily:”‘Roboto Serif’,serif”, fontSize:”11px”,
fontWeight: activeSection === s.id ? 600 : 400,
color: s.id===”output” ? (activeSection===s.id ? “#fff” : SAND) : activeSection===s.id ? “#fff” : “rgba(200,184,154,0.7)”,
background: activeSection===s.id ? “rgba(107,147,178,0.3)” : “transparent”,
border:”none”, cursor:”pointer”,
borderLeft: activeSection===s.id ? `3px solid ${COASTAL_BLUE}` : “3px solid transparent”,
borderTop: s.id===”output” ? “1px solid rgba(200,184,154,0.2)” : “none”,
marginTop: s.id===”output” ? “8px” : 0,
}}>{s.label}
))}
Generate HTML →
{renderSection()}
{activeSection !== “output” && (
Generate Newsletter HTML →
Fill in all sections then generate. The HTML will appear for you to copy into Flodesk or Mailchimp.
)}
);
}