# МојМајстор - Implementation Plan ## Overview МојМајстор (My Handyman) is a mobile app connecting local handymen with customers in Macedonia. Built with Expo React Native and a self-deployed Convex backend, all UI text in Macedonian. --- ## Tech Stack | Layer | Technology | |-------|-----------| | Frontend | Expo SDK 52+, React Native, TypeScript | | Navigation | Expo Router (file-based) | | Backend | Convex (self-hosted) | | Auth | Convex Auth (email/password + phone) | | Styling | NativeWind (Tailwind for RN) | | Chat | Convex real-time queries | | Maps | react-native-maps | | Image Upload | Convex file storage + expo-image-picker | | Deployment | EAS Build + Update | --- ## Data Model (Convex Schema) ### users - `_id`, `name`, `phone`, `email`, `role` ("handyman" | "customer"), `avatarId?`, `createdAt` ### ads - `_id`, `handymanId` (ref users), `title`, `description`, `category`, `location`, `lat?`, `lng?`, `priceRange?`, `imageIds[]`, `availability`, `ratingAvg?`, `reviewCount`, `createdAt`, `updatedAt` ### categories - `_id`, `name` (Macedonian), `slug`, `icon?`, `sortOrder` ### reviews - `_id`, `adId` (ref ads), `customerId` (ref users), `handymanId` (ref users), `rating` (1-5), `comment`, `createdAt` ### chats - `_id`, `participantIds[]` (ref users), `lastMessageAt`, `createdBy` ### messages - `_id`, `chatId` (ref chats), `senderId` (ref users), `content`, `imageId?`, `createdAt` ### posts (customer needs) - `_id`, `customerId` (ref users), `title`, `description`, `category`, `location`, `budget?`, `status` ("open" | "closed"), `createdAt`, `updatedAt` --- ## Project Structure ``` mojmajstor/ ├── app/ # Expo Router pages │ ├── _layout.tsx # Root layout + auth state │ ├── (auth)/ │ │ ├── _layout.tsx │ │ ├── login.tsx │ │ └── register.tsx │ ├── (tabs)/ │ │ ├── _layout.tsx # Bottom tab navigator │ │ ├── index.tsx # Home / search │ │ ├── explore.tsx # Browse categories & ads │ │ ├── posts.tsx # Customer needs feed │ │ ├── chat.tsx # Chat list │ │ └── profile.tsx # User profile │ ├── ad/ │ │ ├── [id].tsx # Ad detail │ │ └── create.tsx # Create ad (handyman) │ ├── post/ │ │ ├── [id].tsx # Post detail │ │ └── create.tsx # Create post (customer) │ ├── chat/ │ │ └── [id].tsx # Chat conversation │ └── review/ │ └── create.tsx # Leave a review ├── components/ │ ├── ui/ # Reusable UI primitives │ │ ├── Button.tsx │ │ ├── Card.tsx │ │ ├── Input.tsx │ │ ├── Rating.tsx │ │ ├── Avatar.tsx │ │ ├── Badge.tsx │ │ └── Loading.tsx │ ├── AdCard.tsx │ ├── PostCard.tsx │ ├── ChatListItem.tsx │ ├── MessageBubble.tsx │ ├── CategoryGrid.tsx │ ├── SearchBar.tsx │ ├── LocationPicker.tsx │ └── ReviewCard.tsx ├── convex/ # Backend │ ├── _generated/ │ ├── schema.ts │ ├── auth.config.ts │ ├── users.ts │ ├── ads.ts │ ├── categories.ts │ ├── reviews.ts │ ├── chats.ts │ ├── messages.ts │ └── posts.ts ├── lib/ │ ├── constants.ts # Colors, spacing, Macedonian strings │ ├── hooks.ts # Custom hooks │ └── utils.ts ├── assets/ │ └── images/ ├── app.json ├── package.json ├── tailwind.config.js ├── tsconfig.json └── eas.json ``` --- ## Implementation Phases ### Phase 1: Project Setup & Auth (Week 1) **Goal:** Bootable app with authentication. 1. Initialize Expo project with TypeScript template 2. Install dependencies: `expo-router`, `nativewind`, `convex`, `@convex-dev/auth`, `expo-image-picker`, `react-native-maps`, `expo-location` 3. Configure NativeWind (Tailwind) + constants (colors, Macedonian strings) 4. Set up Convex project & self-deploy 5. Define `schema.ts` with all tables 6. Configure Convex Auth (email/password + phone) 7. Build root `_layout.tsx` with auth state observer 8. Build `(auth)/login.tsx` - email/phone login 9. Build `(auth)/register.tsx` - role selection (handyman/customer) + profile creation 10. Build UI primitives: Button, Input, Card, Loading **Deliverable:** User can sign up, log in, see role-specific tab layout. --- ### Phase 2: Home & Categories (Week 2) **Goal:** Browse and discover handymen. 1. Seed `categories` table (Мајстор за сѐ, Водоинсталатер, Електричар, Тескар, Фарбар, Керамичар, Зидар, Градежник, столар, Молер, Електричар, Клима монтажер, etc.) 2. Build `(tabs)/_layout.tsx` - bottom nav (Почетна, Пребарување, Огласи, Чат, Профил) 3. Build `(tabs)/index.tsx` - home screen with hero search + category grid + featured ads 4. Build `CategoryGrid` component with icons per category 5. Build `SearchBar` component with text + location filter 6. Build `(tabs)/explore.tsx` - category list → filtered ad list 7. Build `AdCard` component (image, title, rating, location, price range) 8. Create `ads.ts` Convex queries: `list`, `getByCategory`, `search`, `getByHandyman` 9. Wire up real data to ad listings **Deliverable:** Customer can browse categories and see handyman ads. --- ### Phase 3: Ad Creation & Detail (Week 3) **Goal:** Handymen can post and manage ads. 1. Build `ad/create.tsx` - multi-step form: - Step 1: Category selection - Step 2: Title, description, price range - Step 3: Location (map picker or text) - Step 4: Availability schedule - Step 5: Photo upload (up to 5) 2. Build `ad/[id].tsx` - ad detail page: - Gallery, description, location map, availability, rating, reviews - "Започни разговор" (Start chat) button - "Напиши оценка" (Write review) button 3. Create `ads.ts` mutations: `create`, `update`, `delete` 4. Handle image upload via Convex file storage + `expo-image-picker` 5. Build `profile.tsx` - handyman view with their ads list, edit/delete **Deliverable:** Handymen can create, view, edit, delete their ads. Customers can view full details. --- ### Phase 4: Customer Posts (Week 4) **Goal:** Customers can post their needs; handymen can respond. 1. Build `post/create.tsx` - customer need form (title, description, category, location, budget, urgency) 2. Build `post/[id].tsx` - post detail with responses 3. Build `(tabs)/posts.tsx` - feed of open customer posts 4. Create `posts.ts` Convex queries & mutations: `create`, `list`, `getByCustomer`, `close` 5. Add "Одговори на оглас" (Respond to post) flow for handymen → starts a chat **Deliverable:** Customers post needs, handymen browse and respond. --- ### Phase 5: In-App Chat (Week 5) **Goal:** Real-time messaging between customer and handyman. 1. Build `(tabs)/chat.tsx` - chat list with last message preview, unread indicator 2. Build `chat/[id].tsx` - full conversation screen with: - Message bubbles (text + optional image) - Input bar with send button + image picker - Real-time updates via Convex `onUpdate` 3. Create `chats.ts` Convex queries & mutations: `create`, `listByUser` 4. Create `messages.ts` Convex queries & mutations: `send`, `listByChat` (paginated) 5. Add push notification support via Expo Notifications 6. Add "Започни разговор" button on ad detail → creates or opens existing chat **Deliverable:** Users can chat in real-time with image support. --- ### Phase 6: Reviews & Ratings (Week 6) **Goal:** Customer can rate and review handymen. 1. Build `review/create.tsx` - star rating + comment form 2. Build `ReviewCard` component 3. Add review summary to `AdCard` and ad detail page 4. Create `reviews.ts` Convex queries & mutations: `create`, `getByAd`, `getByHandyman` 5. Update `ads` table: compute `ratingAvg` and `reviewCount` on review creation (Convex trigger) 6. Sort ads by rating in search/explore **Deliverable:** Customers leave reviews; ratings visible on ads. --- ### Phase 7: Polish & Production (Week 7) **Goal:** Production-ready app. 1. Full Macedonian localization (all strings in `lib/constants.ts`) 2. Error handling & loading states on every screen 3. Pull-to-refresh on list screens 4. Pagination on ad feeds and chat messages 5. Offline-first considerations (Convex optimistic updates) 6. Deep linking configuration 7. App icon & splash screen (Macedonian-themed) 8. EAS Build configuration for iOS + Android 9. App store metadata (Македонски) 10. Performance audit (list virtualization, image optimization) 11. Accessibility pass (labels, contrast, font scaling) **Deliverable:** Published app on App Store & Google Play. --- ## Key Decisions & Notes - **Language:** All user-facing text is in Macedonian (Македонски). Code variables and comments in English. - **Role system:** Determined at registration. Handymen see ad creation; customers see post creation. Both can chat. - **Maps:** Use `react-native-maps` with OpenStreetMap tiles (no Google API key needed for MVP). - **Convex self-deploy:** Deploy via Docker on own infra for full data sovereignty. - **Auth strategy:** Start with email/password, add phone OTP via Twilio in Phase 7. - **Image optimization:** Compress before upload using `expo-image-manipulator`. Max 5 images per ad. - **Search:** Convex full-text search on ad title/description. Location filter via lat/lng bounding box.