Skip to content

code-gio/shoot-circle

Repository files navigation

ShootCircle - Technical Specification

Project Overview

ShootCircle is a creative talent platform that connects models, photographers, makeup artists, stylists, and producers in one place. Users can showcase their portfolios, find new projects, collaborate with other talents, and grow their creative careers.

Mission: Drive connections between creative talents and real opportunities, building a global community of visual artists.


Tech Stack

Frontend

  • Framework: SvelteKit (latest stable version)
  • Language: TypeScript
  • Styling: Tailwind CSS
  • UI Language: Spanish
  • Code Language: English

Backend & Services

  • Authentication: Firebase Auth
  • Database: Firestore
  • Storage: Firebase Storage
  • Real-time: Firestore real-time listeners
  • Hosting: Vercel (recommended) or Firebase Hosting

Development Tools

  • Package Manager: pnpm (or npm)
  • Code Editor: Cursor
  • Version Control: Git

Domain Architecture

Component Technology URL Purpose
Marketing Site WordPress https://shootcircle.com Landing, blog, SEO
Web App SvelteKit + Firebase https://app.shootcircle.com Main platform

Project Structure

shootcircle-app/
├── src/
│   ├── routes/
│   │   ├── +layout.svelte
│   │   ├── +layout.ts
│   │   ├── +page.svelte                    # Landing/Redirect
│   │   │
│   │   ├── auth/
│   │   │   ├── login/
│   │   │   │   └── +page.svelte           # Login page
│   │   │   ├── signup/
│   │   │   │   └── +page.svelte           # Registration
│   │   │   ├── verify-email/
│   │   │   │   └── +page.svelte           # Email verification
│   │   │   └── reset-password/
│   │   │       └── +page.svelte           # Password reset
│   │   │
│   │   ├── dashboard/
│   │   │   └── +page.svelte               # User dashboard
│   │   │
│   │   ├── explore/
│   │   │   └── +page.svelte               # Browse talents
│   │   │
│   │   ├── u/
│   │   │   └── [username]/
│   │   │       └── +page.svelte           # Public profile
│   │   │
│   │   ├── settings/
│   │   │   ├── profile/
│   │   │   │   └── +page.svelte           # Edit profile
│   │   │   ├── account/
│   │   │   │   └── +page.svelte           # Account settings
│   │   │   └── privacy/
│   │   │       └── +page.svelte           # Privacy settings
│   │   │
│   │   ├── projects/
│   │   │   ├── +page.svelte               # Projects list
│   │   │   ├── new/
│   │   │   │   └── +page.svelte           # Create project
│   │   │   └── [id]/
│   │   │       └── +page.svelte           # Project details
│   │   │
│   │   ├── messages/
│   │   │   ├── +page.svelte               # Messages inbox
│   │   │   └── [chatId]/
│   │   │       └── +page.svelte           # Chat conversation
│   │   │
│   │   ├── terms/
│   │   │   └── +page.svelte               # Terms of service
│   │   ├── privacy/
│   │   │   └── +page.svelte               # Privacy policy
│   │   └── +error.svelte                  # Error page
│   │
│   ├── lib/
│   │   ├── components/
│   │   │   ├── ui/
│   │   │   │   ├── Button.svelte
│   │   │   │   ├── Input.svelte
│   │   │   │   ├── Card.svelte
│   │   │   │   ├── Avatar.svelte
│   │   │   │   ├── Modal.svelte
│   │   │   │   └── Dropdown.svelte
│   │   │   ├── layout/
│   │   │   │   ├── Navbar.svelte
│   │   │   │   ├── Sidebar.svelte
│   │   │   │   └── Footer.svelte
│   │   │   ├── profile/
│   │   │   │   ├── ProfileCard.svelte
│   │   │   │   ├── PortfolioGallery.svelte
│   │   │   │   └── ProfileStats.svelte
│   │   │   ├── projects/
│   │   │   │   ├── ProjectCard.svelte
│   │   │   │   └── ProjectForm.svelte
│   │   │   └── messages/
│   │   │       ├── ChatList.svelte
│   │   │       ├── ChatMessage.svelte
│   │   │       └── MessageInput.svelte
│   │   │
│   │   ├── stores/
│   │   │   ├── auth.ts                    # Auth state
│   │   │   ├── user.ts                    # User data
│   │   │   └── notifications.ts           # Notifications
│   │   │
│   │   ├── firebase/
│   │   │   ├── config.ts                  # Firebase configuration
│   │   │   ├── auth.ts                    # Auth helpers
│   │   │   ├── firestore.ts               # Firestore helpers
│   │   │   └── storage.ts                 # Storage helpers
│   │   │
│   │   ├── utils/
│   │   │   ├── validators.ts              # Form validation
│   │   │   ├── formatters.ts              # Date, text formatters
│   │   │   └── constants.ts               # App constants
│   │   │
│   │   └── types/
│   │       ├── user.ts                    # User types
│   │       ├── project.ts                 # Project types
│   │       └── message.ts                 # Message types
│   │
│   ├── app.html
│   └── app.css
│
├── static/
│   ├── images/
│   ├── icons/
│   └── fonts/
│
├── .env.example
├── .gitignore
├── package.json
├── svelte.config.js
├── tailwind.config.js
├── tsconfig.json
└── vite.config.ts

Firebase Structure

Firestore Collections

users

{
  uid: string;
  username: string;
  email: string;
  displayName: string;
  photoURL: string;
  bio: string;
  role: 'model' | 'photographer' | 'makeup_artist' | 'stylist' | 'producer';
  location: {
    city: string;
    country: string;
  };
  socialLinks: {
    instagram?: string;
    website?: string;
    behance?: string;
  };
  portfolio: string[]; // Array of image URLs
  followers: number;
  following: number;
  isVerified: boolean;
  createdAt: Timestamp;
  updatedAt: Timestamp;
}

projects

{
  id: string;
  title: string;
  description: string;
  creatorId: string;
  creatorName: string;
  type: 'photoshoot' | 'video' | 'campaign' | 'editorial';
  status: 'open' | 'in_progress' | 'completed' | 'cancelled';
  lookingFor: string[]; // ['model', 'photographer', etc.]
  location: string;
  date: Timestamp;
  budget?: string;
  participants: {
    userId: string;
    role: string;
  }[];
  images: string[];
  createdAt: Timestamp;
  updatedAt: Timestamp;
}

chats

{
  id: string;
  participants: string[]; // Array of user IDs
  lastMessage: string;
  lastMessageTime: Timestamp;
  unreadCount: {
    [userId: string]: number;
  };
  createdAt: Timestamp;
}

messages

{
  id: string;
  chatId: string;
  senderId: string;
  senderName: string;
  senderPhoto: string;
  content: string;
  type: 'text' | 'image' | 'file';
  fileURL?: string;
  isRead: boolean;
  createdAt: Timestamp;
}

Firebase Storage Structure

users/
  {userId}/
    profile-photo.jpg
    portfolio/
      image-1.jpg
      image-2.jpg
      ...

projects/
  {projectId}/
    cover.jpg
    gallery/
      image-1.jpg
      ...

messages/
  {chatId}/
    {messageId}/
      attachment.jpg

Pages & Features

🔓 Public Pages

Landing Page (/)

  • Hero section with value proposition
  • Features overview
  • Sample profiles showcase
  • CTA buttons: "Registrarse" / "Explorar talentos"

Explore Talents (/explore)

  • Grid of user profiles
  • Filters: role, location, availability
  • Search by name or username
  • No login required (basic view)

Authentication (/auth/*)

  • Login: Email/password + Google OAuth
  • Signup: Multi-step form
    • Step 1: Email, password, name
    • Step 2: Choose role (model, photographer, etc.)
    • Step 3: Basic profile info
  • Email verification
  • Password reset

🔒 Protected Pages (Require Authentication)

Dashboard (/dashboard)

  • Activity feed
  • Recent messages preview
  • Active projects
  • Profile stats (views, followers)
  • Quick actions

Profile (/u/[username])

  • Public profile view
  • Portfolio gallery (masonry/grid layout)
  • Bio and social links
  • Action buttons:
    • "Seguir" (Follow)
    • "Enviar mensaje" (Send message)
    • "Colaborar" (Collaborate)
  • Stats: followers, following, projects

Settings (/settings/*)

  • Profile: Edit name, bio, photo, portfolio
  • Account: Change email, password
  • Privacy: Profile visibility, blocked users

Projects (/projects/*)

  • List: Browse all projects (open, in progress, completed)
  • Create: Form to create new project
  • Details: View project info, participants, gallery
  • Apply: Button to join project

Messages (/messages/*)

  • Inbox: List of conversations
  • Chat: Real-time messaging
  • Attachments: Send images/files
  • Online status indicators

Key Features Implementation

1. Authentication Flow

// lib/firebase/auth.ts
export async function signUp(email: string, password: string, displayName: string) {
	const userCredential = await createUserWithEmailAndPassword(auth, email, password);
	await updateProfile(userCredential.user, { displayName });
	await sendEmailVerification(userCredential.user);
	return userCredential.user;
}

export async function signIn(email: string, password: string) {
	return await signInWithEmailAndPassword(auth, email, password);
}

export async function signInWithGoogle() {
	const provider = new GoogleAuthProvider();
	return await signInWithPopup(auth, provider);
}

export async function signOut() {
	return await firebaseSignOut(auth);
}

2. Real-time Chat

// lib/firebase/firestore.ts
export function subscribeToMessages(chatId: string, callback: (messages: Message[]) => void) {
	const messagesRef = collection(db, 'messages');
	const q = query(messagesRef, where('chatId', '==', chatId), orderBy('createdAt', 'asc'));

	return onSnapshot(q, (snapshot) => {
		const messages = snapshot.docs.map((doc) => ({
			id: doc.id,
			...doc.data()
		})) as Message[];
		callback(messages);
	});
}

3. Image Upload

// lib/firebase/storage.ts
export async function uploadProfilePhoto(userId: string, file: File): Promise<string> {
	const storageRef = ref(storage, `users/${userId}/profile-photo.jpg`);
	await uploadBytes(storageRef, file);
	return await getDownloadURL(storageRef);
}

export async function uploadPortfolioImage(userId: string, file: File): Promise<string> {
	const timestamp = Date.now();
	const storageRef = ref(storage, `users/${userId}/portfolio/${timestamp}-${file.name}`);
	await uploadBytes(storageRef, file);
	return await getDownloadURL(storageRef);
}

4. Search & Filters

// lib/firebase/firestore.ts
export async function searchUsers(filters: {
	role?: string;
	location?: string;
	searchTerm?: string;
}) {
	let q = query(collection(db, 'users'));

	if (filters.role) {
		q = query(q, where('role', '==', filters.role));
	}

	if (filters.location) {
		q = query(q, where('location.city', '==', filters.location));
	}

	const snapshot = await getDocs(q);
	return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
}

UI/UX Guidelines

Spanish Text (UI)

All user-facing text must be in Spanish:

  • Buttons: "Registrarse", "Iniciar sesión", "Enviar", "Guardar"
  • Labels: "Nombre", "Correo electrónico", "Contraseña"
  • Navigation: "Inicio", "Explorar", "Proyectos", "Mensajes", "Perfil"
  • Messages: "Bienvenido a ShootCircle", "Perfil actualizado correctamente"

Code (English)

All code, variables, functions, and comments must be in English:

// ✅ Correct
const userName = user.displayName;
async function updateUserProfile() {}

// ❌ Incorrect
const nombreUsuario = usuario.nombreCompleto;
async function actualizarPerfilUsuario() {}

Design System

  • Primary Color: #FF6B35 (creative orange)
  • Secondary Color: #004E89 (professional blue)
  • Accent: #F7B801 (energy yellow)
  • Neutral: #F5F5F5, #E0E0E0, #333333
  • Success: #4CAF50
  • Error: #F44336

Typography

  • Headings: Inter or Poppins (700)
  • Body: Inter (400, 500)
  • UI: System font stack

Development Guidelines

Code Standards

  1. Use TypeScript for all logic
  2. Component names in PascalCase
  3. File names in kebab-case
  4. Use Svelte stores for global state
  5. Implement proper error handling
  6. Add loading states for async operations
  7. Use Tailwind utility classes (avoid custom CSS when possible)

Security Rules (Firestore)

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read: if true;
      allow write: if request.auth != null && request.auth.uid == userId;
    }

    match /projects/{projectId} {
      allow read: if true;
      allow create: if request.auth != null;
      allow update, delete: if request.auth != null &&
        request.auth.uid == resource.data.creatorId;
    }

    match /messages/{messageId} {
      allow read, write: if request.auth != null &&
        request.auth.uid in get(/databases/$(database)/documents/chats/$(resource.data.chatId)).data.participants;
    }
  }
}

Environment Variables

# .env.example
PUBLIC_FIREBASE_API_KEY=
PUBLIC_FIREBASE_AUTH_DOMAIN=
PUBLIC_FIREBASE_PROJECT_ID=
PUBLIC_FIREBASE_STORAGE_BUCKET=
PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
PUBLIC_FIREBASE_APP_ID=

Deployment

Build Commands

# Install dependencies
pnpm install

# Development server
pnpm dev

# Build for production
pnpm build

# Preview production build
pnpm preview

Vercel Deployment

  1. Connect GitHub repository
  2. Set environment variables
  3. Build command: pnpm build
  4. Output directory: .svelte-kit
  5. Deploy to app.shootcircle.com

Priority Features (MVP)

Phase 1 - Core (Week 1-2)

  • Authentication (email + Google)
  • User profile creation
  • Portfolio upload
  • Basic profile view

Phase 2 - Discovery (Week 3-4)

  • Explore page with filters
  • Search functionality
  • Follow system
  • Profile stats

Phase 3 - Collaboration (Week 5-6)

  • Projects creation
  • Projects listing
  • Apply to projects
  • Real-time chat

Phase 4 - Polish (Week 7-8)

  • Notifications
  • Email notifications
  • Advanced search
  • Analytics dashboard

Notes for Cursor

Suggested Commands

# Generate authentication pages
"Create auth pages with login, signup, and password reset following the Firebase auth pattern"

# Create profile component
"Build a ProfileCard component that displays user info, portfolio, and action buttons in Spanish"

# Implement chat
"Create a real-time chat system using Firestore with message list and input components"

# Build explore page
"Design an explore page with user grid, filters by role and location, and search bar"

Testing Checklist

  • Auth flow works (signup, login, logout)
  • Profile CRUD operations
  • Image upload to Storage
  • Real-time chat updates
  • Search and filters work
  • Responsive design (mobile, tablet, desktop)
  • Spanish text throughout UI
  • Error handling and loading states

Ready to build! 🚀

This spec should give you everything needed to start development in Cursor. Focus on Phase 1 first, then iterate.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published