Skip to content

Comments

feat: implement newsletter page with localization and subscription form#280

Merged
danielmarv merged 1 commit intonext-js-migrationfrom
239-newsletter-page-rendering-and-functionality
Feb 20, 2026
Merged

feat: implement newsletter page with localization and subscription form#280
danielmarv merged 1 commit intonext-js-migrationfrom
239-newsletter-page-rendering-and-functionality

Conversation

@danielmarv
Copy link
Member

This pull request introduces a new localized newsletter signup page available only in German and implements a custom newsletter signup form using the Brevo (formerly Sendinblue) platform. The changes include both the new page logic and a dedicated React component for rendering and integrating the Brevo form, along with required scripts and styling.

The most important changes are:

Newsletter Signup Page Implementation

  • Added a new page at src/app/[locale]/newsletter/page.tsx that displays the newsletter signup form. The page is only available for the 'de' (German) locale; for all other locales, it returns a not found response. The page also generates locale-specific metadata for SEO and social sharing. (src/app/[locale]/newsletter/page.tsxR1-R96)

Newsletter Form Integration

  • Introduced a new React component NewsletterForm in src/components/newsletter/NewsletterForm.tsx that renders the Brevo subscription form using raw HTML, includes required Brevo styles and scripts, and initializes the Brevo SDK for form handling and analytics. The form and all messages are fully localized in German.

Documentation Update

  • Updated the README.md to remove the obsolete src/layouts entry, reflecting the removal of legacy Hugo templates.

@danielmarv danielmarv self-assigned this Feb 19, 2026
Copilot AI review requested due to automatic review settings February 19, 2026 11:02
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request introduces a German-only newsletter signup page using Brevo (formerly Sendinblue) for newsletter management. The implementation includes locale-specific access control, SEO metadata, and a custom React component that integrates the Brevo subscription form.

Changes:

  • Added a new /newsletter page that is only accessible in German locale and returns a 404 for other locales
  • Created a NewsletterForm component that renders a Brevo subscription form with embedded HTML, styles, and scripts
  • Removed an obsolete reference to src/layouts from the README

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 12 comments.

File Description
src/app/[locale]/newsletter/page.tsx New page component implementing locale-restricted newsletter signup with metadata generation and page layout
src/components/newsletter/NewsletterForm.tsx Client-side component integrating Brevo subscription form with hardcoded HTML, inline styles, and third-party scripts
README.md Documentation cleanup removing reference to legacy Hugo templates directory

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

for="VORNAME">Gib dein(e) VORNAME ein</label>
<div class="entry__field">
<input class="input" maxlength="200" type="text" id="VORNAME" name="VORNAME"
autocomplete="off" placeholder="VORNAME" />
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The placeholder "VORNAME" is in all caps, which is typically used for field names in databases, not user-facing text. Consider using a more user-friendly placeholder like "Dein Vorname" or an example name like "Max".

Suggested change
autocomplete="off" placeholder="VORNAME" />
autocomplete="off" placeholder="Dein Vorname" />

Copilot uses AI. Check for mistakes.
<div class="form__label-row ">
<label class="entry__label"
style="font-weight: 700; text-align:left; font-size:16px; font-family:Helvetica, sans-serif; color:#3c4858;"
for="NACHNAME">Gib dein(e) NACHNAME ein</label>
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

Similar to the first name field, the label text "Gib dein(e) NACHNAME ein" is awkward. Consider changing to something like "Nachname" for the label, which is more natural German.

Suggested change
for="NACHNAME">Gib dein(e) NACHNAME ein</label>
for="NACHNAME">Nachname</label>

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +53
<input class="input" maxlength="200" type="text" id="VORNAME" name="VORNAME"
autocomplete="off" placeholder="VORNAME" />
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The autocomplete attribute is set to "off" which prevents browsers from helping users autofill their names. Consider removing this attribute or using appropriate autocomplete values like "given-name" for first name and "family-name" for last name to improve user experience and accessibility.

Copilot uses AI. Check for mistakes.
for="NACHNAME">Gib dein(e) NACHNAME ein</label>
<div class="entry__field">
<input class="input" maxlength="200" type="text" id="NACHNAME" name="NACHNAME"
autocomplete="off" placeholder="NACHNAME" />
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The autocomplete attribute is set to "off" which prevents browsers from helping users autofill their last name. Consider removing this attribute or using "family-name" for the autocomplete value to improve user experience and accessibility.

Suggested change
autocomplete="off" placeholder="NACHNAME" />
autocomplete="family-name" placeholder="NACHNAME" />

Copilot uses AI. Check for mistakes.
style="font-weight: 700; text-align:left; font-size:16px; font-family:Helvetica, sans-serif; color:#3c4858;"
for="EMAIL" data-required="*">Gib deine E-Mail-Adresse ein, um dich anzumelden</label>
<div class="entry__field">
<input class="input" type="text" id="EMAIL" name="EMAIL" autocomplete="off"
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The email input field has type="text" instead of type="email". Using type="email" would provide better validation, show an appropriate keyboard on mobile devices, and improve accessibility. The Brevo form validation script may handle this, but using the correct input type is a best practice.

Suggested change
<input class="input" type="text" id="EMAIL" name="EMAIL" autocomplete="off"
<input class="input" type="email" id="EMAIL" name="EMAIL" autocomplete="off"

Copilot uses AI. Check for mistakes.
for="EMAIL" data-required="*">Gib deine E-Mail-Adresse ein, um dich anzumelden</label>
<div class="entry__field">
<input class="input" type="text" id="EMAIL" name="EMAIL" autocomplete="off"
placeholder="EMAIL" data-required="true" required />
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The placeholder "EMAIL" is in all caps. Consider using a more user-friendly placeholder like "deine@email.de" or "max@beispiel.de" to show the expected format.

Suggested change
placeholder="EMAIL" data-required="true" required />
placeholder="deine@email.de" data-required="true" required />

Copilot uses AI. Check for mistakes.
{/* Brevo SDK init */}
<Script id="brevo-sdk-init" strategy="afterInteractive">{`
window.Brevo = window.Brevo || [];
Brevo.push(["init", { client_key: "v3lh6minrpfap69vhy5am8if" }]);
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The Brevo client key "v3lh6minrpfap69vhy5am8if" is hardcoded in the component. While this is a public client-side key that's expected to be visible, consider using an environment variable like NEXT_PUBLIC_BREVO_CLIENT_KEY for better configuration management and to follow the pattern established elsewhere in the codebase (see src/app/sitemap.xml/route.ts:5).

Copilot uses AI. Check for mistakes.
style="font-weight: 700; text-align:left; font-size:16px; font-family:Helvetica, sans-serif; color:#3c4858;"
for="EMAIL" data-required="*">Gib deine E-Mail-Adresse ein, um dich anzumelden</label>
<div class="entry__field">
<input class="input" type="text" id="EMAIL" name="EMAIL" autocomplete="off"
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The autocomplete attribute is set to "off" for the email field. Consider using "email" as the autocomplete value instead to help users autofill their email address, improving both user experience and accessibility.

Suggested change
<input class="input" type="text" id="EMAIL" name="EMAIL" autocomplete="off"
<input class="input" type="text" id="EMAIL" name="EMAIL" autocomplete="email"

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +96
export default async function NewsletterPage({ params }: NewsletterPageProps) {
const { locale } = await params

if (locale !== 'de') {
notFound()
}

return (
<div>
{/* Hero background */}
<div className="absolute left-0 w-full top-0 h-48 -z-10 overflow-hidden">
<Image
src="/illustrations/hero-bg-2.svg"
alt="Hero background"
fill
className="object-cover"
priority
/>
</div>

<div className="container max-w-sm lg:max-w-7xl md:max-w-2xl sm:max-w-xl sm:w-full">
{/* Page title */}
<div className="flex items-center justify-center pt-16 pb-4 sm:pt-36 sm:pb-12">
<div className="relative flex flex-col items-center justify-center w-full">
<h1 className="text-center h1">Unser Newsletter</h1>
<Image
src="/illustrations/underline.svg"
alt="Unterstrich"
width={288}
height={24}
className="absolute w-36 -bottom-3 sm:w-56 shrink-0"
/>
</div>
</div>
</div>

{/* Form section */}
<div className="lg:pb-48 sm:pb-32 pb-28">
<div className="container mt-12 xl:max-w-1xl">
<div className="flex flex-col items-center justify-center gap-8">
<p className="text-center text-blue max-w-xl text-lg">
Bleib auf dem Laufenden über Open Source, Java und die neuesten Nachrichten von Open Elements.
</p>
<NewsletterForm />
</div>
</div>
</div>
</div>
)
}
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The new newsletter page lacks test coverage. The codebase has comprehensive Playwright tests for other pages (see tests/e2e/support-care.spec.ts as an example). Consider adding a test file tests/e2e/newsletter.spec.ts that verifies the page loads correctly for the 'de' locale and returns a 404 for other locales.

Copilot uses AI. Check for mistakes.
Comment on lines +193 to +194
{/* eslint-disable-next-line @next/next/no-css-tags */}
<link rel="stylesheet" href="https://sibforms.com/forms/end-form/build/sib-styles.css" />
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

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

The external CSS is loaded using a link tag which is disabled from the ESLint no-css-tags rule. While this works, consider whether the styles could be imported through Next.js's built-in CSS handling or if this external stylesheet could be loaded via the head in _document.tsx or through next/head. However, given this is a third-party form integration, the current approach may be acceptable if alternative methods don't work with the Brevo form.

Copilot uses AI. Check for mistakes.
@danielmarv danielmarv merged commit f7b0e9f into next-js-migration Feb 20, 2026
7 of 8 checks passed
@github-project-automation github-project-automation bot moved this from Backlog to Done in Migration to NextJS Feb 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant