Files
my_openplace/frontend-src/IMPLEMENTATION_NOTES.md
2025-10-02 02:40:11 -07:00

6.8 KiB

Frontend Implementation Notes

Based on analysis of compiled frontend in /frontend folder.

Key Findings from Compiled Code

Tech Stack (Confirmed)

  • SvelteKit 2.x with adapter-static
  • TailwindCSS + DaisyUI 4.x for styling
  • Leaflet for map/canvas
  • Cloudflare Turnstile for captcha/bot protection
  • No additional state libraries - uses Svelte stores

API Client Pattern

// Found in chunks/1lh-LSvX.js
class ApiClient {
  async request(endpoint, options) {
    const response = await fetch(`${this.url}${endpoint}`, options);
    this.online = true;
    return response;
  }
}

Endpoints found:

  • /me - GET user profile
  • /auth/logout - POST logout
  • /me/update - POST update profile
  • /alliance - GET/POST alliance operations
  • /alliance/update-description - POST
  • /alliance/update-headquarters - POST
  • /alliance/invites - GET
  • /alliance/give-admin - POST
  • /alliance/ban - POST
  • /alliance/unban - POST
  • /purchase - POST store purchases
  • /favorite-location - POST
  • /favorite-location/update - POST
  • /moderator/tickets - GET
  • /moderator/severe-open-tickets-count - GET
  • /me/profile-pictures - GET
  • /otp/cooldown, /otp/send, /otp/verify - OTP system (phone verification)

Authentication

  • OAuth providers: Google, Twitch
  • Auth redirects to: ${API_URL}/auth/{provider}?token={turnstile_token}&r={redirect}
  • JWT stored in j cookie (HttpOnly)
  • Turnstile captcha required before OAuth

Global State (from chunks/1lh-LSvX.js)

let globalState = {
  dropletsDialogOpen: false,
  muted: false,
  language: getLanguage(),  // 'en' or 'pt' detected from navigator
  captcha: undefined,       // Turnstile token
  now: Date.now(),         // Updates every 500ms
  turnstatileLoaded: false
};

setInterval(() => {
  globalState.now = Date.now()
}, 500);

Cloudflare Turnstile

  • Site key: 0x4AAAAAABpqJe8FO0N84q0F (from constant qt)
  • Script: https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit
  • Required before login/OAuth

Routes (from app.iDaujbEI.js dictionary)

/ - Main canvas (node 2)
/404 - 404 page (node 3)
/join - Join/onboarding (node 4)
/admin - Admin panel (node 5)
/offline - Offline page (node 6)
/payment/success - Payment success (node 7)
/profile-picture - Profile picture selector (node 8)
/terms/privacy - Privacy policy (node 9)
/terms/return - Return policy (node 10)
/terms/terms-of-service - Terms of service (node 11)
/moderation - Moderation panel (node 14)

Styling Patterns

  • Base classes: bg-base-100, bg-base-200, text-base-content
  • Buttons: btn, btn-ghost, btn-circle, btn-sm, btn-lg, btn-error
  • Modals: modal, modal-box, modal-backdrop
  • Tabs: tabs, tabs-border, tab
  • Loading: loading loading-spinner loading-md
  • Tooltips: tooltip tooltip-bottom
  • Layout: Uses Tailwind grid/flex extensively

Report/Moderation System

Report reasons (from fZ59cmjx.js):

  • inappropriate-content - "+18, inappropriate link, highly suggestive content"
  • hate-speech - "Racism, homophobia, hate groups"
  • doxxing - "Released personal information"
  • bot - "Automated painting software"
  • griefing - "Messed up artworks for no reason"
  • other - "Other reason"

Report form endpoint: ${API_URL}/report-user Timeout endpoint: ${API_URL}/moderator/timeout-user Ban endpoint: ${API_URL}/admin/ban-user

Internationalization

  • Supports English (en) and Portuguese (pt) minimum
  • Language detection from navigator.languages or navigator.language
  • Translation functions: (params, {locale}) => locale === "en" ? englishText : portugueseText

Toast Notifications

  • Global W object with W.error(), W.info() methods
  • Aria-live region: aria-label="Notifications alt+T"

PWA Features

  • Service worker: /service-worker.js
  • Install prompt: window.pwaInstallPrompt
  • Manifest: /site.webmanifest

CSP Header

script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval' https://challenges.cloudflare.com blob:

Constants

  • Nt = "files" - Files base path
  • Season: Default s1
  • Version displayed as span: Version: 1759175263375

Implementation Priority

  1. Core Setup (DONE)

    • Package.json with DaisyUI + Tailwind
    • Svelte config
    • PostCSS/Tailwind config
  2. Next Steps

    • API client (src/lib/api/client.ts)
    • Global stores (src/lib/stores/)
    • i18n utilities (src/lib/i18n/)
    • Toast notification system
    • Turnstile component
    • Layout components
    • Auth pages (login with OAuth)
    • Main canvas route
    • Admin/moderation routes
  3. File Structure

src/
├── lib/
│   ├── api/
│   │   └── client.ts          # API client class
│   ├── stores/
│   │   ├── global.ts          # Global state (turnstile, language, etc.)
│   │   ├── user.ts            # Current user
│   │   ├── canvas.ts          # Canvas state
│   │   └── alliance.ts        # Alliance state
│   ├── i18n/
│   │   ├── index.ts           # Translation utilities
│   │   ├── en.ts              # English translations
│   │   └── pt.ts              # Portuguese translations
│   ├── components/
│   │   ├── common/
│   │   │   ├── Button.svelte
│   │   │   ├── Modal.svelte
│   │   │   └── Toast.svelte
│   │   ├── auth/
│   │   │   ├── LoginForm.svelte     # OAuth buttons + Turnstile
│   │   │   └── Turnstile.svelte     # Cloudflare Turnstile
│   │   ├── canvas/
│   │   │   └── LeafletMap.svelte
│   │   └── layout/
│   │       ├── Header.svelte
│   │       └── Logo.svelte
│   ├── constants/
│   │   ├── colors.ts          # Color palette
│   │   └── config.ts          # API URLs, etc.
│   └── utils/
│       ├── bitmap.ts          # Bitmap helpers
│       ├── charges.ts         # Charge calculation
│       └── level.ts           # Level calculation
├── routes/
│   ├── +layout.svelte         # Root layout
│   ├── +page.svelte           # Main canvas
│   ├── admin/
│   │   └── +page.svelte       # Admin dashboard
│   ├── moderation/
│   │   └── +page.svelte       # Moderation panel
│   └── join/
│       └── +page.svelte       # Login/onboarding
└── app.html                   # HTML template

Notes

  • Original frontend uses Svelte 5 runes syntax ($state, $derived)
  • We can use Svelte 4 with traditional stores for simplicity
  • No additional HTTP library needed - uses native fetch
  • Leaflet needs import 'leaflet/dist/leaflet.css' in layout