|
1 | | -# MAC Job Board |
| 1 | +# MPloy Job Board |
2 | 2 |
|
3 | 3 | Hey there! 👋 |
4 | 4 |
|
5 | 5 | This is a modern, intelligent job board platform that automatically aggregates job listings, providing users with a streamlined experience to search, filter, and discover relevant opportunities. The platform updates daily with fresh listings through our smart AI robots. |
6 | 6 |
|
7 | 7 | ## Features 🚀 |
| 8 | + |
8 | 9 | - Jobs update automatically every single day from various sources (automatically deduplicated) |
9 | 10 | - We use AI to help fix, sort and summarise the listings |
10 | | -- You can filter for exactly what you want (e.g. Big Tech Intern Roles for Interational students) |
| 11 | +- You can filter for exactly what you want (e.g. Big Tech Intern Roles for International students) |
11 | 12 | - Works perfectly on phone or laptop |
| 13 | +- Server-side rendering (where possible) with Next.js 15 App Router |
| 14 | +- Multiple filters can be applied at once, including a text search filter |
| 15 | +- Desktop/mobile responsive UI: list/details on desktop, modal on mobile |
| 16 | +- State persists in URL: search, filters, pagination (`/jobs?q=dev&location=sydney&page=2`) |
| 17 | +- Direct job links supported (`/jobs/[id]`) |
| 18 | +- Parallel data fetching for faster loads |
| 19 | +- Real-time job search with debouncing |
| 20 | +- Data refreshed daily via Go scraper (not open source) |
| 21 | +- Around 1k jobs, each ~4kB |
| 22 | + |
| 23 | +## Tech Stack |
12 | 24 |
|
13 | | -## Frontend |
| 25 | +### Frontend |
14 | 26 |
|
15 | 27 | - Next.js 15: Utilizing the App Router for server-side rendering and optimized client-side navigation |
16 | 28 | - React 19: For building the interactive user interface components |
17 | 29 | - TypeScript: Ensuring type safety across the codebase |
18 | | -- Mantine UI: For consistent, accessible UI components |
19 | 30 | - Tailwind CSS: For utility-first styling and responsive design |
20 | 31 |
|
21 | | -## Backend |
| 32 | +### Backend (Data Layer) |
22 | 33 |
|
23 | | -- Server Actions: Answers search and feedback requests |
| 34 | +- Server Actions: Handle search and feedback requests |
24 | 35 | - MongoDB: Stores job listings and related metadata |
25 | | -- GoLang: Powers our web robots (this part is not open source) |
26 | 36 |
|
27 | 37 | ## Getting Started |
28 | 38 |
|
29 | 39 | ### Prerequisites |
| 40 | + |
30 | 41 | - Node.js 20+ |
31 | | -- Java 17 |
32 | | -- Go 1.21+ |
33 | 42 | - Docker & Docker Compose |
34 | | -- Redis |
| 43 | +- MongoDB (local or cloud, set MONGODB_URI) |
35 | 44 |
|
36 | 45 | ### Local Development |
| 46 | + |
37 | 47 | ```bash |
38 | | -# Start all services |
| 48 | +# Start with Docker (includes dev server) |
39 | 49 | docker compose -f docker-compose.dev.yml up |
40 | 50 | # Alternative if Make is installed |
41 | 51 | make dev |
42 | 52 |
|
43 | | -# Frontend only |
44 | | -cd frontend |
| 53 | +# Or run frontend directly |
45 | 54 | npm install |
46 | 55 | npm run dev |
47 | | - |
48 | | -# Backend only |
49 | | -cd backend |
50 | | -./gradlew bootRun |
51 | 56 | ``` |
52 | 57 |
|
53 | 58 | ## Development Guidelines |
54 | 59 |
|
55 | | -### Git Workflow |
| 60 | +### Naming & File Structuring Conventions |
| 61 | + |
| 62 | +- Everything uses kebab-case `product-card.ts` unless there's an agreed standard e.g. `useCustomHook` for hooks |
| 63 | +- Group related components in feature directories (e.g. `components/layout/search/filter/` contains all components used for search filtering) |
| 64 | +- Most UI components are 50-150 lines of code. Keep pages thin, move complex logic to components |
| 65 | +- Use layouts for shared UI across routes |
| 66 | + |
| 67 | +### State Management & Data Passing Patterns |
| 68 | + |
| 69 | +- Begin with simple props passing - max 2 levels of components |
| 70 | +- When stateful logic needs to be reused, move it to custom hooks |
| 71 | +- When props drilling becomes cumbersome or state needs to be widely available, use Context (e.g. the global filter state of jobs should be context) |
| 72 | +- Pre-fetch the data in the next job page |
| 73 | +- Load the essential data first and display the page, while other job listings and details are being loaded |
| 74 | +- Implement parallel data fetching when possible |
| 75 | + |
| 76 | +### Next / React Features |
| 77 | + |
| 78 | +- Intercepting Routes: Use intercepting routes for modal-like experiences |
| 79 | +- Lazy Loading: use when we can defer the loading of heavy components |
| 80 | +- Error Boundaries: define error.tsx files to catch errors to prevent the entire site from breaking |
| 81 | +- Add `<Suspense/>` boundaries for loading state |
| 82 | +- Use useMemo for expensive calculations (e.g. filtered results) |
| 83 | +- Use useRef to maintain filter input values |
| 84 | + |
| 85 | +## Frontend Structure |
| 86 | + |
| 87 | +``` |
| 88 | +├── next.config.ts # Next.js configuration, API routes, environment |
| 89 | +├── src |
| 90 | +│ ├── app |
| 91 | +│ │ ├── error.tsx # Global error boundary UI |
| 92 | +│ │ ├── jobs |
| 93 | +│ │ │ ├── [id] # Dynamic route for individual job pages |
| 94 | +│ │ │ │ ├── @modal # Intercepted route - shows job details as modal on mobile |
| 95 | +│ │ │ │ ├── page.tsx # Individual job page UI |
| 96 | +│ │ │ ├── error.tsx # Job section error boundary |
| 97 | +│ │ │ ├── layout.tsx # Job section layout wrapper (includes JobsProvider) |
| 98 | +│ │ │ ├── loading.tsx # Job section loading state |
| 99 | +│ │ │ ├── page.tsx # Main jobs listing page |
| 100 | +│ │ ├── layout.tsx # Root layout with nav and theme providers |
| 101 | +│ │ ├── page.tsx # Home page (redirects to /jobs) |
| 102 | +│ ├── components |
| 103 | +│ │ ├── jobs |
| 104 | +│ │ │ ├── details |
| 105 | +│ │ │ │ ├── job-card.tsx # Individual job preview card |
| 106 | +│ │ │ │ ├── job-details.tsx # Full job details view |
| 107 | +│ │ │ │ ├── job-list.tsx # Container for job cards with virtualization |
| 108 | +│ │ │ ├── filters |
| 109 | +│ │ │ │ ├── dropdown-filter.tsx # Reusable filter dropdown |
| 110 | +│ │ │ │ ├── dropdown-sort.tsx # Sort options dropdown |
| 111 | +│ │ │ │ ├── filter-section.tsx # Container for all filters |
| 112 | +│ │ │ ├── search |
| 113 | +│ │ │ │ └── search-bar.tsx # Search input with suggestions |
| 114 | +│ │ │ ├── layout |
| 115 | +│ │ │ │ └── logo.tsx # Site logo component |
| 116 | +│ │ │ │ └── nav-bar.tsx # Navigation bar |
| 117 | +│ ├── context |
| 118 | +│ │ ├── jobs |
| 119 | +│ │ │ └── filter-context.tsx # Job state and actions context |
| 120 | +│ │ │ └── jobs-provider.tsx # Provider wrapper with initial state |
| 121 | +│ ├── hooks |
| 122 | +│ │ ├── use-job-filters.ts # Filter logic and state management |
| 123 | +│ │ ├── use-job-search.ts # Search functionality and API calls |
| 124 | +│ │ ├── use-pagination.ts # Pagination state and navigation |
| 125 | +│ │ ├── use-url-state.ts # URL parameters sync with app state |
| 126 | +│ ├── lib |
| 127 | +│ │ ├── theme.ts # Theme configuration |
| 128 | +│ ├── types |
| 129 | +│ │ └── api.ts # API response/request types |
| 130 | +│ │ └── filters.ts # Filter option types |
| 131 | +│ │ └── job.ts # Job data types |
| 132 | +├── tailwind.config.ts # Tailwind CSS configuration |
| 133 | +``` |
| 134 | + |
| 135 | +## Git Workflow |
56 | 136 |
|
57 | 137 | #### Branch Structure |
| 138 | + |
58 | 139 | - `main` - Production branch |
59 | 140 | - `dev` - Development branch |
60 | 141 | - Feature branches follow the pattern: |
61 | 142 | ``` |
62 | 143 | <component>/<developer>/<feature-name> |
63 | 144 | Examples: |
64 | | - - backend/edwn/redis-caching |
65 | | - - frontend/sarah/job-filters |
| 145 | + - ui/edwn/dark-mode |
| 146 | + - jobs/sarah/advanced-filters |
66 | 147 | ``` |
67 | | - |
| 148 | + |
68 | 149 | ## License |
69 | | -This project is licensed under the MIT License. |
| 150 | + |
| 151 | +This project is licensed under the MIT License. |
0 commit comments