A clean, minimal surf forecasting application that provides AI-generated surf reports for St. Augustine, Florida. Built with Next.js, TypeScript, and powered by OpenAI to deliver conversational surf reports in the voice of a local surfer.
- AI-Powered Surf Reports: Natural language surf reports generated by OpenAI GPT-4 in the voice of a local surfer
- Real-time Data Integration: Live wave height, period, wind conditions, and NOAA tide information
- Smart Caching: Database-backed caching with 4-hour report cycles and 5-minute data updates
- Progressive Web App: Installable PWA with offline support and service worker caching
- Automated Updates: Cron jobs refresh data 4 times daily at optimal surf check times
- Mobile-First Design: Clean, responsive interface optimized for quick surf checks
- Frontend: Next.js 14, React, TypeScript, Tailwind CSS
- Backend: Next.js API Routes, Vercel AI SDK (OpenAI)
- Database: Neon PostgreSQL for surf report caching
- AI: OpenAI GPT-4 Mini for generating conversational surf reports
- Data Sources:
- Open-Meteo API for marine and weather data
- NOAA Tides & Currents API for real-time tide information
- State Management: TanStack Query for data fetching and caching
- Deployment: Vercel with automated cron jobs for data refresh
- Node.js 18.17 or later
- npm, yarn, or pnpm
- Neon PostgreSQL database
- OpenAI API key
Create a .env.local file in the root directory:
# Database
NEON_DATABASE_URL="postgresql://username:[email protected]/neondb?sslmode=require"
# OpenAI
OPENAI_API_KEY="sk-..."
# Cron Security (for automated updates)
CRON_SECRET="your-secure-random-string"
# Optional
NEXT_PUBLIC_API_URL="https://your-domain.com"- Clone the repository:
git clone <your-repo-url>
cd surf-lab- Install dependencies:
npm install- Set up the database:
npm run setup-db- Run the development server:
npm run dev- Open http://localhost:3000 to view the app
src/app/
βββ api/
β βββ surfability/ # Real-time surf conditions API
β βββ surf-report/ # AI-generated reports API
β βββ health/ # Health check endpoint
β βββ admin/request-forecast/ # Cron job endpoint for data refresh
βββ components/
β βββ surf/ # Surf-specific components
β β βββ SurfReportCard.tsx # Main AI report display
β β βββ StatusCard.tsx # Surf rating and score (unused)
β β βββ WeatherHeader.tsx # Weather info (unused)
β β βββ SurfDetails.tsx # Detailed conditions (unused)
β β βββ TideCard.tsx # Tide information (unused)
β βββ ui/ # Reusable UI components
β β βββ Card.tsx # Base card component
β β βββ Toast.tsx # Notification component
β β βββ LoadingShimmer.tsx # Loading states
β β βββ ErrorCard.tsx # Error handling
β βββ animations/ # Visual animations (unused)
βββ hooks/ # Custom React hooks
β βββ useSurfData.ts # Surf conditions hook (unused)
β βββ useSurfReport.ts # AI report hook
βββ lib/ # Utilities and database
β βββ db.ts # Neon database functions
β βββ utils.ts # Utility functions
βββ providers/
β βββ QueryProvider.tsx # TanStack Query setup
βββ types/ # TypeScript definitions
β βββ surf.ts # Surf data types
β βββ surf-report.ts # AI report types
βββ globals.css # Global styles
βββ layout.tsx # App layout with providers
βββ page.tsx # Main app page (simplified)
Note: The current implementation focuses on AI surf reports. Many components for detailed conditions and visualizations exist but are not actively used in the main interface.
- Cron Jobs: Automated refresh 4 times daily (5 AM, 9 AM, 1 PM, 4 PM ET)
- Surf Conditions: Fetched from Open-Meteo marine API and NOAA tides via
/api/surfability - AI Report Generation: Current conditions processed by OpenAI GPT-4 Mini via
/api/surf-report - Database Caching: Reports cached in Neon PostgreSQL for 2 hours (was 4 hours)
- Frontend: TanStack Query fetches AI reports with 4-hour cache and automatic refetch
- User Interface: Clean, minimal display focusing on the AI-generated surf report
Current State: The app primarily displays AI surf reports. While detailed surf condition components exist in the codebase, the main interface focuses on the conversational AI report for simplicity.
GET /api/surf-report- AI-generated surf report (main endpoint, cached 2 hours)GET /api/surfability- Real-time surf conditions and scoring (used by AI generation)GET /api/health- Service health checkGET /api/admin/request-forecast- Cron job endpoint for cache clearing and data refresh
Authentication: Cron endpoint requires CRON_SECRET or Vercel cron headers for security.
- Connect your repository to Vercel
- Set environment variables in Vercel dashboard
- Deploy - Vercel will automatically build and deploy
Add these cron expressions in Vercel dashboard to hit /api/admin/request-forecast:
# 4 times daily updates (Eastern Time)
0 9 * * * # 5:00 AM ET (9:00 UTC)
0 13 * * * # 9:00 AM ET (13:00 UTC)
0 17 * * * # 1:00 PM ET (17:00 UTC)
0 20 * * * # 4:00 PM ET (20:00 UTC)Each cron job clears cached reports and generates fresh data.
# Build for production
npm run build
# Start production server
npm startTo change from St. Augustine, FL to another location:
- Update coordinates in
/api/surfability/route.ts:
const marineRes = await fetch(
'https://api.open-meteo.com/v1/marine?latitude=YOUR_LAT&longitude=YOUR_LON&...'
);- Update NOAA station ID for tides:
const stationId = 'YOUR_NOAA_STATION_ID'; // Find at tidesandcurrents.noaa.gov- Update location references in AI prompts and database queries
Modify the prompt in /api/surf-report/route.ts to change:
- Voice & tone (local vs. professional, casual vs. technical)
- Content focus (beginner tips, advanced analysis, safety warnings)
- Surf spots (update spot recommendations for your area)
- Local knowledge (tides, winds, seasonal patterns specific to your region)
To show detailed surf conditions alongside the AI report, edit src/app/page.tsx:
// Add these imports and components to page.tsx
import { useSurfData } from './hooks/useSurfData';
import { StatusCard } from './components/surf/StatusCard';
import { WeatherHeader } from './components/surf/WeatherHeader';
import { SurfDetails } from './components/surf/SurfDetails';
import { TideCard } from './components/surf/TideCard';
// Then include them in your JSX alongside SurfReportCard- Offline Support: Service worker caches data and provides fallbacks
- Install Prompt: Can be installed as a native app
- Push Notifications: Ready for surf condition alerts (requires setup)
- Optimized Performance: Lazy loading, image optimization, code splitting
npm run dev- Start development servernpm run build- Build for productionnpm run start- Start production servernpm run lint- Run ESLintnpm run setup-db- Initialize Neon databasenpm run type-check- TypeScript type checking
- Marine Data: Open-Meteo Marine API
- Weather Data: Open-Meteo Weather API
- Tide Data: NOAA Tides & Currents API
- AI Reports: OpenAI GPT-4 Mini
- Lighthouse Score: 95+ across all metrics
- Core Web Vitals: Optimized for speed and user experience
- Caching Strategy: Multi-layer caching (API, database, service worker)
- Bundle Size: Optimized with code splitting and tree shaking
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Database Connection Errors:
- Verify
NEON_DATABASE_URLis correct - Check database permissions and SSL settings
OpenAI API Errors:
- Verify
OPENAI_API_KEYis valid - Check API quota and billing
Cron Jobs Not Running:
- Verify
CRON_SECRETis set in environment - Check Vercel cron configuration
Add to .env.local for detailed logging:
NODE_ENV=developmentThis project is licensed under the MIT License - see the LICENSE file for details.
- Open-Meteo for free marine weather data
- NOAA for tide information
- OpenAI for AI-powered surf reports
- Vercel for seamless deployment and hosting
- The wonderful beaches and beach community of St. Augustine, FL
Made with π for surfers, by surfers
For questions or support, please open an issue on GitHub.