Files
dating-app-frontend/dating-app-frontend-prompt.md
Oscar f5e34f3a97 feat(src/stores/auth.store.ts): обновляет логику получения пользователя после входа и регистрации
 feat(src/components/layout/TauriTitlebar.vue): изменяет название приложения с "Daiting" на "Dating"

 feat(src/components/layout/SideNav.vue): изменяет название приложения с "Daiting" на "Dating"

 fix(README.md): исправляет название приложения с "Daiting" на "Dating"

 fix(src/api/client.ts): обновляет базовый URL API с 'localhost:3000' на 'localhost:1337'

 fix(src/views/auth/LoginView.vue): изменяет название приложения с "Daiting" на "Dating"

 fix(src/views/auth/RegisterView.vue): изменяет название приложения с "Daiting" на "Dating"

 fix(src-tauri/Cargo.toml): исправляет описание приложения с "Daiting" на "Dating"

 fix(src-tauri/tauri.conf.json): изменяет имя продукта с "Daiting" на "Dating"

 fix(vite.config.ts): обновляет порт разработки с 1420 на 3000

 fix(index.html): изменяет заголовок страницы с "Daiting" на "Dating"

 fix(dating-app-frontend-prompt.md): исправляет название приложения с "Daiting" на "Dating"

 fix(PRODUCT.md): изменяет название приложения с "Daiting" на "Dating"
2026-06-08 14:17:45 +03:00

15 KiB

Dating App Frontend — Claude Code Master Prompt

Context & Orientation

You are building the complete frontend for a dating application called Dating. The backend is already implemented. The generated API client lives at src/api/api.ts — use it as the source of truth for all endpoint shapes, DTOs, and types. Do not re-declare types that already exist in the API client; import them.

Project root: C:\MyApps\dating-app-frontend Package manager: pnpm Stack: Vue 3 (Composition API + <script setup>) + Vite + Tauri v2 The app must work in three contexts simultaneously:

  1. Browser (dev/PWA) — desktop viewport
  2. Browser — mobile viewport (responsive, ≥ 375 px)
  3. Tauri desktop window (Windows / macOS / Linux)

All user-facing text (button labels, placeholders, error messages, toast notifications, empty states, navigation items, form hints, section headings) must be written in Russian. Brand name, logo, and any decorative/editorial text remain in English.


Design Skills — Read Before Writing a Single Line

Before writing any code, internalize these two skill files in full:

.claude/skills/impeccable/SKILL.md          (+ all 7 files in reference/)
.claude/skills/taste-skill/SKILL.md

Apply Impeccable design principles throughout every component. Apply Taste-skill with these parameters:

  • DESIGN_VARIANCE: 8
  • MOTION_INTENSITY: 6
  • VISUAL_DENSITY: 4

Aesthetic Direction

The visual language is "warm brutalism meets editorial intimacy":

  • Dark base (#0d0d0d) with warm cream (#f0ebe0) as the primary text/accent surface
  • A single vivid signal color — deep terracotta #c45c3a — used sparingly for CTAs, likes, active states
  • Typography: pair Instrument Serif (display, headers, profile names) with DM Mono (UI labels, metadata, counts). Load both from Google Fonts.
  • Layouts that feel editorial — asymmetric cards, overlapping text on images, offset grids
  • Micro-interactions via CSS transitions + Vue <Transition> + GSAP (install it). Nothing gratuitous — motion serves information hierarchy.
  • Grain texture overlay (SVG <feTurbulence>) on the app shell background for tactility
  • NO: purple gradients, Inter/Roboto, glassmorphism clichés, floating hearts, soft pastels, rounded-rectangle cards that look like every other dating app

This should feel like an independent editorial magazine for human connection — not Tinder, not Bumble.


Project Bootstrap

# If scaffolding from scratch:
pnpm create tauri-app@latest dating-app-frontend --template vue-ts
cd dating-app-frontend

# Core dependencies
pnpm add vue-router@4 pinia @vueuse/core axios gsap @vuelidate/core @vuelidate/validators

# UI primitives (no opinionated component library — build custom)
pnpm add @floating-ui/vue

# Dev
pnpm add -D sass tailwindcss @tailwindcss/vite autoprefixer

Configure Tailwind in CSS-only mode (no JIT utility classes in templates — use scoped SCSS instead; Tailwind is for reset and baseline only).


File & Folder Architecture

src/
├── api/
│   └── api.ts                  # ← generated, do not touch
├── assets/
│   ├── fonts.css               # @font-face / Google Fonts import
│   └── grain.svg               # noise texture
├── composables/
│   ├── useAuth.ts
│   ├── useFeed.ts
│   ├── useChat.ts
│   ├── useMedia.ts
│   └── useGeolocation.ts
├── stores/
│   ├── auth.store.ts           # Pinia
│   ├── profile.store.ts
│   ├── feed.store.ts
│   ├── chat.store.ts
│   └── ui.store.ts
├── router/
│   └── index.ts                # vue-router with guards
├── views/
│   ├── auth/
│   │   ├── LoginView.vue
│   │   └── RegisterView.vue
│   ├── onboarding/
│   │   └── ProfileSetupView.vue
│   ├── feed/
│   │   └── FeedView.vue
│   ├── matches/
│   │   └── MatchesView.vue
│   ├── chat/
│   │   ├── ChatsListView.vue
│   │   └── ChatRoomView.vue
│   ├── dates/
│   │   └── DatesView.vue
│   ├── profile/
│   │   ├── MyProfileView.vue
│   │   └── ProfileDetailView.vue
│   └── admin/
│       └── ReportsView.vue
├── components/
│   ├── layout/
│   │   ├── AppShell.vue        # grain bg, Tauri titlebar, nav
│   │   ├── BottomNav.vue       # mobile navigation
│   │   ├── SideNav.vue         # desktop sidebar navigation
│   │   └── TauriTitlebar.vue   # custom Tauri drag region
│   ├── feed/
│   │   ├── FeedCard.vue        # the main profile card
│   │   ├── FeedCardStack.vue   # swipe stack with GSAP
│   │   ├── FeedFilters.vue     # filter drawer/panel
│   │   └── LikeButton.vue
│   ├── profile/
│   │   ├── ProfileAvatar.vue
│   │   ├── ProfileBadge.vue    # tags rendered as editorial labels
│   │   ├── ProfileEditor.vue   # form for create/edit profile
│   │   └── MediaGallery.vue
│   ├── chat/
│   │   ├── ChatBubble.vue
│   │   ├── ChatInput.vue       # text + media attach
│   │   ├── VoiceRecorder.vue
│   │   └── MediaMessage.vue
│   ├── dates/
│   │   ├── DateCard.vue
│   │   ├── DateProposalForm.vue
│   │   └── MapPicker.vue       # Leaflet for lat/lng picking
│   ├── common/
│   │   ├── AppButton.vue
│   │   ├── AppInput.vue
│   │   ├── AppModal.vue
│   │   ├── AppDrawer.vue       # bottom sheet on mobile, side panel on desktop
│   │   ├── AppToast.vue
│   │   ├── LoadingSpinner.vue
│   │   └── EmptyState.vue
│   └── reports/
│       └── ReportModal.vue
└── styles/
    ├── _variables.scss
    ├── _typography.scss
    ├── _animations.scss
    └── main.scss

API Integration — Full Coverage

Implement every endpoint from src/api/api.ts. Below is the complete feature map:

Auth (/api/v1/auth/)

  • POST /register — registration form with phone + password, validation via Vuelidate
  • POST /login — login form
  • POST /logout — clear store + redirect
  • POST /refresh — silent token refresh interceptor in Axios (auto-retry once on 401)
  • POST /fcm-token — call after login (stub FCM token for web; use Tauri plugin for desktop)

Store access token in memory (Pinia), refresh token in localStorage. Never store access token in localStorage.

Users (/api/v1/users/)

  • GET /me — populate auth store on app load
  • GET /:id — view any user (admin use)
  • PATCH /:id/ban and /activate — admin panel actions

Profiles (/api/v1/profiles/)

  • POST / — profile creation wizard (multi-step: basic info → location → tags → photo)
  • GET /my — list own profiles in MyProfileView
  • GET /:profileId — public profile detail page
  • PUT /:profileId — profile editor
  • DELETE /:profileId — with confirmation modal

Media (/api/v1/profiles/:profileId/media/)

  • POST /upload?type= — drag-and-drop + file picker; show upload progress bar
  • GET / — grid gallery with lightbox
  • DELETE /:mediaId — with optimistic UI removal

Feed (/api/v1/feed)

  • Infinite scroll OR card-stack swipe (implement BOTH modes, togglable via UI switch)
  • Filter panel: cityId, districtId, ageMin/ageMax, keyword, tagIds (multi-select chips)
  • Show "search paused" banner when match limit is exceeded (detect via API response or a dedicated flag)

Likes (/api/v1/likes)

  • POST / — like/dislike with swipe gesture (GSAP drag) or button
  • GET /matches?profileId= — matches list with match animation (confetti-lite or editorial flash)

Chat (/api/v1/chats)

  • POST / — open chat from a match card
  • GET /?profileId= — chats list; lock icon on inactive chats (only one active at a time)
  • GET /:chatId/messages?profileId= — message history with virtual scroll
  • POST /:chatId/messages?profileId= — send text/media
  • DELETE /:chatId?profileId= — close chat with confirmation
  • Implement polling (2 s interval) for new messages; note in code where WebSocket would replace this

Dates (/api/v1/dates)

  • POST / — proposal form: map picker (Leaflet) for lat/lng, datetime picker, optional statusId
  • GET /?profileId= — list with status chips
  • PATCH /:id/status?profileId= — accept / decline / complete actions
  • GET /statuses — fetch on mount, cache in Pinia

Reports (/api/v1/reports)

  • POST /ReportModal triggered from profile or chat bubble context menu
  • GET / — admin table view with pagination

Tags, Cities, Greetings

  • GET /tags, GET /cities, GET /cities/:cityId/districts, GET /greetings — fetch on app init, cache in Pinia
  • Admin: create/delete tags, cities, districts, greetings

Component Implementation Standards

FeedCard.vue

The centerpiece. Execute this with exceptional care:

  • Full-bleed image background
  • Profile name in large Instrument Serif, overlapping bottom of image
  • Age, city, tags as DM Mono micro-labels
  • Drag-to-like: GSAP Draggable on desktop; touch events on mobile
  • Color bleed on drag direction: terracotta tint for right (like), cool grey tint for left (dislike)
  • Discard animation: card flies off screen with rotation, next card scales up from behind
  • Tap to expand into ProfileDetailView

ChatRoomView.vue

  • Messages grouped by date separator
  • Own messages: right-aligned, cream background
  • Partner messages: left-aligned, dark card with subtle border
  • Voice messages: custom waveform player (Web Audio API for visualization)
  • Video messages: inline <video> with poster frame
  • Photos: open in lightbox modal
  • Locked chat state: blurred message list + overlay "You have X other open chats. Close one to unlock."
  • Input bar: text area auto-grows, attach button opens media type picker

AppShell.vue

  • Desktop: left sidebar (64px collapsed / 240px expanded) + main content area
  • Mobile: top header + bottom nav (5 items)
  • Tauri: custom titlebar with drag region, traffic lights on macOS (use data-tauri-drag-region)
  • Grain SVG filter applied as a pseudo-element over the entire shell

Responsive breakpoints

$mobile: 375px;
$tablet: 768px;
$desktop: 1024px;
$wide: 1440px;

Use @container queries inside card components where possible.


Routing & Guards

/                    → redirect → /feed (if authed) or /login
/login
/register
/setup               → profile creation wizard (redirect here if user has no profiles)
/feed
/matches
/chats
/chats/:chatId
/dates
/profile/me
/profile/:profileId  → public view
/admin/reports       → role guard (admin only)

Navigation guard: check auth store on every route change. Refresh token silently if access token expired.


State Management (Pinia)

auth.store.ts

state: { user, accessToken, profiles, activeProfileId }
actions: login, logout, register, refreshToken, setActiveProfile

feed.store.ts

state: { cards[], filters, page, hasMore, searchPaused }
actions: fetchNextPage, applyFilters, likeCard, dislikeCard

chat.store.ts

state: { chats[], activeChat, messages[], polling: NodeJS.Timer | null }
actions: openChat, closeChat, sendMessage, fetchMessages, startPolling, stopPolling

Tauri-Specific

  • Use @tauri-apps/api/window for window controls in TauriTitlebar.vue
  • Detect Tauri context: window.__TAURI__ exists → show custom titlebar, hide browser-nav elements
  • File upload: use Tauri dialog.open() for native file picker; fall back to <input type="file"> in browser
  • Deep link handling skeleton (for future push notification routing)

CSS Architecture

src/styles/main.scss imports in order:

  1. _variables.scss — all CSS custom properties
  2. _typography.scss — font definitions, heading scale
  3. _animations.scss — keyframes, transition utilities
  4. Tailwind base/reset
// _variables.scss
:root {
  --color-base:      #0d0d0d;
  --color-surface:   #161614;
  --color-surface-2: #1e1e1b;
  --color-cream:     #f0ebe0;
  --color-muted:     #6b6860;
  --color-signal:    #c45c3a;
  --color-signal-dim:#7a3822;
  --color-border:    rgba(240, 235, 224, 0.08);

  --font-display: 'Instrument Serif', Georgia, serif;
  --font-mono:    'DM Mono', 'Courier New', monospace;

  --radius-sm:  4px;
  --radius-md:  8px;
  --radius-lg:  16px;

  --shadow-card: 0 2px 24px rgba(0,0,0,0.6);

  --transition-fast:   150ms cubic-bezier(0.4, 0, 0.2, 1);
  --transition-base:   280ms cubic-bezier(0.4, 0, 0.2, 1);
  --transition-spring: 420ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

Quality Bar

Every component must meet these standards before considered done:

  • Works in Chrome mobile emulation (375px) without horizontal scroll
  • Works in desktop browser at 1280px+
  • Works in Tauri window
  • Loading states: skeleton loaders (not spinners) for feed and chat history
  • Empty states: custom illustrated SVG + copy (no generic "Nothing here yet")
  • Error states: inline error with retry action
  • All forms validated client-side via Vuelidate before API call
  • API errors surfaced as toasts (not console.error)
  • Keyboard navigable (Tab order, Enter to submit, Escape to close modals)
  • No any TypeScript types — use types from the generated API client
  • GSAP animations respect prefers-reduced-motion (wrap in matchMedia check)

Implementation Order (follow strictly)

  1. Project scaffold + Tauri config + pnpm install
  2. Styles: variables, fonts, grain texture, AppShell skeleton
  3. Auth stores + Login/Register views + router guards
  4. API interceptor (Axios instance with token refresh)
  5. Pinia stores: auth, profile, ui
  6. Profile setup wizard (onboarding)
  7. Feed: store, FeedCard, FeedCardStack with swipe
  8. Feed filters drawer
  9. Matches view
  10. Chat: store (with polling), ChatsListView, ChatRoomView, media messages
  11. Dates: form with Leaflet map, list, status updates
  12. My Profile view + editor + media gallery
  13. Public profile view
  14. Reports modal
  15. Admin views (reports table, tags/cities management)
  16. Tauri titlebar + native file picker integration
  17. Polish pass: animations, transitions, empty states, error states
  18. pnpm tauri build smoke test

Commands Reference

pnpm dev                  # Vite dev server (browser)
pnpm tauri dev            # Tauri dev window
pnpm build                # Vite build
pnpm tauri build          # Tauri production build

Final Note

Do not scaffold placeholder components. Every component you create must be fully implemented — real logic, real styles, real API calls. If a feature is complex, implement it incrementally but completely within each file. The goal is a shippable, visually distinctive dating app that feels nothing like a template.

Start with step 1 and work sequentially. Announce each step as you begin it.