4.2 KiB
4.2 KiB
Copilot Instructions for This Repo
This workspace has a small Flask backend and a Vite + React + TypeScript frontend. Use these notes to be productive immediately and follow the codebase’s patterns.
Big picture
- Frontend:
frontend/using Vite, React Router v7, Tailwind v4, Framer Motion, i18next. - Backend:
backend/small Flask service for form email with reCAPTCHA. - Integration: The current frontend API client expects a JWT/auth API under
/api/...usingVITE_BACKEND_URL, but the Flask app only implements/send-incentive. Treat the API client as scaffolding unless those endpoints exist.
Frontend architecture & conventions
- Entrypoint:
src/main.tsx(imports./i18nto enable translations). App routes defined insrc/App.tsx. - Routing: React Router v7 with layouts in
src/layout/and pages insrc/pages/. Protected routes viasrc/routes/Privateroute.tsxusingApiClient.checkAuth(). - Styling: Tailwind CSS v4 (via
@tailwindcss/vite). Utility classes throughout; minimal custom CSS insrc/styles/. - Animations: Framer Motion used for subtle motion in Nav, Footer, and sections.
- i18n: i18next + react-i18next + language detector. Resources in
src/locales/<lng>/translation.json. Initialize insrc/i18n.ts. Global language switcher atsrc/components/main/LanguageSwitcher.tsxand embedded inNav.- Pattern: Category strings in
categoriesData.tsuse the Czech text as translation keys;CategoryCardcallst(title)andt(description). If you change data text, update bothcsandenJSON files.
- Pattern: Category strings in
- Assets: Put static assets in
frontend/public. Reference them as absolute paths (/images/...,/assets/...,/videos/...). Do not import from/public/...at runtime.
API client & data flow
- Client:
src/api/Client.tswraps Axios with two instances:apiClient(auth) andpublicClient(CSRF for anonymous calls).- Base URL:
${import.meta.env.VITE_BACKEND_URL}/api— setVITE_BACKEND_URLin an environment file (e.g.,.env) for Vite. - Auth flow: Intercepts 401s to refresh tokens via
ApiClient.refreshToken(); on failure redirects to/login. - Helpers:
ApiClient.request(method, endpoint, data, config)returnsresponse.dataand normalizes params vs body.
- Base URL:
- Current backend mismatch: Only
/send-incentiveexists in Flask. If you consumeApiClientendpoints (/account/...), ensure the backend implements them or mock responses.
Developer workflows
- Frontend
- Dev:
npm run devinfrontend/(Vite server) - Build:
npm run build(outputs tofrontend/dist) - Env: Use
VITE_*variables (e.g.,VITE_BACKEND_URL=http://localhost:5000). CRA-style vars likeREACT_APP_*are ignored by Vite.
- Dev:
- Backend
- Setup:
pip install -r backend/requirements.txt - Run:
python backend/app.py(defaults tohttp://0.0.0.0:5000) - Env:
backend/.envcontainsRECAPTCHA_SECRET, email credentials, SMTP settings.
- Setup:
Patterns to follow
- Routing: Place route shells in
src/layout/and pages insrc/pages/; nest via<Outlet />. - Protected routes: Wrap sections with
<Route element={<PrivateRoute />} />and place guarded routes inside. - i18n usage:
const { t } = useTranslation();thent('nav.home'), etc. Add new keys to bothcsandenJSON files. - Category copy: Keep
categoriesData.tsas the single source of keys (Czech text), and ensure translations exist for other languages. - Axios calls: Prefer
ApiClient.request('get', '/resource', {q: 'x'})for consistency and interceptor benefits.
Examples
- Add a new translatable label:
- Put
"nav.profile": "Profile"inen/translation.jsonand"nav.profile": "Profil"incs/translation.json. - Use in code:
{t('nav.profile')}.
- Put
- Call backend API:
const data = await ApiClient.request('get', '/items', { page: 1 });
Gotchas
- Vite env vars must start with
VITE_..env-frontendwithREACT_APP_*keys won’t be read by Vite. - Public asset paths are absolute from web root (e.g.,
/assets/logo.png), not/public/.... - If i18n keys are missing, you’ll see the raw key in UI; add it to both locale files.
If anything here looks off or incomplete (e.g., backend endpoints you actually have but aren’t in this repo), tell me and I’ll refine these rules.