From 02eb1eb804dce96ecc0a7fbf3774349bdb73f442 Mon Sep 17 00:00:00 2001 From: Vasyl Yaremchuk Date: Tue, 4 Nov 2025 20:20:52 +0100 Subject: [PATCH] BE for Landing Pages. --- website/app.js | 1 + website/modules/@apostrophecms/page/index.js | 62 ++++++++++++++++++++ website/modules/landing-pages/index.js | 36 ++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 website/modules/landing-pages/index.js diff --git a/website/app.js b/website/app.js index 90a860cb..457dad46 100644 --- a/website/app.js +++ b/website/app.js @@ -116,6 +116,7 @@ function createAposConfig() { // Custom Pieces 'team-members': {}, 'testimonials': {}, + 'landing-pages': {}, // `asset` supports the project"s webpack build for client-side assets. 'asset': {}, diff --git a/website/modules/@apostrophecms/page/index.js b/website/modules/@apostrophecms/page/index.js index 7cc1102b..03ea65f3 100644 --- a/website/modules/@apostrophecms/page/index.js +++ b/website/modules/@apostrophecms/page/index.js @@ -3,6 +3,8 @@ * pages menu */ +const fetch = require('node-fetch'); + module.exports = { options: { types: [ @@ -30,4 +32,64 @@ module.exports = { }, ], }, + handlers(self) { + return { + 'notFound': { + async checkLandingPages(req) { + // Only check if response hasn't been sent yet + if (req.res.headersSent) { + return; + } + + try { + // Get the landing pages module + const landingPages = self.apos.modules['landing-pages']; + if (!landingPages) { + return; + } + + // Extract slug from the path (remove leading slash) + const slug = req.url.substring(1).split('?')[0]; + + if (!slug) { + return; + } + + // Try to find a landing page with this slug + const landingPage = await landingPages.find(req, { slug }).toObject(); + + if (!landingPage || !landingPage.externalUrl) { + return; + } + + // TEST MODE: Just output the link + const html = ` + + + + ${landingPage.title} + + +

Landing Page: ${landingPage.title}

+

Slug: ${landingPage.slug}

+

External URL: ${landingPage.externalUrl}

+ + + `; + + // Send the test HTML + req.res.set('Content-Type', 'text/html'); + req.res.send(html); + + // Mark as handled + req.notFound = false; + + } catch (error) { + self.apos.util.error('Error checking landing pages:', error); + // Don't send error response, let normal 404 handle it + } + } + } + }; + } }; diff --git a/website/modules/landing-pages/index.js b/website/modules/landing-pages/index.js new file mode 100644 index 00000000..a8a53c41 --- /dev/null +++ b/website/modules/landing-pages/index.js @@ -0,0 +1,36 @@ +module.exports = { + extend: '@apostrophecms/piece-type', + options: { + label: 'Landing Page', + pluralLabel: 'Landing Pages', + alias: 'landingPages' + }, + fields: { + add: { + title: { + type: 'string', + label: 'Title', + required: true + }, + slug: { + type: 'slug', + label: 'Slug', + help: 'Relative path for this landing page', + required: true, + following: 'title' + }, + externalUrl: { + type: 'url', + label: 'External URL', + help: 'Full external URL for this landing page', + required: false + } + }, + group: { + basics: { + label: 'Basics', + fields: ['title', 'slug', 'externalUrl'] + } + } + } +};