Skip to main content

Public Landing Pages

Terra provides two public-facing page types for applicants:
RoutePurpose
/p/[slug]Program Landing Page - Overview, description, and “Start Application” CTA
/f/[slug]Form Page - The actual application form

Program Landing Page (/p/[slug])

The landing page provides context before applicants start an application.

Features

  • Hero Section: Cover image with gradient overlay
  • Brand Bar: Logo, program title, and status badge (Open/Closed)
  • About Section: Markdown-rendered program description
  • Action Box (sticky):
    • Deadline display (color-coded by urgency)
    • User context (logged in vs guest)
    • “Start Application” button
  • Login Context: Shows submission count for logged-in users

URL Structure

https://yourdomain.com/p/seattle-rental-assistance

                    Form slug

Example

┌─────────────────────────────────────────────────────────────┐
│ [Logo]                                    [Language ▼]      │
├─────────────────────────────────────────────────────────────┤
│ ░░░░░░░░░░░░░░░░░ Cover Image ░░░░░░░░░░░░░░░░░░░░░░░░░░░ │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ [Logo] Seattle Rental Assistance        ● Open      │   │
│  │                                                     │   │
│  │ Program Support →                                   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────┐  ┌──────────────────────────┐ │
│  │ About This Program      │  │ 📅 Apply by              │ │
│  │                         │  │ Friday, January 31, 2025 │ │
│  │ This program provides   │  │ 5:00 PM PST              │ │
│  │ emergency rental        │  ├──────────────────────────┤ │
│  │ assistance to...        │  │ ✓ Welcome back, Jane     │ │
│  │                         │  │ You have 1 submission    │ │
│  │ **Eligibility:**        │  │            [My Portal →] │ │
│  │ • Income below 80% AMI  │  ├──────────────────────────┤ │
│  │ • King County resident  │  │                          │ │
│  │ • Behind on rent        │  │  [ Start Application → ] │ │
│  │                         │  │                          │ │
│  └─────────────────────────┘  └──────────────────────────┘ │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Status States

StatusBadgeButton
published🟢 Open”Start Application”
draft🟡 Draft”Preview Application” + warning
closed⚫ ClosedDisabled “Applications Closed”

User Context Box

Guest (not logged in):
🔑 Sign in to save your progress
   Your responses will be saved so you can return later.
                                              [Sign In]
Logged in (no submissions):
✓ Welcome back, Jane
  You haven't submitted an application yet.
                                          [My Portal →]
Logged in (has submissions):
✓ Welcome back, Jane
  You have 2 submissions for this program.
                                          [My Portal →]

Deadline Display

The deadline box changes color based on urgency:
ConditionColorIcon
> 7 days away🟢 GreenCalendar
< 7 days away🟡 AmberCalendar
Past deadline⚫ GrayCalendar

Form Page (/f/[slug])

The actual application form with all fields.

Layout

┌─────────────────────────────────────────────────────────────┐
│ [Logo] Organization Name              [Language ▼]          │
├─────────────────────────────────────────────────────────────┤
│ ░░░░░░░░░░░░░░░░░ Cover Image ░░░░░░░░░░░░░░░░░░░░░░░░░░░ │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  [S]  Seattle Rental Assistance            ● Open          │
│                                                             │
│  This program provides emergency rental assistance to       │
│  qualifying King County residents.                          │
│                                                             │
│  ─────────────────────────────────────────────────────────  │
│                                                             │
│  Eligibility                                                │
│  Optional section description                               │
│                                                             │
│  First Name                      Last Name                  │
│  ┌─────────────────────┐        ┌─────────────────────┐    │
│  │ Type here...        │        │ Type here...        │    │
│  └─────────────────────┘        └─────────────────────┘    │
│                                                             │
│  ...more fields...                                          │
│                                                             │
├─────────────────────────────────────────────────────────────┤
│ Powered by Terra                             [ Submit ]     │
└─────────────────────────────────────────────────────────────┘

Preview Mode

When admins preview draft forms:
┌─────────────────────────────────────────────────────────────┐
│ ⚠️ Preview Mode — This form is not yet published            │
├─────────────────────────────────────────────────────────────┤
│ ... form content ...                                        │
  • Yellow banner at top
  • “Preview” badge instead of “Open”
  • Submit creates fake submission (no database write)

Alert Banner

Admins can add custom alerts to forms:
┌─────────────────────────────────────────────────────────────┐
│ ℹ️ Applications are reviewed weekly. Please allow 5-7       │
│    business days for a response.                       [✕]  │
└─────────────────────────────────────────────────────────────┘
Configure in Form Settings:
  • Type: Info (blue), Warning (amber), Error (red)
  • Content: Message text
  • Dismissible: User can close

Linking Between Pages

From Landing Page to Form

// In landing page action box
<Link href={`/f/${form.slug}`}>
  Start Application
</Link>

From Dashboard to Landing Page

// Admin preview link
<Link href={`/p/${form.slug}`} target="_blank">
  View Landing Page
</Link>

With Custom Domains

If a workspace has a custom domain:
Standard URLCustom Domain URL
/p/seattle-renthttps://apply.seattle.gov/p/seattle-rent
/f/seattle-renthttps://apply.seattle.gov/f/seattle-rent

Customization

Cover Image

Set via Form Settings → Branding:
  • Recommended: 1600x400px
  • Falls back to default gradient if not set
  • Graceful error handling for broken images

Program Description

Supports basic Markdown:
  • **bold** for emphasis
  • - bullets for lists
  • [text](url) for links
  • Paragraph breaks with double newlines

Deadline

Set via Form Settings → General:
  • Stored as ISO 8601 timestamp
  • Displayed in user’s locale
  • Timezone shown

Implementation Details

File Structure

src/app/
├── p/[slug]/
│   ├── page.tsx       # Server component (data fetching)
│   ├── client.tsx     # Client component (UI)
│   ├── layout.tsx     # Language provider wrapper
│   └── not-found.tsx  # Custom 404
└── f/[slug]/
    ├── page.tsx       # Server component
    └── client.tsx     # Form viewer

Data Flow

// p/[slug]/page.tsx
export default async function PublicProgramPage({ params }) {
  const { slug } = await params;
  const [session, { form }, { settings }] = await Promise.all([
    getSession(),
    getPublicForm(slug),
    getSystemSettings(),
  ]);

  // Get submission count for logged-in users
  let submissionCount = 0;
  if (session?.user?.id) {
    submissionCount = await getUserSubmissionCount(form.id, session.user.id);
  }

  return (
    <ProgramLandingPage
      form={form}
      user={session?.user}
      submissionCount={submissionCount}
    />
  );
}

Next: Form Organization

Learn how to organize forms into workspaces.