diff --git a/public/blog-post.html b/public/blog-post.html index 4c97ce3d..fef56100 100644 --- a/public/blog-post.html +++ b/public/blog-post.html @@ -213,6 +213,22 @@
+ +
+
+

Enjoyed this article?

+

Subscribe to stay updated on AI governance research and insights.

+ +
+
+ @@ -227,6 +243,9 @@ + + + diff --git a/public/blog.html b/public/blog.html index 1517cba9..f9126423 100644 --- a/public/blog.html +++ b/public/blog.html @@ -61,9 +61,31 @@

Tractatus Blog

-

+

Insights on AI governance, safety frameworks, and the boundary between automation and human judgment.

+

+ New + Now publishing — subscribe to follow our research +

+
+ + + + + + RSS + +
@@ -163,108 +185,14 @@ - -
-
-

Stay Updated

-

- Get notified when we publish new insights on AI governance and safety frameworks. -

- -
-
- - - - + + + diff --git a/public/js/blog.js b/public/js/blog.js index 67bba458..fd1ae743 100644 --- a/public/js/blog.js +++ b/public/js/blog.js @@ -16,17 +16,11 @@ const activeFilters = { sort: 'date-desc' }; -// CSRF token (fetched on page load) -let csrfToken = null; - /** * Initialize the blog page */ async function init() { try { - // Fetch CSRF token first (required for newsletter subscription) - await fetchCsrfToken(); - await loadPosts(); attachEventListeners(); } catch (error) { @@ -35,25 +29,6 @@ async function init() { } } -/** - * Fetch CSRF token from server - * Required because nginx serves blog.html as static file (bypasses setCsrfToken middleware) - */ -async function fetchCsrfToken() { - try { - const response = await fetch('/api/csrf-token'); - const data = await response.json(); - - if (data.csrfToken) { - csrfToken = data.csrfToken; - console.log('CSRF token fetched successfully'); - } - } catch (error) { - console.warn('Failed to fetch CSRF token:', error); - // Non-critical - newsletter subscription will fail but blog browsing still works - } -} - /** * Load all published blog posts from API */ @@ -527,128 +502,7 @@ function escapeHtml(text) { return div.innerHTML; } -/** - * Newsletter Modal Functionality - */ -function setupNewsletterModal() { - const modal = document.getElementById('newsletter-modal'); - const openBtn = document.getElementById('open-newsletter-modal'); - const closeBtn = document.getElementById('close-newsletter-modal'); - const cancelBtn = document.getElementById('cancel-newsletter'); - const form = document.getElementById('newsletter-form'); - const successMsg = document.getElementById('newsletter-success'); - const errorMsg = document.getElementById('newsletter-error'); - const errorText = document.getElementById('newsletter-error-message'); - const submitBtn = document.getElementById('newsletter-submit'); - - // Open modal - if (openBtn) { - openBtn.addEventListener('click', () => { - modal.classList.remove('hidden'); - document.getElementById('newsletter-email').focus(); - }); - } - - // Close modal - function closeModal() { - modal.classList.add('hidden'); - form.reset(); - successMsg.classList.add('hidden'); - errorMsg.classList.add('hidden'); - } - - if (closeBtn) { - closeBtn.addEventListener('click', closeModal); - } - - if (cancelBtn) { - cancelBtn.addEventListener('click', closeModal); - } - - // Close on backdrop click - modal.addEventListener('click', (e) => { - if (e.target === modal) { - closeModal(); - } - }); - - // Close on Escape key - document.addEventListener('keydown', (e) => { - if (e.key === 'Escape' && !modal.classList.contains('hidden')) { - closeModal(); - } - }); - - // Handle form submission - if (form) { - form.addEventListener('submit', async (e) => { - e.preventDefault(); - - // Reset messages - successMsg.classList.add('hidden'); - errorMsg.classList.add('hidden'); - - const email = document.getElementById('newsletter-email').value; - const name = document.getElementById('newsletter-name').value; - - // Disable submit button - submitBtn.disabled = true; - submitBtn.textContent = 'Subscribing...'; - - try { - // Ensure we have a CSRF token - if (!csrfToken) { - await fetchCsrfToken(); - } - - if (!csrfToken) { - throw new Error('Unable to obtain CSRF token'); - } - - const response = await fetch('/api/newsletter/subscribe', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRF-Token': csrfToken - }, - body: JSON.stringify({ - email, - name: name || null, - source: 'blog' - }) - }); - - const data = await response.json(); - - if (response.ok && data.success) { - // Show success message - successMsg.classList.remove('hidden'); - form.reset(); - - // Close modal after 2 seconds - setTimeout(() => { - closeModal(); - }, 2000); - } else { - // Show error message - errorText.textContent = data.error || 'Failed to subscribe. Please try again.'; - errorMsg.classList.remove('hidden'); - } - } catch (error) { - console.error('Newsletter subscription error:', error); - errorText.textContent = 'Network error. Please check your connection and try again.'; - errorMsg.classList.remove('hidden'); - } finally { - // Re-enable submit button - submitBtn.disabled = false; - submitBtn.textContent = 'Subscribe'; - } - }); - } -} - // Initialize on page load document.addEventListener('DOMContentLoaded', () => { init(); - setupNewsletterModal(); });