Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/thelia/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "thelia",
"description": "Develop Thelia 3 with Claude Code: skills and agents for modules, Propel ORM, the API Platform bridge, the Flexy front-office, the default-twig back-office, and Thelia 2 to 3 migration.",
"version": "0.4.0",
"version": "0.5.0",
"author": {
"name": "Thelia"
},
Expand Down
2 changes: 1 addition & 1 deletion plugins/thelia/skills/ddev/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ hooks:
- composer: install
- exec-host: ddev mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS db_test; GRANT ALL PRIVILEGES ON db_test.* TO 'db'@'%'; FLUSH PRIVILEGES;"
- exec: php Thelia cache:clear
- exec: bin/console sass:build
- exec: php bin/console tailwind:build
- exec: symfony run --daemon bin/console messenger:consume async -vv
```

Expand Down
9 changes: 7 additions & 2 deletions plugins/thelia/skills/ddev/references/hooks-et-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,16 @@ hooks:

### Hook: Compile assets

The two theme families do not share a toolchain: the Flexy front office runs on AssetMapper
plus the Tailwind CLI binary and has no `package.json`, while the `default-twig` back office
is still a Webpack Encore theme.

```yaml
hooks:
post-start:
- exec: bin/console sass:build
- exec: npm run build
- exec: php bin/console importmap:install
- exec: php bin/console tailwind:build
- exec: bash -c "cd templates/backOffice/default-twig && npm install && npm run build"
```

### Hook: Start Messenger
Expand Down
4 changes: 2 additions & 2 deletions plugins/thelia/skills/fresh-install-test/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ ddev exec composer install

# 5. Install Thelia with demo data and admin account
ddev exec php bin/install \
--frontoffice_theme=flexy --backoffice_theme=default \
--frontoffice_theme=flexy --backoffice_theme=default-twig \
--pdf_theme=default --email_theme=default \
--with-demo --with-admin \
--admin_login=thelia --admin_password=thelia \
Expand Down Expand Up @@ -163,7 +163,7 @@ ddev exec composer install

# 5. Install Thelia with demo data and admin account
ddev exec php bin/install \
--frontoffice_theme=flexy --backoffice_theme=default \
--frontoffice_theme=flexy --backoffice_theme=default-twig \
--pdf_theme=default --email_theme=default \
--with-demo --with-admin \
--admin_login=thelia --admin_password=thelia \
Expand Down
8 changes: 4 additions & 4 deletions plugins/thelia/skills/thelia3/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: "Thelia 3 e-commerce framework (Symfony 7.4 LTS, API Platform 4.3,

# Thelia 3 - Module Development Guide

> Stack: Symfony 7.4 LTS, API Platform 4.3, PHP 8.3 or 8.4, Propel ORM. Front in Twig (Flexy, AssetMapper, Tailwind CLI), back-office in Twig via the default-twig theme. Email and PDF templates are Twig too. No Doctrine, no Messenger, no Turbo/Mercure.
> Stack: Symfony 7.4 LTS, API Platform 4.3, PHP 8.3 or 8.4, Propel ORM. Front in Twig (Flexy, AssetMapper, Tailwind CLI), back-office in Twig via the default-twig theme. Email and PDF templates are Twig too. No Doctrine, no Messenger, no Mercure; Turbo ships with Flexy but Drive is off by default.

## 0. Install and version constraints

Expand Down Expand Up @@ -172,7 +172,7 @@ final class MyModule extends BaseModule
- Twig: `resources('/api/front/...')`, `attr('product', 'id')`, `getForm(name)`, `hook(name)`, `theme_hook(name, params)`, `path(routeId)`.
- Facades in LiveComponents: `CartFacade`, `CustomerFacade`, `OrderFacade`, `CheckoutFacade`.
- Template overrides: place in `{module}/templates/frontOffice/flexy/`.
- Assets: AssetMapper + Tailwind CLI, no Node build for the theme. Turbo/Mercure are ABSENT.
- Assets: AssetMapper + Tailwind CLI, no Node build for the theme. Mercure is ABSENT; Turbo ships but Drive is opt-in per zone.
- The theme carries the front catch-all route `/{_view}` (`FlexyBundle\Controller\ViewController`), which serves categories, products, contents and folders. No `thelia/front-module` is involved.
- Details: [references/front-office.md](references/front-office.md)

Expand Down Expand Up @@ -256,7 +256,7 @@ final class MyModule extends BaseModule
| `SecurityContext::getSession()` in CLI | `requestStack->getMainRequest()->getSession()` null | push Request manually or use `IntegrationTestCase` |
| `getComponent()` Stimulus without `await` | async hydration | always `await getComponent(this.element)` |
| Stale `module_template_dirs.php` cache | not invalidated outside `module:post-activate-all` | `cache:clear` after activation |
| Missing `templates-assets/{theme}/dist` symlink | first boot | ensure `THELIA_WEB_DIR/templates-assets/` is writable |
| Missing `templates-assets/backOffice/{theme}/dist` symlink | first boot; back-office Encore themes only, the AssetMapper front never reads this path | ensure `THELIA_WEB_DIR/templates-assets/` is writable |
| Propel `TINYINT` setter (`setVisible(true)`...) | column typed `?int`, `strict_types` rejects `bool` | pass `0`/`1` (DECIMAL = `?string`, never `float`) |
| `trans('X')` PHP without domain gives unexpected French text | injected `TranslatorInterface` = **`core`** domain (Twig `\|trans` = `messages` domain); missing key returns raw string | specify module domain (`trans('X', [], 'mymodule')`) |
| `Lang::getDefaultLanguage()` mistaken for current locale | = store default language (often `en_US`) | `$request->getLocale()` for the UI locale |
Expand All @@ -277,7 +277,7 @@ When working on a module, these patterns are more modern but not yet standard Th
- DTO mapping: manual transformations -> `ObjectMapper` SF 7.3
- Web security: Thelia `SecurityContext` + `checkAuth()` -> Symfony Voters + `#[IsGranted]` (Propel profile integration to design)
- AP serialization perf: `JsonStreamer` SF 7.3 on large collections
- Front interactivity: LiveComponents only -> Turbo Drive + Streams + Mercure (real-time)
- Front interactivity: LiveComponents, plus Turbo Drive on the checkout only -> Drive site-wide + Streams + Mercure (real-time)

## 7. Essential vocabulary

Expand Down
4 changes: 2 additions & 2 deletions plugins/thelia/skills/thelia3/references/front-office.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,14 @@ export default class extends Controller {
}
```

**Turbo and Mercure: ABSENT** from Flexy. Architectural choice - interactivity = LiveComponents only.
**Mercure: ABSENT** from Flexy. Turbo ships - `@hotwired/turbo` sits in the theme's `importmap.php` and `assets/app.js` imports it - but the same file sets `Turbo.session.drive = false`, so Drive is off globally and only a zone marked `data-turbo="true"` (the checkout tunnel) navigates client-side. Everywhere else, interactivity = LiveComponents.

### Stimulus / front JS traps

- **`Intl` locale**: Thelia exposes locale as `fr_FR` (underscore) but `Intl.NumberFormat`/`Intl.DateTimeFormat` require `fr-FR` (`RangeError: Invalid language tag` otherwise). Always `(document.documentElement.lang || 'fr-FR').replace('_', '-')` before instantiating.
- **`data-*-value` JSON**: for a Stimulus `Object`/`Array` value, always `{{ data|json_encode|e('html_attr') }}`. Without `e('html_attr')`, a quote in the JSON (e.g. a product title) silently breaks the HTML attribute (Stimulus parses a partial/empty value).
- **URL template + route with regex constraint**: `path('route', {x: 'PLACEHOLDER'})` throws `InvalidParameterException` at **Twig render time** if the route declares a `requirement` on `x`. Pass a **valid** value as anchor (e.g. `'image'` for `image|document|virtual`) then substitute on the JS side on a slash-delimited segment (`url.replace('/image/', '/'+value+'/')`).
- **Module front + Stimulus**: the theme loads its own `Application` via `@symfony/stimulus-bridge`. A module that starts a second `Application.start()` (`@hotwired/stimulus`) conflicts (double-loading of the same controller). Prefer vanilla JS, or register the controller in the theme's existing app.
- **Module front + Stimulus**: the theme starts its own `Application` in `assets/stimulus_bootstrap.js` via `startStimulusApp()` from `@symfony/stimulus-bundle`. A module that starts a second `Application.start()` (`@hotwired/stimulus`) conflicts (double-loading of the same controller). Prefer vanilla JS, or register the controller in the theme's existing app.

## 8. Domain facades

Expand Down
Loading