Marketing Application
The marketing application is the primary public-facing website for the Sustentus platform, built with Next.js 15 and the App Router.
Overview
Package Name: @sustentus/marketing
Framework: Next.js 15
Port: 3001
Path: apps/marketing/
Purpose
The marketing site serves as the main entry point for potential customers, featuring:
- Product information and value proposition
- Pricing and plan comparison
- Waitlist signup functionality
- User authentication (sign-up/sign-in)
Technology Stack
Core
- Next.js 15: React framework with App Router
- React 19: UI library
- TypeScript: Type safety
- Tailwind CSS v4: Utility-first styling
Authentication
- Clerk: User authentication and management
- @clerk/nextjs: Next.js integration
- @clerk/themes: Pre-built UI themes
UI Components
- @sustentus/ui: Shared component library
- Radix UI: Accessible primitives
- Lucide React: Icons
- Framer Motion: Animations
Forms & Validation
- React Hook Form: Form state management
- Zod: Schema validation
- @hookform/resolvers: React Hook Form + Zod integration
Additional Features
- Vercel Analytics: Performance monitoring
- PostHog: Product analytics
- Sonner: Toast notifications
- Next Themes: Theme management
Directory Structure
marketing/
├── app/
│ ├── layout.tsx # Root layout with providers
│ ├── page.tsx # Home/landing page
│ ├── globals.css # Global styles
│ ├── pricing/
│ │ └── page.tsx # Pricing page
│ ├── sign-in/
│ │ └── [[...sign-in]]/
│ │ └── page.tsx # Clerk sign-in page
│ ├── sign-up/
│ │ └── [[...sign-up]]/
│ │ └── page.tsx # Clerk sign-up page
│ ├── waitlist/
│ │ └── page.tsx # Waitlist signup
│ └── waitlist-confirmation/
│ └── page.tsx # Post-signup confirmation
├── components/
│ ├── ui/ # shadcn/ui components
│ ├── home/ # Landing page sections
│ │ ├── hero.tsx
│ │ ├── problem.tsx
│ │ ├── solution.tsx
│ │ ├── features.tsx
│ │ ├── how-it-works.tsx
│ │ ├── testimonials.tsx
│ │ └── cta.tsx
│ ├── pricing/
│ │ └── pricing-cards.tsx
│ ├── background/
│ │ └── grid-background.tsx
│ ├── navigation.tsx # Global navigation
│ ├── theme-provider.tsx # Theme context
│ ├── auth-provider.tsx # Clerk provider
│ └── waitlist.tsx # Waitlist form
├── lib/
│ └── utils.ts # Utility functions
├── public/ # Static assets
├── middleware.ts # Clerk middleware
├── next.config.mjs # Next.js configuration
└── package.jsonKey features
- Landing page (
app/page.tsx): hero, problem, solution, feature highlights, how it works, testimonials, and call-to-action sections. - Pricing page (
app/pricing/page.tsx): plan cards, monthly/annual toggle, and signup CTAs. - Authentication (Clerk):
/sign-upfor registration,/sign-infor login; users are redirected to/waitlist-confirmationafter auth. - Waitlist: validated signup form that creates a Clerk user and shows a confirmation page.
Development
Running the App
# From root
pnpm marketing:dev
# From marketing directory
cd apps/marketing
pnpm devThe app runs on http://localhost:3001.
Environment Variables
Create .env.local in apps/marketing/:
# Clerk Authentication
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
# Optional: Analytics
NEXT_PUBLIC_POSTHOG_KEY=...
NEXT_PUBLIC_POSTHOG_HOST=...Building
# From root
pnpm marketing:build
# From marketing directory
cd apps/marketing
pnpm buildConfiguration Files
next.config.mjs: image domains, redirects, headers, experimental features.middleware.ts: Clerk middleware — protects authenticated routes, configures public routes, and handles post-auth redirects.components.json: shadcn/ui configuration (style, Tailwind config path, aliases).
Routing
The app uses Next.js App Router with file-based routing:
| Route | Purpose |
|---|---|
/ | Landing page |
/pricing | Pricing information |
/sign-in | User login |
/sign-up | User registration |
/waitlist | Waitlist signup |
/waitlist-confirmation | Post-signup confirmation |
Forms
Forms use React Hook Form with a Zod resolver and the <Form> primitives from @sustentus/ui:
const schema = z.object({
email: z.string().email(),
// ... more fields
});
const form = useForm({
resolver: zodResolver(schema),
});
const onSubmit = async (data) => {
// Handle submission
};Learn More
Last updated on