Skip to content

Add monthly newsletter page#4082

Draft
ewels wants to merge 57 commits intomainfrom
claude/nf-core-newsletter-page-XyTgs
Draft

Add monthly newsletter page#4082
ewels wants to merge 57 commits intomainfrom
claude/nf-core-newsletter-page-XyTgs

Conversation

@ewels
Copy link
Member

@ewels ewels commented Mar 23, 2026

Create a newsletter page at /newsletter/[year]/[month] that aggregates
monthly community content for email distribution:

  • Events this month + upcoming events (next 2 months)
  • Blog posts this month + "in case you missed it" (past 2 months)
  • Pipeline releases with highlighted first releases
  • New pipeline repositories and approved proposals from nf-core/proposals

Uses email-friendly HTML (table-based layout, inline styles, 600px max-width)
inside a #newsletter-content div for easy extraction. Month/year selector
navigation sits outside this div.

https://claude.ai/code/session_01DHK3ARtaSYevNH85QYBDBD

@netlify /newsletter

Create a newsletter page at /newsletter/[year]/[month] that aggregates
monthly community content for email distribution:

- Events this month + upcoming events (next 2 months)
- Blog posts this month + "in case you missed it" (past 2 months)
- Pipeline releases with highlighted first releases
- New pipeline repositories and approved proposals from nf-core/proposals

Uses email-friendly HTML (table-based layout, inline styles, 600px max-width)
inside a #newsletter-content div for easy extraction. Month/year selector
navigation sits outside this div.

https://claude.ai/code/session_01DHK3ARtaSYevNH85QYBDBD
@netlify
Copy link

netlify bot commented Mar 23, 2026

Deploy Preview for nf-core-main-site ready!

Name Link
🔨 Latest commit 8855524
🔍 Latest deploy log https://app.netlify.com/projects/nf-core-main-site/deploys/69c314bb1fdc430008050ea7
😎 Deploy Preview https://deploy-preview-4082--nf-core-main-site.netlify.app/newsletter
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions bot deleted a comment from netlify bot Mar 23, 2026
@ewels ewels marked this pull request as draft March 23, 2026 11:45
@ewels
Copy link
Member Author

ewels commented Mar 23, 2026

@nf-core-bot fix linting

return `/newsletter/${m.year}/${String(m.month).padStart(2, "0")}`;
}

function blogUrl(postId: string): string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you get that through content collections already I think

claude and others added 22 commits March 23, 2026 12:19
- Reorder events: upcoming events (next 2 months) is now the primary
  section, events this month shown smaller as secondary
- Add nf-core/newsletter logo PNG generated from old-site base
  templates (light + dark background versions)
- Force white background on #newsletter-content div so it's always
  readable regardless of web dark mode or email client dark mode
- Logo displayed at top of newsletter using the light background variant

https://claude.ai/code/session_01DHK3ARtaSYevNH85QYBDBD
- Add @media (prefers-color-scheme: dark) overrides for Apple Mail,
  Outlook Mac, and web browsers
- Add [data-ogsc] selectors for Outlook iOS/Android apps
- Swap logo images: light bg logo by default, dark bg logo in dark mode
- Add nl-muted CSS class to secondary text elements for dark mode
  targeting with !important overrides over inline styles
- Light mode inline styles serve as fallback for Gmail and other
  clients that strip <style> blocks

https://claude.ai/code/session_01DHK3ARtaSYevNH85QYBDBD
Fetch logos from https://oldsite.nf-co.re/logo?t=newsletter
instead of generating locally with incorrect font sizes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…heme

The nf-core site uses Bootstrap's data-bs-theme attribute on <html>
toggled via ThemeSwitch.svelte, not @media (prefers-color-scheme).
The newsletter CSS was using the wrong selector, causing it to
respond to OS dark mode setting instead of the site's theme toggle.

Now uses :global([data-bs-theme="dark"]) for the web page, while
keeping @media (prefers-color-scheme: dark) and [data-ogsc] for
email client dark mode support.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The data-bs-theme dark mode rules need !important to beat inline
styles, and child class selectors (.nl-logo-light, .nl-logo-dark,
.nl-muted) need :global() wrappers to prevent Astro from scoping
them with hash attributes.

Tested locally with dev server in both light and dark modes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Multiple releases of the same pipeline in a month (e.g. pixelator
v3.0.0 and v3.0.1) are now shown as a single row with multiple
version badges, using the most recent release date.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Split proposals into "Pipeline Proposals" (strip "New pipeline:"
  prefix) and "Other Proposals" (RFCs, SIGs, etc. keep their prefix)
- Show status badges: "Accepted" (green) for closed issues,
  "New" (blue) for issues opened that month
- Include both newly opened and closed/accepted issues for the month
- Sort accepted proposals first within each group

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…erImage

Layout changes:
- Widen email from 600px to 800px
- Primary content (upcoming events, blog posts, first releases) is full-width
- Secondary content (this month's events, older blogs, pipeline releases,
  proposals) uses 2-column table layout for visual hierarchy
- Blog posts show header images with clickable links

Blog images:
- Make headerImage and headerImageAlt required in blog content schema
- Add headerImage to the one blog post missing it (2020/data_management.md)
- Add blogImageUrl() helper for unsplash size params

Other fixes:
- Sort release tags ascending (left to right) so latest tag + date are adjacent

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reorder sections to: blog posts, first releases, pipeline releases,
upcoming events, events this month, older blog posts, pipelines &
proposals.

Add missing headerImage + headerImageAlt to:
- 2025/paper-v2.mdx
- 2026/configs-strict-syntax.mdx
- 2026/statement-on-ai.mdx

These were failing the build after headerImage was made required.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add optional headerImage/headerImageAlt fields to events schema
- Events with headerImage show it in the newsletter's upcoming events
- Events without headerImage fall back to the dynamic OG social card
- Add headerImage to hackathon-boston event using existing summit card

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove OG social card fallback for events without a headerImage.
Events without an explicit headerImage just show text, no image.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Local /assets/ paths don't exist as-is on the deployed site — they
get processed through Astro's build pipeline into /_astro/ URLs.
Use import.meta.glob to resolve the built URLs, matching how the
blog page handles headerImage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The newsletter is at src/pages/newsletter/[year]/[month].astro (4
levels deep from src/), not 2 like the blog page. Fix the relative
glob path and key prefix accordingly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Glob-resolved assets return relative paths (/_astro/...) that work
on any domain. Remove the nf-co.re fallback which broke deploy
previews and hit the /assets/* → oldsite redirect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The glob returns lazy loaders that need await, which can't be done
in the template. Pre-resolve all blog and event image URLs into
Maps during frontmatter execution, then look them up synchronously
in the template.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tended

In light mode, most links are dark (#333/#555) with only a few
accent links in green. The dark mode was turning ALL links green
via the blanket `a { color: #4ade80 }` rule.

Now dark mode links default to light text (#e0e0e0) matching the
body, with green reserved for elements that use the `nl-green`
class: first-release pipeline names, proposals link, and footer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Make "Events That Happened This Month" and "In Case You Missed It"
  headings green (h2 style) so they stand out from list content
- Upcoming events: 2-column layout with title left, date + tag
  right-aligned; full-width header image above when present
- Switch to Astro <Image> component for blog and event images
  to get proper asset pipeline URLs (.netlify/images)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The relative ../../../../assets/** glob wasn't resolving correctly.
Use Vite's root-relative /src/assets/** pattern instead, which
reliably resolves regardless of file depth.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GitHub Issues have a state_reason field: "completed" or "not_planned".
Only proposals closed as "completed" should appear as "Accepted" in
the newsletter. Rejected proposals (closed as "not_planned") are
now excluded entirely.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bump Image width to 1600px (covers 800px container at 2x) and add
densities=[1.5, 2] for srcset. The CSS max-height and object-fit
still control the visual size.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ewels and others added 30 commits March 24, 2026 11:00
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use fixed dimensions with object-fit: cover instead of height: auto
to ensure all images display at a consistent 16:9 landscape ratio
regardless of the original image orientation.

- Primary images: 240x135px
- Thumbnails: 80x45px

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gmail shows ~90 chars of preview text in the inbox list. Add a
concise summary (e.g. "1 blog post, 7 pipeline releases, 1
upcoming event, 5 events this month.") as the first text in the
newsletter, followed by a "View in browser" link.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Newsletter now assumes posture of being sent at start of its month,
looking back at the previous month's content. Blog posts, releases,
events, and proposals all come from month-1. Upcoming events show
the reader's current month + next. "Events that happened this month"
merged into "In case you missed it" as "Recent events" subsection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…in header

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…log images

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, subtitle below

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…width

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move border-bottom from table to td elements so the existing dark mode
CSS rule (#newsletter-content td border-bottom-color) applies correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Applies to pipeline releases, recent events, older blog posts,
and proposals sections.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add advisories section to newsletter (after blog posts, with severity badges)
- Add RSS feed at /newsletter/rss.xml with per-month content summaries
- Add bare HTML email version at /newsletter/[year]/[month]/email
- Add Newsletter link to Community dropdown nav after Blog
- Extract newsletter content into shared NewsletterContent.astro component
- Extract shared data-fetching helpers (getNewsletterStaticPathsData,
  getNewsletterContentData) to avoid duplication between web and email pages
- Fix pre-existing TS errors in fetchAllProposals (octokit.paginate typing,
  Proposal vs RawProposal return type)
- Add newsletter RSS <link> tag in BaseHead for newsletter pages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Astro hoists getStaticPaths and may not have access to module-level
variables declared outside it during the build. Declare pipelines
inside getStaticPaths and again in the per-page section.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add getAdvisoriesForPreviousMonths() helper for past 2 months
- Add olderAdvisories to newsletter content data
- Remove 'Recent events', 'Older blog posts' subheadings from ICYMI section
- Add older advisories 2-column list below older blog posts in ICYMI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add responsive 2-column layout: @media query stacks .nl-col cells
  on narrow screens (<600px) for mobile email clients
- Add role="presentation" to all layout tables for accessibility
- Add aria-label to image-only links
- Fix email page body styles (margin: 0; padding: 0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace table-cell 2-column layout with inline-block divs that
naturally stack on narrow screens without @media queries. Each column
uses display: inline-block; width: 100%; max-width: 50% — on wide
screens two fit side-by-side, on narrow screens they wrap to full
width. @media query kept as enhancement for supporting clients.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Astro <Image> component routes through Netlify's image service
(/.netlify/images?url=...) which produces relative URLs that break
in email clients. Replace all <Image> with plain <img> tags using the
asset's .src property directly, which is already absolute thanks to
Astro's assetsPrefix config. All images now render consistently —
same approach as the logo images which already worked.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move getAdvisoryBadgeColors() calls and regex-based URL construction
out of JSX template literals into map callback variables. The complex
expressions (function().property and regex) inside template literals
inside JSX attributes confused esbuild's parser.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace table-cell 2-column with standalone div containers using
inline-block + max-width: 50%. Stacks naturally on narrow screens
without @media queries (Gmail compatible). Previous attempt using
divs inside tables caused esbuild parse errors in Astro compilation.

Also replaces <Image> with plain <img> for consistent absolute URLs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add div to dark mode border-bottom-color rules alongside td, since
the fluid hybrid 2-column sections now use div instead of td.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace aria-label with meaningful alt text on img tags (email
  clients don't support aria-label, but alt text counts as link text)
- Add explicit height attribute to event images

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reduce max-width from 50% to 49% to create visible spacing between
side-by-side columns, separating the divider lines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The @media query needs both max-width: 100% (to override inline 49%)
and display: block (to force stacking). Also use #newsletter-content
.nl-col selector in email page for specificity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace table layout with inline-block divs for blog posts. Text
block uses max-width: calc(100% - 256px) so the image naturally
wraps below on narrow screens without media queries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use inline-block divs with max-width instead of fixed width for blog
post text/image columns. Add nl-blog-text and nl-blog-img classes to
@media query for stacking on narrow screens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants