Newsletter - #63

Merged
Darkest-Teddy merged 3 commits into
mainfrom
newsletter
Apr 20, 2026
Merged

Newsletter#63
Darkest-Teddy merged 3 commits into
mainfrom
newsletter

Conversation

@Darkest-Teddy

@Darkest-TeddyDarkest-Teddy commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a newsletter/beta waitlist signup modal to the landing page. Users can enter their email to get early access and receive the Sapling newsletter. Emails are stored in Supabase and deduplicated on insert. The modal features entrance/exit animations, a success state that auto-dismisses after 3.2 seconds, and body scroll lock while open.

Changes Made

  • Added a two-panel newsletter signup modal to page.tsx with animated open/close transitions and a compact auto-dismissing success popup
  • Added modal animation keyframes (modal-backdrop-in/out, modal-card-in/out) to globals.css
  • Fixed Playfair Display italic and extended weight loading in layout.tsx
  • Added backend/routes/newsletter.pyPOST /api/newsletter/subscribe endpoint that upserts emails into a newsletter_emails Supabase table with TLD validation
  • Registered the newsletter router in main.py under /api/newsletter
  • Added email-validator to requirements.txt
  • Added backend/db/migration_newsletter.sql to create the newsletter_emails table

Related Issues

Closes #

Testing

  • Run migration_newsletter.sql in Supabase SQL Editor before deploying
  • Tested locally — valid email returns {"ok": true}, missing TLD returns 422
  • Frontend validates email format client-side before hitting the backend
  • Emails show up in newsletters_emails table on Supabase

Notes for Reviewers

The newsletter_emails table migration must be applied to Supabase before the backend route will work. See backend/db/migration_newsletter.sql.

Summary by CodeRabbit

  • New Features

    • Added "Sign up for Beta Testing" button on the landing page.
    • Introduced a newsletter signup modal with email validation, submit flow, and success confirmation.
    • Modal disables page scrolling while open and auto-closes after successful submission.
  • Style

    • Added smooth fade, scale and translate animations for modal backdrop and card on enter/exit.

@coderabbitai

coderabbitaiBot commented Apr 20, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 180da33f-e2f3-4dd8-bc9e-e5d09794ff81

📥 Commits

Reviewing files that changed from the base of the PR and between bdd4c96 and db6f4d9.

📒 Files selected for processing (1)
  • frontend/src/app/page.tsx

📝 Walkthrough

Walkthrough

Adds CSS keyframe animations for a newsletter modal, extends Playfair_Display font weights/styles, and implements a landing-page beta newsletter signup modal with state, lifecycle effects (auto-close, closing delay, body scroll lock), basic email validation, and POST submission to the newsletter API.

Changes

Cohort / File(s)Summary
Modal Animations
frontend/src/app/globals.css
Added four CSS keyframes (modal-backdrop-in, modal-backdrop-out, modal-card-in, modal-card-out) and corresponding utility classes to orchestrate modal enter/exit transitions (opacity, scale, translateY) with specific timings and easings.
Font Configuration
frontend/src/app/layout.tsx
Extended Playfair_Display font configuration to explicitly include weights 400–900 (excluding 300) and both normal and italic styles.
Newsletter Modal Feature
frontend/src/app/page.tsx
Added beta newsletter modal: state variables (betaModalOpen, betaModalClosing, betaEmail, betaEmailError, betaSubmitted, betaSubmitting), close-delay and auto-close effects, body scroll lock while open, hero CTA to open modal, conditional render for form vs success, client-side email validation, and POST to ${API_URL}/api/newsletter/subscribe.

Sequence Diagram(s)

sequenceDiagram
actor User
participant Landing as Frontend (page.tsx)
participant Modal as Modal UI
participant API as Backend API
User->>Landing: Click "Sign up for Beta"
Landing->>Landing: set betaModalOpen = true
Landing->>Landing: disable body scroll
Landing->>Modal: render email form
User->>Modal: Enter email & submit
Modal->>Landing: submit handler
Landing->>Landing: validate email
alt invalid
Landing->>Modal: set betaEmailError (show error)
else valid
Landing->>Landing: set betaSubmitting = true
Landing->>API: POST { email } to /api/newsletter/subscribe
API-->>Landing: response (errors swallowed)
Landing->>Landing: set betaSubmitted = true
Landing->>Modal: render success UI
Landing->>Landing: schedule auto-close (3200ms)
end
Landing->>Landing: closeModal triggered
Landing->>Landing: set betaModalClosing = true
Landing->>Landing: wait 200ms, then reset state
Landing->>Landing: re-enable body scroll
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A modal flutters in with charm,
Backdrop fades and card grows warm,
I nibble keys and validate,
A signup hops to celebrate,
Success — the newsletter's a cheerful swarm 📧

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check❓ InconclusiveThe title 'Newsletter' is partially related to the changeset but is overly broad and lacks specificity about the main change.Use a more specific title that captures the primary change, such as 'Add newsletter signup modal to landing page' or 'Implement beta waitlist signup functionality'.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe description is comprehensive and follows the template structure with all major sections completed, including description, changes made, testing, and notes for reviewers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch newsletter

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment threadfrontend/src/app/page.tsx Outdated
import { useRouter } from 'next/navigation';
import { useUser } from '@/context/UserContext';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare } from 'lucide-react';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare, Bell, Map, Shield } from 'lucide-react';
…tion or class'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:db6f4d9
Status:⚡️ Build in progress...

View logs

@Darkest-Teddy
Darkest-Teddy merged commit 08da3f3 into mainApr 20, 2026
2 of 3 checks passed
Sign up for freeto 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.

1 participant

@Darkest-Teddy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Newsletter - #63

Merged
Darkest-Teddy merged 3 commits into
mainfrom
newsletter
Apr 20, 2026
Merged

Newsletter#63
Darkest-Teddy merged 3 commits into
mainfrom
newsletter

Conversation

@Darkest-Teddy

@Darkest-TeddyDarkest-Teddy commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a newsletter/beta waitlist signup modal to the landing page. Users can enter their email to get early access and receive the Sapling newsletter. Emails are stored in Supabase and deduplicated on insert. The modal features entrance/exit animations, a success state that auto-dismisses after 3.2 seconds, and body scroll lock while open.

Changes Made

  • Added a two-panel newsletter signup modal to page.tsx with animated open/close transitions and a compact auto-dismissing success popup
  • Added modal animation keyframes (modal-backdrop-in/out, modal-card-in/out) to globals.css
  • Fixed Playfair Display italic and extended weight loading in layout.tsx
  • Added backend/routes/newsletter.pyPOST /api/newsletter/subscribe endpoint that upserts emails into a newsletter_emails Supabase table with TLD validation
  • Registered the newsletter router in main.py under /api/newsletter
  • Added email-validator to requirements.txt
  • Added backend/db/migration_newsletter.sql to create the newsletter_emails table

Related Issues

Closes #

Testing

  • Run migration_newsletter.sql in Supabase SQL Editor before deploying
  • Tested locally — valid email returns {"ok": true}, missing TLD returns 422
  • Frontend validates email format client-side before hitting the backend
  • Emails show up in newsletters_emails table on Supabase

Notes for Reviewers

The newsletter_emails table migration must be applied to Supabase before the backend route will work. See backend/db/migration_newsletter.sql.

Summary by CodeRabbit

  • New Features

    • Added "Sign up for Beta Testing" button on the landing page.
    • Introduced a newsletter signup modal with email validation, submit flow, and success confirmation.
    • Modal disables page scrolling while open and auto-closes after successful submission.
  • Style

    • Added smooth fade, scale and translate animations for modal backdrop and card on enter/exit.

@coderabbitai

coderabbitaiBot commented Apr 20, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 180da33f-e2f3-4dd8-bc9e-e5d09794ff81

📥 Commits

Reviewing files that changed from the base of the PR and between bdd4c96 and db6f4d9.

📒 Files selected for processing (1)
  • frontend/src/app/page.tsx

📝 Walkthrough

Walkthrough

Adds CSS keyframe animations for a newsletter modal, extends Playfair_Display font weights/styles, and implements a landing-page beta newsletter signup modal with state, lifecycle effects (auto-close, closing delay, body scroll lock), basic email validation, and POST submission to the newsletter API.

Changes

Cohort / File(s)Summary
Modal Animations
frontend/src/app/globals.css
Added four CSS keyframes (modal-backdrop-in, modal-backdrop-out, modal-card-in, modal-card-out) and corresponding utility classes to orchestrate modal enter/exit transitions (opacity, scale, translateY) with specific timings and easings.
Font Configuration
frontend/src/app/layout.tsx
Extended Playfair_Display font configuration to explicitly include weights 400–900 (excluding 300) and both normal and italic styles.
Newsletter Modal Feature
frontend/src/app/page.tsx
Added beta newsletter modal: state variables (betaModalOpen, betaModalClosing, betaEmail, betaEmailError, betaSubmitted, betaSubmitting), close-delay and auto-close effects, body scroll lock while open, hero CTA to open modal, conditional render for form vs success, client-side email validation, and POST to ${API_URL}/api/newsletter/subscribe.

Sequence Diagram(s)

sequenceDiagram
actor User
participant Landing as Frontend (page.tsx)
participant Modal as Modal UI
participant API as Backend API
User->>Landing: Click "Sign up for Beta"
Landing->>Landing: set betaModalOpen = true
Landing->>Landing: disable body scroll
Landing->>Modal: render email form
User->>Modal: Enter email & submit
Modal->>Landing: submit handler
Landing->>Landing: validate email
alt invalid
Landing->>Modal: set betaEmailError (show error)
else valid
Landing->>Landing: set betaSubmitting = true
Landing->>API: POST { email } to /api/newsletter/subscribe
API-->>Landing: response (errors swallowed)
Landing->>Landing: set betaSubmitted = true
Landing->>Modal: render success UI
Landing->>Landing: schedule auto-close (3200ms)
end
Landing->>Landing: closeModal triggered
Landing->>Landing: set betaModalClosing = true
Landing->>Landing: wait 200ms, then reset state
Landing->>Landing: re-enable body scroll
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A modal flutters in with charm,
Backdrop fades and card grows warm,
I nibble keys and validate,
A signup hops to celebrate,
Success — the newsletter's a cheerful swarm 📧

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check❓ InconclusiveThe title 'Newsletter' is partially related to the changeset but is overly broad and lacks specificity about the main change.Use a more specific title that captures the primary change, such as 'Add newsletter signup modal to landing page' or 'Implement beta waitlist signup functionality'.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe description is comprehensive and follows the template structure with all major sections completed, including description, changes made, testing, and notes for reviewers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch newsletter

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment threadfrontend/src/app/page.tsx Outdated
import { useRouter } from 'next/navigation';
import { useUser } from '@/context/UserContext';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare } from 'lucide-react';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare, Bell, Map, Shield } from 'lucide-react';
…tion or class'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:db6f4d9
Status:⚡️ Build in progress...

View logs

@Darkest-Teddy
Darkest-Teddy merged commit 08da3f3 into mainApr 20, 2026
2 of 3 checks passed
Sign up for freeto 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.

1 participant

@Darkest-Teddy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Newsletter - #63

Merged
Darkest-Teddy merged 3 commits into
mainfrom
newsletter
Apr 20, 2026
Merged

Newsletter#63
Darkest-Teddy merged 3 commits into
mainfrom
newsletter

Conversation

@Darkest-Teddy

@Darkest-TeddyDarkest-Teddy commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a newsletter/beta waitlist signup modal to the landing page. Users can enter their email to get early access and receive the Sapling newsletter. Emails are stored in Supabase and deduplicated on insert. The modal features entrance/exit animations, a success state that auto-dismisses after 3.2 seconds, and body scroll lock while open.

Changes Made

  • Added a two-panel newsletter signup modal to page.tsx with animated open/close transitions and a compact auto-dismissing success popup
  • Added modal animation keyframes (modal-backdrop-in/out, modal-card-in/out) to globals.css
  • Fixed Playfair Display italic and extended weight loading in layout.tsx
  • Added backend/routes/newsletter.pyPOST /api/newsletter/subscribe endpoint that upserts emails into a newsletter_emails Supabase table with TLD validation
  • Registered the newsletter router in main.py under /api/newsletter
  • Added email-validator to requirements.txt
  • Added backend/db/migration_newsletter.sql to create the newsletter_emails table

Related Issues

Closes #

Testing

  • Run migration_newsletter.sql in Supabase SQL Editor before deploying
  • Tested locally — valid email returns {"ok": true}, missing TLD returns 422
  • Frontend validates email format client-side before hitting the backend
  • Emails show up in newsletters_emails table on Supabase

Notes for Reviewers

The newsletter_emails table migration must be applied to Supabase before the backend route will work. See backend/db/migration_newsletter.sql.

Summary by CodeRabbit

  • New Features

    • Added "Sign up for Beta Testing" button on the landing page.
    • Introduced a newsletter signup modal with email validation, submit flow, and success confirmation.
    • Modal disables page scrolling while open and auto-closes after successful submission.
  • Style

    • Added smooth fade, scale and translate animations for modal backdrop and card on enter/exit.

@coderabbitai

coderabbitaiBot commented Apr 20, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 180da33f-e2f3-4dd8-bc9e-e5d09794ff81

📥 Commits

Reviewing files that changed from the base of the PR and between bdd4c96 and db6f4d9.

📒 Files selected for processing (1)
  • frontend/src/app/page.tsx

📝 Walkthrough

Walkthrough

Adds CSS keyframe animations for a newsletter modal, extends Playfair_Display font weights/styles, and implements a landing-page beta newsletter signup modal with state, lifecycle effects (auto-close, closing delay, body scroll lock), basic email validation, and POST submission to the newsletter API.

Changes

Cohort / File(s)Summary
Modal Animations
frontend/src/app/globals.css
Added four CSS keyframes (modal-backdrop-in, modal-backdrop-out, modal-card-in, modal-card-out) and corresponding utility classes to orchestrate modal enter/exit transitions (opacity, scale, translateY) with specific timings and easings.
Font Configuration
frontend/src/app/layout.tsx
Extended Playfair_Display font configuration to explicitly include weights 400–900 (excluding 300) and both normal and italic styles.
Newsletter Modal Feature
frontend/src/app/page.tsx
Added beta newsletter modal: state variables (betaModalOpen, betaModalClosing, betaEmail, betaEmailError, betaSubmitted, betaSubmitting), close-delay and auto-close effects, body scroll lock while open, hero CTA to open modal, conditional render for form vs success, client-side email validation, and POST to ${API_URL}/api/newsletter/subscribe.

Sequence Diagram(s)

sequenceDiagram
actor User
participant Landing as Frontend (page.tsx)
participant Modal as Modal UI
participant API as Backend API
User->>Landing: Click "Sign up for Beta"
Landing->>Landing: set betaModalOpen = true
Landing->>Landing: disable body scroll
Landing->>Modal: render email form
User->>Modal: Enter email & submit
Modal->>Landing: submit handler
Landing->>Landing: validate email
alt invalid
Landing->>Modal: set betaEmailError (show error)
else valid
Landing->>Landing: set betaSubmitting = true
Landing->>API: POST { email } to /api/newsletter/subscribe
API-->>Landing: response (errors swallowed)
Landing->>Landing: set betaSubmitted = true
Landing->>Modal: render success UI
Landing->>Landing: schedule auto-close (3200ms)
end
Landing->>Landing: closeModal triggered
Landing->>Landing: set betaModalClosing = true
Landing->>Landing: wait 200ms, then reset state
Landing->>Landing: re-enable body scroll
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A modal flutters in with charm,
Backdrop fades and card grows warm,
I nibble keys and validate,
A signup hops to celebrate,
Success — the newsletter's a cheerful swarm 📧

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check❓ InconclusiveThe title 'Newsletter' is partially related to the changeset but is overly broad and lacks specificity about the main change.Use a more specific title that captures the primary change, such as 'Add newsletter signup modal to landing page' or 'Implement beta waitlist signup functionality'.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe description is comprehensive and follows the template structure with all major sections completed, including description, changes made, testing, and notes for reviewers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch newsletter

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment threadfrontend/src/app/page.tsx Outdated
import { useRouter } from 'next/navigation';
import { useUser } from '@/context/UserContext';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare } from 'lucide-react';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare, Bell, Map, Shield } from 'lucide-react';
…tion or class'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:db6f4d9
Status:⚡️ Build in progress...

View logs

@Darkest-Teddy
Darkest-Teddy merged commit 08da3f3 into mainApr 20, 2026
2 of 3 checks passed
Sign up for freeto 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.

1 participant

@Darkest-Teddy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Newsletter - #63

Merged
Darkest-Teddy merged 3 commits into
mainfrom
newsletter
Apr 20, 2026
Merged

Newsletter#63
Darkest-Teddy merged 3 commits into
mainfrom
newsletter

Conversation

@Darkest-Teddy

@Darkest-TeddyDarkest-Teddy commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a newsletter/beta waitlist signup modal to the landing page. Users can enter their email to get early access and receive the Sapling newsletter. Emails are stored in Supabase and deduplicated on insert. The modal features entrance/exit animations, a success state that auto-dismisses after 3.2 seconds, and body scroll lock while open.

Changes Made

  • Added a two-panel newsletter signup modal to page.tsx with animated open/close transitions and a compact auto-dismissing success popup
  • Added modal animation keyframes (modal-backdrop-in/out, modal-card-in/out) to globals.css
  • Fixed Playfair Display italic and extended weight loading in layout.tsx
  • Added backend/routes/newsletter.pyPOST /api/newsletter/subscribe endpoint that upserts emails into a newsletter_emails Supabase table with TLD validation
  • Registered the newsletter router in main.py under /api/newsletter
  • Added email-validator to requirements.txt
  • Added backend/db/migration_newsletter.sql to create the newsletter_emails table

Related Issues

Closes #

Testing

  • Run migration_newsletter.sql in Supabase SQL Editor before deploying
  • Tested locally — valid email returns {"ok": true}, missing TLD returns 422
  • Frontend validates email format client-side before hitting the backend
  • Emails show up in newsletters_emails table on Supabase

Notes for Reviewers

The newsletter_emails table migration must be applied to Supabase before the backend route will work. See backend/db/migration_newsletter.sql.

Summary by CodeRabbit

  • New Features

    • Added "Sign up for Beta Testing" button on the landing page.
    • Introduced a newsletter signup modal with email validation, submit flow, and success confirmation.
    • Modal disables page scrolling while open and auto-closes after successful submission.
  • Style

    • Added smooth fade, scale and translate animations for modal backdrop and card on enter/exit.

@coderabbitai

coderabbitaiBot commented Apr 20, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 180da33f-e2f3-4dd8-bc9e-e5d09794ff81

📥 Commits

Reviewing files that changed from the base of the PR and between bdd4c96 and db6f4d9.

📒 Files selected for processing (1)
  • frontend/src/app/page.tsx

📝 Walkthrough

Walkthrough

Adds CSS keyframe animations for a newsletter modal, extends Playfair_Display font weights/styles, and implements a landing-page beta newsletter signup modal with state, lifecycle effects (auto-close, closing delay, body scroll lock), basic email validation, and POST submission to the newsletter API.

Changes

Cohort / File(s)Summary
Modal Animations
frontend/src/app/globals.css
Added four CSS keyframes (modal-backdrop-in, modal-backdrop-out, modal-card-in, modal-card-out) and corresponding utility classes to orchestrate modal enter/exit transitions (opacity, scale, translateY) with specific timings and easings.
Font Configuration
frontend/src/app/layout.tsx
Extended Playfair_Display font configuration to explicitly include weights 400–900 (excluding 300) and both normal and italic styles.
Newsletter Modal Feature
frontend/src/app/page.tsx
Added beta newsletter modal: state variables (betaModalOpen, betaModalClosing, betaEmail, betaEmailError, betaSubmitted, betaSubmitting), close-delay and auto-close effects, body scroll lock while open, hero CTA to open modal, conditional render for form vs success, client-side email validation, and POST to ${API_URL}/api/newsletter/subscribe.

Sequence Diagram(s)

sequenceDiagram
actor User
participant Landing as Frontend (page.tsx)
participant Modal as Modal UI
participant API as Backend API
User->>Landing: Click "Sign up for Beta"
Landing->>Landing: set betaModalOpen = true
Landing->>Landing: disable body scroll
Landing->>Modal: render email form
User->>Modal: Enter email & submit
Modal->>Landing: submit handler
Landing->>Landing: validate email
alt invalid
Landing->>Modal: set betaEmailError (show error)
else valid
Landing->>Landing: set betaSubmitting = true
Landing->>API: POST { email } to /api/newsletter/subscribe
API-->>Landing: response (errors swallowed)
Landing->>Landing: set betaSubmitted = true
Landing->>Modal: render success UI
Landing->>Landing: schedule auto-close (3200ms)
end
Landing->>Landing: closeModal triggered
Landing->>Landing: set betaModalClosing = true
Landing->>Landing: wait 200ms, then reset state
Landing->>Landing: re-enable body scroll
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A modal flutters in with charm,
Backdrop fades and card grows warm,
I nibble keys and validate,
A signup hops to celebrate,
Success — the newsletter's a cheerful swarm 📧

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check❓ InconclusiveThe title 'Newsletter' is partially related to the changeset but is overly broad and lacks specificity about the main change.Use a more specific title that captures the primary change, such as 'Add newsletter signup modal to landing page' or 'Implement beta waitlist signup functionality'.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe description is comprehensive and follows the template structure with all major sections completed, including description, changes made, testing, and notes for reviewers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch newsletter

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment threadfrontend/src/app/page.tsx Outdated
import { useRouter } from 'next/navigation';
import { useUser } from '@/context/UserContext';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare } from 'lucide-react';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare, Bell, Map, Shield } from 'lucide-react';
…tion or class'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:db6f4d9
Status:⚡️ Build in progress...

View logs

@Darkest-Teddy
Darkest-Teddy merged commit 08da3f3 into mainApr 20, 2026
2 of 3 checks passed
Sign up for freeto 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.

1 participant

@Darkest-Teddy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Newsletter - #63

Merged
Darkest-Teddy merged 3 commits into
mainfrom
newsletter
Apr 20, 2026
Merged

Newsletter#63
Darkest-Teddy merged 3 commits into
mainfrom
newsletter

Conversation

@Darkest-Teddy

@Darkest-TeddyDarkest-Teddy commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a newsletter/beta waitlist signup modal to the landing page. Users can enter their email to get early access and receive the Sapling newsletter. Emails are stored in Supabase and deduplicated on insert. The modal features entrance/exit animations, a success state that auto-dismisses after 3.2 seconds, and body scroll lock while open.

Changes Made

  • Added a two-panel newsletter signup modal to page.tsx with animated open/close transitions and a compact auto-dismissing success popup
  • Added modal animation keyframes (modal-backdrop-in/out, modal-card-in/out) to globals.css
  • Fixed Playfair Display italic and extended weight loading in layout.tsx
  • Added backend/routes/newsletter.pyPOST /api/newsletter/subscribe endpoint that upserts emails into a newsletter_emails Supabase table with TLD validation
  • Registered the newsletter router in main.py under /api/newsletter
  • Added email-validator to requirements.txt
  • Added backend/db/migration_newsletter.sql to create the newsletter_emails table

Related Issues

Closes #

Testing

  • Run migration_newsletter.sql in Supabase SQL Editor before deploying
  • Tested locally — valid email returns {"ok": true}, missing TLD returns 422
  • Frontend validates email format client-side before hitting the backend
  • Emails show up in newsletters_emails table on Supabase

Notes for Reviewers

The newsletter_emails table migration must be applied to Supabase before the backend route will work. See backend/db/migration_newsletter.sql.

Summary by CodeRabbit

  • New Features

    • Added "Sign up for Beta Testing" button on the landing page.
    • Introduced a newsletter signup modal with email validation, submit flow, and success confirmation.
    • Modal disables page scrolling while open and auto-closes after successful submission.
  • Style

    • Added smooth fade, scale and translate animations for modal backdrop and card on enter/exit.

@coderabbitai

coderabbitaiBot commented Apr 20, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 180da33f-e2f3-4dd8-bc9e-e5d09794ff81

📥 Commits

Reviewing files that changed from the base of the PR and between bdd4c96 and db6f4d9.

📒 Files selected for processing (1)
  • frontend/src/app/page.tsx

📝 Walkthrough

Walkthrough

Adds CSS keyframe animations for a newsletter modal, extends Playfair_Display font weights/styles, and implements a landing-page beta newsletter signup modal with state, lifecycle effects (auto-close, closing delay, body scroll lock), basic email validation, and POST submission to the newsletter API.

Changes

Cohort / File(s)Summary
Modal Animations
frontend/src/app/globals.css
Added four CSS keyframes (modal-backdrop-in, modal-backdrop-out, modal-card-in, modal-card-out) and corresponding utility classes to orchestrate modal enter/exit transitions (opacity, scale, translateY) with specific timings and easings.
Font Configuration
frontend/src/app/layout.tsx
Extended Playfair_Display font configuration to explicitly include weights 400–900 (excluding 300) and both normal and italic styles.
Newsletter Modal Feature
frontend/src/app/page.tsx
Added beta newsletter modal: state variables (betaModalOpen, betaModalClosing, betaEmail, betaEmailError, betaSubmitted, betaSubmitting), close-delay and auto-close effects, body scroll lock while open, hero CTA to open modal, conditional render for form vs success, client-side email validation, and POST to ${API_URL}/api/newsletter/subscribe.

Sequence Diagram(s)

sequenceDiagram
actor User
participant Landing as Frontend (page.tsx)
participant Modal as Modal UI
participant API as Backend API
User->>Landing: Click "Sign up for Beta"
Landing->>Landing: set betaModalOpen = true
Landing->>Landing: disable body scroll
Landing->>Modal: render email form
User->>Modal: Enter email & submit
Modal->>Landing: submit handler
Landing->>Landing: validate email
alt invalid
Landing->>Modal: set betaEmailError (show error)
else valid
Landing->>Landing: set betaSubmitting = true
Landing->>API: POST { email } to /api/newsletter/subscribe
API-->>Landing: response (errors swallowed)
Landing->>Landing: set betaSubmitted = true
Landing->>Modal: render success UI
Landing->>Landing: schedule auto-close (3200ms)
end
Landing->>Landing: closeModal triggered
Landing->>Landing: set betaModalClosing = true
Landing->>Landing: wait 200ms, then reset state
Landing->>Landing: re-enable body scroll
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A modal flutters in with charm,
Backdrop fades and card grows warm,
I nibble keys and validate,
A signup hops to celebrate,
Success — the newsletter's a cheerful swarm 📧

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check❓ InconclusiveThe title 'Newsletter' is partially related to the changeset but is overly broad and lacks specificity about the main change.Use a more specific title that captures the primary change, such as 'Add newsletter signup modal to landing page' or 'Implement beta waitlist signup functionality'.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe description is comprehensive and follows the template structure with all major sections completed, including description, changes made, testing, and notes for reviewers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch newsletter

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment threadfrontend/src/app/page.tsx Outdated
import { useRouter } from 'next/navigation';
import { useUser } from '@/context/UserContext';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare } from 'lucide-react';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare, Bell, Map, Shield } from 'lucide-react';
…tion or class'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:db6f4d9
Status:⚡️ Build in progress...

View logs

@Darkest-Teddy
Darkest-Teddy merged commit 08da3f3 into mainApr 20, 2026
2 of 3 checks passed
Sign up for freeto 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.

1 participant

@Darkest-Teddy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Newsletter - #63

Merged
Darkest-Teddy merged 3 commits into
mainfrom
newsletter
Apr 20, 2026
Merged

Newsletter#63
Darkest-Teddy merged 3 commits into
mainfrom
newsletter

Conversation

@Darkest-Teddy

@Darkest-TeddyDarkest-Teddy commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a newsletter/beta waitlist signup modal to the landing page. Users can enter their email to get early access and receive the Sapling newsletter. Emails are stored in Supabase and deduplicated on insert. The modal features entrance/exit animations, a success state that auto-dismisses after 3.2 seconds, and body scroll lock while open.

Changes Made

  • Added a two-panel newsletter signup modal to page.tsx with animated open/close transitions and a compact auto-dismissing success popup
  • Added modal animation keyframes (modal-backdrop-in/out, modal-card-in/out) to globals.css
  • Fixed Playfair Display italic and extended weight loading in layout.tsx
  • Added backend/routes/newsletter.pyPOST /api/newsletter/subscribe endpoint that upserts emails into a newsletter_emails Supabase table with TLD validation
  • Registered the newsletter router in main.py under /api/newsletter
  • Added email-validator to requirements.txt
  • Added backend/db/migration_newsletter.sql to create the newsletter_emails table

Related Issues

Closes #

Testing

  • Run migration_newsletter.sql in Supabase SQL Editor before deploying
  • Tested locally — valid email returns {"ok": true}, missing TLD returns 422
  • Frontend validates email format client-side before hitting the backend
  • Emails show up in newsletters_emails table on Supabase

Notes for Reviewers

The newsletter_emails table migration must be applied to Supabase before the backend route will work. See backend/db/migration_newsletter.sql.

Summary by CodeRabbit

  • New Features

    • Added "Sign up for Beta Testing" button on the landing page.
    • Introduced a newsletter signup modal with email validation, submit flow, and success confirmation.
    • Modal disables page scrolling while open and auto-closes after successful submission.
  • Style

    • Added smooth fade, scale and translate animations for modal backdrop and card on enter/exit.

@coderabbitai

coderabbitaiBot commented Apr 20, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 180da33f-e2f3-4dd8-bc9e-e5d09794ff81

📥 Commits

Reviewing files that changed from the base of the PR and between bdd4c96 and db6f4d9.

📒 Files selected for processing (1)
  • frontend/src/app/page.tsx

📝 Walkthrough

Walkthrough

Adds CSS keyframe animations for a newsletter modal, extends Playfair_Display font weights/styles, and implements a landing-page beta newsletter signup modal with state, lifecycle effects (auto-close, closing delay, body scroll lock), basic email validation, and POST submission to the newsletter API.

Changes

Cohort / File(s)Summary
Modal Animations
frontend/src/app/globals.css
Added four CSS keyframes (modal-backdrop-in, modal-backdrop-out, modal-card-in, modal-card-out) and corresponding utility classes to orchestrate modal enter/exit transitions (opacity, scale, translateY) with specific timings and easings.
Font Configuration
frontend/src/app/layout.tsx
Extended Playfair_Display font configuration to explicitly include weights 400–900 (excluding 300) and both normal and italic styles.
Newsletter Modal Feature
frontend/src/app/page.tsx
Added beta newsletter modal: state variables (betaModalOpen, betaModalClosing, betaEmail, betaEmailError, betaSubmitted, betaSubmitting), close-delay and auto-close effects, body scroll lock while open, hero CTA to open modal, conditional render for form vs success, client-side email validation, and POST to ${API_URL}/api/newsletter/subscribe.

Sequence Diagram(s)

sequenceDiagram
actor User
participant Landing as Frontend (page.tsx)
participant Modal as Modal UI
participant API as Backend API
User->>Landing: Click "Sign up for Beta"
Landing->>Landing: set betaModalOpen = true
Landing->>Landing: disable body scroll
Landing->>Modal: render email form
User->>Modal: Enter email & submit
Modal->>Landing: submit handler
Landing->>Landing: validate email
alt invalid
Landing->>Modal: set betaEmailError (show error)
else valid
Landing->>Landing: set betaSubmitting = true
Landing->>API: POST { email } to /api/newsletter/subscribe
API-->>Landing: response (errors swallowed)
Landing->>Landing: set betaSubmitted = true
Landing->>Modal: render success UI
Landing->>Landing: schedule auto-close (3200ms)
end
Landing->>Landing: closeModal triggered
Landing->>Landing: set betaModalClosing = true
Landing->>Landing: wait 200ms, then reset state
Landing->>Landing: re-enable body scroll
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A modal flutters in with charm,
Backdrop fades and card grows warm,
I nibble keys and validate,
A signup hops to celebrate,
Success — the newsletter's a cheerful swarm 📧

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check❓ InconclusiveThe title 'Newsletter' is partially related to the changeset but is overly broad and lacks specificity about the main change.Use a more specific title that captures the primary change, such as 'Add newsletter signup modal to landing page' or 'Implement beta waitlist signup functionality'.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe description is comprehensive and follows the template structure with all major sections completed, including description, changes made, testing, and notes for reviewers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch newsletter

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment threadfrontend/src/app/page.tsx Outdated
import { useRouter } from 'next/navigation';
import { useUser } from '@/context/UserContext';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare } from 'lucide-react';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare, Bell, Map, Shield } from 'lucide-react';
…tion or class'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:db6f4d9
Status:⚡️ Build in progress...

View logs

@Darkest-Teddy
Darkest-Teddy merged commit 08da3f3 into mainApr 20, 2026
2 of 3 checks passed
Sign up for freeto 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.

1 participant

@Darkest-Teddy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Newsletter - #63

Merged
Darkest-Teddy merged 3 commits into
mainfrom
newsletter
Apr 20, 2026
Merged

Newsletter#63
Darkest-Teddy merged 3 commits into
mainfrom
newsletter

Conversation

@Darkest-Teddy

@Darkest-TeddyDarkest-Teddy commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a newsletter/beta waitlist signup modal to the landing page. Users can enter their email to get early access and receive the Sapling newsletter. Emails are stored in Supabase and deduplicated on insert. The modal features entrance/exit animations, a success state that auto-dismisses after 3.2 seconds, and body scroll lock while open.

Changes Made

  • Added a two-panel newsletter signup modal to page.tsx with animated open/close transitions and a compact auto-dismissing success popup
  • Added modal animation keyframes (modal-backdrop-in/out, modal-card-in/out) to globals.css
  • Fixed Playfair Display italic and extended weight loading in layout.tsx
  • Added backend/routes/newsletter.pyPOST /api/newsletter/subscribe endpoint that upserts emails into a newsletter_emails Supabase table with TLD validation
  • Registered the newsletter router in main.py under /api/newsletter
  • Added email-validator to requirements.txt
  • Added backend/db/migration_newsletter.sql to create the newsletter_emails table

Related Issues

Closes #

Testing

  • Run migration_newsletter.sql in Supabase SQL Editor before deploying
  • Tested locally — valid email returns {"ok": true}, missing TLD returns 422
  • Frontend validates email format client-side before hitting the backend
  • Emails show up in newsletters_emails table on Supabase

Notes for Reviewers

The newsletter_emails table migration must be applied to Supabase before the backend route will work. See backend/db/migration_newsletter.sql.

Summary by CodeRabbit

  • New Features

    • Added "Sign up for Beta Testing" button on the landing page.
    • Introduced a newsletter signup modal with email validation, submit flow, and success confirmation.
    • Modal disables page scrolling while open and auto-closes after successful submission.
  • Style

    • Added smooth fade, scale and translate animations for modal backdrop and card on enter/exit.

@coderabbitai

coderabbitaiBot commented Apr 20, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 180da33f-e2f3-4dd8-bc9e-e5d09794ff81

📥 Commits

Reviewing files that changed from the base of the PR and between bdd4c96 and db6f4d9.

📒 Files selected for processing (1)
  • frontend/src/app/page.tsx

📝 Walkthrough

Walkthrough

Adds CSS keyframe animations for a newsletter modal, extends Playfair_Display font weights/styles, and implements a landing-page beta newsletter signup modal with state, lifecycle effects (auto-close, closing delay, body scroll lock), basic email validation, and POST submission to the newsletter API.

Changes

Cohort / File(s)Summary
Modal Animations
frontend/src/app/globals.css
Added four CSS keyframes (modal-backdrop-in, modal-backdrop-out, modal-card-in, modal-card-out) and corresponding utility classes to orchestrate modal enter/exit transitions (opacity, scale, translateY) with specific timings and easings.
Font Configuration
frontend/src/app/layout.tsx
Extended Playfair_Display font configuration to explicitly include weights 400–900 (excluding 300) and both normal and italic styles.
Newsletter Modal Feature
frontend/src/app/page.tsx
Added beta newsletter modal: state variables (betaModalOpen, betaModalClosing, betaEmail, betaEmailError, betaSubmitted, betaSubmitting), close-delay and auto-close effects, body scroll lock while open, hero CTA to open modal, conditional render for form vs success, client-side email validation, and POST to ${API_URL}/api/newsletter/subscribe.

Sequence Diagram(s)

sequenceDiagram
actor User
participant Landing as Frontend (page.tsx)
participant Modal as Modal UI
participant API as Backend API
User->>Landing: Click "Sign up for Beta"
Landing->>Landing: set betaModalOpen = true
Landing->>Landing: disable body scroll
Landing->>Modal: render email form
User->>Modal: Enter email & submit
Modal->>Landing: submit handler
Landing->>Landing: validate email
alt invalid
Landing->>Modal: set betaEmailError (show error)
else valid
Landing->>Landing: set betaSubmitting = true
Landing->>API: POST { email } to /api/newsletter/subscribe
API-->>Landing: response (errors swallowed)
Landing->>Landing: set betaSubmitted = true
Landing->>Modal: render success UI
Landing->>Landing: schedule auto-close (3200ms)
end
Landing->>Landing: closeModal triggered
Landing->>Landing: set betaModalClosing = true
Landing->>Landing: wait 200ms, then reset state
Landing->>Landing: re-enable body scroll
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A modal flutters in with charm,
Backdrop fades and card grows warm,
I nibble keys and validate,
A signup hops to celebrate,
Success — the newsletter's a cheerful swarm 📧

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check❓ InconclusiveThe title 'Newsletter' is partially related to the changeset but is overly broad and lacks specificity about the main change.Use a more specific title that captures the primary change, such as 'Add newsletter signup modal to landing page' or 'Implement beta waitlist signup functionality'.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe description is comprehensive and follows the template structure with all major sections completed, including description, changes made, testing, and notes for reviewers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch newsletter

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment threadfrontend/src/app/page.tsx Outdated
import { useRouter } from 'next/navigation';
import { useUser } from '@/context/UserContext';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare } from 'lucide-react';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare, Bell, Map, Shield } from 'lucide-react';
…tion or class'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:db6f4d9
Status:⚡️ Build in progress...

View logs

@Darkest-Teddy
Darkest-Teddy merged commit 08da3f3 into mainApr 20, 2026
2 of 3 checks passed
Sign up for freeto 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.

1 participant

@Darkest-Teddy
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Newsletter - #63

Merged
Darkest-Teddy merged 3 commits into
mainfrom
newsletter
Apr 20, 2026
Merged

Newsletter#63
Darkest-Teddy merged 3 commits into
mainfrom
newsletter

Conversation

@Darkest-Teddy

@Darkest-TeddyDarkest-Teddy commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a newsletter/beta waitlist signup modal to the landing page. Users can enter their email to get early access and receive the Sapling newsletter. Emails are stored in Supabase and deduplicated on insert. The modal features entrance/exit animations, a success state that auto-dismisses after 3.2 seconds, and body scroll lock while open.

Changes Made

  • Added a two-panel newsletter signup modal to page.tsx with animated open/close transitions and a compact auto-dismissing success popup
  • Added modal animation keyframes (modal-backdrop-in/out, modal-card-in/out) to globals.css
  • Fixed Playfair Display italic and extended weight loading in layout.tsx
  • Added backend/routes/newsletter.pyPOST /api/newsletter/subscribe endpoint that upserts emails into a newsletter_emails Supabase table with TLD validation
  • Registered the newsletter router in main.py under /api/newsletter
  • Added email-validator to requirements.txt
  • Added backend/db/migration_newsletter.sql to create the newsletter_emails table

Related Issues

Closes #

Testing

  • Run migration_newsletter.sql in Supabase SQL Editor before deploying
  • Tested locally — valid email returns {"ok": true}, missing TLD returns 422
  • Frontend validates email format client-side before hitting the backend
  • Emails show up in newsletters_emails table on Supabase

Notes for Reviewers

The newsletter_emails table migration must be applied to Supabase before the backend route will work. See backend/db/migration_newsletter.sql.

Summary by CodeRabbit

  • New Features

    • Added "Sign up for Beta Testing" button on the landing page.
    • Introduced a newsletter signup modal with email validation, submit flow, and success confirmation.
    • Modal disables page scrolling while open and auto-closes after successful submission.
  • Style

    • Added smooth fade, scale and translate animations for modal backdrop and card on enter/exit.

@coderabbitai

coderabbitaiBot commented Apr 20, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 180da33f-e2f3-4dd8-bc9e-e5d09794ff81

📥 Commits

Reviewing files that changed from the base of the PR and between bdd4c96 and db6f4d9.

📒 Files selected for processing (1)
  • frontend/src/app/page.tsx

📝 Walkthrough

Walkthrough

Adds CSS keyframe animations for a newsletter modal, extends Playfair_Display font weights/styles, and implements a landing-page beta newsletter signup modal with state, lifecycle effects (auto-close, closing delay, body scroll lock), basic email validation, and POST submission to the newsletter API.

Changes

Cohort / File(s)Summary
Modal Animations
frontend/src/app/globals.css
Added four CSS keyframes (modal-backdrop-in, modal-backdrop-out, modal-card-in, modal-card-out) and corresponding utility classes to orchestrate modal enter/exit transitions (opacity, scale, translateY) with specific timings and easings.
Font Configuration
frontend/src/app/layout.tsx
Extended Playfair_Display font configuration to explicitly include weights 400–900 (excluding 300) and both normal and italic styles.
Newsletter Modal Feature
frontend/src/app/page.tsx
Added beta newsletter modal: state variables (betaModalOpen, betaModalClosing, betaEmail, betaEmailError, betaSubmitted, betaSubmitting), close-delay and auto-close effects, body scroll lock while open, hero CTA to open modal, conditional render for form vs success, client-side email validation, and POST to ${API_URL}/api/newsletter/subscribe.

Sequence Diagram(s)

sequenceDiagram
actor User
participant Landing as Frontend (page.tsx)
participant Modal as Modal UI
participant API as Backend API
User->>Landing: Click "Sign up for Beta"
Landing->>Landing: set betaModalOpen = true
Landing->>Landing: disable body scroll
Landing->>Modal: render email form
User->>Modal: Enter email & submit
Modal->>Landing: submit handler
Landing->>Landing: validate email
alt invalid
Landing->>Modal: set betaEmailError (show error)
else valid
Landing->>Landing: set betaSubmitting = true
Landing->>API: POST { email } to /api/newsletter/subscribe
API-->>Landing: response (errors swallowed)
Landing->>Landing: set betaSubmitted = true
Landing->>Modal: render success UI
Landing->>Landing: schedule auto-close (3200ms)
end
Landing->>Landing: closeModal triggered
Landing->>Landing: set betaModalClosing = true
Landing->>Landing: wait 200ms, then reset state
Landing->>Landing: re-enable body scroll
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A modal flutters in with charm,
Backdrop fades and card grows warm,
I nibble keys and validate,
A signup hops to celebrate,
Success — the newsletter's a cheerful swarm 📧

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check❓ InconclusiveThe title 'Newsletter' is partially related to the changeset but is overly broad and lacks specificity about the main change.Use a more specific title that captures the primary change, such as 'Add newsletter signup modal to landing page' or 'Implement beta waitlist signup functionality'.
✅ Passed checks (1 passed)
Check nameStatusExplanation
Description check✅ PassedThe description is comprehensive and follows the template structure with all major sections completed, including description, changes made, testing, and notes for reviewers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch newsletter

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment threadfrontend/src/app/page.tsx Outdated
import { useRouter } from 'next/navigation';
import { useUser } from '@/context/UserContext';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare } from 'lucide-react';
import { Network, Sparkles, FilePlus2, Brain, CalendarClock, Users, PenSquare, Bell, Map, Shield } from 'lucide-react';
…tion or class'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying web with Cloudflare Pages Cloudflare Pages

Latest commit:db6f4d9
Status:⚡️ Build in progress...

View logs

@Darkest-Teddy
Darkest-Teddy merged commit 08da3f3 into mainApr 20, 2026
2 of 3 checks passed
Sign up for freeto 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.

1 participant

@Darkest-Teddy