Appearance
Marketing Site Overview
The Jubiloop marketing site is a Next.js 15 application serving as the public-facing website for the platform.
Technology Stack
- Framework: Next.js 15 with App Router
- Language: TypeScript
- Styling: Tailwind CSS
- UI Components: shadcn/ui
- CMS: Sanity (for blog content)
- Animations: Framer Motion
- Deployment: Cloudflare Pages
Architecture Overview
Core Concepts
App Router Structure
- File-based routing with RSC support
- Route groups for organization
- Metadata API for SEO
Server Components
- Default to server components
- Client components only when needed
- Optimized bundle size
Static Generation
- All pages statically generated
- Excellent performance
- SEO optimized
Project Structure
src/
├── app/ # App Router pages
│ ├── (main)/ # Main layout group
│ │ ├── contact/ # Contact page
│ │ ├── demo/ # Demo request
│ │ ├── faq/ # FAQ page
│ │ ├── newsletter/ # Newsletter signup
│ │ ├── page.tsx # Homepage
│ │ └── layout.tsx # Shared layout
│ ├── early-access/ # Standalone page
│ │ └── page.tsx
│ ├── layout.tsx # Root layout
│ └── globals.css # Global styles
├── components/
│ ├── animations/ # Interactive demos
│ ├── sections/ # Page sections
│ └── ui/ # shadcn/ui components
└── lib/
└── utils.ts # Utility functionsKey Features
Blog System
- Sanity CMS integration for content management
- Server-side pagination and search
- Author profiles and category filtering
- Responsive grid layouts and loading states
Homepage Components
Hero Section
- Value proposition
- Primary CTA
- Background animations
Features Section
- Interactive feature demos
- Animated on scroll
- Responsive grid layout
Event Types
- Supported event categories
- Visual cards
- Use case examples
Interactive Animations
Located in src/components/animations/:
- AI suggestions demo
- Drag & drop visualization
- Collaboration preview
- Vendor search animation
Early Access Page
Standalone landing page with:
- Unique layout (no nav/footer)
- Signup form with validation
- Confetti celebration effect
- Vision statement
Documentation: Early Access Feature
Development Workflow
Available Scripts
bash
npm run dev # Start dev server
npm run build # Build for production
npm run start # Start production server
npm run lint # Run ESLint
npm run format # Format with PrettierEnvironment Variables
Required variables in .env.local:
bash
NEXT_PUBLIC_API_URL=http://localhost:3333
NEXT_PUBLIC_APP_URL=http://localhost:5173Feature Flags:
bash
# Early Access Redirects
ENABLE_GLOBAL_REDIRECTS=true
# Analytics (optional)
NEXT_PUBLIC_ENABLE_ANALYTICS=true
NEXT_PUBLIC_ANALYTICS_ID=your_analytics_id
NEXT_PUBLIC_GTM_ID=your_gtm_idSEO & Performance
Metadata API
Each page uses Next.js Metadata API:
typescript
export const metadata: Metadata = {
title: 'Jubiloop - Event Planning Made Simple',
description: 'Collaborative event planning platform',
}Image Optimization
- Next.js Image component for automatic optimization
- Proper alt texts for accessibility
- Lazy loading by default
Performance Features
- Static generation for all pages
- Automatic code splitting
- Font optimization
- CSS optimization
Deployment
The marketing site deploys to Cloudflare Pages:
Build Process
- Next.js static export
- Optimized for edge runtime
- Environment variables injected
Deployment
- Automatic on push to branches
- Preview deployments for PRs
- Separate projects per environment
Common Tasks
Adding a New Page
- Create directory in
app/(main)/ - Add
page.tsxwith metadata - Update navigation if needed
Creating Animations
- Add component to
components/animations/ - Use Framer Motion for effects
- Ensure performance on mobile
Updating Content
Most content is in the page components:
- Homepage:
app/(main)/page.tsx - FAQ:
app/(main)/faq/page.tsx - Contact:
app/(main)/contact/page.tsx
API Integration
Shared API Client Architecture
The marketing site uses the @jubiloop/api-client package for consistent API communication with minimal configuration overhead.
Marketing Site Configuration
Located in src/lib/api/setup.ts:
typescript
import { createApiPackage } from '@jubiloop/api-client'
export const api = createApiPackage({
baseURL: process.env.NEXT_PUBLIC_API_URL || 'https://api.jubiloop.localhost',
withCredentials: true,
})
// Export hooks and client for use in components
export const { useHealthCheck, useDetailedHealth } = api.hooks
export const apiClient = api.clientKey Marketing Site Characteristics:
- Minimal Configuration: Uses package defaults without custom auth handling
- Public Content: No need for session management or auth invalidation
- CSRF Protection: Still enabled for form submissions (newsletter, contact)
- Server Components: Can make API calls during SSR when needed
Usage Examples
typescript
// In a server component (for SSR/SSG)
import { apiClient } from '@/lib/api/setup'
async function HomePage() {
const response = await apiClient.get('/public/stats')
return <div>{/* Render with data */}</div>
}
// In a client component (for dynamic data)
'use client'
import { useHealthCheck } from '@/lib/api/setup'
function HealthStatus() {
const { data, isLoading } = useHealthCheck()
return <div>{/* Show health status */}</div>
}
// For form submissions
import { apiClient } from '@/lib/api/setup'
async function handleNewsletterSignup(email: string) {
// CSRF token automatically included
await apiClient.post('/newsletter/subscribe', { email })
}Best Practices
Performance First
- Minimize client components
- Optimize images and fonts
- Monitor bundle size
SEO Optimization
- Use semantic HTML
- Add proper metadata
- Implement structured data
Accessibility
- ARIA labels where needed
- Keyboard navigation
- Color contrast compliance
Responsive Design
- Mobile-first approach
- Test on various devices
- Use Tailwind breakpoints
Future Enhancements
- Analytics integration (GA4/Plausible)
- A/B testing framework
- Blog/content system
- Internationalization
- Email service integration