mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:41:09 +02:00
Final cleanup of references missed in previous rename commits: - Dockerfiles: PUBLIC_MANA_CORE_AUTH_URL → PUBLIC_MANA_AUTH_URL - Go modules: github.com/manacore/* → github.com/mana/* (7 go.mod files) - launchd plists: com.manacore.* → com.mana.* (14 files renamed + content) - Image assets: *_Manacore_AI_Credits* → *_Mana_AI_Credits* (11 files) - .env.example files: ManaCore brand strings → Mana - .prettierignore: stale apps/manacore/* paths → apps/mana/* - Markdown docs (CLAUDE.md, /docs/*): mana-core-auth → mana-auth, etc. Excluded from rename: .claude/, devlog/, manascore/ (historical content), client testimonials, blueprints, npm package refs (@mana-core/*). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
128 lines
3.9 KiB
Markdown
128 lines
3.9 KiB
Markdown
# uLoad — URL Shortener & Link Management
|
|
|
|
**Live:** https://ulo.ad
|
|
|
|
## Architecture
|
|
|
|
uLoad uses a **local-first** architecture with a lightweight Hono/Bun server for redirects and analytics.
|
|
|
|
```
|
|
Browser → IndexedDB (Links, Tags, Folders)
|
|
↕ sync
|
|
mana-sync → PostgreSQL
|
|
|
|
Browser → /r/:code → Hono Server → PostgreSQL (redirect + click tracking)
|
|
```
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
apps/uload/
|
|
├── apps/
|
|
│ ├── web/ # SvelteKit web app (local-first)
|
|
│ ├── server/ # Hono/Bun redirect & analytics server
|
|
│ └── landing/ # Astro marketing page
|
|
├── packages/
|
|
│ └── uload-database/ # Shared Drizzle schema
|
|
└── package.json
|
|
```
|
|
|
|
## Tech Stack
|
|
|
|
| Layer | Technology |
|
|
|-------|-----------|
|
|
| **Web** | SvelteKit 2, Svelte 5 (runes), Tailwind CSS 4 |
|
|
| **Server** | Hono + Bun |
|
|
| **Data** | Local-first (Dexie.js + mana-sync) |
|
|
| **Database** | PostgreSQL via Drizzle ORM |
|
|
| **Auth** | mana-auth (Better Auth + EdDSA JWT) |
|
|
| **Landing** | Astro 5 |
|
|
| **PWA** | @vite-pwa/sveltekit |
|
|
| **i18n** | svelte-i18n (DE/EN) |
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# Development
|
|
pnpm dev:uload:web # SvelteKit dev server
|
|
pnpm dev:uload:server # Hono/Bun server (port 3070)
|
|
pnpm dev:uload:landing # Landing page
|
|
pnpm dev:uload:local # Web + Sync + Server (no auth)
|
|
pnpm dev:uload:full # Everything incl. auth
|
|
|
|
# Build & Deploy
|
|
pnpm --filter @uload/web build
|
|
pnpm --filter @uload/landing build
|
|
pnpm deploy:landing:uload # Deploy landing to Cloudflare Pages
|
|
|
|
# Type Check
|
|
pnpm --filter @uload/web check
|
|
pnpm --filter @uload/server type-check
|
|
pnpm --filter @mana/uload-database type-check
|
|
```
|
|
|
|
## Ports
|
|
|
|
| Service | Dev Port | Prod Port |
|
|
|---------|----------|-----------|
|
|
| Web | 5173 | 5029 |
|
|
| Server | 3070 | 3041 |
|
|
| Landing | 4321 | Cloudflare Pages |
|
|
|
|
## Hono Server Routes
|
|
|
|
| Route | Auth | Description |
|
|
|-------|------|-------------|
|
|
| `GET /health` | No | Health check |
|
|
| `GET /r/:code` | No | Redirect + click tracking |
|
|
| `GET /public/u/:username` | No | Public user profile + links |
|
|
| `GET /api/v1/analytics/:linkId` | JWT | Click stats |
|
|
| `GET /api/v1/analytics/:linkId/timeline` | JWT | Clicks over time |
|
|
| `GET /api/v1/analytics/:linkId/devices` | JWT | Device breakdown |
|
|
| `GET /api/v1/analytics/:linkId/referrers` | JWT | Top referrers |
|
|
| `GET /api/v1/analytics/:linkId/countries` | JWT | Country breakdown |
|
|
| `POST /api/v1/stripe/checkout` | JWT | Stripe session (stub) |
|
|
| `POST /api/v1/stripe/webhook` | No | Stripe webhook (stub) |
|
|
| `POST /api/v1/email/send-invitation` | JWT | Team invite (stub) |
|
|
|
|
## Local-First Collections
|
|
|
|
| Collection | Fields |
|
|
|-----------|--------|
|
|
| `links` | shortCode, originalUrl, title, isActive, clickCount, utmSource/Medium/Campaign, folderId |
|
|
| `tags` | name, slug, color, icon, isPublic, usageCount |
|
|
| `folders` | name, color, order |
|
|
| `linkTags` | linkId, tagId |
|
|
|
|
## Web App Pages
|
|
|
|
| Route | Description |
|
|
|-------|-------------|
|
|
| `/my/links` | Link management (CRUD, QR, UTM, bulk) |
|
|
| `/my/tags` | Tag management |
|
|
| `/my/analytics/[id]` | Per-link analytics dashboard |
|
|
| `/settings` | Account & data settings |
|
|
| `/pricing` | Subscription plans (static) |
|
|
| `/u/[username]` | Public user profile |
|
|
| `/login` | Login (shared-auth-ui) |
|
|
| `/register` | Register (shared-auth-ui) |
|
|
|
|
## Docker
|
|
|
|
```bash
|
|
# Build
|
|
./scripts/mac-mini/build-app.sh uload-web
|
|
./scripts/mac-mini/build-app.sh uload-server
|
|
|
|
# Services in docker-compose.macmini.yml:
|
|
# - uload-server (port 3041, Bun)
|
|
# - uload-web (port 5029, Node)
|
|
```
|
|
|
|
## Key Patterns
|
|
|
|
- **Svelte 5 Runes**: Use `$state`, `$derived`, `$effect` — never `$:`
|
|
- **Local-first**: All CRUD via `linkCollection.insert/update/delete` (IndexedDB)
|
|
- **Analytics**: Fetched from Hono server, not local (server-only click data)
|
|
- **Auth**: `authStore` from `@mana/shared-auth-ui`, `AuthGate` with guest mode
|
|
- **Sync**: Starts on login via `uloadStore.startSync()`, stops on logout
|