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
13 changes: 13 additions & 0 deletions .opencode/command/check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
description: Check a page for common mistakes
agent: plan
---

Check the page $ARGUMENTS for errors. When no language is provided, check all languages of the page. Common errors are:

- Grammatical, typographical, or spelling errors
- Not following the common terms in defined in the glossary of `AGENTS.md`
- Content differs between the different languages. The content should always be the same.
- The page structure doesn't follow the archetype defined in `archetypes`
- Anchors of internal links are not matching the referenced and translated title
- Keywords are not translated as defined in the translations table in `AGENTS.md`
16 changes: 16 additions & 0 deletions .opencode/command/translate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
description: Translate a page
agent: build
---

Translate the page $ARGUMENTS into the other languages.
If the page already exists, only translate the added or changed parts. If the page doesn't exist, create it.

Follow these rules:

- Do not modify the meaning of content. Translate as 1:1 where possible.
- Use names of the translation language for cities (e.g., Köln in German, "Cologne" in English and "eau de Cologne" in French).
- Enforce the glossary and translations as defined in `AGENTS.md`.
- Do not translate the keys of the front matter section, the keys of shortcodes or partials.
- Use the corresponding archetype (defined in `archetypes`) as base for the translated page.
- Update anchors of internal links to the corresponding section in the target language.
57 changes: 57 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# FIP Guide Guidelines

## Content Guidelines

- Content MUST support all three languages (en, de, fr)
- NEVER change the meaning of content when translating. Always translate as 1:1.
- ALWAYS align the content with the corresponding base (defined in `archetypes`)
- ALWAYS use the exact translations for headlines (defined in `archetypes`)
- ALWAYS create new content pages with `hugo new {base}/{name}` where base can be `country`, `operator` or `booking`.

### Glossary

- Use "Freifahrtschein" instead of "Freifahrtsschein"
- Use "FIP Coupon" instead of "FIP free travel"
- Use "Motorail train" instead of "car train"
- Use "Break of journey" instead of "Journey Interruption"

### Translations

| Deutsch | Englisch | Französisch |
| ------------------- | --------------- | ---------------- |
| FIP Freifahrtschein | FIP Coupon | Coupon FIP |
| FIP Globalpreis | FIP Global Fare | Tarif Global FIP |
| FIP 50 Ticket | FIP 50 Ticket | Billet FIP 50 |

## Development Guidelines

### Build/Test Commands

- `hugo serve`: Start local development server
- `hugo --gc --minify`: Build for production
- `npx prettier --write .`: Format code
- `npx pagefind --site public`: Generate search index
- `pre-commit run --all-files`: Run all pre-commit checks

### Code Style & Conventions

- **HTML Templates**: Use Hugo / Go template syntax
- **JavaScript**: ES6 modules with relative imports (`./filename.js`).
- **CSS/SCSS**: Use SCSS with BEM-like naming, variables defined in `_variables.scss`
- **Markdown**: Frontmatter in YAML format, use shortcodes for complex layouts
- **i18n**: Files in `i18n/` sorted alphabetically by key, support en/de/fr languages

### File Structure

- Content in `content/` with multilingual structure (`index.en.md`, `index.de.md`, `index.fr.md`)
- Layouts in `layouts/` following Hugo conventions:
- Partials for reusable components in HTML files in `layouts/partials/`
- Shortcodes for reusable components in Markdown files in `layouts/shortcodes/`
- Assets in `assets/` (processed) and `static/` (copied as-is)

## Quality Standards

- All commits MUST pass the pre-commit hooks defined in `.pre-commit-config.yaml`
- HTML templates must be valid Go template syntax
- Do NOT add any comments to the code
- NEVER create markdown files outside the content directory
20 changes: 20 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ Now, enable `pre-commit` to run the check every time you want to commit changes:
pre-commit install
```

## Content Contributions

### Add new pages

To add a new country:
Expand All @@ -84,3 +86,21 @@ To add a new booking platform:
```zsh
hugo new booking/${PLATFORM} # Replace ${PLATFORM} with the name of the booking platform
```

### Use AI for translation and quality checks

We provide commands to automatically translate and check pages. To define the commands, we use the [OpenCode AI framework](https://opencode.ai/). It's open source and can be used with different providers, models (OpenAI, Github Copilot, Anthropic), and [IDEs](https://opencode.ai/docs/ide/#installation).

#### Installation

1. Install OpenCode: https://opencode.ai/docs#install.
2. Run `opencode auth login` in a terminal, select the provider and log in.
3. Open the OpenCode CLI with `opencode` in a terminal.
4. Run `/models` to select the model you want to use.

Inside the OpenCode Terminal, you can ask any question, similarly to Github Copilot or Claude Chat. In addition, we provide helpful commands:

- `/translate {page}`: Update the translations and add missing translations of the page. `{page}` can be the name of an operator, a country, a booking plattform, or a path to a file.
- `/check {page}`: Check the page for common mistakes and report them. `{page}` can be the name of an operator, a country, a booking plattform, or a path to a file.

That's the recommended way. However, you can still use other frontend ends like GitHub Copilot Chat and Claude Code. We provide an [`AGENTS.md`](https://agents.md/) file for these providers in the repository, but the custom commands are not available without OpenCode.
4 changes: 4 additions & 0 deletions archetypes/operator/index.de.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ operator: "{{ .File.ContentBaseName }}"

## Gültigkeit FIP Tickets

<!--
Die Ticketkategorien können je nach Betreiber abweichen.
-->

FIP Freifahrtschein: <✅/⛔> \
FIP Freifahrt Angehörige: <✅/⛔> \
FIP 50 Tickets: <✅/⛔> \
Expand Down
4 changes: 4 additions & 0 deletions archetypes/operator/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ operator: "{{ .File.ContentBaseName }}"

## Validity of FIP Tickets

<!--
The ticket categories may vary depending on the operator.
-->

FIP Coupon: <✅/⛔> \
FIP Coupon for relatives: <✅/⛔> \
FIP 50 Tickets: <✅/⛔> \
Expand Down
20 changes: 17 additions & 3 deletions archetypes/operator/index.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ title: "{{ .File.ContentBaseName | upper }}"
description: "" # Complète une description pour la compagnie ferroviaire
country:
# Ajoutez les abréviations des pays dans lesquels la compagnie ferroviaire opère en anglais.
- "pays1"
- "pays2"
- "pays3"
- "country1"
- "country2"
- "country3"
operator: "{{ .File.ContentBaseName }}"
---

Expand All @@ -30,6 +30,10 @@ operator: "{{ .File.ContentBaseName }}"

## Validité des Billets FIP

<!--
Les catégories de billets peuvent varier selon l'opérateur.
-->

Coupon FIP : <✅/⛔> \
Coupon FIP accompagnant : <✅/⛔> \
Billets FIP 50 : <✅/⛔> \
Expand Down Expand Up @@ -76,6 +80,16 @@ Tarif Global FIP : <✅/⛔>

## Catégories de classes

<!--
Si les catégories de classes incluent des classes supplémentaires/différentes au-delà de la 1ère et 2ème classe, elles peuvent être décrites ici. Sinon, cette section peut être supprimée.
-->

<!--
**Standard** : Comparable à la 2ème classe. \
**Plus** : 1ère classe sans restauration. Un pass FIP pour la 1ère classe est requis. \
**Premium** : 1ère classe avec restauration. Non réservable avec FIP.
-->

## Achat de billets et réservations

### En ligne
Expand Down
2 changes: 1 addition & 1 deletion content/operator/ns/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ Trains of the Sneltrein / Regional-Express `RE` category, including the connecti
### Online

{{% booking id="db-website"
subtitle="For national and cross-border connections"
subtitle="For cross-border ICE and IC connections"
/%}}

{{% booking id="db-website-fip-db"
Expand Down
2 changes: 1 addition & 1 deletion content/operator/ns/index.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ Les trains de la catégorie Sneltrein / Regional-Express `RE`, notamment les lia
### En ligne

{{% booking id="db-website"
subtitle="Pour les trajets nationaux et internationaux"
subtitle="Pour les connexions ICE et IC transfrontalières"
/%}}

{{% booking id="db-website-fip-db"
Expand Down
8 changes: 4 additions & 4 deletions content/operator/oebb/index.de.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Die ÖBB (Österreichische Bundesbahnen) ist die nationale Eisenbahngesellschaft
- Aufpassen bei Zügen anderer Betreiber ohne FIP Akzeptanz
- Kein FIP im Wiener Flughafenexpress `CAT`
- Besondere Regeln in Zügen nach Italien, Nightjets, Autozügen und IC Bussen
- FIP Freifahrt der ÖBB gilt auch in Lichtenstein
- FIP Freifahrt der ÖBB gilt auch in Liechtenstein

## Gültigkeit FIP Tickets

Expand Down Expand Up @@ -208,9 +208,9 @@ FIP Freifahrtscheine der ÖBB, **jedoch nicht der FS**, gelten im italienischen

Auf der Linie REX63 werden zwischen Pamhagen und Neusiedl am See werden sowohl FIP Fahrkarten der ÖBB als auch der GySEV anerkannt.

### Lichtenstein
### Liechtenstein

Die Eisenbahn in Lichtenstein wird von der ÖBB betrieben. FIP Fahrkarten sind hier zu den österreichischen Konditionen und ohne Aufpreis gültig (Feldkirchen-Buchs SG).
Die Eisenbahn in Liechtenstein wird von der ÖBB betrieben. FIP Fahrkarten sind hier zu den österreichischen Konditionen und ohne Aufpreis gültig (Feldkirchen-Buchs SG).

### Wien Flughafen: City Airport Train (CAT)

Expand All @@ -226,7 +226,7 @@ Wer mit regulären Wiener Öffi-Tickets (z. B. Einzelfahrten oder 24/48/72-Stund

### Schneebergbahn

Die Schneebergbahn ist zwar kein Teil der ÖBB oder FIP gewähnt jedoch bei Vorlage des FIP Ausweises 50% Rabatt auf Tickets.
Die Schneebergbahn ist zwar kein Teil der ÖBB oder FIP gewährt jedoch bei Vorlage des FIP Ausweises 50% Rabatt auf Tickets.

### ÖBB Postbus

Expand Down
2 changes: 1 addition & 1 deletion content/operator/oebb/index.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Coût : \
**Description :** \
Trains rapides nationaux et internationaux de la catégorie la plus élevée des ÖBB. Ils relient régulièrement les principales villes autrichiennes, ainsi que l’Allemagne, l’Italie, la Tchéquie, la Hongrie, la Slovaquie et la Suisse. Trois classes de confort et un bistro à bord. Les Railjet avec moins d’arrêts sont commercialisés comme Railjet Xpress.

Pour les Railjet vers l’Italie, un supplément est à payer à partir de la frontière italienne. Voir [Conditions spéciales](##conditions-tarifaires-spéciales). \
Pour les Railjet vers l’Italie, un supplément est à payer à partir de la frontière italienne. Voir [Conditions spéciales](#conditions-tarifaires-spéciales). \
**Réservation possible :** oui \
**Réservation obligatoire :** non
{{% /expander %}}
Expand Down
Loading