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
/swaggerendpoint
Authentication Flow
- User authenticates via AWS Cognito (use
@aws-amplify/authoramazon-cognito-identity-js) - Receive JWT token from Cognito
- Include token in all API requests:
Authorization: Bearer {token} - Token expires - refresh using Cognito refresh token
Recommended Tech Stack
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.mdfor 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 entriesGET /api/social/posts- Recent postsGET /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 entriesPOST /api/fishinglog/entries- Create entryGET /api/fishinglog/entries/{id}- Get entryPUT /api/fishinglog/entries/{id}- Update entryDELETE /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 feedPOST /api/social/posts- Create postPOST /api/social/posts/{id}/like- Like postPOST /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 tournamentsGET /api/tournament/{id}- Tournament detailsPOST /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 chartersPOST /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 rodsGET /api/gear/reels- Get reelsGET /api/gear/setups- Get setupsPOST /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 profilePUT /api/userprofile/me- Update profileGET /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
- User initiates action (register for tournament, book charter)
- Backend creates payment intent and returns
clientSecret - Frontend renders Stripe Payment Element
- User enters payment details
- Frontend confirms payment with Stripe
- Webhook updates backend (async)
- 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
- Always check flags before rendering features
- Use FeatureGate component for conditional rendering
- Cache flags for 5 minutes (matches backend)
- Handle loading/error states gracefully
- Default to false if flags unavailable
Stripe Payments
- Never expose secret keys - only use publishable key
- Handle payment errors gracefully
- Poll for payment status if needed (webhooks are async)
- Use test cards during development
- Show clear success/error messages
Authentication
- Store tokens securely (httpOnly cookies preferred)
- Implement automatic token refresh
- Handle 401 errors by redirecting to login
- Clear tokens on logout
- 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)