# property-match — Development Guidelines ## Stack - **Vite 8** + **React 19** + **TypeScript 6** - **MUI v9** (`@mui/material`) — primary component library - **Tailwind CSS v4** — utility classes via `@tailwindcss/vite` (no `tailwind.config.js`) - **React Router v7** — import from `react-router`, not `react-router-dom` ## Components Always reach for an existing MUI component before writing a custom one. Check the [MUI component list](https://mui.com/material-ui/all-components/) first. Only build a custom component when MUI has no equivalent or the required behavior diverges significantly from what MUI provides. ## Styling Use Tailwind utility classes for all layout and styling. Do not write plain CSS rules or add styles to `.css` files. The only CSS file is `src/index.css`, which holds the Tailwind layer imports — do not add project styles there. ## Providers All data access and data actions live in `src/provider/`. ### Naming | Rule | Example | |------|---------| | Every provider file/class is suffixed `Provider` | `PropertyProvider`, `UserProvider` | | Every provider backed by mock data is also prefixed `Mockup` | `MockupPropertyProvider`, `MockupUserProvider` | ### Interface pattern Define a TypeScript interface for each provider so the mockup and the real implementation are interchangeable: Every Interface should be prefixed with a capitalized I. ```ts // src/provider/IPropertyProvider.ts export interface PropertyProvider { getAll(): Promise getById(id: string): Promise create(data: CreatePropertyInput): Promise update(id: string, data: UpdatePropertyInput): Promise remove(id: string): Promise } ``` ### Async methods Every method in a provider must be `async` and return a `Promise`, even in the mockup. This ensures the real provider can be swapped in without changing any call sites. ```ts // src/provider/MockupPropertyProvider.ts import type { PropertyProvider } from './PropertyProvider' const properties: Property[] = [ /* seed data */ ] export const MockupPropertyProvider: PropertyProvider = { async getAll() { return [...properties] }, async getById(id) { return properties.find(p => p.id === id) ?? null }, async create(data) { const next: Property = { id: crypto.randomUUID(), ...data } properties.push(next) return next }, async update(id, data) { const idx = properties.findIndex(p => p.id === id) properties[idx] = { ...properties[idx], ...data } return properties[idx] }, async remove(id) { const idx = properties.findIndex(p => p.id === id) properties.splice(idx, 1) }, } ``` Swap to a real implementation by replacing `MockupPropertyProvider` with a provider that calls an API — no other code changes required.