Skip to main content

Web Application Frontend Build Prompt

Use this prompt when building the FishingLog web application (Progressive Web App).

Project Overview

FishingLog Web App is a comprehensive fishing log and social platform web application. Users can track fishing trips, catches, gear, participate in tournaments, connect with other anglers, and access fishing regulations.

Backend API

  • Base URL: https://api.fishinglog.com/api (or configured via environment variable)
  • Authentication: AWS Cognito JWT Bearer tokens
  • User Pool ID: us-east-2_TZtGx1T3X
  • Client ID: 6i1opt39o2n5h5ihq471l1ev07
  • Swagger Docs: Available at /swagger endpoint

Authentication Flow

  1. User authenticates via AWS Cognito (use @aws-amplify/auth or amazon-cognito-identity-js)
  2. Receive JWT token from Cognito
  3. Include token in all API requests: Authorization: Bearer {token}
  4. Token expires - refresh using Cognito refresh token

Framework

  • React (v18+) with TypeScript
  • Next.js (recommended) or Vite + React Router
  • Tailwind CSS - Styling
  • TamaGUI (Pro version) - Component library

State Management

  • TanStack Query (React Query) - Server state
  • Zustand or Jotai - Client state (if needed)
  • React Context - Auth state

Forms & Validation

  • react-hook-form - Form management
  • zod - Schema validation

API Client

  • axios or fetch with interceptors
  • Auto token refresh
  • Error handling

Maps

  • Google Maps or Mapbox - Map integration
  • react-map-gl (Mapbox) or @react-google-maps/api

Charts

  • recharts or Chart.js - Data visualization
  • @tanstack/react-charts - Advanced charts

File Uploads

  • react-dropzone - File uploads
  • Direct S3 uploads (if backend supports)

Payments

  • @stripe/stripe-js - Stripe integration
  • @stripe/react-stripe-js - Stripe React components

Feature Flags

  • Feature flag hooks for conditional rendering
  • See feature-flags.md for implementation guide

Project Structure

src/
├── app/ # Next.js app directory (if using Next.js)
│ ├── (auth)/
│ │ ├── login/
│ │ ├── register/
│ │ └── layout.tsx
│ ├── (dashboard)/
│ │ ├── dashboard/
│ │ ├── fishing-log/
│ │ ├── circles/
│ │ ├── tournaments/
│ │ └── layout.tsx
│ └── api/ # API routes (if needed)
├── components/
│ ├── ui/ # Reusable UI components
│ ├── fishing/ # Fishing-specific components
│ │ ├── FishingLogEntry/
│ │ ├── CatchDetail/
│ │ └── GearSetup/
│ ├── social/ # Social components
│ │ ├── Post/
│ │ ├── Comment/
│ │ └── Feed/
│ ├── payments/ # Payment components
│ │ ├── PaymentForm/
│ │ └── RefundStatus/
│ └── layout/ # Layout components
├── lib/
│ ├── api/ # API client
│ │ ├── client.ts
│ │ └── endpoints/
│ │ ├── fishingLog.ts
│ │ ├── social.ts
│ │ ├── tournaments.ts
│ │ └── payments.ts
│ ├── auth/ # Auth utilities
│ ├── stripe/ # Stripe utilities
│ └── utils/ # Utilities
├── hooks/
│ ├── useAuth.ts
│ ├── useFeatureFlags.ts
│ ├── useFishingLog.ts
│ └── usePayments.ts
├── store/ # State management
│ ├── authStore.ts
│ └── uiStore.ts
├── types/ # TypeScript types
└── styles/ # Global styles

Core Features & Implementation

1. Authentication

Implementation:

  • Login/Register pages
  • Password reset flow
  • Token management (localStorage or httpOnly cookies)
  • Protected routes
  • Auth context/provider

Key Endpoints:

  • Cognito authentication (not API endpoint)
  • GET /api/userprofile/me - Get current user

Components:

  • Login form
  • Register form
  • Password reset form
  • Protected route wrapper

2. Dashboard

Page: /dashboard

Features:

  • Recent fishing log entries
  • Quick stats (total catches, species, etc.)
  • Recent social posts
  • Upcoming tournaments
  • Quick actions

Key Endpoints:

  • GET /api/fishinglog/entries - Recent entries
  • GET /api/social/posts - Recent posts
  • GET /api/tournament/upcoming - Upcoming tournaments

3. Fishing Log

Pages:

  • /fishing-log - List of entries
  • /fishing-log/new - Create entry
  • /fishing-log/{id} - Entry detail

Features:

  • Create fishing log entries
  • Add catch details with photos
  • Link to gear setups
  • Set visibility (Public, Private, Friends, Circle)
  • Filter by date, species, location
  • Map view of fishing locations

Key Endpoints:

  • GET /api/fishinglog/entries - Get entries
  • POST /api/fishinglog/entries - Create entry
  • GET /api/fishinglog/entries/{id} - Get entry
  • PUT /api/fishinglog/entries/{id} - Update entry
  • DELETE /api/fishinglog/entries/{id} - Delete entry

Feature Flag Check:

import { FeatureGate } from '@/components/FeatureGate';

function FishingLogPage() {
return (
<FeatureGate feature="FishingLog">
<FishingLogContent />
</FeatureGate>
);
}

4. Social Features

Pages:

  • /feed - Social feed
  • /posts/{id} - Post detail
  • /circles - Circles (if enabled)

Features:

  • Create posts with photos
  • Comment and like posts
  • Share to circles (if Circles feature enabled)
  • Follow users
  • View user profiles

Key Endpoints:

  • GET /api/social/posts - Get feed
  • POST /api/social/posts - Create post
  • POST /api/social/posts/{id}/like - Like post
  • POST /api/social/posts/{id}/comments - Add comment

Circles Feature (Feature Flagged):

import { useFeatureFlag } from '@/hooks/useFeatureFlags';

function Navigation() {
const circlesEnabled = useFeatureFlag('Circles');

return (
<nav>
<Link to="/feed">Feed</Link>
{circlesEnabled && <Link to="/circles">Circles</Link>}
<Link to="/tournaments">Tournaments</Link>
</nav>
);
}

5. Tournaments

Pages:

  • /tournaments - List tournaments
  • /tournaments/{id} - Tournament detail
  • /tournaments/{id}/register - Registration with payment

Features:

  • Browse tournaments
  • Register for tournaments
  • Pay entry fees via Stripe
  • View tournament results
  • Submit catches for tournaments

Key Endpoints:

  • GET /api/tournament - List tournaments
  • GET /api/tournament/{id} - Tournament details
  • POST /api/tournament/{id}/register - Register (creates payment intent)

Stripe Payment Integration:

// components/payments/TournamentPaymentForm.tsx
import { Elements, PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!);

function TournamentRegistration({ tournamentId }: { tournamentId: number }) {
const [clientSecret, setClientSecret] = useState<string | null>(null);

const handleRegister = async () => {
// Create registration and payment intent
const response = await fetch(`/api/tournament/${tournamentId}/register`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}` },
body: JSON.stringify({ /* registration data */ })
});

const data = await response.json();
setClientSecret(data.stripeClientSecret);
};

if (clientSecret) {
return (
<Elements stripe={stripePromise} options={{ clientSecret }}>
<PaymentForm tournamentId={tournamentId} />
</Elements>
);
}

return <button onClick={handleRegister}>Register</button>;
}

function PaymentForm({ tournamentId }: { tournamentId: number }) {
const stripe = useStripe();
const elements = useElements();

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();

if (!stripe || !elements) return;

const { error, paymentIntent } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: `${window.location.origin}/tournament/${tournamentId}/success`,
},
redirect: 'if_required',
});

if (error) {
showError(error.message);
} else if (paymentIntent.status === 'succeeded') {
// Payment succeeded - webhook will update registration
showSuccess('Registration confirmed!');
}
};

return (
<form onSubmit={handleSubmit}>
<PaymentElement />
<button type="submit" disabled={!stripe}>
Pay Entry Fee
</button>
</form>
);
}

6. Charter Bookings

Pages:

  • /charters - Browse charters
  • /charters/{id} - Charter detail
  • /charters/{id}/book - Booking with payment

Features:

  • Browse charter listings
  • Book charter trips
  • Pay via Stripe
  • View booking history

Key Endpoints:

  • GET /api/charter/listings - List charters
  • POST /api/charter/listings/{id}/book - Create booking (creates payment intent)

Feature Flag Check:

<FeatureGate feature="Charters">
<CharterListings />
</FeatureGate>

7. Gear Management

Pages:

  • /gear - Gear catalog
  • /gear/setups - My gear setups
  • /gear/setups/new - Create setup

Features:

  • Browse gear catalog (rods, reels, lures, etc.)
  • Create custom gear setups
  • Link setups to catches
  • Track gear usage

Key Endpoints:

  • GET /api/gear/rods - Get rods
  • GET /api/gear/reels - Get reels
  • GET /api/gear/setups - Get setups
  • POST /api/gear/setups - Create setup

8. User Profile

Pages:

  • /profile - My profile
  • /profile/{userId} - Other user's profile

Features:

  • View/edit profile
  • View fishing statistics
  • View personal bests
  • View gear collection
  • View social posts

Key Endpoints:

  • GET /api/userprofile/me - My profile
  • PUT /api/userprofile/me - Update profile
  • GET /api/userprofile/{userId} - Other user's profile

Feature Flags Implementation

Feature Flag Hook

// hooks/useFeatureFlags.ts
import { useQuery } from '@tanstack/react-query';

export function useFeatureFlags() {
return useQuery({
queryKey: ['featureFlags'],
queryFn: async () => {
const response = await fetch('/api/admin/feature-flags/current-environment', {
headers: { 'Authorization': `Bearer ${token}` }
});
const data = await response.json();
return data.featureFlags;
},
staleTime: 5 * 60 * 1000, // Cache for 5 minutes
});
}

export function useFeatureFlag(featureKey: string) {
const { data: flags } = useFeatureFlags();
return flags?.[featureKey] ?? false;
}

Feature Gate Component

// components/FeatureGate.tsx
import { useFeatureFlag } from '@/hooks/useFeatureFlags';

interface FeatureGateProps {
feature: string;
children: React.ReactNode;
fallback?: React.ReactNode;
}

export function FeatureGate({ feature, children, fallback = null }: FeatureGateProps) {
const isEnabled = useFeatureFlag(feature);

if (!isEnabled) {
return <>{fallback}</>;
}

return <>{children}</>;
}

Usage Examples

// Conditional navigation
const navigationItems = [
{ path: '/dashboard', label: 'Dashboard' },
{ path: '/circles', label: 'Circles', feature: 'Circles' },
{ path: '/tournaments', label: 'Tournaments', feature: 'Tournaments' },
].filter(item => !item.feature || useFeatureFlag(item.feature));

// Conditional routes (Next.js)
// app/circles/page.tsx
import { redirect } from 'next/navigation';
import { useFeatureFlag } from '@/hooks/useFeatureFlags';

export default function CirclesPage() {
const isEnabled = useFeatureFlag('Circles');

if (!isEnabled) {
redirect('/404');
}

return <CirclesContent />;
}

Stripe Payment Integration

Setup

// lib/stripe.ts
import { loadStripe } from '@stripe/stripe-js';

export const stripePromise = loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!
);

Payment Flow Pattern

  1. User initiates action (register for tournament, book charter)
  2. Backend creates payment intent and returns clientSecret
  3. Frontend renders Stripe Payment Element
  4. User enters payment details
  5. Frontend confirms payment with Stripe
  6. Webhook updates backend (async)
  7. Frontend shows success/redirects

Error Handling

const handleStripeError = (error: StripeError) => {
switch (error.type) {
case 'card_error':
showError(error.message);
break;
case 'validation_error':
showError('Please check your payment details');
break;
case 'api_error':
showError('Payment service temporarily unavailable');
break;
default:
showError('An unexpected error occurred');
}
};

API Client Setup

// lib/api/client.ts
import axios from 'axios';

export const apiClient = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL || 'https://api.fishinglog.com/api',
});

apiClient.interceptors.request.use(async (config) => {
const token = await getAuthToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});

apiClient.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response?.status === 401) {
// Handle token refresh
await refreshToken();
return apiClient.request(error.config);
}
return Promise.reject(error);
}
);

Environment Variables

NEXT_PUBLIC_API_URL=https://api.fishinglog.com/api
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
NEXT_PUBLIC_COGNITO_USER_POOL_ID=us-east-2_TZtGx1T3X
NEXT_PUBLIC_COGNITO_CLIENT_ID=6i1opt39o2n5h5ihq471l1ev07

Implementation Checklist

Phase 1: Foundation

  • Initialize Next.js/Vite project with TypeScript
  • Set up TamaGUI and Tailwind CSS
  • Configure API client with auth interceptors
  • Set up TanStack Query
  • Create auth context/provider
  • Implement protected routes
  • Set up error handling

Phase 2: Core Features

  • Implement authentication flow
  • Build dashboard
  • Create fishing log entry forms
  • Build social feed
  • Implement feature flag hooks/components
  • Add conditional rendering based on flags

Phase 3: Payments & Advanced Features

  • Integrate Stripe payments
  • Implement tournament registration with payment
  • Build charter booking flow
  • Add gear management
  • Build user profiles

Phase 4: Polish

  • Add loading states
  • Implement error boundaries
  • Add toast notifications
  • Optimize performance (code splitting, lazy loading)
  • Add analytics tracking
  • Implement error logging (Sentry)

Critical Implementation Notes

Feature Flags

  1. Always check flags before rendering features
  2. Use FeatureGate component for conditional rendering
  3. Cache flags for 5 minutes (matches backend)
  4. Handle loading/error states gracefully
  5. Default to false if flags unavailable

Stripe Payments

  1. Never expose secret keys - only use publishable key
  2. Handle payment errors gracefully
  3. Poll for payment status if needed (webhooks are async)
  4. Use test cards during development
  5. Show clear success/error messages

Authentication

  1. Store tokens securely (httpOnly cookies preferred)
  2. Implement automatic token refresh
  3. Handle 401 errors by redirecting to login
  4. Clear tokens on logout
  5. Validate token expiration before API calls

Testing

Feature Flags

  • Test with flags enabled/disabled
  • Test flag loading states
  • Verify features are hidden when disabled

Stripe Payments

  • Use test cards: 4242 4242 4242 4242 (success)
  • Test payment failures
  • Verify webhook updates (check backend logs)

Documentation References

  • Web App Guide: docs/frontend/web-app.md
  • Stripe Integration: docs/frontend/stripe-integration.md
  • Feature Flags: docs/frontend/feature-flags.md
  • Backend API: docs/api/README.md

Success Criteria

A successful web app implementation should:

  • ✅ Handle authentication and token management
  • ✅ Respect feature flags for all features
  • ✅ Integrate Stripe payments correctly
  • ✅ Handle errors gracefully
  • ✅ Provide good user feedback
  • ✅ Be responsive and performant
  • ✅ Follow accessibility best practices
  • ✅ Work offline (PWA features)