🚀 Complete App Rebuild Prompt
Your backup prompt to rebuild the entire MatchPlay Pro AI application from scratch
# MATCHPLAY PRO AI - COMPLETE APPLICATION REBUILD PROMPT
## APPLICATION OVERVIEW
Build a comprehensive performance analytics and tracking platform for racket sports players called "MatchPlay Pro AI". The app supports 5 sports: Table Tennis, Tennis, Badminton, Squash, and Pickleball (with Paddle as 6th). It provides match tracking, opponent intelligence, coaching resources, AI-powered insights, social networking, and team/fixture management.
## TECHNOLOGY STACK
### Frontend
- React 18.2.0
- React Router DOM 6.26.0
- @tanstack/react-query 5.84.1 for state management
- Tailwind CSS + shadcn/ui components
- Framer Motion 11.16.4 for animations
- React Hook Form 7.54.2
- Recharts 2.15.4 for charts
- Lucide React 0.475.0 for icons
- date-fns 3.6.0
- React Markdown 9.0.1
- React Leaflet 4.2.1
- @hello-pangea/dnd 17.0.0
### Backend & Infrastructure
- Base44 BaaS platform
- @base44/sdk 0.8.6
- Deno Deploy for backend functions
- PostgreSQL via Base44 Entity System
- Base44 Auth (Email/Password)
- Supabase Storage for files
- Stripe for payments
- Base44 InvokeLLM for AI features
## PROJECT STRUCTURE
```
entities/ # JSON schemas for data models
pages/ # Route pages (FLAT - no subfolders)
components/ # Reusable components (CAN have subfolders)
ui/ # shadcn/ui components
dashboard/ # Dashboard widgets
social/ # Social network components
sport/ # Sport configuration
language/ # Multi-language support
admin/ # Admin components
coach/ # Coaching components
partners/ # Partner widgets
auth/ # Authentication
functions/ # Backend Deno functions
agents/ # AI agent configs
Layout.jsx # App layout wrapper
globals.css # Global styles
```
## CRITICAL ARCHITECTURE PRINCIPLES
### 1. Multi-Sport Support
- Sport configuration system in components/sport/sportConfig.js
- Provides sport-specific: terminology, colors, scoring rules, playing styles, equipment
- SportContext provider manages current sport selection
- All entities have `sport` field for filtering
- User.preferred_sport persists selection
### 2. Multi-Language Support
- LanguageContext provider with translation function t(key)
- Supports: en, es, fr, de, it, pt, nl, ru, zh, ja, ko
- translations.js contains all translation keys
- Persists in User profile and localStorage
### 3. Row Level Security (RLS)
- Entity-level security enforced automatically
- Pattern: created_by = {{user.email}} for user-owned data
- User roles: "admin" | "user"
- Admin can access all data, users only their own
### 4. Component-First Design
- Small, focused, reusable components
- Dashboard widgets are independent
- Forms use React Hook Form
- UI from shadcn/ui library
## COMPLETE ENTITY SCHEMAS
### User (Built-in - Extend Only)
```json
{
"name": "User",
"type": "object",
"properties": {
"preferred_sport": { "type": "string" },
"bio": { "type": "string" },
"location": { "type": "string" },
"country": { "type": "string" },
"profile_image_url": { "type": "string" },
"phone": { "type": "string" },
"clubs": { "type": "array", "items": { "type": "string" } },
"teams": { "type": "array", "items": { "type": "string" } },
"leagues": { "type": "array", "items": { "type": "string" } },
"playing_level": {
"type": "string",
"enum": ["beginner", "intermediate", "advanced", "expert", "professional"]
},
"onboarding_completed": { "type": "boolean", "default": false },
"has_seen_welcome": { "type": "boolean", "default": false },
"show_profile_publicly": { "type": "boolean", "default": true },
"show_match_stats_publicly": { "type": "boolean", "default": false }
}
}
```
### Match
```json
{
"name": "Match",
"type": "object",
"properties": {
"opponent_id": { "type": "string" },
"opponent_partner_id": { "type": "string" },
"player_partner_id": { "type": "string" },
"sport": {
"type": "string",
"enum": ["tabletennis", "tennis", "badminton", "squash", "pickleball", "paddle"]
},
"match_format": { "type": "string", "enum": ["singles", "doubles"], "default": "singles" },
"match_date": { "type": "string", "format": "date" },
"location": { "type": "string" },
"match_type": {
"type": "string",
"enum": ["friendly", "league", "tournament", "practice", "custom"],
"default": "friendly"
},
"league_name": { "type": "string" },
"tournament_name": { "type": "string" },
"custom_match_type": { "type": "string" },
"weather_conditions": {
"type": "string",
"enum": ["sunny", "cloudy", "overcast", "light_rain", "windy", "hot", "cold", "indoors"]
},
"playing_surface": {
"type": "string",
"enum": ["hard_court", "clay_court", "grass_court", "carpet", "artificial_grass"]
},
"court_number": { "type": "string" },
"ball_brand": { "type": "string" },
"sets": {
"type": "array",
"items": {
"type": "object",
"properties": {
"player_score": { "type": "number" },
"opponent_score": { "type": "number" },
"games": { "type": "string" }
}
}
},
"final_result": { "type": "string", "enum": ["win", "loss"] },
"duration_minutes": { "type": "number" },
"player_serves_first": { "type": "boolean" },
"video_urls": { "type": "array", "items": { "type": "string" } },
"notes": { "type": "string" },
"show_on_profile": { "type": "boolean", "default": false }
},
"required": ["opponent_id", "sport", "match_date", "sets", "final_result"],
"rls": {
"create": { "created_by": "{{user.email}}" },
"read": { "created_by": "{{user.email}}" },
"update": { "created_by": "{{user.email}}" },
"delete": { "created_by": "{{user.email}}" },
"write": { "created_by": "{{user.email}}" }
}
}
```
### Opponent
```json
{
"name": "Opponent",
"type": "object",
"properties": {
"name": { "type": "string" },
"sport": { "type": "string" },
"playing_style": {
"type": "array",
"items": {
"type": "string",
"enum": ["aggressive", "defensive", "all_around", "counter_attacker", "chopper", "modern_defender", "blocker"]
}
},
"dominant_hand": { "type": "string", "enum": ["right", "left"], "default": "right" },
"club": { "type": "string" },
"skill_level": {
"type": "string",
"enum": ["beginner", "intermediate", "advanced", "expert", "professional"]
},
"bat_rubbers_setup": {
"type": "string",
"enum": ["normal_both_sides", "combination_long_pips", "combination_short_pips", "combination_anti", "combination_short_long_pips"],
"default": "normal_both_sides"
},
"strengths": { "type": "array", "items": { "type": "string" } },
"weaknesses": { "type": "array", "items": { "type": "string" } },
"notes": { "type": "string" },
"serve_notes": { "type": "string" },
"receive_notes": { "type": "string" },
"forehand_notes": { "type": "string" },
"backhand_notes": { "type": "string" },
"footwork_notes": { "type": "string" },
"mental_game": { "type": "string" },
"general_notes": { "type": "string" },
"skill_rating": { "type": "number", "minimum": 1, "maximum": 10 },
"avatar_color": { "type": "string", "default": "#10B981" },
"last_scouted_at": { "type": "string", "format": "date-time" },
"scouting_notes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"date": { "type": "string", "format": "date-time" },
"note": { "type": "string" }
}
}
},
"opponent_video_clips": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"url": { "type": "string" },
"title": { "type": "string" },
"added_date": { "type": "string", "format": "date-time" }
}
}
}
},
"required": ["name", "sport"],
"rls": {
"create": { "created_by": "{{user.email}}" },
"read": { "created_by": "{{user.email}}" },
"update": { "created_by": "{{user.email}}" },
"delete": { "created_by": "{{user.email}}" },
"write": { "created_by": "{{user.email}}" }
}
}
```
### PlayerNetworkPost (Social Feed)
```json
{
"name": "PlayerNetworkPost",
"type": "object",
"properties": {
"author_email": { "type": "string" },
"author_name": { "type": "string" },
"author_avatar": { "type": "string" },
"content": { "type": "string" },
"image_url": { "type": "string" },
"sport": {
"type": "string",
"enum": ["tabletennis", "tennis", "badminton", "squash", "pickleball", "paddle"]
},
"likes_count": { "type": "number", "default": 0 },
"comments_count": { "type": "number", "default": 0 },
"is_trending": { "type": "boolean", "default": false }
},
"required": ["content", "author_email", "author_name", "sport"],
"rls": {
"create": { "created_by": "{{user.email}}" },
"update": { "created_by": "{{user.email}}" },
"delete": { "created_by": "{{user.email}}" },
"write": { "created_by": "{{user.email}}" }
}
}
```
### Comment
```json
{
"name": "Comment",
"type": "object",
"properties": {
"post_id": { "type": "string" },
"author_email": { "type": "string" },
"author_name": { "type": "string" },
"author_avatar": { "type": "string" },
"content": { "type": "string" },
"likes_count": { "type": "number", "default": 0 }
},
"required": ["post_id", "author_email", "author_name", "content"],
"rls": {
"create": { "created_by": "{{user.email}}" },
"update": { "created_by": "{{user.email}}" },
"delete": { "created_by": "{{user.email}}" },
"write": { "created_by": "{{user.email}}" }
}
}
```
### PostLike
```json
{
"name": "PostLike",
"type": "object",
"properties": {
"post_id": { "type": "string" },
"user_email": { "type": "string" }
},
"required": ["post_id", "user_email"],
"rls": {
"create": { "created_by": "{{user.email}}" },
"delete": { "created_by": "{{user.email}}" },
"write": { "created_by": "{{user.email}}" }
}
}
```
### Follow
```json
{
"name": "Follow",
"type": "object",
"properties": {
"follower_email": { "type": "string" },
"following_email": { "type": "string" },
"status": { "type": "string", "default": "accepted" }
},
"required": ["follower_email", "following_email"],
"rls": {
"create": { "created_by": "{{user.email}}" },
"read": {
"$or": [
{ "follower_email": "{{user.email}}" },
{ "following_email": "{{user.email}}" }
]
},
"update": { "following_email": "{{user.email}}" },
"delete": {
"$or": [
{ "follower_email": "{{user.email}}" },
{ "following_email": "{{user.email}}" }
]
},
"write": { "created_by": "{{user.email}}" }
}
}
```
### Coach
```json
{
"name": "Coach",
"type": "object",
"properties": {
"user_email": { "type": "string" },
"full_name": { "type": "string" },
"sport": {
"type": "string",
"enum": ["tabletennis", "tennis", "badminton", "squash", "pickleball", "paddle"]
},
"specialty": { "type": "string" },
"bio": { "type": "string" },
"experience_years": { "type": "number" },
"certifications": { "type": "array", "items": { "type": "string" } },
"playing_level": {
"type": "string",
"enum": ["recreational", "club", "regional", "national", "international"]
},
"coaching_style": { "type": "array", "items": { "type": "string" } },
"hourly_rate": { "type": "number" },
"rate_currency": {
"type": "string",
"enum": ["GBP", "USD", "EUR", "AUD", "CAD"],
"default": "GBP"
},
"location": { "type": "string" },
"availability": {
"type": "object",
"properties": {
"online": { "type": "boolean" },
"in_person": { "type": "boolean" }
}
},
"contact_email": { "type": "string" },
"phone": { "type": "string" },
"hide_email": { "type": "boolean", "default": false },
"hide_phone": { "type": "boolean", "default": false },
"social_links": {
"type": "object",
"properties": {
"facebook": { "type": "string" },
"twitter": { "type": "string" },
"instagram": { "type": "string" },
"linkedin": { "type": "string" },
"youtube": { "type": "string" },
"website": { "type": "string" }
}
},
"show_social_links": { "type": "boolean", "default": true },
"profile_image_url": { "type": "string" },
"video_intro_url": { "type": "string" },
"youtube_video_urls": { "type": "array", "items": { "type": "string" } },
"rating": { "type": "number", "default": 0 },
"total_sessions": { "type": "number", "default": 0 },
"total_reviews": { "type": "number", "default": 0 },
"languages": { "type": "array", "items": { "type": "string" } },
"approved": { "type": "boolean", "default": true },
"hidden": { "type": "boolean", "default": false },
"featured": { "type": "boolean", "default": false },
"avatar_color": { "type": "string", "default": "#3B82F6" },
"has_premium": { "type": "boolean", "default": false },
"premium_granted_at": { "type": "string", "format": "date-time" }
},
"required": ["user_email", "full_name", "sport", "specialty", "hourly_rate"]
}
```
### Fixture
```json
{
"name": "Fixture",
"type": "object",
"properties": {
"team_id": { "type": "string" },
"opponent_name": { "type": "string" },
"sport": { "type": "string" },
"fixture_date": { "type": "string", "format": "date" },
"fixture_time": { "type": "string" },
"venue": { "type": "string" },
"competition_type": {
"type": "string",
"enum": ["league", "cup", "friendly", "tournament"],
"default": "league"
},
"league_name": { "type": "string" },
"team_name": { "type": "string" },
"home_away": { "type": "string", "enum": ["home", "away"], "default": "home" },
"notes": { "type": "string" },
"result": { "type": "string" },
"status": {
"type": "string",
"enum": ["scheduled", "completed", "cancelled", "postponed"],
"default": "scheduled"
},
"reminder_sent": { "type": "boolean", "default": false }
},
"required": ["opponent_name", "sport", "fixture_date"],
"rls": {
"create": { "created_by": "{{user.email}}" },
"read": { "created_by": "{{user.email}}" },
"update": { "created_by": "{{user.email}}" },
"delete": { "created_by": "{{user.email}}" },
"write": { "created_by": "{{user.email}}" }
}
}
```
### My_Teams
```json
{
"name": "My_Teams",
"type": "object",
"properties": {
"team_name": { "type": "string" },
"league_name": { "type": "string" },
"league_url": { "type": "string" },
"sport": {
"type": "string",
"enum": ["tabletennis", "tennis", "badminton", "squash", "pickleball", "paddle"]
},
"color": { "type": "string", "default": "#3B82F6" },
"last_sync_date": { "type": "string", "format": "date-time" }
},
"required": ["team_name", "sport"],
"rls": {
"create": { "created_by": "{{user.email}}" },
"read": { "created_by": "{{user.email}}" },
"update": { "created_by": "{{user.email}}" },
"delete": { "created_by": "{{user.email}}" },
"write": { "created_by": "{{user.email}}" }
}
}
```
[CONTINUE WITH ALL OTHER ENTITIES: Drill, Resource, Event, Club, Advertisement, Sponsor, Partner, Referral, etc.]
## LAYOUT STRUCTURE
Layout.jsx wraps all pages with:
```jsx
<LanguageProvider>
<SportProvider>
<LayoutContent>
{children}
</LayoutContent>
</SportProvider>
</LanguageProvider>
```
Features:
- Collapsible sidebar menu with sections: General, My Activity, Community, Admin & Coaching
- Sport selector for authenticated users
- User account menu
- Dashboard navigation bar
- Responsive design
- Dynamic menu items based on auth status and role
## CONTEXT PROVIDERS
### SportContext (components/sport/SportContext.jsx)
```jsx
const SportContext = createContext();
export const useSport = () => useContext(SportContext);
export const SportProvider = ({ children }) => {
const [currentSport, setCurrentSport] = useState('tabletennis');
const [sportConfig, setSportConfig] = useState(getSportConfig('tabletennis'));
const changeSport = async (sportId) => {
setCurrentSport(sportId);
setSportConfig(getSportConfig(sportId));
await User.updateMyUserData({ preferred_sport: sportId });
localStorage.setItem('preferred_sport', sportId);
};
return (
<SportContext.Provider value={{
currentSport,
sportConfig,
changeSport,
getTerm: (term) => sportConfig.terminology[term],
getScoring: () => sportConfig.scoring,
getColor: () => sportConfig.color
}}>
{children}
</SportContext.Provider>
);
};
```
### LanguageContext (components/language/LanguageContext.jsx)
```jsx
const LanguageContext = createContext();
export const useLanguage = () => useContext(LanguageContext);
export const LanguageProvider = ({ children }) => {
const [currentLanguage, setCurrentLanguage] = useState('en');
const [isLoading, setIsLoading] = useState(true);
const t = (key, placeholders = {}) => {
let text = translations[currentLanguage]?.[key] || translations.en[key] || key;
Object.keys(placeholders).forEach(placeholder => {
text = text.replace(`{{${placeholder}}}`, placeholders[placeholder]);
});
return text;
};
const changeLanguage = async (langCode) => {
setCurrentLanguage(langCode);
localStorage.setItem('language', langCode);
try {
await User.updateMyUserData({ preferred_language: langCode });
} catch (error) {
console.log('Could not save language preference');
}
};
return (
<LanguageContext.Provider value={{
currentLanguage,
t,
changeLanguage,
availableLanguages: ['en', 'es', 'fr', 'de', 'it', 'pt', 'nl', 'ru', 'zh', 'ja', 'ko'],
isLoading
}}>
{children}
</LanguageContext.Provider>
);
};
```
## KEY PAGES TO BUILD
### Public Pages
1. **Home.jsx** - Landing page with hero, features, sports showcase, screenshots, testimonials, CTA
2. **Pricing.jsx** - Subscription plans with Stripe integration
3. **CoachesLanding.jsx** - Landing page for coaches
4. **SportsTennis.jsx, SportsTableTennis.jsx, etc.** - Sport-specific landing pages using SportLandingTemplate
5. **TermsOfService.jsx, PrivacyPolicy.jsx** - Legal pages
6. **Support.jsx** - Contact form
### Authenticated Player Pages
1. **Dashboard.jsx** - Main hub with widgets, stats, charts, quick actions
2. **Matches.jsx** - Match history list with filters
3. **RecordMatch.jsx** - Add/edit match form
4. **Opponents.jsx** - Opponent directory with cards
5. **OpponentDetail.jsx** - Full opponent profile with match history
6. **PlayersHub.jsx** - Social network feed with posts, likes, comments, follow system
7. **MyTeams.jsx** - Team management
8. **AIInsights.jsx** - AI-powered performance analysis
### Community Pages
1. **Players.jsx** - Player directory
2. **UserProfile.jsx** - User profile (own & others)
3. **CoachingHub.jsx** - Coach directory, drills, resources
4. **Events.jsx** - Event listings
5. **Clubs.jsx** - Club directory
### Admin Pages
1. **AdminDashboard.jsx** - Tabbed admin control panel
## SOCIAL NETWORK IMPLEMENTATION (PLAYERS HUB)
### Pages
**PlayersHub.jsx**
```jsx
- Three tabs: Following, Trending, All Posts
- Create Post button opens CreatePostModal
- SocialFeed component renders posts based on tab
- Requires authentication (use AuthGuard)
```
### Components
**SocialFeed.jsx**
```jsx
- Fetches posts based on feedType (following/trending/all)
- Following: Posts from followed users + own posts
- Trending: Posts sorted by likes_count + comments_count
- All: All posts in current sport
- Maps posts to PostCard components
```
**PostCard.jsx**
```jsx
- Displays: Author avatar, name, timestamp, content, image
- Like button (heart icon) - creates PostLike, updates likes_count
- Comment button - toggles comment section
- Comment section: Input + existing comments
- Delete option for own posts (3-dot menu)
```
**CreatePostModal.jsx**
```jsx
- Dialog with text input and image upload
- Upload image using base44.integrations.Core.UploadFile
- Creates PlayerNetworkPost entity
- Sets: author_email, author_name, author_avatar, content, image_url, sport
```
**UserProfilePreview.jsx**
```jsx
- Compact user card with avatar, name, bio, stats
- Shows post count, follower count
- Follow/Unfollow button (creates/deletes Follow entity)
- Message button
- Link to full profile
```
## BACKEND FUNCTIONS
### Stripe Payment Functions
**createCheckoutSession.js**
```javascript
import { createClientFromRequest } from 'npm:@base44/sdk@0.8.4';
import Stripe from 'npm:stripe';
const stripe = new Stripe(Deno.env.get("STRIPE_SECRET_KEY"));
Deno.serve(async (req) => {
try {
const base44 = createClientFromRequest(req);
const user = await base44.auth.me();
if (!user) return Response.json({ error: 'Unauthorized' }, { status: 401 });
const { priceId } = await req.json();
const session = await stripe.checkout.sessions.create({
customer_email: user.email,
line_items: [{ price: priceId, quantity: 1 }],
mode: 'subscription',
success_url: `${req.headers.get('origin')}/Home?success=true`,
cancel_url: `${req.headers.get('origin')}/Pricing?canceled=true`
});
return Response.json({ url: session.url });
} catch (error) {
return Response.json({ error: error.message }, { status: 500 });
}
});
```
**stripeWebhook.js**
```javascript
import { createClientFromRequest } from 'npm:@base44/sdk@0.8.4';
import Stripe from 'npm:stripe';
const stripe = new Stripe(Deno.env.get("STRIPE_SECRET_KEY"));
const webhookSecret = Deno.env.get("STRIPE_WEBHOOK_SECRET");
Deno.serve(async (req) => {
const base44 = createClientFromRequest(req);
const sig = req.headers.get('stripe-signature');
const body = await req.text();
let event;
try {
event = await stripe.webhooks.constructEventAsync(body, sig, webhookSecret);
} catch (err) {
return Response.json({ error: 'Invalid signature' }, { status: 400 });
}
// Handle events: checkout.session.completed, invoice.paid, etc.
// Create/update Subscription and Payment entities
return Response.json({ received: true });
});
```
## BASE44 SDK USAGE PATTERNS
### Entity Operations
```javascript
import { base44 } from "@/api/base44Client";
// List all
const matches = await base44.entities.Match.list();
// Filter
const myMatches = await base44.entities.Match.filter({
sport: currentSport
}, "-match_date", 50);
// Create
const newMatch = await base44.entities.Match.create({
opponent_id: "123",
sport: "tennis",
match_date: "2025-01-15",
sets: [{ player_score: 6, opponent_score: 4 }],
final_result: "win"
});
// Update
await base44.entities.Match.update(matchId, { notes: "Great match!" });
// Delete
await base44.entities.Match.delete(matchId);
```
### Authentication
```javascript
// Get current user
const user = await base44.auth.me();
// Update current user
await base44.auth.updateMe({ bio: "Tennis enthusiast" });
// Logout
base44.auth.logout();
// Redirect to login
base44.auth.redirectToLogin();
// Check if authenticated
const isAuth = await base44.auth.isAuthenticated();
```
### Integrations
```javascript
// AI with LLM
const result = await base44.integrations.Core.InvokeLLM({
prompt: "Analyze this player's performance",
add_context_from_internet: true,
response_json_schema: { type: "object", properties: {...} }
});
// Upload file
const { file_url } = await base44.integrations.Core.UploadFile({
file: fileBlob
});
// Send email
await base44.integrations.Core.SendEmail({
to: "user@example.com",
subject: "Welcome!",
body: "Thanks for joining..."
});
// Generate image
const { url } = await base44.integrations.Core.GenerateImage({
prompt: "Tennis court aerial view",
existing_image_urls: []
});
```
## UI PATTERNS
### AuthGuard Usage
```jsx
import AuthGuard from "../components/auth/AuthGuard";
export default function ProtectedPage() {
return (
<AuthGuard title="Page Title" message="Login required" icon={IconComponent}>
{/* Page content */}
</AuthGuard>
);
}
```
### Sport Context Usage
```jsx
import { useSport } from "../components/sport/SportContext";
export default function MyComponent() {
const { currentSport, sportConfig, changeSport } = useSport();
return (
<div className={`bg-gradient-to-r ${sportConfig.gradient}`}>
<h1>{sportConfig.name}</h1>
</div>
);
}
```
### Language Context Usage
```jsx
import { useLanguage } from "../components/language/LanguageContext";
export default function MyComponent() {
const { t } = useLanguage();
return <h1>{t('dashboard.title')}</h1>;
}
```
## STYLING GUIDELINES
### Tailwind Classes
- Primary colors: cyan-500, blue-600
- Gradients: `bg-gradient-to-br from-slate-50 via-cyan-50 to-blue-50`
- Cards: `bg-white border-2 border-gray-100 rounded-lg shadow-lg`
- Buttons: `bg-gradient-to-r from-cyan-500 to-blue-600 hover:from-cyan-600 hover:to-blue-700`
### Responsive Design
- Mobile-first approach
- Use md:, lg: breakpoints
- Grid layouts: `grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3`
### Animations
```jsx
import { motion } from "framer-motion";
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
>
{/* Content */}
</motion.div>
```
## DEPLOYMENT CHECKLIST
1. Set environment variables:
- STRIPE_SECRET_KEY
- STRIPE_WEBHOOK_SECRET
2. Configure Stripe webhook endpoint
3. Test payment flow in test mode
4. Verify all backend functions deploy
5. Test RLS rules for each entity
6. Verify sport context persists
7. Test multi-language switching
8. Configure PWA manifest
## IMPORTANT NOTES
- Pages MUST be flat (no subfolders in pages/)
- Components CAN have subfolders
- Always filter by sport when fetching data
- Use @tanstack/react-query for caching
- Entity RLS rules enforce automatically
- Base44 handles auth, no manual JWT
- Use find_replace for code edits
- Keep components small and focused
- Always include loading states
- Toast notifications for user feedback
## REBUILD COMMAND
To rebuild this app from scratch, provide this entire prompt to an AI assistant with access to the Base44 platform, and request:
"Build the complete MatchPlay Pro AI application following this specification. Create all entities, pages, components, and backend functions as described. Implement all features including match tracking, opponent intelligence, social network (Players Hub), coaching platform, team fixtures, AI insights, and payment integration."📋 How to Use This Prompt
- Copy the prompt above or download it as a text file
- Save it securely as your backup documentation
- If you ever need to rebuild the app, provide this prompt to an AI assistant with Base44 access
- The AI will recreate the entire application following the specifications
- This includes all entities, pages, components, features, and integrations
