2.2 KiB

Landing Page (Public Page Renderer)

Overview

File Path: admin/src/pages/public/LandingPage.tsx (68 lines)

Route: /p/:slug

Role Requirements: Public access

Purpose: Simple renderer for admin-authored landing pages created with GrapesJS editor. Fetches page by slug and displays HTML/CSS content with SEO meta tags.

Key Features:

  • Minimal wrapper around admin-authored HTML
  • SEO meta tags (title, description, og:image)
  • dangerouslySetInnerHTML for HTML + CSS rendering
  • Loading spinner during fetch
  • 404 page for invalid slugs
  • No layout wrapper (pages are self-contained)

Features

1. SEO Meta Tags

<Helmet>
  <title>{page.title}</title>
  <meta name="description" content={page.description || ''} />
  <meta property="og:title" content={page.title} />
  <meta property="og:description" content={page.description || ''} />
  {page.coverImage && <meta property="og:image" content={page.coverImage} />}
</Helmet>

2. HTML Rendering

<div dangerouslySetInnerHTML={{ __html: page.html }} />
<style>{page.css}</style>

3. Loading State

{loading && (
  <div style={{ textAlign: 'center', padding: 100 }}>
    <Spin size="large" />
  </div>
)}

4. 404 Handling

{!loading && !page && (
  <Result
    status="404"
    title="Page Not Found"
    subTitle="The page you're looking for doesn't exist."
    extra={<Link to="/"><Button type="primary">Go Home</Button></Link>}
  />
)}

API Integration

GET /api/public/pages/:slug

Response:

{
  "slug": "welcome",
  "title": "Welcome to Our Campaign",
  "description": "Join us in making a difference",
  "html": "<div><h1>Welcome</h1>...</div>",
  "css": "h1 { color: #1890ff; }",
  "coverImage": "https://example.com/cover.jpg",
  "isPublished": true
}

Security Considerations

XSS Risk Accepted:

  • Pages authored by trusted admins only
  • dangerouslySetInnerHTML allows full HTML/JS
  • No user-submitted content
  • Alternative would break GrapesJS output