--- description: Rules for working with the Telegram Mini App frontend (webapp-next/) globs: - webapp-next/** --- # Frontend — Telegram Mini App (Next.js) The Mini App lives in `webapp-next/`. It is built as a static export and served by FastAPI at `/app`. ## Stack - **Next.js** (App Router, `output: 'export'`, `basePath: '/app'`) - **TypeScript** - **Tailwind CSS** — theme extended with custom tokens (surface, muted, accent, duty, today, etc.) - **shadcn/ui** — Button, Card, Sheet, Popover, Tooltip, Skeleton, Badge - **Zustand** — app store (month, lang, duties, calendar events, loading, view state) - **@telegram-apps/sdk-react** — SDKProvider, useThemeParams, useLaunchParams, useMiniApp, useBackButton ## Structure | Area | Location | |------|----------| | App entry, layout | `src/app/layout.tsx`, `src/app/page.tsx` | | Providers | `src/components/providers/TelegramProvider.tsx` | | Calendar | `src/components/calendar/` — CalendarHeader, CalendarGrid, CalendarDay, DayIndicators | | Duty list | `src/components/duty/` — DutyList, DutyTimelineCard, DutyItem | | Day detail | `src/components/day-detail/` — DayDetail (Sheet/Popover), DayDetailContent | | Current duty view | `src/components/current-duty/CurrentDutyView.tsx` | | Admin | `src/components/admin/` — useAdminPage, AdminDutyList, ReassignSheet | | Contact links | `src/components/contact/ContactLinks.tsx` | | State views | `src/components/states/` — LoadingState, ErrorState, AccessDenied | | Hooks | `src/hooks/` — use-telegram-theme, use-telegram-auth, use-month-data, use-swipe, use-media-query, use-sticky-scroll, use-auto-refresh | | Lib | `src/lib/` — api, calendar-data, date-utils, phone-format, constants, utils | | i18n | `src/i18n/` — messages.ts, use-translation.ts | | Store | `src/store/app-store.ts` | | Types | `src/types/index.ts` | ## Conventions - **Client components:** Use `'use client'` where hooks or browser APIs are used (layout loads config script; page and most UI are client). - **Theme:** CSS variables in `globals.css`; `useTelegramTheme` maps Telegram theme params to `--tg-theme-*` and sets `data-theme` on ``. - **Auth:** `useTelegramAuth` provides initData for API; access gated for non-Telegram except localhost. - **i18n:** `useTranslation()` for React UI; `getLang()/translate()` only for early bootstrap or non-React boundaries. - **API:** `fetchDuties`, `fetchCalendarEvents` in `src/lib/api.ts`; pass initData, lang, AbortSignal; handle ACCESS_DENIED. - **Heavy pages:** For feature-heavy routes (e.g. admin), use a custom hook (state, effects, callbacks) plus presentational components; keep the page as a thin layer (early returns + composition). Example: `admin/page.tsx` uses `useAdminPage`, `AdminDutyList`, and `ReassignSheet`. - **Platform boundary:** Use `src/hooks/telegram/*` adapters for Back/Settings/Close/swipe/closing behavior instead of direct SDK control calls in feature components. - **Screen shells:** Reuse `src/components/layout/MiniAppScreen.tsx` wrappers for route and full-screen states. ## Testing - **Runner:** Vitest in `webapp-next/`; environment: jsdom; React Testing Library. - **Config:** `webapp-next/vitest.config.ts`; setup in `src/test/setup.ts`. - **Run:** `cd webapp-next && npm test` (or `npm run test`). Build: `npm run build`. - **Coverage:** Unit tests for lib (api, date-utils, calendar-data, i18n, etc.) and component tests for calendar, duty list, day detail, current duty, states. ## Design guideline When adding or changing UI in the Mini App, **follow the [Mini App design guideline](../../docs/miniapp-design.md)**: - Use only design tokens from `globals.css` and Tailwind/shadcn aliases (no hardcoded colours). - Page wrappers: `content-safe`, `max-w-[var(--max-width-app)]`, viewport height; respect safe area for sheets/modals. - Reuse component patterns (buttons, cards, calendar grid, timeline list) and left-stripe semantics (`border-l-duty`, `border-l-today`, etc.). - Add ARIA labels and roles for interactive elements and grids; respect `prefers-reduced-motion` and `data-perf="low"` for animations. - Keep all user-facing strings and `aria-label`/`sr-only` text localized. - Follow Telegram interaction policy from the design guideline: vertical swipes enabled by default, closing confirmation only for stateful flows. Use the checklist in the design doc when introducing new screens or components. Consider these rules when changing the Mini App or adding frontend features.