|
| 1 | +# Bonjourr Development Guide |
| 2 | + |
| 3 | +This document provides essential information for agentic coding agents working on the Bonjourr codebase. Bonjourr is a minimalist and customizable "new tab" browser extension built using Deno. |
| 4 | + |
| 5 | +## 1. Development Environment & Commands |
| 6 | + |
| 7 | +Bonjourr uses **Deno** as its primary runtime and task runner. Avoid using `npm` or `yarn` directly unless specified. |
| 8 | + |
| 9 | +### Build Commands |
| 10 | + |
| 11 | +- **Full Build:** `deno task build` |
| 12 | +- **Platform-Specific (Dev Mode):** |
| 13 | + - Chrome: `deno task chrome` |
| 14 | + - Firefox: `deno task firefox` |
| 15 | + - Edge: `deno task edge` |
| 16 | + - Safari: `deno task safari` |
| 17 | + - Online (Web version): `deno task online` |
| 18 | +- **Serve Locally:** `deno task serve` (runs on port 8000 by default) |
| 19 | + |
| 20 | +### Linting & Formatting |
| 21 | + |
| 22 | +Bonjourr strictly follows Deno's built-in formatting and linting rules. |
| 23 | + |
| 24 | +- **Format Code:** `deno task format` (runs `deno fmt`) |
| 25 | +- **Lint Code:** `deno lint` |
| 26 | +- **Type Checking:** `deno task types` (runs `deno check`) |
| 27 | + |
| 28 | +### Testing |
| 29 | + |
| 30 | +- Run all tests everytime |
| 31 | +- **Run All Tests:** `deno task test` |
| 32 | + |
| 33 | +--- |
| 34 | + |
| 35 | +## 2. Code Style & Conventions |
| 36 | + |
| 37 | +### Imports |
| 38 | + |
| 39 | +- **Mandatory Extensions:** ALWAYS include the file extension in imports (e.g., `import { foo } from './utils.ts'`). |
| 40 | +- **Deno Modules:** Use `jsr:` or `npm:` prefixes for external dependencies as defined in `deno.json`. |
| 41 | +- **Absolute Paths:** Use relative paths for internal modules. |
| 42 | + |
| 43 | +### Formatting (`deno fmt` configuration) |
| 44 | + |
| 45 | +- **Indentation:** Use **Tabs**. |
| 46 | +- **Indent Width:** 4. |
| 47 | +- **Line Width:** 120 characters. |
| 48 | +- **Semicolons:** **NO semicolons** (except where syntactically required). |
| 49 | +- **Quotes:** Use **single quotes** for strings. |
| 50 | + |
| 51 | +### Typing & Naming |
| 52 | + |
| 53 | +- **Strict Typing:** Always prefer explicit types over `any`. Leverage TypeScript interfaces and types in `src/types/`. |
| 54 | +- **Constants:** Use `UPPER_SNAKE_CASE` (e.g., `CURRENT_VERSION`, `SYNC_DEFAULT`). |
| 55 | +- **Functions/Variables:** Use `camelCase`. |
| 56 | +- **File Naming:** Use `kebab-case` or lowercase for filenames (e.g., `webext-storage.js`, `settings.ts`). |
| 57 | + |
| 58 | +### Error Handling |
| 59 | + |
| 60 | +- Use `try/catch` blocks for operations that might fail (e.g., storage access, API calls). |
| 61 | +- Log warnings/errors using `console.warn` or `console.error` with descriptive messages. |
| 62 | +- Avoid silent failures in critical paths like `startup()`. |
| 63 | + |
| 64 | +### DOM Manipulation |
| 65 | + |
| 66 | +- Bonjourr is a browser extension; direct DOM manipulation is standard. |
| 67 | +- Use `document.getElementById` or `document.querySelector`. |
| 68 | +- Use `dataset` for state management on the `<html>` or `<body>` elements (e.g., `document.documentElement.dataset.theme = 'dark'`). |
| 69 | + |
| 70 | +--- |
| 71 | + |
| 72 | +## 3. Project Structure |
| 73 | + |
| 74 | +- `/src/scripts/`: Main application logic. |
| 75 | + - `features/`: Modular components (clock, weather, backgrounds, etc.). |
| 76 | + - `shared/`: Utility functions used across features. |
| 77 | + - `utils/`: Low-level helpers (translations, permissions, etc.). |
| 78 | + - `services/`: Background services and storage management. |
| 79 | +- `/src/types/`: TypeScript definitions. |
| 80 | +- `/tasks/`: Build and automation scripts (written in TypeScript). |
| 81 | +- `/tests/`: Test suite using `deno test`. |
| 82 | +- `/_locales/`: Internationalization JSON files. |
| 83 | + |
| 84 | +--- |
| 85 | + |
| 86 | +## 4. Internationalization (i18n) |
| 87 | + |
| 88 | +- All user-facing strings should be localized. |
| 89 | +- Use `traduction(null, sync.lang)` for initial translation and `setTranslationCache` for caching. |
| 90 | +- To update translations after adding new keys to `_locales`, run: |
| 91 | + ```bash |
| 92 | + deno task translate |
| 93 | + ``` |
| 94 | + |
| 95 | +--- |
| 96 | + |
| 97 | +## 5. Best Practices for Agents |
| 98 | + |
| 99 | +1. **Self-Verification:** After modifying code, always run `deno task types` and `deno lint` to ensure no regressions. |
| 100 | +2. **Tab Consistency:** Ensure your editor settings respect the use of tabs for this project. |
| 101 | +3. **No Semicolons:** Do not add semicolons as they will be stripped by the formatter anyway. |
| 102 | +4. **Platform Awareness:** When modifying features, consider if the change affects all platforms (Chrome, Firefox, Safari, Online). Use constants from `src/scripts/defaults.ts` to check `PLATFORM` or `BROWSER` if necessary. |
| 103 | +5. **Storage:** Use the `storage` abstraction in `src/scripts/storage.ts` instead of direct `chrome.storage` calls where possible to ensure cross-browser compatibility. |
| 104 | +6. Do not try to add dependencies, find a native solution |
| 105 | +7. Repeat yourself instead of writing difficult code |
| 106 | + |
| 107 | +--- |
| 108 | + |
| 109 | +## 6. Feature Script & Settings Architecture |
| 110 | + |
| 111 | +### Core Entry Point: The Dispatcher |
| 112 | + |
| 113 | +Each feature exports a single function that acts as a state switcher. It handles two distinct phases: **Initialization** and **Live Updates**. |
| 114 | + |
| 115 | +```typescript |
| 116 | +export function feature(init?: FeatureSync, update?: FeatureUpdate) { |
| 117 | + if (update) { |
| 118 | + updateFeature(update); // Live update from Settings |
| 119 | + return; |
| 120 | + } |
| 121 | + if (init) { |
| 122 | + initFeature(init); // Initial load on Startup |
| 123 | + } |
| 124 | +} |
| 125 | +``` |
| 126 | +
|
| 127 | +### UI Handlers (Setters) |
| 128 | +
|
| 129 | +Features use internal "handle" or "set" functions to manipulate the DOM. This keeps logic DRY as both initialization and updates use the same UI handles. |
| 130 | +
|
| 131 | +- **Styling**: Prefer CSS variables on `document.documentElement` (`--feature-property`). |
| 132 | +- **State**: Use `dataset` attributes or class toggles on the feature's container. |
| 133 | +
|
| 134 | +```typescript |
| 135 | +const setWidth = (val: number) => |
| 136 | + document.documentElement.style.setProperty("--feature-width", `${val}em`); |
| 137 | +
|
| 138 | +const handleToggle = (state: boolean) => |
| 139 | + container?.classList.toggle("hidden", !state); |
| 140 | +``` |
| 141 | +
|
| 142 | +### The `updateFeature` Logic |
| 143 | +
|
| 144 | +This internal function processes partial changes from the settings menu. |
| 145 | +
|
| 146 | +1. **Read**: Fetches the current feature state from `storage.sync`. |
| 147 | +2. **Apply**: Updates the object and immediately triggers the relevant **UI Handlers**. |
| 148 | +3. **Persist**: Saves the updated object using `eventDebounce({ feature })` to optimize storage writes. |
| 149 | +
|
| 150 | +### Settings Wiring (`src/scripts/settings.ts`) |
| 151 | +
|
| 152 | +The settings module acts as a declarative controller that connects HTML inputs to feature functions. |
| 153 | +
|
| 154 | +Settings are wired using standard DOM events or the `onclickdown` utility. The convention is to pass `undefined` as the first argument to signify a live update. |
| 155 | +
|
| 156 | +```typescript |
| 157 | +// Example Wiring in initOptionsEvents() |
| 158 | +paramId("i_feature-property").addEventListener("input", function () { |
| 159 | + feature(undefined, { property: this.value }); |
| 160 | +}); |
| 161 | +``` |
| 162 | +
|
| 163 | +### Input Mapping Convention |
| 164 | +
|
| 165 | +| UI Input Type | Event | Feature Payload | |
| 166 | +| :----------------------- | :------------ | :----------------------------- | |
| 167 | +| **Sliders / Ranges** | `input` | `{ property: this.value }` | |
| 168 | +| **Dropdowns / Selects** | `change` | `{ property: this.value }` | |
| 169 | +| **Checkboxes / Toggles** | `onclickdown` | `{ property: target.checked }` | |
| 170 | +| **Action Buttons** | `onclickdown` | `{ trigger: true }` | |
| 171 | +
|
| 172 | +### Feature Best Practices |
| 173 | +
|
| 174 | +- **Parallel States**: Ensure the `init` logic and `update` logic are idempotent so settings can be changed repeatedly without side effects. |
| 175 | +- **Decoupling**: The settings menu should never manipulate the feature's DOM directly; it must always go through the `feature()` entry point. |
| 176 | +- **Persistence**: Only use `eventDebounce` for values that change frequently (like sliders) to avoid hitting browser storage limits. |
| 177 | +- **Naming**: File names use `kebab-case`, while entry point functions use `camelCase` matching the feature name. |
| 178 | +
|
| 179 | +--- |
| 180 | +
|
| 181 | +## 7. CSS Architecture & Styling |
| 182 | +
|
| 183 | +### Main Entry Point |
| 184 | +
|
| 185 | +The primary CSS entry point is `src/styles/style.css`. This file acts as a manifest that imports all other CSS modules in a specific order. |
| 186 | +
|
| 187 | +### Import Order |
| 188 | +
|
| 189 | +1. `_global.css` - Must be imported first (CSS custom properties and global variables) |
| 190 | +2. Interface styles (global layout, backgrounds, settings display) |
| 191 | +3. Settings menu styles (global settings, inputs, dropdowns) |
| 192 | +4. Components (reusable dialog boxes, forms) |
| 193 | +5. Features (time, searchbar, notes, links, etc.) |
| 194 | +6. `_responsive.css` - Must be imported last (responsive breakpoints) |
| 195 | +
|
| 196 | +### File Structure Convention |
| 197 | +
|
| 198 | +CSS files are organized by functional area: |
| 199 | +
|
| 200 | +- `interface/` - Main page styling |
| 201 | +- `settings/` - Settings panel styling |
| 202 | +- `features/` - Individual feature styling |
| 203 | +- `components/` - Reusable UI components |
| 204 | +- `_global.css` - CSS custom properties |
| 205 | +- `_responsive.css` - Responsive breakpoints |
| 206 | +
|
| 207 | +### Selector Specificity Strategy |
| 208 | +
|
| 209 | +The project follows a **low selector specificity** approach: |
| 210 | +
|
| 211 | +1. **Class-based styling** preferred over ID selectors where possible |
| 212 | +2. **Repeat selectors** rather than complex nested rules |
| 213 | +3. **Group related rules** by functional area with clear comments |
| 214 | +
|
| 215 | +### Variable System |
| 216 | +
|
| 217 | +Global variables are defined in `_global.css` as CSS custom properties: |
| 218 | +
|
| 219 | +```css |
| 220 | +:root { |
| 221 | + --page-width: 1600px; |
| 222 | + --page-gap: 1em; |
| 223 | + --font-family: -apple-system, system-ui, Ubuntu, Roboto, "Open Sans"; |
| 224 | + --border-radius: 25px; |
| 225 | +} |
| 226 | +``` |
| 227 | +
|
| 228 | +### Theme Support |
| 229 | +
|
| 230 | +Light and dark themes are handled via data attributes: |
| 231 | +
|
| 232 | +```css |
| 233 | +[data-theme="light"] { |
| 234 | + --color-text: #222222; |
| 235 | + --color-param: 255, 255, 255; |
| 236 | + --color-settings: #f2f2f7; |
| 237 | +} |
| 238 | +
|
| 239 | +[data-theme="dark"] { |
| 240 | + --color-text: #ffffff; |
| 241 | + --color-param: 0, 0, 0; |
| 242 | + --color-settings: #000000; |
| 243 | +} |
| 244 | +``` |
| 245 | +
|
| 246 | +### Styling Principles |
| 247 | +
|
| 248 | +#### 1. Progressive Enhancement |
| 249 | +
|
| 250 | +- Use `@supports` for feature detection |
| 251 | +- Provide fallbacks for modern CSS features |
| 252 | +- Only target modern Chromium, Firefox, and Safari. No IE or Opera Mini. |
| 253 | +
|
| 254 | +#### 2. Responsive Design |
| 255 | +
|
| 256 | +- Breakpoints defined in `_responsive.css` |
| 257 | +- Use `dvh` units with `vh` fallbacks |
| 258 | +
|
| 259 | +#### 3. Performance |
| 260 | +
|
| 261 | +- Minimal CSS nesting |
| 262 | +- No `!important` declarations |
| 263 | +- Efficient selector patterns |
| 264 | +- CSS custom properties for runtime theming |
| 265 | +
|
| 266 | +#### 4. Maintainability |
| 267 | +
|
| 268 | +- Clear file organization |
| 269 | +- Descriptive comments when creating complex selectors |
| 270 | +- Consistent naming conventions |
| 271 | +- Logical grouping of related styles |
| 272 | +
|
| 273 | +### Naming Conventions |
| 274 | +
|
| 275 | +#### ID Selectors |
| 276 | +
|
| 277 | +- `kebab-case` for element IDs |
| 278 | +- Descriptive names indicating purpose |
| 279 | +- Feature-specific prefixes where appropriate |
| 280 | +
|
| 281 | +#### CSS Classes |
| 282 | +
|
| 283 | +- Semantic names over presentational |
| 284 | +- Reusable utility classes in `other.css` |
| 285 | +- State classes like `.shown`, `.hidden`, `.active` |
| 286 | +
|
| 287 | +#### CSS Custom Properties |
| 288 | +
|
| 289 | +- `--prefix-description` format |
| 290 | +- Group related properties |
| 291 | +- Document default values |
| 292 | +
|
| 293 | +### Animation Guidelines |
| 294 | +
|
| 295 | +#### Transition Patterns |
| 296 | +
|
| 297 | +- Use CSS custom properties for timing functions |
| 298 | +- Consistent easing curves (`--out-cubic`) |
| 299 | +- Hardware-accelerated properties (`transform`, `opacity`) |
| 300 | +
|
| 301 | +#### Performance Considerations |
| 302 | +
|
| 303 | +- `will-change` for animated elements |
| 304 | +- Minimize paint operations |
| 305 | +- Debounce rapid animations |
| 306 | +
|
| 307 | +### Browser Support |
| 308 | +
|
| 309 | +#### Core Support |
| 310 | +
|
| 311 | +- Modern browsers (Chrome 90+, Firefox 88+, Safari 14+) |
| 312 | +- Progressive enhancement for older browsers |
| 313 | +- Cross-browser testing for all platforms |
| 314 | +
|
| 315 | +#### Vendor Prefixes |
| 316 | +
|
| 317 | +- Limited use of vendor prefixes |
| 318 | +- Autoprefixer in build process |
| 319 | +- Feature detection where needed |
| 320 | +
|
| 321 | +### Testing |
| 322 | +
|
| 323 | +#### Visual Testing |
| 324 | +
|
| 325 | +- Test across all supported browsers |
| 326 | +- Verify responsive breakpoints |
| 327 | +- Check theme switching functionality |
| 328 | +
|
| 329 | +#### Performance Testing |
| 330 | +
|
| 331 | +- CSS bundle size monitoring |
| 332 | +- Render performance metrics |
| 333 | +- Animation smoothness |
| 334 | +
|
| 335 | +--- |
| 336 | +
|
| 337 | +_Created for automated development assistance in the Bonjourr repository._ |
0 commit comments