Files
2026-08-14 08:51:55 +03:00

67 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Plan: devodytyji — open-air cultural venue website
Stack decisions
- Astro 7 (SSR mode via @astrojs/node) — fast static pages + dynamic SSR pages. Astro's i18n routing handles /en + /ua.
- React islands for all interactive parts: auth UI, review forms, admin editor, map. Server-rendered Astro components for content pages (SEO-friendly).
- Supabase (Postgres + Auth + Storage) — sessions via @supabase/ssr 0.12 with cookie management in Astro middleware.
- Leaflet + react-leaflet for the Map page — single venue marker, no API key needed (OSM tiles).
- i18n: Astro i18n config, locales ['ua','en'], default ua, locale-prefixed routes + translation dictionaries + hreflang alternates. React islands receive translations via props/context.
- Package manager: npm (Node 20 present).
Supabase data model (SQL migration in supabase/migrations/)
profiles (id uuid PK → auth.users, full_name text, avatar_url text, is_admin bool default false)
events (id uuid PK, slug text unique, title jsonb, description jsonb, cover_image_url text,
starts_at timestamptz, ends_at timestamptz, venue_name text, status text check draft|published,
created_by uuid → profiles, created_at, updated_at)
event_reviews (id uuid PK, event_id → events, user_id → profiles, rating int 1-5, comment text, created_at)
venue_reviews (id uuid PK, user_id → profiles, rating int 1-5, comment text, created_at)
contact_messages (id, name, email, message, created_at, read bool)
- title/description as jsonb {ua, en} for bilingual content.
- RLS policies: events (published visible to all; admin full CRUD), reviews (public read, authenticated insert, owner update/delete, rating validation 1–5), profiles (public read, self-edit), contact_messages (anon insert with honeypot + rate-limit, admin read).
- Seed: one admin profile + a few published sample events.
- Auth providers enabled in dashboard: email/password + Google + GitHub (multiple OAuth).
- Cover images → Supabase Storage bucket event-covers (public read, authenticated write for admins).
Pages & routing
Public (locale-prefixed: /ua/..., /en/...):
- index.astro — Home: hero, next 3 upcoming published events, latest venue reviews, CTA
- events/index.astro — Events list with filters (upcoming/past, search)
- events/[slug].astro — Event detail: info, cover, event reviews section (list + ReviewForm island for logged-in users)
- map.astro — single venue location via Leaflet + contact/address info
- about.astro — about the venue + venue reviews + VenueReviewForm
- contacts.astro — contact form (→ contact_messages), contact details, map mini-embed
- login.astro / register.astro — auth UI island (email/password + OAuth buttons)
Admin (/admin, middleware-protected, checked for is_admin):
- admin/index.astro — dashboard (stats: published/draft counts, unread messages)
- admin/events/index.astro — table with create/edit/publish-toggle
- admin/events/new.astro + admin/events/[id]/edit.astro — EventEditor island (bilingual fields, cover upload, dates, status)
- admin/reviews.astro — review moderation (delete)
- admin/messages.astro — contact messages inbox
Auth flow
- src/middleware.ts: create server client from cookies, refresh session, protect /admin/**, redirect authed users away from login, redirect / to default locale.
- createServerClient helper in src/lib/supabase.ts (server) + createBrowserClient (browser islands).
- Endpoints: api/auth/login, api/auth/register, api/auth/callback (OAuth), api/auth/logout, api/auth/me.
Project structure
astro.config.mjs (react, node adapter, i18n config, output: server)
supabase/migrations/0001_init.sql
.env.example (PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, site URL)
src/
lib/ supabase.ts, i18n.ts, dictionaries (ua.ts, en.ts), db helpers
components/ ui/* (Button, Card…), islands (AuthForm, ReviewForm, EventEditor, MapView, LangSwitcher)
layouts/ BaseLayout.astro (SEO, OG, hreflang, header/nav, footer)
middleware.ts
pages/ …as above
styles/ global.css (design tokens)
Execution order
1. Scaffold: npm create astro@latest (TS, React integration), node adapter, SSR + i18n config
2. Supabase: project, SQL migration, RLS, storage bucket, seed, auth providers
3. Core: supabase client helpers, middleware, i18n dictionaries + layout
4. Public pages: Home → Events list → Event detail → About → Contacts → Map
5. Auth: login/register/OAuth/logout + session-aware nav
6. Reviews: event + venue forms and display
7. Admin: route guard, dashboard, event CRUD + publish toggle, moderation inbox
8. Polish: SEO/OG/i18n meta, empty/loading states, error handling, npm run build + typecheck
9. Deploy: Netlify or Vercel adapter + env vars + webhook to rebuild
Open items
- Admin grants: no public signup grants is_admin — set via SQL (seed) or Supabase dashboard. OK?
- Deploy target: Netlify or Vercel (affects adapter choice)?
- Contact emails: just stored in DB inbox, or also sent via email (Resend edge function)?