# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## What this is

**Placeo** — a Russian classifieds marketplace (Avito-like): category tree, ads with photos + maps, feed/search, chat, reviews, notifications, an **embeddable widget** for third-party sites, **Telegram mini-apps**, and a Filament admin.

Stack: **PHP 8.3 / Laravel 13 · MySQL 8.4 · Filament 5 (`/admin`) · Blade + Alpine.js + Tailwind v4 (Vite) · Material Design 3**. Categories use nested sets (`kalnoy/nestedset`); the widget authenticates via Sanctum; images convert to WebP via `intervention/image`.

## Documentation

`docs/` is the source of truth for architecture and every module — read the relevant one before making changes. Start with [docs/architecture.md](docs/architecture.md) (stack, structure, DB schema, conventions) and [docs/setup.md](docs/setup.md) (env, DB rebuild). Module docs: `auth`, `cabinet`, `ads`, `catalog`, `seller`, `messaging`, `widget`, `telegram-miniapp`, `imports`, `blog`, `admin`, `integrations`, `deploy-hestia`. Docs are written in Russian.

## Environment (local)

This is a **Laragon on Windows** setup. PHP/Composer/MySQL/Node binaries are **not on the global PATH** — either use the Laragon terminal or prepend them per-session (exact paths in [docs/setup.md](docs/setup.md)). Local site is served by Apache+mod_php at a vhost domain (see setup.md / `.env` `APP_URL`), not `php artisan serve`.

## Commands

```bash
# Frontend
npm run build            # prod build → public/build
npm run dev              # Vite watcher

# Tests (SQLite in-memory, see phpunit.xml)
php artisan test                                   # full suite
php artisan test --filter=SomeTest                 # single test/class
composer test                                      # clears config, then runs suite

# Lint / format
vendor/bin/pint                                    # Laravel Pint (PSR-12)

# All-in-one dev (server + queue + logs + vite)
composer dev

# Background workers (needed for full functionality)
php artisan queue:work       # DeepSeek moderation, Telegram alerts, imports
php artisan schedule:work    # batched new-ad notifications, expiry, sitemap warm, import auto-update
```

### DB rebuild (order matters — attributes and ads depend on imported categories)

```bash
php artisan migrate:fresh --seed                    # schema + cities + admin
php artisan placeo:import-categories --fresh        # ~1133 categories from samples/
php artisan db:seed --class=CategoryAttributeSeeder
php artisan db:seed --class=AdSeeder
npm run build
```

### Project-specific artisan commands

`placeo:import-categories`, `ads:archive-expired`, `sitemap:warm`, plus category-attribute generators (`app/Console/Commands/`). Scheduler wiring lives in `routes/console.php`.

### MD3 theme regeneration

Colors are generated from seed `#87C540`, not hand-edited: `node --import ./scripts/register-hook.mjs scripts/gen-md3-theme.mjs > resources/css/_md3-colors.css`.

## Conventions specific to this codebase

- **Models use Laravel 13 PHP attributes** (`#[Fillable([...])]`, `#[Hidden([...])]`) instead of `$fillable`/`$hidden` properties.
- **Design system**: MD3 role tokens (`--md-sys-color-*` in `resources/css/_md3-colors.css`) are mapped to Tailwind utilities in `resources/css/app.css` (`@theme`). Write normal classes (`bg-brand-500`, `text-muted`) and components (`.btn-brand`, `.btn-tonal`, `.input`, `.card`) — they render MD3 colors.
- **Interactivity** is Alpine components registered in `resources/js/app.js` (`infiniteFeed`, `feedMap`, `chat`, `adForm`, `catPicker`, `authModal`, `chatWidget`, etc.).
- **All listing/feed rendering goes through a single `FeedController`** (see [docs/catalog.md](docs/catalog.md)).
- **Routes** are split: `routes/web.php` (public + cabinet), `routes/widget.php` (widget API — CORS, no CSRF), `routes/console.php` (scheduler).
- **Cities are path-based** (`/krasnodar/...`) via `App\Support\ActiveCity`, not subdomains; use the `category_url()` / city-aware helpers in `app/helpers.php` for links.
- **Settings from `/admin → Настройки`** (DeepSeek, Telegram) live in the `settings` table and take priority over `.env`.
- **The widget** (`public/widget/*.js|css`) is static — served as-is, does **not** go through Vite; no rebuild needed after editing it.
- Root-level `test_*.php` and `check_status.php` / `queue_status.php` are ad-hoc debug scripts, **not** part of the phpunit suite.

## Deploy

Production deploy is local → GitLab → prod (`deploy-placeo.sh` over SSH); see [docs/deploy-hestia.md](docs/deploy-hestia.md). Only commit/push when asked.
