Files
Calendink/Provider/.agents/rules/coding-guidelines.md

125 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Calendink Coding Guidelines
These rules apply to all code in this workspace.
---
## Backend — C++ / ESP-IDF
### Philosophy: C-with-Utilities
Write **C-style code** using C++ convenience features. No classes, no methods, no RAII, no exceptions.
**Use freely:** `template`, `auto`, `constexpr`, `enum class`, type aliases from `types.hpp`
**Avoid:** classes, constructors/destructors, `std::` containers, inheritance, virtual functions, RAII wrappers
`goto` for cleanup/shutdown paths in `app_main` is acceptable.
### Unity Build
All `.cpp` files are `#include`-ed into `main.cpp` as a single translation unit. **Do not register new source files in CMakeLists.txt.**
- Use `unity.cpp` aggregators per API group (e.g., `api/tasks/unity.cpp`)
- Mark all file-scoped symbols with `internal` (defined as `static` in `types.hpp`)
- Use `.hpp` for declarations shared across included files only
### API Handler Pattern
```cpp
// METHOD /api/path — What it does
// Body: { "field": value } (if applicable)
internal esp_err_t api_foo_post_handler(httpd_req_t *req) {
httpd_resp_set_type(req, "application/json");
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
// 1. Parse request
// 2. Call store function
// 3. Build cJSON response
// Always cJSON_Delete() objects and free() printed strings — no leaks
}
internal const httpd_uri_t api_foo_post_uri = { .uri = "/api/foo", .method = HTTP_POST, .handler = api_foo_post_handler, .user_ctx = NULL };
```
### Store / Handler Separation
Data operations in `store.cpp` / `store.hpp`. HTTP parsing in endpoint files. Never mix them.
### Logging
**Always use `ESP_LOGI` / `ESP_LOGW` / `ESP_LOGE`** — never `printf()`.
Since this is a Unity Build (single translation unit), the log tag must be unique per file to avoid redefinition. Name it after the module, not a generic `TAG`:
```cpp
// In each file, use a unique local name:
internal const char *kTagHttpServer = "HTTP_SERVER";
internal const char *kTagMain = "MAIN";
internal const char *kTagMDNS = "MDNS";
```
### Type Aliases
Use `types.hpp` aliases: `uint8`, `uint16`, `uint32`, `uint64`, `int8``int64`, `internal`
### Seed Data
`seed_users()` and `seed_tasks()` must be guarded:
```cpp
#ifndef NDEBUG
seed_users();
seed_tasks();
#endif
```
### Data Persistence
All task/user data is currently **in-RAM only** (intentional — NVS/LittleFS persistence is a future milestone). Do not add persistence without a TDD.
---
## Frontend — Svelte 5 + TailwindCSS v4
### Styling: Tailwind Only
Use TailwindCSS exclusively. **No `<style>` blocks in components.**
- All design tokens are in `app.css` via `@theme`: `bg-bg-card`, `text-text-primary`, `border-border`, `text-accent`, `text-success`, `text-danger`, etc.
- If a utility is missing, add a token to `@theme` — don't add inline CSS
### Reactivity: Svelte 5 Runes Only
| Do ✅ | Don't ❌ |
|---|---|
| `$state()` | `writable()`, `readable()` |
| `$derived()` / `$derived.by()` | `$:` reactive statements |
| `$effect()` | `onMount()`, `onDestroy()`, `.subscribe()` |
| `$props()` / `$bindable()` | `export let` |
### `$state()` vs Plain `let`
- **`$state()`** — values the template reads, or that changes should cause a re-render
- **Plain `let`** — script-only internals (mutex flags, interval handles, etc.) the template never reads
### `$effect()` for Initialization
When an effect has no reactive dependencies and runs once on mount, add a comment:
```js
// Load initial data on mount
$effect(() => { fetchData(); });
```
### Shared Utilities
- Date/time helpers, formatters → `lib/utils.js`
- Cross-component reactive state → `lib/stores.js`
- API calls → `lib/api.js` (always via `trackedFetch()`)
**Never duplicate functions across components.**
### Component Structure
```svelte
<script>
// 1. Imports
// 2. $props()
// 3. $state()
// 4. $derived()
// 5. Functions
// 6. $effect()
</script>
<!-- Template — Tailwind classes only -->
```
---
## General
- **Don't commit build artifacts**: `dist/`, `bundles/`, `temp_*`, `*.gz` — update `.gitignore` accordingly
- **Version** is managed through `version.json`, injected as `__APP_VERSION__` at build time