|
| 1 | +# To My Agents! |
| 2 | + |
| 3 | +It is my fervent wish that this file guide every AI coding agent working with code in this repository. |
| 4 | + |
| 5 | + |
| 6 | +## Project Overview |
| 7 | + |
| 8 | +*Latte by Example* is a course. Each numbered directory teaches one concept of |
| 9 | +the [Latte](https://latte.nette.org) template engine, in order, and every |
| 10 | +chapter runs on its own. |
| 11 | + |
| 12 | +- **PHP**: 8.4+, **Latte**: 3.1.6+ (chapters use 3.1 features such as smart HTML attributes) |
| 13 | +- Code, comments and readmes are in **English**. |
| 14 | + |
| 15 | + |
| 16 | +## Essential Commands |
| 17 | + |
| 18 | +```shell |
| 19 | +php 01-hello-world/example.php # run a chapter, HTML goes to stdout |
| 20 | +composer lint-templates # latte-lint, taught about this project's own tags and filters |
| 21 | +composer phpstan # static analysis of the PHP files |
| 22 | +composer check-outputs # readme Output sections match reality |
| 23 | +composer check # all three |
| 24 | +``` |
| 25 | + |
| 26 | +There are no unit tests. A chapter is verified by running it; `check-outputs` |
| 27 | +then enforces that the *Output* section of its readme still matches what the |
| 28 | +example prints, so the two cannot drift apart unnoticed. |
| 29 | + |
| 30 | + |
| 31 | +## Anatomy of a Chapter |
| 32 | + |
| 33 | +``` |
| 34 | +NN-slug/ |
| 35 | +├── readme.md the text of the chapter |
| 36 | +├── example.php the runnable entry point |
| 37 | +└── templates/ |
| 38 | + ├── index.latte the main template |
| 39 | + └── @*.latte templates not meant to be rendered on their own |
| 40 | +``` |
| 41 | + |
| 42 | +`temp/` appears at runtime and holds compiled templates. It is gitignored and |
| 43 | +must never be edited or committed. |
| 44 | + |
| 45 | + |
| 46 | +## `example.php` |
| 47 | + |
| 48 | +Max ~40 lines. Guard the autoloader, create the engine, set the cache |
| 49 | +directory, build `$params`, render: |
| 50 | + |
| 51 | +```php |
| 52 | +<?php declare(strict_types=1); |
| 53 | + |
| 54 | +if (@!include __DIR__ . '/../vendor/autoload.php') { |
| 55 | + echo 'Install dependencies using `composer install`'; |
| 56 | + exit(1); |
| 57 | +} |
| 58 | + |
| 59 | +$latte = new Latte\Engine; |
| 60 | +$latte->setCacheDirectory(__DIR__ . '/temp'); |
| 61 | + |
| 62 | +$params = [ /* ... */ ]; |
| 63 | + |
| 64 | +$latte->render(__DIR__ . '/templates/index.latte', $params); |
| 65 | +``` |
| 66 | + |
| 67 | +- Use `setCacheDirectory()`, not the deprecated `setTempDirectory()`. |
| 68 | +- Do not call `setAutoRefresh()`; it is on by default. |
| 69 | +- From chapter 03 on, `$latte->setFeature(Latte\Feature::Dedent)` is standard, |
| 70 | + so nesting does not push indentation into the output. |
| 71 | + |
| 72 | + |
| 73 | +## Templates |
| 74 | + |
| 75 | +Max ~50 lines per file; prefer two small templates over one long one. Minimal |
| 76 | +valid HTML5, no external assets. Nothing non-deterministic (`date('Y')`, |
| 77 | +`|random`): the readme quotes real output, so it must not drift. |
| 78 | + |
| 79 | + |
| 80 | +## Chapter `readme.md` |
| 81 | + |
| 82 | +60-140 lines, these sections in this order: |
| 83 | + |
| 84 | +```markdown |
| 85 | +# NN · Chapter Title |
| 86 | + |
| 87 | +One-sentence summary. |
| 88 | + |
| 89 | +**You will learn:** 3-5 bullets |
| 90 | + |
| 91 | +## Run it fenced shell block |
| 92 | +## <Walkthrough> H2 sections named after the concepts, short excerpts |
| 93 | +## Output real output, copy-pasted, trimmed with `...` |
| 94 | +## Try it yourself 2-3 one-sentence exercises, easiest first |
| 95 | +## Further reading links to latte.nette.org |
| 96 | +``` |
| 97 | + |
| 98 | +Second person, concrete, no filler. Every claim must come from an actual run. |
| 99 | + |
| 100 | + |
| 101 | +## Rules |
| 102 | + |
| 103 | +- **One chapter, one concept.** If it does not fit on a screen, split it. |
| 104 | +- **No forward references in code.** A chapter may only use what earlier |
| 105 | + chapters introduced. Referring to a later topic in prose is fine, but do it |
| 106 | + by name, not by number - numbers shift while the course is being written. |
| 107 | +- **Comment only what the current chapter teaches.** Do not re-explain what an |
| 108 | + earlier chapter already covered. |
| 109 | +- **Chapters are self-contained.** Data is copied into each `example.php`; |
| 110 | + there is no shared include. |
| 111 | +- **Verify, do not remember.** Output sections, generated code shown in the |
| 112 | + text and every exercise hint must be checked by running them. |
| 113 | +- **A chapter that registers a filter, function or tag must also register it in |
| 114 | + `bin/lint-templates.php`.** The linter only knows what it has been told, and would |
| 115 | + otherwise report the chapter's own vocabulary as an error. |
| 116 | + |
| 117 | + |
| 118 | +## The Dataset |
| 119 | + |
| 120 | +Chapters that need data use this catalogue of a fictional bookshop called |
| 121 | +`Bits & Books`. Omit fields you do not need, but never change the values - |
| 122 | +identical data across chapters keeps the outputs comparable. |
| 123 | + |
| 124 | +| title | author | price | available | tags | published | note | |
| 125 | +|---|---|---|---|---|---|---| |
| 126 | +| It Works on My Machine | Marta Novak | 24.90 | true | php, web | 2023-04-12 | Staff pick | |
| 127 | +| Escaping & Other Life Skills | Petr Svoboda | 31.00 | false | security | 2021-11-03 | null | |
| 128 | +| Zero to Website in a Weekend | Anna Kral | 18.50 | true | html, css, web | 2024-05-20 | null | |
| 129 | +| Refactoring Legacy Apps | Jan Dvorak | 42.00 | true | php, architecture | 2019-08-01 | Second edition | |
| 130 | +| Coffee & Code | Marta Novak | 12.00 | false | essays | 2022-02-14 | null | |
| 131 | + |
| 132 | +Chapters about security add their own hostile input directly in `example.php`. |
| 133 | + |
| 134 | + |
| 135 | +## Adding a Chapter |
| 136 | + |
| 137 | +1. Pick the single concept; check it needs nothing from later chapters. |
| 138 | +2. Create `NN-slug/` with the skeleton above, taking data from the dataset. |
| 139 | +3. Write the readme in the fixed shape; paste *Output* from a real run. |
| 140 | +4. Keep the limits: example.php ≤ 40 lines, template ≤ 50, readme 60-140. |
| 141 | +5. Run `composer lint-templates` and the example itself, twice - output must be identical. |
| 142 | +6. Add a row to the chapter table in the root readme. |
0 commit comments