ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
1# Contributing to ATlast 2 3Thank you for your interest in contributing! This guide will help you get started with local development. 4 5## Two Development Modes 6 7We support two development modes: 8 9🎨 **Mock Mode** (No backend required) 10**Best for:** Frontend development, UI/UX work, design changes 11 12🔧 **Full Mode** (Complete backend) 13**Best for:** Backend development, API work, OAuth testing, database changes 14 15**Requirements:** 16- PostgreSQL database (local or Neon) 17- OAuth keys 18- Environment configuration 19 20--- 21 22## Mock Mode Starting Guide 23 24Perfect for frontend contributors who want to jump in quickly! 25 261. Clone and Install 27```bash 28git clone <repo-url> 29cd atlast 30pnpm install 31``` 32 332. Create .env.local 34```bash 35# .env.mock 36VITE_LOCAL_MOCK=true 37VITE_ENABLE_OAUTH=false 38VITE_ENABLE_DATABASE=false 39``` 40 413. Start Development 42```bash 43pnpm run dev:mock 44``` 45 464. Open Your Browser 47Go to `http://localhost:5173` 48 495. "Login" with Mock User 50Enter any handle - it will create a mock session. 51 526. Upload Test Data 53Upload your TikTok or Instagram data file. The mock API will generate fake matches for testing the UI. 54 55--- 56 57## Full Mode Starting Guide 58 59For contributors working on backend features, OAuth, or database operations. 60 61### Prerequisites 62 63- Node.js 18+ 64- pnpm (install with `npm install -g pnpm`) 65- PostgreSQL (or Neon account) 66- OpenSSL (for key generation) 67 681. Clone and Install 69```bash 70git clone <repo-url> 71cd atlast 72pnpm install 73``` 74 752. Database Setup 76 77 **Option A: Neon (Recommended)** 78 1. Create account at https://neon.tech 79 2. Create project "atlast-dev" 80 3. Copy connection string 81 82 **Option B: Local PostgreSQL** 83 ```bash 84 # macOS 85 brew install postgresql@15 86 brew services start postgresql@15 87 createdb atlast_dev 88 89 # Ubuntu 90 sudo apt install postgresql 91 sudo systemctl start postgresql 92 sudo -u postgres createdb atlast_dev 93 ``` 94 953. Generate OAuth Keys 96```bash 97# Generate private key 98openssl ecparam -name prime256v1 -genkey -noout -out private-key.pem 99 100# Extract public key 101openssl ec -in private-key.pem -pubout -out public-key.pem 102 103# View private key (copy for .env) 104cat private-key.pem 105``` 106 1074. Extract Public Key JWK 108```bash 109node -e " 110const fs = require('fs'); 111const jose = require('jose'); 112const pem = fs.readFileSync('public-key.pem', 'utf8'); 113jose.importSPKI(pem, 'ES256').then(key => { 114 return jose.exportJWK(key); 115}).then(jwk => { 116 console.log(JSON.stringify(jwk, null, 2)); 117}); 118" 119``` 120 1215. Update netlify/functions/jwks.ts 122 123 Replace `PUBLIC_JWK` with the output from step 4. 124 1256. Create .env 126 127```bash 128VITE_LOCAL_MOCK=false 129VITE_API_BASE=/.netlify/functions 130 131# Database (choose one) 132NETLIFY_DATABASE_URL=postgresql://user:pass@host/db # Neon 133# NETLIFY_DATABASE_URL=postgresql://localhost/atlast_dev # Local 134 135# OAuth (paste your private key) 136OAUTH_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nYOUR_KEY_HERE\n-----END PRIVATE KEY-----" 137 138# Local URLs (MUST use 127.0.0.1 for OAuth) 139URL=http://127.0.0.1:8888 140DEPLOY_URL=http://127.0.0.1:8888 141DEPLOY_PRIME_URL=http://127.0.0.1:8888 142CONTEXT=dev 143``` 144 1457. Initialize Database 146```bash 147pnpm run init-db 148``` 149 1508. Start Development Server 151```bash 152npx netlify-cli dev --filter @atlast/web 153# Or use the alias: 154pnpm run dev 155``` 156 1579. Test OAuth 158 159 1. Open `http://127.0.0.1:8888` (NOT localhost) 160 2. Enter your real Bluesky handle 161 3. Authorize the app 162 4. You should be redirected back and logged in 163 164--- 165 166## Project Structure 167 168**Monorepo using pnpm workspaces:** 169 170``` 171atlast/ 172├── packages/ 173│ ├── web/ # Frontend React app 174│ │ ├── src/ 175│ │ │ ├── assets/ # Logo 176│ │ │ ├── components/ # UI components (React) 177│ │ │ ├── pages/ # Page components 178│ │ │ ├── hooks/ # Custom hooks 179│ │ │ ├── lib/ 180│ │ │ │ ├── api/ # API client (real + mock) 181│ │ │ │ ├── parsers/ # File parsing logic 182│ │ │ │ └── config.ts # Environment config 183│ │ │ └── types/ # TypeScript types 184│ │ └── package.json 185│ ├── functions/ # Netlify serverless functions 186│ │ ├── src/ 187│ │ │ ├── core/ # Middleware, types, config 188│ │ │ ├── infrastructure/ # Database, OAuth, cache 189│ │ │ ├── services/ # Business logic 190│ │ │ ├── repositories/ # Data access layer 191│ │ │ └── utils/ # Shared utilities 192│ │ └── package.json 193│ ├── extension/ # Browser extension 194│ │ ├── src/ 195│ │ │ ├── content/ # Content scripts, scrapers 196│ │ │ ├── popup/ # Extension popup UI 197│ │ │ ├── background/ # Service worker 198│ │ │ └── lib/ # Extension utilities 199│ │ └── package.json 200│ └── shared/ # Shared types (future) 201├── pnpm-workspace.yaml 202└── netlify.toml 203``` 204 205### UI Color System 206 207| **Element** | **Light Mode** | **Dark Mode** | **Notes** | 208|:---:|:---:|:---:|:---:| 209| Text Primary | purple-950 | cyan-50 | Headings, labels | 210| Text Secondary | purple-750 | cyan-250 | Body text, descriptions | 211| Text Tertiary | purple-600 | cyan-400 | Metadata, hints, icons | 212| Borders (Rest) | cyan-500/30 | purple-500/30 | Cards, inputs default | 213| Borders (Hover) | cyan-400 | purple-400 | Interactive hover | 214| Borders (Active/Selected) | cyan-500 | purple-500 | Active tabs, selected items | 215| Backgrounds (Primary) | white | slate-900 | Modal/card base | 216| Backgrounds (Secondary) | purple-50 | slate-900 (nested sections) | Nested cards, sections | 217| Backgrounds (Selected) | cyan-50 | purple-950/30 | Selected platform cards | 218| Buttons Primary | orange-600 | orange-600 | CTAs | 219| Buttons Primary Hover | orange-500 | orange-500 | CTA hover | 220| Buttons Secondary | slate-600 | slate-700 | Cancel, secondary actions | 221| Buttons Secondary Hover | slate-700 | slate-600 | Secondary hover | 222| Interactive Selected | bg-cyan-50 border-cyan-500 | bg-purple-950/30 border-purple-500 | Platform selection cards | 223| Accent/Badge | orange-500 | orange-500 (or amber-500) | Match counts, checkmarks, progress | 224| Progress Complete | orange-500 | orange-500 | Completed progress bars | 225| Progress Incomplete | cyan-500/30 | purple-500/30 | Incomplete progress bars | 226| Success/Green | green-100/800 | green-900/300 | Followed status | 227| Error/Red | red-600 | red-400 | Logout, errors | 228 229### UI Color System: Patterns 230**Disabled States**: 231- Light: Reduce opacity to 50%, use purple-500/50 232- Dark: Reduce opacity to 50%, use cyan-500/50 233 234**Success/Match indicators**: 235Both modes: amber-* or orange-* backgrounds with accessible text contrast 236 237**Tab Navigation**: 238- Inactive: Use text secondary colors 239- Active border: orange-500 (light), amber-500 (dark) 240- Active text: orange-650 (light), amber-400 (dark) 241 242**Gradient Banners**: 243- Both modes: from-amber-* via-orange-* to-pink-* (keep dramatic, adjust shades for mode) 244 245--- 246 247## Task Workflows 248 249### Adding a New Social Platform Parser 250 2511. Add parsing rules to `packages/web/src/lib/parsers/platformDefinitions.ts` 2522. Follow existing patterns (TikTok, Instagram) 2533. Test with real data export file 2544. Update platform selection UI if needed 255 256### Adding a New API Endpoint 257 2581. Create `packages/functions/src/your-endpoint.ts` 2592. Add authentication check using `withAuthErrorHandling()` middleware 2603. Update `packages/web/src/lib/api/adapters/RealApiAdapter.ts` 2614. Update `packages/web/src/lib/api/adapters/MockApiAdapter.ts` 2625. Use in components via `apiClient.yourMethod()` 263 264### Working with the Extension 265 266```bash 267cd packages/extension 268pnpm install 269pnpm run build # Build for Chrome 270pnpm run build:prod # Build for production 271 272# Load in Chrome: 273# 1. Go to chrome://extensions 274# 2. Enable Developer mode 275# 3. Click "Load unpacked" 276# 4. Select packages/extension/dist/chrome/ 277``` 278 279### Styling Changes 280 281- Use Tailwind utility classes 282- Follow dark mode pattern: `class="bg-white dark:bg-gray-800"` 283- Test in both light and dark modes 284- Mobile-first responsive design 285- Check accessibility (if implemented) is retained 286 287--- 288 289## Submitting Changes 290 291### Before Submitting 292 293- [ ] Test in mock mode: `pnpm run dev:mock` 294- [ ] Test in full mode (if backend changes): `npx netlify-cli dev --filter @atlast/web` 295- [ ] Check both light and dark themes 296- [ ] Test mobile responsiveness 297- [ ] No console errors 298- [ ] Code follows existing patterns 299- [ ] Run `pnpm run build` successfully 300 301### Pull Request Process 302 3031. Fork the repository 3042. Create a feature branch: `git checkout -b feature/your-feature` 3053. Make your changes 3064. Commit with clear messages 3075. Push to your fork 3086. Open a Pull Request 309 310### PR Description Should Include 311 312- What changes were made 313- Why these changes are needed 314- Screenshots (for UI changes) 315- Testing steps 316- Related issues 317 318--- 319 320## Resources 321 322- [AT Protocol Docs](https://atproto.com) 323- [Bluesky API](https://docs.bsky.app) 324- [React Documentation](https://react.dev) 325- [Tailwind CSS](https://tailwindcss.com) 326- [Netlify Functions](https://docs.netlify.com/functions/overview) 327 328--- 329 330Thank you for contributing to ATlast!