coding guidelines, agents and gemini.md

This commit is contained in:
2026-03-09 22:07:48 -04:00
parent 9d3a277f45
commit 75d88f441c
4 changed files with 316 additions and 1 deletions

View File

@@ -0,0 +1,124 @@
# 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