diff --git a/.cspellignore b/.cspellignore
index 67ca8d06c4..2699e760ce 100644
--- a/.cspellignore
+++ b/.cspellignore
@@ -53,6 +53,7 @@ retryable
mjml
autonumber
colorpicker
+cspellignore
datetimerangepickerfield
datetimerangepicker
inlinealert
@@ -62,6 +63,7 @@ mailpit
axllent
timestamptz
formatjs
+frontmatter
autoplay
authproxy
xact
diff --git a/spec/adr/.gitkeep b/spec/adr/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/spec/adr/coding-guidelines-ssot.md b/spec/adr/coding-guidelines-ssot.md
new file mode 100644
index 0000000000..e3f8f1246d
--- /dev/null
+++ b/spec/adr/coding-guidelines-ssot.md
@@ -0,0 +1,34 @@
+# ADR: Coding Guidelines as Single Source of Truth
+
+- **Status:** Accepted
+- **Date:** 2026-03-13
+
+## Context
+
+The Comet coding guidelines currently live as hand-written Docusaurus pages in `docs/docs/9-coding-guidelines/` (14 files covering Git, TypeScript, React, NestJS, CSS, accessibility, and more). These docs are written for human consumption and use Docusaurus-specific syntax (admonitions, frontmatter, image references).
+
+AI agents have no structured access to these guidelines. The only way to make agents aware of coding standards is to duplicate the content into agent-consumable formats (Cursor rules, agent skills), which creates a maintenance burden and inevitable drift between the human docs and agent instructions.
+
+Both humans and agents need to follow the same guidelines, so maintaining two separate copies is unsustainable.
+
+## Decision
+
+Move the single source of truth for coding guidelines to `spec/standards/coding-guidelines/` as granular, tool-agnostic markdown files (one per topic, 14 files total). From these standards files, generate:
+
+1. **Docusaurus docs** in `docs/docs/9-coding-guidelines/` -- preserving the current file names, page structure, admonitions, and image references so the human-facing docs remain unchanged
+2. **An agent skill** at `.agents/skills/coding-guidelines/SKILL.md` -- giving AI agents access to the same guidelines as structured, actionable instructions
+
+The standards files use plain markdown with lightweight structured markers (HTML comments) for Docusaurus-specific elements like admonitions and images, keeping the source format portable and not tied to any particular rendering tool.
+
+## Alternatives Considered
+
+1. **Keep Docusaurus docs as the SSoT** -- Agents cannot consume Docusaurus syntax directly; would require manual duplication into agent-friendly formats, leading to drift.
+2. **Single large ADR or markdown file** -- Violates the purpose of ADRs (which capture decisions, not reference material) and would be too large to maintain or consume effectively.
+3. **Cursor rules only** -- Would give agents access but leave humans without rendered documentation; Cursor rules also have size and format constraints that make them unsuitable for 14 topics of guidelines.
+
+## Consequences
+
+- All changes to coding guidelines go through the standards files in `spec/standards/coding-guidelines/`.
+- The Docusaurus docs and agent skill become generated artifacts and must not be edited directly.
+- A generation step is needed to produce both the docs and the skill from the standards.
+- The generated docs must match the current docs as closely as possible to avoid disruption.
diff --git a/spec/specs/.gitkeep b/spec/specs/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/spec/specs/coding-guidelines.md b/spec/specs/coding-guidelines.md
new file mode 100644
index 0000000000..824671de73
--- /dev/null
+++ b/spec/specs/coding-guidelines.md
@@ -0,0 +1,216 @@
+---
+summary: "Generate Docusaurus docs and agent skill from the coding-guidelines standards files"
+implemented: false
+---
+
+# Feature: Coding Guidelines Generation
+
+## Goal / Background
+
+The coding guidelines are maintained as tool-agnostic markdown files in `spec/standards/coding-guidelines/` (the single source of truth, per [ADR: Coding Guidelines as SSoT](../adr/coding-guidelines-ssot.md)). Two artifacts need to be generated from these standards:
+
+1. **Docusaurus docs** — human-readable pages in `docs/docs/9-coding-guidelines/`, preserving the current structure, formatting, and content as closely as possible
+2. **Agent skill** — a machine-readable skill at `.agents/skills/coding-guidelines/SKILL.md` that gives AI agents access to the same guidelines
+
+Both artifacts are generated; neither should be edited directly. All guideline changes go through the standards files.
+
+- **Jira:** N/A
+- **Figma:** N/A
+
+## Requirements & User Stories
+
+### Docusaurus docs generation
+
+- Each standards file maps to exactly one Docusaurus doc file with a specific filename, title, and optional `sidebar_position`
+- Structured markers in the standards files (``, ``) are transformed to their Docusaurus equivalents
+- Cross-file references (`(filename.md)`) are converted to Docusaurus inter-page links (`(./slug)`)
+- The generated output must match the current Docusaurus docs as closely as possible — the current docs serve as the reference/expected output
+- Images remain in `docs/docs/9-coding-guidelines/images/` and are not generated
+
+### Agent skill generation
+
+- The skill aggregates the guidelines into a single actionable document optimized for AI consumption
+- No Docusaurus syntax (admonitions, frontmatter, image references) appears in the skill
+- The skill uses plain markdown with clear structure and imperative instructions
+
+## Acceptance Criteria
+
+- [ ] A generation script (or documented manual process) can produce all 14 Docusaurus doc files from the 14 standards files
+- [ ] The generated Docusaurus docs match the current docs (same file names, page titles, section structure, admonitions, image references, code examples, cross-page links)
+- [ ] The agent skill file exists at `.agents/skills/coding-guidelines/SKILL.md` with valid YAML frontmatter
+- [ ] The agent skill contains all guideline topics in a format suitable for AI agents
+- [ ] `pnpm --filter comet-docs run lint` passes after generation
+- [ ] `pnpm exec cspell "spec/**"` passes
+
+## Implementation Plan
+
+### Step 1: Define the file mapping
+
+Each standards file maps to a Docusaurus doc with specific metadata:
+
+| Standards file | Docusaurus file | `title` | `sidebar_position` |
+| ----------------------- | ----------------------------------- | ----------------------------------------------- | ------------------ |
+| `index.md` | `index.md` | Coding Guidelines | _(none)_ |
+| `git.md` | `01-git-guidelines.md` | Git Guidelines | -5 |
+| `general.md` | `02-general.md` | General (all programming languages) | -5 |
+| `secure-development.md` | `03-secure-software-development.md` | Basic principles of secure software development | -5 |
+| `libraries.md` | `04-libraries-and-techniques.md` | Libraries and techniques | -5 |
+| `naming-conventions.md` | `05-naming-conventions.md` | Naming conventions | -5 |
+| `typescript.md` | `06-typescript.md` | Typescript | -5 |
+| `styling-css.md` | `07-styling-css.md` | Styling / CSS | -5 |
+| `api-nestjs.md` | `08-api-nestjs.md` | API (NestJS) | -5 |
+| `react.md` | `09-react.md` | React | -5 |
+| `kubernetes.md` | `10-kubernetes.md` | Kubernetes | -5 |
+| `cdn.md` | `11-cdn.md` | CDN | -5 |
+| `postgresql.md` | `12-postgresql.md` | PostgreSQL | _(none)_ |
+| `accessibility.md` | `13-accessibility.md` | Accessibility | _(none)_ |
+
+### Step 2: Transformation rules (standards → Docusaurus)
+
+Apply these transformations in order:
+
+#### 2a. Heading → Frontmatter
+
+Strip the top-level `# Heading` from each standards file. Replace it with Docusaurus YAML frontmatter using the `title` and `sidebar_position` values from the mapping table above.
+
+**Standards input:**
+
+```markdown
+# Git Guidelines
+
+## General
+```
+
+**Docusaurus output:**
+
+```markdown
+---
+title: Git Guidelines
+sidebar_position: -5
+---
+
+## General
+```
+
+For `index.md`, the frontmatter has only `title` (no `sidebar_position`).
+
+#### 2b. Admonitions
+
+Convert HTML comment markers to Docusaurus admonition syntax:
+
+- `` becomes `:::TYPE`
+- `` becomes `:::TYPE TITLE`
+- `` becomes `:::`
+
+The `TYPE` is one of: `tip`, `warning`, `caution`, `note`, `info`. The optional `TITLE` follows the type (e.g., `tip Good`, `warning Bad`).
+
+**Standards input:**
+
+```markdown
+
+
+Added margin to footer
+
+
+```
+
+**Docusaurus output:**
+
+```markdown
+:::warning Bad
+Added margin to footer
+:::
+```
+
+Preserve all content between the opening and closing markers, including blank lines and nested elements. Remove the blank line immediately after the opening marker and immediately before the closing marker to match Docusaurus conventions.
+
+#### 2c. Image references
+
+Convert image comments to markdown image syntax:
+
+`` becomes ``
+
+The `ALT_TEXT` is derived from the filename by removing the extension and converting to PascalCase (e.g., `activation-squashing.png` → `ActivationSquashing`, `can-i-use.png` → `CanIUse`).
+
+When the original Docusaurus doc included an italic caption below the image (e.g., `_Activation of squashing in MR_`), this caption text comes from the `DESCRIPTION` in the comment. The standards file should use the `caption` flag to indicate this: ``. When the `caption` flag is present, render the description as `_DESCRIPTION_` on the line immediately below the image.
+
+#### 2d. Cross-file references
+
+Convert internal markdown links from standards-file references to Docusaurus page slugs:
+
+| Standards reference | Docusaurus reference |
+| ------------------- | ------------------------------ |
+| `(kubernetes.md)` | `(./kubernetes)` |
+| `(libraries.md)` | `(./libraries-and-techniques)` |
+| `(typescript.md)` | `(./typescript)` |
+
+The slug is derived from the Docusaurus filename by stripping the numeric prefix and `.md` extension (e.g., `06-typescript.md` → `./typescript`).
+
+#### 2e. Preserved elements
+
+The following elements require no transformation and pass through as-is:
+
+- Standard markdown (headings, lists, bold, italic, links, code blocks)
+- ` ` tags
+- External URLs
+- Code examples and fenced code blocks
+
+### Step 3: Generate Docusaurus docs
+
+Apply the transformation rules from Step 2 to each standards file, producing the corresponding Docusaurus file in `docs/docs/9-coding-guidelines/`. The generated files should be written with a header comment indicating they are generated:
+
+```markdown
+
+```
+
+Alternatively, if adding this comment breaks Docusaurus rendering, omit it and rely on the ADR and this spec to document that the files are generated.
+
+### Step 4: Generate agent skill
+
+Create `.agents/skills/coding-guidelines/SKILL.md` with:
+
+1. **YAML frontmatter** with `name`, `description`, and `compatibility` fields
+2. **Introductory paragraph** explaining the skill's purpose
+3. **Instructions** telling the agent to read and follow the coding guidelines
+4. **Condensed guidelines** — all 14 topics concatenated and reformatted for AI consumption:
+ - Strip image references (agents cannot view images)
+ - Convert admonition markers to plain emphasis (e.g., `**Bad:**` / `**Good:**` instead of admonition blocks)
+ - Keep all code examples, rules, and conventions intact
+ - Use clear section headers for each topic
+ - Prioritize actionable rules over background context
+
+The skill should be structured so an agent can quickly find the relevant section for its current task (e.g., "Git commit rules", "React conventions", "TypeScript patterns").
+
+### Step 5: Validate
+
+1. Run `pnpm --filter comet-docs run lint` to verify the generated Docusaurus docs pass all checks
+2. Run `pnpm exec cspell "spec/**"` and add any unknown words to `.cspellignore`
+3. Visually diff the generated Docusaurus docs against the current docs to verify minimal deviation
+
+## Files to Create or Modify
+
+| File | Action | Purpose | Package |
+| ----------------------------------------------------------------- | ------------ | ---------------------------------------- | ------------ |
+| `spec/standards/coding-guidelines/*.md` (14 files) | Read (input) | SSoT standards files — generation source | N/A |
+| `docs/docs/9-coding-guidelines/index.md` | Generate | Docusaurus index page | `comet-docs` |
+| `docs/docs/9-coding-guidelines/01-git-guidelines.md` | Generate | Git guidelines doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/02-general.md` | Generate | General guidelines doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/03-secure-software-development.md` | Generate | Secure development doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/04-libraries-and-techniques.md` | Generate | Libraries doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/05-naming-conventions.md` | Generate | Naming conventions doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/06-typescript.md` | Generate | TypeScript doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/07-styling-css.md` | Generate | Styling/CSS doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/08-api-nestjs.md` | Generate | API/NestJS doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/09-react.md` | Generate | React doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/10-kubernetes.md` | Generate | Kubernetes doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/11-cdn.md` | Generate | CDN doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/12-postgresql.md` | Generate | PostgreSQL doc | `comet-docs` |
+| `docs/docs/9-coding-guidelines/13-accessibility.md` | Generate | Accessibility doc | `comet-docs` |
+| `.agents/skills/coding-guidelines/SKILL.md` | Create | Agent skill for coding guidelines | N/A |
+
+## Dependencies & Open Questions
+
+- **Image caption encoding:** The standards files use `` for all images. For the few images that had italic captions in the original docs (e.g., the squashing activation screenshot), the standards files should include a `caption` flag: ``. The existing standards files may need a minor update to add this flag where captions are expected.
+- **Generation approach:** The transformation can be implemented as a Node.js script, a shell script, or done manually by an agent following this spec. A script is recommended for repeatability but not strictly required for the initial generation.
+- **Generated file markers:** Adding `` comments to the Docusaurus files would make it clear they shouldn't be edited directly, but this needs to be tested to ensure Docusaurus doesn't render or break on the comment.
+- **Skill size:** Concatenating all 14 topics into a single skill file may be large. If the file exceeds practical size limits for agent context windows, consider splitting into a skill that references individual topic files rather than inlining everything.
diff --git a/spec/standards/coding-guidelines/accessibility.md b/spec/standards/coding-guidelines/accessibility.md
new file mode 100644
index 0000000000..2556ce797d
--- /dev/null
+++ b/spec/standards/coding-guidelines/accessibility.md
@@ -0,0 +1,19 @@
+# Accessibility
+
+Comet projects aim to conform to [WCAG 2.1 Level AA](https://www.w3.org/TR/WCAG21/).
+
+## POUR Principles
+
+- **Perceivable:** Provide text alternatives, captions, and sufficient contrast.
+- **Operable:** All functionality must be keyboard accessible.
+- **Understandable:** Use predictable behavior, clear instructions, and helpful error messages.
+- **Robust:** Ensure content works with a wide range of devices and assistive technologies.
+
+## Key Rules
+
+- Use semantic HTML (``, ``, ``, ``, etc.).
+- Color contrast: at least **4.5:1** for normal text, **3:1** for large text.
+- All interactive elements must be keyboard operable with visible focus indicators.
+- Images need meaningful `alt` text; use `alt=""` for decorative images.
+- Associate form inputs with `` (or `aria-label` / `aria-labelledby`).
+- Respect `prefers-reduced-motion`; avoid autoplay animations for users who have requested reduced motion.
diff --git a/spec/standards/coding-guidelines/api-nestjs.md b/spec/standards/coding-guidelines/api-nestjs.md
new file mode 100644
index 0000000000..f8a8cf5943
--- /dev/null
+++ b/spec/standards/coding-guidelines/api-nestjs.md
@@ -0,0 +1,188 @@
+# API (NestJS)
+
+## General
+
+For new requirements, always check the [documentation](https://docs.nestjs.com/) first. There are already established techniques or patterns for many common problems.
+
+> NestJS is agnostic in many ways, and one of them is communication. It provides wrappers (or allows us to create our own) for third-party libraries.
+
+See: [What is the NestJS Runtime - Trilon Consulting](https://trilon.io/blog/what-is-the-nestjs-runtime)
+
+## Logging
+
+- Only log **warnings and errors** by default.
+- Additional logs (for debugging/profiling) should be toggleable via flags/settings.
+
+
+
+**Recommendation:** Use the built-in [NestJS Logger](https://docs.nestjs.com/techniques/logger).
+
+
+
+## Services vs. Controller/Resolver
+
+- **Controller/Resolver:** Represent the HTTP or GraphQL layer.
+- **Service:** Represents the **business logic** layer.
+
+### Service Best Practices
+
+- Services should be **decoupled from the HTTP/GraphQL layer** (e.g., avoid using `InputTypes` directly).
+ - This allows them to be reused (e.g., in console jobs) without mocking types.
+- Prefer passing the entire **entity** rather than just the ID.
+- Services should be **easily testable**. ([Using MikroORM with NestJS framework](https://mikro-orm.io/docs/usage-with-nestjs#testing))
+- Use **Dependency Injection (DI)** to control access to services and enforce clear module boundaries/interfaces.
+
+### Service FAQs
+
+- **Is a service always required?**
+ No — don't create pass-through methods just for the sake of it.
+ Yes — if business logic is reused or the HTTP layer becomes messy.
+
+- **Can I create utility files?**
+ Yes, as long as they are **stateless helper functions**.
+ Do **not** consume other services or repositories within them.
+
+
+
+Give them specific names — avoid generic `utils` dump folders.
+
+
+
+### Access Control Lists (ACL) / Authorization Checks
+
+- Place ACL logic in a **dedicated ACL service** (e.g., `products.acl.service.ts`) or inline in the controller/resolver for specific permission checks.
+- **Do not** perform ACL checks in shared services: Console jobs, for instance, have no authenticated user and may lead to double-checking permissions.
+- ACLs should be **covered by unit tests**.
+
+## Avoid Using `process.env` Directly
+
+Directly accessing environment variables in the code has downsides:
+
+- Not testable (no dependency injection)
+- No central place to manage environment variables
+- No validation
+
+**Exception:** It's technically necessary in some cases, such as in app entry points (`main.ts`, `bootstrap.ts`).
+
+## Dependency Injection
+
+**Constructor-based** injection is preferred over **property-based** injection (see: [Documentation | NestJS - A progressive Node.js framework](https://docs.nestjs.com/providers#property-based-injection)).
+Use property injection only when technically necessary.
+
+## ORM / Database
+
+### Repository
+
+Prefer `repository.create` over `new Entity()` since `create` expects a complete data object.
+
+### Migrations
+
+Down migrations are not required – using `throw new Error("Unsupported")` is sufficient.
+
+We do not use rollbacks; issues are resolved with a new deployment.
+
+### Data Types
+
+- Prefer `type: "uuid"` for IDs. See [Prefer UUIDs for IDs](postgresql.md#prefer-uuids-for-ids).
+- Always use `columnType: text` for strings. Explanation: See [Don't Do This - PostgreSQL wiki.](https://wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_varchar.28n.29_by_default)
+- Prefer `jsonb` over `json`. Explanation: See [8.14. JSON Types](https://www.postgresql.org/docs/current/datatype-json.html)
+- For timestamps, always use `columnType: "timestamp with time zone"`.
+
+### DB Defaults
+
+Avoid using DB defaults as they are not available before inserting/updating. This also falsifies the types of the entity.
+
+
+
+```ts
+@Property({ default: false })
+@Field()
+visible: boolean;
+```
+
+
+
+
+
+```ts
+@Property()
+@Field()
+visible: boolean;
+```
+
+
+
+(if GQL Field → provide default value for InputType)
+
+
+
+```ts
+@Property()
+visible: boolean = false;
+```
+
+
+
+(if not a GQL Field)
+
+
+
+If you are using the Upsert-Pattern, you may use DB defaults **additionally**
+
+```ts
+@Field()
+@Property({
+ columnType: "timestamp with time zone",
+ onUpdate: () => new Date(),
+ defaultRaw: "now()", // fallback for upsert
+})
+updatedAt: Date = new Date();
+```
+
+
+
+## GraphQL
+
+### Enum Keys = Values
+
+Enum keys and values must be identical.
+
+
+
+```ts
+enum Category {
+ MAIN = "main"
+ SECONDARY = "secondary"
+}
+```
+
+
+
+
+
+```ts
+enum Category {
+ Main = "Main"
+ Secondary = "Secondary"
+}
+```
+
+
+
+Reason: Admin and Site only know the GraphQL schema, where the enum keys are used. Therefore, queries and mutations also send the keys. If the values differ from the keys, this causes API errors because the wrong values are used for the enum.
+
+Regarding naming conventions, see also [TypeScript | Enums](typescript.md).
+
+### TypeScript number vs GraphQL Int/Float
+
+TypeScript has only one number type, but GraphQL distinguishes between Int and Float, so the type must be specified manually, otherwise, Float is the less strict default.
+
+```ts
+class Product {
+ @Field(() => Int)
+ position: number;
+
+ @Field(() => Float)
+ price: number;
+}
+```
diff --git a/spec/standards/coding-guidelines/cdn.md b/spec/standards/coding-guidelines/cdn.md
new file mode 100644
index 0000000000..afb661c781
--- /dev/null
+++ b/spec/standards/coding-guidelines/cdn.md
@@ -0,0 +1,13 @@
+# CDN
+
+The caching strategy must always be controlled by the origin (i.e., the application itself). **There must be no dependency on the default settings of the CDN.**
+
+### Requirements
+
+- All GET requests (Site and API) must explicitly set a Cache-Control header (see [Cache-Control header - HTTP | MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control)).
+- Caching duration: The lifetime of assets should be chosen appropriately depending on the content (e.g., for static assets with [Cache Buster](https://www.keycdn.com/support/what-is-cache-busting): long validity with `immutable`; for API responses: short validity or `no-store`).
+- Comet: Header setting is already ensured for all routes.
+
+### Background
+
+Proper control of cache lifetime not only improves loading speed but also affects SEO (see e.g., [Serve static assets with an efficient cache policy | Lighthouse | Chrome for Developers](https://developer.chrome.com/docs/lighthouse/performance/uses-long-cache-ttl?hl=de)).
diff --git a/spec/standards/coding-guidelines/general.md b/spec/standards/coding-guidelines/general.md
new file mode 100644
index 0000000000..bfc7b34e24
--- /dev/null
+++ b/spec/standards/coding-guidelines/general.md
@@ -0,0 +1,148 @@
+# General (all programming languages)
+
+## Use Descriptive Naming
+
+The goal of names is to help developers understand the code without having to read the detailed implementation.
+
+Try to avoid comments as descriptions, as they may not always be up to date with the code.
+
+
+
+```ts
+// calculates the sum of all products in the cart and removes the discount
+const price = (c: C) => {
+ return c.prods.reduce((s, p) => s + p.price - p.disc, 0);
+};
+```
+
+
+
+
+
+```ts
+const getCartPriceWithDiscounts = (cart: Cart) => {
+ return cart.products.reduce((total, product) => total + product.price - product.discount, 0);
+};
+```
+
+
+
+### Boolean Naming
+
+The name should indicate that the variable is a boolean.
+
+
+
+```ts
+const error = true;
+```
+
+
+
+
+
+```ts
+const hasError = true;
+```
+
+
+
+
+
+Prefix with is/has/should (see: [Tips on naming boolean variables - Cleaner Code](https://dev.to/michi/tips-on-naming-boolean-variables-cleaner-code-35ig)).
+Not necessary for: loading, disabled ...
+
+
+
+### Affirmative Variables
+
+Try to name variables in an affirmative form (avoid negative naming of variables)
+
+
+
+```ts
+const isNotComplete = false; // !isComplete is usually better
+const isIncomplete = true; // could make sense if 'isComplete' is a known state of the object
+
+if (!isNotComplete) {
+} // hard to read
+```
+
+
+
+
+
+```ts
+const isComplete = true;
+```
+
+
+
+## Don't use Abbreviations
+
+Abbreviations make it harder read code. Even more for new Devs or Devs who are not regularly working on that project.
+
+> It's better to save time thinking than to save time typing.
+
+### Exceptions:
+
+- Well-known abbreviations such as protocols (HTML, CSS, TCP, IP, SSO, API, …)
+- Abbreviations coming from a 3rd party (API, Library, …)
+
+When using PascalCase or camelCase abbreviations must not violate it.
+
+
+
+GUIController
+UIElement
+
+
+
+
+
+GuiController
+UiElement
+
+
+
+## Don't use Exceptions as Flow Control
+
+
+
+```ts
+async function getFileName(fileId: string): string | undefined {
+ try {
+ const file = await fileService.findFileOrFail(fileId);
+ return file.name;
+ } catch (error) {
+ if (error.message === "FileNotFound") {
+ return undefined;
+ }
+ }
+}
+```
+
+
+
+
+
+```ts
+async function getFileName(fileId: string): string | undefined {
+ if (!(await fileService.checkIfFileExists(fileId))) {
+ return undefined;
+ }
+
+ const file = await fileService.findFileOrFail(fileId);
+ return file.name;
+}
+```
+
+
+
+### Why?
+
+Using exceptions as flow control is a considered anti-patterns. The reasons for this common consensus are manifold: For instance, an exception is basically a `GOTO` statement.
+
+A good question to ask yourself is: **"if you use exceptions for normal situations, how do you locate unusual (i.e. exceptional) situations?"**
+
+[Are exceptions as control flow considered a serious anti-pattern? If so, Why?](https://softwareengineering.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why)
diff --git a/spec/standards/coding-guidelines/git.md b/spec/standards/coding-guidelines/git.md
new file mode 100644
index 0000000000..2c9e5afdb0
--- /dev/null
+++ b/spec/standards/coding-guidelines/git.md
@@ -0,0 +1,260 @@
+# Git Guidelines
+
+## General
+
+- In principle, we follow the concept of [trunk-based development](https://www.atlassian.com/continuous-delivery/continuous-integration/trunk-based-development).
+- We aim for a high level of quality in our source code.
+- The Git commit history should be clean and understandable to make it easier to trace changes.
+
+A clean Git history can be achieved in two ways:
+
+- **Recommended:** On merge request level **(requires [squashing](https://www.geeksforgeeks.org/git/git-squash/))**
+- On commit level
+
+## Merge Requests
+
+### Rules
+
+- One merge request per change (feature, fix, or refactoring)
+- If the `main` pipeline is red (i.e., not passing), nothing may be merged unless it contributes to fixing the issue (see also environments in [Kubernetes](kubernetes.md))
+
+### Goal
+
+Make the review process as easy as possible for the reviewer.
+
+### Possible measures:
+
+- Link the relevant JIRA ticket
+- Add the **Timr** time tracking entry
+- Generate the MR description (JIRA ticket + Timr) using the GitLab button in JIRA
+- Link the screen design
+- Attach screenshots or screen recordings
+- Keep merge requests as small as possible
+- Avoid unnecessary dependencies (only add them if absolutely necessary)
+- Do not combine multiple tasks in a single MR (e.g., bugfix and new feature in the same MR)
+
+### Squashing
+
+Squashing combines all commits of a merge request into a single commit during the merge process.
+
+
+
+The squash commit will include the title and description of the merge request.
+
+#### Advantages:
+
+- Improved integration between GitLab, Git, and IDEs
+ (Title, description, and links are included in the squash commit; the related MR can be more easily identified in the IDE)
+- Commit messages within the MR become irrelevant. Suggestions can be applied directly without needing amends or force-pushes.
+ Concerns can be addressed in individual commits during the review.
+- Title and description can be edited directly in GitLab, making it easier for reviewers or lead developers to adjust wording.
+
+#### Disadvantages:
+
+- Stacked MRs always cause conflicts (rebasing is required).
+- Individual commits of the MR are no longer visible in the `main` branch.
+ You need to navigate to the MR in GitLab to view them.
+
+#### Rules:
+
+- Squashing is the recommended default setting.
+- If a merge request has a messy commit history, it **must** be squashed.
+
+
+
+All dependent (stacked) MRs must then be rebased.
+
+
+
+- Even if the commit history is clean, squashing is still allowed.
+
+### Selecting Reviewers
+
+- All merge requests must go through peer review.
+- The project's lead developer should generally review every merge request in the project.
+- For infrastructure changes: always select someone from the **infra team**.
+- For styling changes: always select someone from the **styling focus group**.
+- A merge request can only be merged **after all reviewers have approved**.
+
+
+
+Always use **reviewers**, not approvers. The review system is better integrated into GitLab.
+
+
+
+### Conventions
+
+- Merge requests prefixed with `Draft:` should only be reviewed if a reviewer has been explicitly assigned.
+
+### Concerns
+
+- Concerns should always be resolved by the **reviewer** (exception: obvious things like typos).
+- A merge request may **only be merged once all concerns are resolved**.
+
+### Commits
+
+
+
+The following rules apply **if the merge request is _not_ squashed**
+
+Even if squashing is used, commit cleanliness is still important for easier reviews.
+
+
+
+- Commits should be **atomic** (i.e., the code should be in a runnable state).
+ Exception: if a CodeMod or CRUD generator is used, the generated changes should be in a **separate commit**, so they can be excluded from review.
+- Prefer multiple small commits (e.g., separate docs and feature work).
+- One commit per **logical change**.
+- Write **clear and descriptive commit messages**:
+ - Avoid vague messages like `fix`, `polish`, `wip`, or `another try`. These may be used temporarily, but must be cleaned up before merging.
+ - Start commit messages with a **capital letter**.
+- We recommend using **English** for all commit messages.
+
+#### Meaningful Commits for Suggestions
+
+When applying a suggestion, make sure to use a **meaningful commit message**.
+
+
+
+
+
+
+
+
+
+#### Tips for Writing Good Commit Messages
+
+Use the imperative
+
+
+
+Added margin to footer
+
+
+
+
+
+Add margin to footer
+
+
+
+Explain **what** and **why**, not **how**
+
+
+
+Add margin
+
+
+
+
+
+Add margin to nav items to prevent them from overlapping the logo
+
+
+
+
+
+
+
+Use `git commit --amend` to update existing commits (force push required).
+
+
+
+
+
+Multi-line commit messages automatically fill the **description field** in GitLab MRs. This is preferred over writing explanations in the MR description, because:
+
+- The information is stored directly in Git.
+- It is more visible and better integrated into IDEs (e.g., via GitLens or JetBrains tools).
+
+
+
+
+
+Results In:
+
+
+
+### Reviews
+
+Reviews are intended to ensure our quality standards are met. They should never be taken personally — see them as an opportunity for personal growth.
+
+#### Objectives
+
+- Keep the **bigger picture** in mind
+ - Is the chosen technique appropriate?
+ - Are the requirements fully covered?
+- Identify potential bugs
+- Check adherence to coding best practices
+- Question security and data privacy concerns
+
+#### Non-Objectives
+
+- Imposing your own personal style on the developer
+- Nitpicking
+- Verifying code correctness (This is usually not possible and is the clear responsibility of the developer)
+
+#### Conventions
+
+Optional suggestions can be marked with:
+
+- `OPT:`
+- `Note:`
+- `Nit:`
+
+These are not mandatory to fix but are intended to support communication and knowledge sharing.
+
+#### Tips for Reviewers
+
+- If possible (e.g., typos), use **[GitLab Suggestions](https://docs.gitlab.com/user/project/merge_requests/reviews/suggestions/)** to make it easy to fix or highlight what should change.
+- For naming concerns, provide a concrete improvement proposal.
+
+### Feature Branches
+
+#### Why?
+
+If a feature takes longer to develop or multiple developers are working on it simultaneously, a **feature branch** should be created first.
+These branches are **protected** — you **cannot push directly** to them. They serve only as a **target for multiple Merge Requests**. This prevents unfinished changes from being merged into the `master/main` branch too early.
+
+#### How to Create?
+
+Since you cannot push to them directly, you must create them via the GitLab UI:
+
+> Navigate to `Repository → Branches → New Branch`.
+
+
+
+Protection only works if the branch name **starts with `feature/`**.
+
+
+
+#### What to Do in Case of Conflicts?
+
+If the `master/main` branch has changed and causes conflicts in your feature branch:
+
+- You cannot fix it via `rebase` (due to branch protection).
+- Instead:
+ - Create a **new branch**.
+ - **Merge `master/main` into it**.
+ - Fix the conflicts.
+ - Create a new **Merge Request** for this branch.
+
+#### How to Merge?
+
+
+
+Never merge feature branches **with squashing**.
+
+
+
+### Cherry Picking
+
+In **production**, you may only cherry-pick commits that already exist in the `master/main` branch.
+
+### FAQs
+
+**Q:** Is it allowed to include a bugfix from an unrelated area in a PR that implements a specific feature (as a separate commit)?
+**A:** No.
+
+**Q:** Should changes to `api`, `admin`, and `site` be split into separate commits, if done in one PR?
+**A:** No.
diff --git a/spec/standards/coding-guidelines/index.md b/spec/standards/coding-guidelines/index.md
new file mode 100644
index 0000000000..e4db86038c
--- /dev/null
+++ b/spec/standards/coding-guidelines/index.md
@@ -0,0 +1,17 @@
+# Coding Guidelines
+
+## Scope
+
+These coding best practices were primarily developed for Comet projects. However, many of the principles are generally applicable.
+
+## Goals
+
+We aim to establish a common baseline that everyone can largely agree with. The coding best practices should be continuously improved with input from all team members. The following pages are intended to serve as a foundation for code reviews.
+
+## Non-Goals
+
+Strict 100% compliance at all times is not a goal. Exceptions are acceptable when they are well-justified. Full consensus on every point from everyone is also not required.
+
+## Principles
+
+We generally agree on certain principles and paradigms, such as [Clean Code](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882).
diff --git a/spec/standards/coding-guidelines/kubernetes.md b/spec/standards/coding-guidelines/kubernetes.md
new file mode 100644
index 0000000000..0f47fb3286
--- /dev/null
+++ b/spec/standards/coding-guidelines/kubernetes.md
@@ -0,0 +1,73 @@
+# Kubernetes
+
+## CronJobs
+
+Do not create cron jobs with intervals of less than 10 minutes. The resource savings do not apply here, and the overhead for cold starts is too high.
+
+**Alternative:** Deploy a continuous process with fewer resources.
+
+## Logging
+
+Be sparing with unnecessary logging, as it causes significant costs. Enable debug/info/trace logs via flag or environment variable.
+
+## Standard Environments
+
+- **dev:** Auto-deployment from main/master. Mainly serves as an integration test (Does deployment work? Do migrations work? Does the API start?). The pipeline
+ must ALWAYS be functional. If the pipeline is red, NOTHING may be merged that does not contribute to fixing the pipeline.
+ **Automatically deleted after 12 hours without deployment (data is retained).**
+
+- **test:** For internal tests, demos of unmerged or in-progress features allowed. Pushing without review permitted.
+ **Automatically deleted after 7 days without deployment (data is retained).**
+
+- **staging:** For customer acceptance. Serves as the base for future production deployments. Only `master/main` may be reset here (= only reviewed code).
+ **Permanently operational (= features can be tested here, demo content maintained, etc.).**
+
+- **prod:** Manual deployment from staging.
+
+## Replicas
+
+**TLDR:** Everything on non-prod runs with one replica; everything on prod runs with at least 2 replicas.
+
+Why? On non-prod, we focus on cost-efficiency, so minor interruptions are not a problem. On prod, everything must be highly available. Cluster auto-scaler events or node upgrades MUST NOT interrupt application availability. Consequence: Every microservice needs to be designed to handle multiple replicas (= stateless).
+
+## Resources
+
+### Request
+
+Amount of memory/CPU guaranteed for your container.
+
+### Limit
+
+Amount of memory/CPU your container cannot exceed.
+
+- Exceed CPU → Process throttled
+- Exceed RAM → Process killed, exit code 137 (OOM Killed)
+
+Containers are always scheduled based on the Request.
+
+### Which values for request/limit?
+
+- DO NOT over-commit memory (limit higher than request).
+- DO NOT limit CPU (we set 2 because we almost always use NodeJS, which is single-threaded).
+- CPU-Request: Used CPU at average load.
+- RAM-Request: Used RAM at average load + safety margin.
+
+### Example
+
+```yaml
+resources:
+ requests:
+ cpu: 50m
+ memory: 512Mi
+ limits:
+ cpu: 2
+ memory: 512Mi
+```
+
+### Why set the CPU Limit to 2 instead of 1?
+
+Previously, we set the cpu limit for our single threaded NodeJS applications to 1. But in kubernetes even single threaded applications
+can benefit from more than 1 cpu core. This way processes like garbage collections or kubernetes processes can be offloaded to an additional
+core, keeping the main core free for the NodeJS application.
+
+We did some tests and came to the conclusion that a cpu limit of 2 is the sweet spot.
diff --git a/spec/standards/coding-guidelines/libraries.md b/spec/standards/coding-guidelines/libraries.md
new file mode 100644
index 0000000000..521cd6589d
--- /dev/null
+++ b/spec/standards/coding-guidelines/libraries.md
@@ -0,0 +1,62 @@
+# Libraries and techniques
+
+## General
+
+We have many different projects, and usually several people work on one project. Therefore, it is important that we have a as uniform environment as possible where one can quickly find their way around.
+
+This also applies to the selection of libraries and technologies. There are several reasons for this:
+
+- For a specific feature, there should ideally be one go-to solution, not a separate solution in every project (e.g., 10 different date-picker libraries in 10 projects).
+- By using established go-to solutions, existing know-how can be reused.
+- Island solutions that no one can continue working on when the responsible person is unavailable (e.g., on vacation) should be avoided.
+
+We are still fundamentally open to new technologies and libraries. However, the decision whether to use a new technology or library should ideally be made generally, not within the project.
+
+This does not mean that no new npm packages may be used, but rather refers to "larger" things. Such far-reaching decisions should be well evaluated and coordinated with the architects.
+
+### Examples
+
+- A developer wants to use RxJS in a project because he knows it from his old company. RxJS is fundamentally different in programming paradigm from what we are used to.
+
+
+
+Here, coordination with the architects should take place.
+
+
+
+- A developer wants to use clsx in a project to build the className prop. Using this package is simple and does not have far-reaching effects.
+
+
+
+Coordination is not necessarily required here. However, it does not hurt either.
+
+
+
+## 3rd Party NPM Packages
+
+Using 3rd-party npm packages carries some risks:
+
+- Potential security vulnerabilities that attackers can exploit.
+- Incompatibilities that prevent or complicate updates (e.g., a library is not compatible with a newer React version).
+- Impact on bundle size (JS that must be downloaded by the browser, mainly in the frontend).
+
+The selection of a package should consider the following criteria:
+
+- Is the package long-lived?
+ - How long has the package existed?
+ - Are there multiple independent contributors?
+- Is the package actively maintained?
+ - Have there been new versions in recent months?
+ - Are there regular commits in the default branch?
+ - Are open issues answered/handled?
+- Is the package compatible with our stack?
+- Do we already have a go-to solution for the feature (e.g., [Swiper](https://swiperjs.com/) for image sliders)?
+- How does the package affect the bundle size?
+- Does the npm package have known vulnerabilities (CVEs)?
+- Does the npm package have an open source license?
+
+### Further Links
+
+- Guide for choosing an npm package: [How to Choose the Right NPM Package for Your Project](https://medium.com/better-programming/how-to-choose-the-right-npm-package-for-your-project-c3d1cc25285e)
+- Determine package size: [Bundlephobia | Size of npm dependencies](https://bundlephobia.com/)
+- Identify known vulnerabilities of a package: [Snyk Vulnerability Database | Snyk](https://security.snyk.io/)
diff --git a/spec/standards/coding-guidelines/naming-conventions.md b/spec/standards/coding-guidelines/naming-conventions.md
new file mode 100644
index 0000000000..a0eeacb346
--- /dev/null
+++ b/spec/standards/coding-guidelines/naming-conventions.md
@@ -0,0 +1,32 @@
+# Naming conventions
+
+## Azure Naming Conventions
+
+[Naming rules and restrictions for Azure resources - Azure Resource Manager](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-name-rules)
+
+## Kubernetes Naming Conventions
+
+myproject-prod
+myproject-test
+myproject-dev
+
+## Database Naming Conventions
+
+Database: `db_myproject_dev`
+User: `myproject_dev`
+Entities: Always singular starting with a capital letter (e.g., Product)
+
+## Git Naming Conventions
+
+**Standard branches:**
+
+- main
+- test (optional)
+- staging
+
+## File/Folder Naming Conventions
+
+| | API (TLDR: like Nest) | ADMIN (TLDR: like MUI/React) | SITE (TLDR: like Next) |
+| ------ | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Folder | kebab-case page-tree | camelCase pageTree | camelCase contentScope |
+| File | kebab-case with dot structure for components page-tree.service.ts / page-tree.module.ts | PascalCase for components; camelCase otherwise (z.B: hooks, functions) DashboardPage.tsx / useUser.ts | PascalCase for components; camelCase otherwise (e.g., hooks, functions), exception: Page in lowercasepage page.tsx / Layout.tsx / useUser.ts |
diff --git a/spec/standards/coding-guidelines/postgresql.md b/spec/standards/coding-guidelines/postgresql.md
new file mode 100644
index 0000000000..2ad7f7b4ab
--- /dev/null
+++ b/spec/standards/coding-guidelines/postgresql.md
@@ -0,0 +1,11 @@
+# PostgreSQL
+
+## Prefer UUIDs for IDs
+
+Prefer UUIDs for IDs instead of auto-incrementing integers.
+
+Reasons:
+
+- Sequential IDs can be guessed. For example, a URL https://example.com/users/1 implies that there may be a URL https://example.com/users/2 as well
+- UUIDs can be generated on the client before storing them in the database (this is done for page tree documents)
+- UUIDs are unique, which allows migrating data across different environments
diff --git a/spec/standards/coding-guidelines/react.md b/spec/standards/coding-guidelines/react.md
new file mode 100644
index 0000000000..2f83f3533b
--- /dev/null
+++ b/spec/standards/coding-guidelines/react.md
@@ -0,0 +1,488 @@
+# React
+
+## General
+
+- Prefer Function Components over Class Components.
+- Create one file per "logical component." Multiple Function Components per file are allowed for structuring, styling, etc.
+- Always use JSX (use React's `createElement` only for app initialization).
+- Use React's `PropsWithChildren` instead of defining children manually.
+- Inject dependencies to services/APIs via Context.
+- How to structure folders: "Move files around until it feels right."
+ Recommendation: separate by modules instead of by type ([File Structure – React](https://legacy.reactjs.org/docs/faq-structure.html#grouping-by-features-or-routes)).
+
+## Naming
+
+### Casing
+
+Use PascalCase for React components and camelCase for instances.
+
+
+
+```tsx
+import carCard from "./CarCard";
+const CarItem = ;
+```
+
+
+
+
+
+```tsx
+import CarCard from "./CarCard";
+const carItem = ;
+```
+
+
+
+### Naming components and their file
+
+A component and its file should have the same name.
+
+_The exception would be the rare case where a file exports multiple components._
+
+
+
+
+
+```tsx
+export const Footer = () => {
+ // ...
+};
+```
+
+
+
+
+
+
+
+```tsx
+export const Footer = () => {
+ // ...
+};
+```
+
+
+
+### File names
+
+Prefer meaningful file names over short, generic ones, even when the files are already in a descriptive folder.
+
+
+
+```
+clients/Table.tsx
+clients/Table.sc.ts
+clients/Table.gql.ts
+```
+
+
+
+
+
+```
+clients/ClientsTable.tsx
+clients/ClientsTable.sc.ts
+clients/ClientsTable.gql.ts
+```
+
+
+
+### Prop naming
+
+- Name props in camelCase.
+- Do not name props after DOM attributes.
+
+
+
+```ts
+type FooProps = {
+ phone_number: number;
+ UserName: string;
+};
+```
+
+```ts
+type BarProps = {
+ className?: "default" | "fancy";
+};
+```
+
+
+
+
+
+```ts
+type FooProps = {
+ phoneNumber: number;
+ userName: string;
+};
+```
+
+```ts
+type BarProps = {
+ variant?: "default" | "fancy";
+};
+```
+
+
+
+## Defining boolean props
+
+Boolean props should generally be optional and not have a default value, as they are falsy by default.
+
+
+
+```tsx
+type FooProps = {
+ hidden: boolean;
+};
+```
+
+```tsx
+const Bar = ({ hidden = false }: BarProps) => {
+ if (hidden) {
+ // ...
+ }
+ // ...
+};
+```
+
+
+
+
+
+```tsx
+type BazProps = {
+ hidden?: boolean;
+};
+
+const Baz = ({ hidden }: BazProps) => {
+ if (hidden) {
+ // ...
+ }
+ // ...
+};
+```
+
+
+
+## Using boolean props
+
+To set a prop to true, simply add the prop, without a value.
+
+
+
+```tsx
+
+```
+
+
+
+
+
+```tsx
+
+```
+
+
+
+## React states
+
+Name the state value in camelCase, and the setter function as the value name prefixed with "set", also in camelCase.
+
+
+
+```tsx
+const [UserName, setName] = useState();
+```
+
+
+
+
+
+```tsx
+const [userName, setUserName] = useState();
+```
+
+
+
+## Recommendations
+
+- If a component becomes too complex:
+ - Move GraphQL and styled components into separate files with `.gql.ts` and `.sc.ts` extensions.
+
+
+
+These files should be treated as **private** and must **not** be imported from other files.
+
+
+
+- Split the component into smaller sub-components.
+- Use `parameter?: type` instead of `parameter: type | undefined`, otherwise `parameter = undefined` must be explicitly set.
+
+## Working with SVGs
+
+If possible, use SVGs inline with ``.
+
+It is important that the SVG file contains an `id`, which is then referenced via the hash parameter in the path.
+
+**You can use it like this:**
+
+
+
+```tsx
+
+
+
+```
+
+
+
+**SVG File:**
+
+
+
+```tsx
+
+ icon
+
+
+```
+
+
+
+
+
+```tsx
+import Icon from "../assets/icon.svg"
+
+...
+
+
+```
+
+
+
+
+
+```tsx
+
+```
+
+
+
+**Background:** SVGs imported as modules end up in the JS bundle, which increases download and compile time. Additionally, when used as ` ` tags, they cannot be manipulated (e.g., changing path color).
+
+## Common Bugs
+
+
+
+These are common pitfalls, not strict rules that must always be followed.
+
+
+
+### Avoid array index as `key`
+
+Use a unique identifier as the key, such as the item's `id`.
+
+Explanation: [Index as a key is considered an anti-pattern](https://robinpokorny.medium.com/index-as-a-key-is-an-anti-pattern-e0349aece318)
+
+
+
+```tsx
+{
+ todos.map((todo, index) => );
+}
+```
+
+
+
+
+
+```tsx
+{
+ todos.map((todo) => );
+}
+```
+
+
+
+### Conditional rendering
+
+Don't use the `&&` syntax when rendering, depending on a number. The value `0` will be rendered by React.
+
+Instead, compare the value to 0 or use the ternary operator (`? :`).
+
+See React docs: [Conditional Rendering](https://react.dev/learn/conditional-rendering#logical-and-operator-)
+
+
+
+```tsx
+export const PostDetails = ({ post }) => (
+ <>
+
+ {post.comments.length && }
+ >
+);
+```
+
+
+
+
+
+```tsx
+export const PostDetails = ({ post }) => (
+ <>
+
+ {post.comments.length > 0 && }
+ >
+);
+```
+
+```tsx
+export const PostDetails = ({ post }) => (
+ <>
+
+ {post.comments.length ? : null}
+ >
+);
+```
+
+
+
+## Common Anti-Patterns
+
+Components or functions declared as constants inside a component are recreated on every render.
+
+
+
+```tsx
+const Foo = (jobs) => {
+ const sortJobs = (a: Job, b: Job) => {
+ return a.createdAt - b.createdAt;
+ };
+
+ const Wrapper = styled.div`...`;
+
+ return ... ;
+};
+```
+
+
+
+**Explanation:** They are recreated on every render and can lead to performance issues. (See also [Hooks API Reference – React](https://legacy.reactjs.org/docs/hooks-reference.html#usecallback))
+
+
+
+```tsx
+const sortJobs = (a: Job, b: Job) => {
+ return a.createdAt - b.createdAt;
+};
+
+const Wrapper = styled.div`...`;
+
+const Foo = (jobs) => {
+ return ... ;
+};
+```
+
+
+
+## GraphQL
+
+Use a fragment to define the required data of a component (see [Colocating Fragments](https://www.apollographql.com/docs/react/data/fragments#colocating-fragments))
+
+
+
+
+
+```tsx
+function DisplayName({
+ user: { firstName, lastName }: GQLUserDetailQuery,
+}) {
+ return <>{firstName} {lastName}>
+}
+```
+
+
+
+```tsx
+const userDetailQuery = gql`
+ query UserDetail($id: ID!) {
+ user(id: $id) {
+ firstName
+ lastName
+ }
+ }
+`;
+
+function UserDetail({ id }: { id: string }) {
+ const user = useQuery(userDetailQuery);
+ // ...
+ return (
+ <>
+
+ {/* ... */}
+ >
+ );
+}
+```
+
+
+
+
+
+
+
+```tsx
+export const displayNameFragment = gql`
+ fragment DisplayName on User {
+ firstName
+ lastName
+ }
+`;
+
+function DisplayName({
+ user: { firstName, lastName }: { user: GQLDisplayNameFragment },
+}): JSX.Element {
+ return <>{firstName} {lastName}>;
+}
+```
+
+
+
+```tsx
+const userDetailQuery = gql`
+ query UserDetail($id: ID!) {
+ user(id: $id) {
+ ...DisplayName
+ }
+ }
+ ${displayNameFragment}
+`;
+
+function UserDetail({ id }: { id: string }) {
+ const user = useQuery(userDetailQuery);
+ // ...
+ return (
+ <>
+
+ {/* ... */}
+ >
+ );
+}
+```
+
+
+
+**Explanation:** The child component should define for itself which fields of a GraphQL object it needs (and not rely on the parent component's query!). This way,
+the child component is not directly affected by changes in the parent query, for example if a field is no longer queried.
+
+## Further reading / sources:
+
+- [Hello World - React](https://legacy.reactjs.org/docs/hello-world.html)
+- [TypeScript and React](https://fettblog.eu/typescript-react/)
diff --git a/spec/standards/coding-guidelines/secure-development.md b/spec/standards/coding-guidelines/secure-development.md
new file mode 100644
index 0000000000..dae39581d1
--- /dev/null
+++ b/spec/standards/coding-guidelines/secure-development.md
@@ -0,0 +1,100 @@
+# Basic principles of secure software development
+
+
+
+Not all principles are always applicable. They should be regarded as fundamental guidelines and serve as a basis for reasoning when designing features.
+
+
+
+
+
+This document is not a complete documentation but highlights points relevant to our products and workflows. Detailed documentation on secure software development is provided as links at the end of this document.
+
+
+
+## Security by Design
+
+Security must be considered from the very beginning by all project participants. Features should be questioned with respect to security.
+
+**Technical measures (examples):**
+
+- Input validation: The more precise, the better, e.g. use `IsUrl` instead of just `IsString`. This also helps limit further attacks (e.g., in XSS, where a URL allows much less exploitation than free text).
+- Canonicalization:
+ - For email addresses (A@b.com vs. a@b.com) to prevent duplicate accounts and thereby prevent many other attacks (email spoofing or exploiting bugs where email addresses are compared canonically).
+ - For URLs (https://www.a.com vs. https://www.a.com/ vs. https://www.a.com:443/) e.g., to prevent bypassing Allow or Deny lists.
+- Generate random numbers only with cryptographically secure means (e.g., [Node.js v24.2.0 Crypto Documentation](https://nodejs.org/api/crypto.html)).
+
+## Privacy by Design
+
+Privacy must be considered from the very beginning by all project participants. Features should be questioned with respect to data privacy.
+
+**Example:** When developing a "Forgot Password" function, after entering the email address it shows: "If an account exists for this email address, a link with instructions to reset your password has been sent to your inbox." This does not reveal whether an account exists for the entered address.
+
+**Technical measures (examples):**
+
+- Store data only when necessary.
+- Privacy-friendly default settings.
+- Delete data after processing (e.g., delete contact requests after one year).
+
+## Least Privilege
+
+The software or user must not request or use more system permissions than absolutely necessary.
+
+**Technical measures (examples):**
+
+- User authorization always starts with no rights and only grants what is necessary — not the other way around.
+
+## Defense in Depth
+
+Many mechanisms — on many levels — provide good protection against threats.
+
+**Technical measures (examples):**
+
+- Combination of IP blocking + authentication.
+- Rate limiting.
+
+## Fail-Secure / Fail-Safe
+
+It should be defined how the software reacts in case of failure. Forced failure cases can pose security risks if, for example, stack traces become visible.
+
+**Technical measures (examples):**
+
+- Deny-Access-By-Default (if a request is not specifically allowed, it is denied; e.g., ACLs query the positive case and deny access by default).
+- Database transactions to avoid partial updates (A bank transfer is only successful if both account balances have been updated. If only one balance could be changed, it must be rolled back).
+
+## Keep it Simple
+
+The software design should be kept as simple as possible to facilitate understanding and testing. Understandability and testability are important foundations of software security. See also the [KISS principle](https://en.wikipedia.org/wiki/KISS_principle).
+
+## Complete Mediation
+
+Access control should be enforced on every access.
+
+## Least Common Mechanisms
+
+Administrative interfaces should be separated from non-administrative ones as much as possible.
+
+**Technical measures (examples):**
+
+- Access to the API from the site (without authentication) should only occur via BFF (Backend for Frontend).
+
+## Psychological Acceptability
+
+User acceptance should be considered in the development of security mechanisms.
+
+**Example:** If a user is asked too often to change their password, they might circumvent this by appending a running number to their password.
+
+## Weakest Link
+
+The security of software or a process is measured by its weakest link.
+
+## Open Design / Leveraging Existing Components
+
+[Security through obscurity](https://en.wikipedia.org/wiki/Security_through_obscurity) concepts are not allowed.
+
+Security components should ideally be developed only once, well tested, maintained, and reused. See also [Don't roll your own crypto.](https://www.oreilly.com/library/view/practical-security/9781680506679/f_0028.xhtml)
+
+**Technical measures (examples):**
+
+- Use libraries or proven technologies.
+- Comet offers all necessary tools for authentication / authorization.
diff --git a/spec/standards/coding-guidelines/styling-css.md b/spec/standards/coding-guidelines/styling-css.md
new file mode 100644
index 0000000000..03dfaef071
--- /dev/null
+++ b/spec/standards/coding-guidelines/styling-css.md
@@ -0,0 +1,309 @@
+# Styling / CSS
+
+## Theme
+
+- A theme should help developers style quickly and consistently. It should contain definitions/variables for: colors, buttons, forms, fonts, breakpoints, easings, typography.
+
+### Color Naming
+
+Besides basic color definitions (like primary, secondary, grey, etc.), there should be specific definitions with a context in mind (e.g. "colorUiLabel" with "colorUiLabelHover"). If there is no meaningful specific context for multiple uses, it is better to just use the basic colors.
+
+### Buttons
+
+Define buttons or form elements very specifically to reuse the theme structure in other applications.
+
+
+
+```ts
+buttons: {
+ primaryBg: "#ea5d1a",
+ primaryBgHover: "#f08d5e",
+ primaryBorder: "none",
+ primaryBorderHover: "none",
+ primaryBorderRadius: "4px",
+ primaryHeightMobile: "46px",
+ primaryFontSizeMobile: "16px",
+ primaryHeightTablet: "46px",
+ primaryFontSizeTablet: "16px",
+ primaryHeightDesktop: "46px",
+ primaryFontSizeDesktop: "16px",
+ ...
+}
+```
+
+
+
+### Typography
+
+For Typography you can take a step further and use css in theme:
+
+
+
+```ts
+typography: {
+ headline650: (disableMargin?: boolean) => css`
+ font-size: 30px;
+ line-height: 38px;
+ font-weight: 900;
+ margin-bottom: ${disableMargin ? 0 : "40px"};
+
+ ${({ theme }) => theme.breakpoints.m.mediaQuery} {
+ font-size: 68px;
+ line-height: 94px;
+ margin-bottom: ${disableMargin ? 0 : "56px"};
+ }
+ `,
+ headline600: (disableMargin?: boolean) => css`
+ font-size: 30px;
+ line-height: 38px;
+ font-weight: 900;
+ margin-bottom: ${disableMargin ? 0 : "32px"};
+
+ ${({ theme }) => theme.breakpoints.m.mediaQuery} {
+ font-size: 50px;
+ line-height: 58px;
+ margin-bottom: ${disableMargin ? 0 : "36px"};
+ }
+ `,
+ ...
+ paragraph250: (disableMargin?: boolean) => css`
+ font-size: 16px;
+ line-height: 30px;
+ margin-bottom: ${disableMargin ? 0 : "24px"};
+ font-weight: 400;
+
+ ${({ theme }) => theme.breakpoints.m.mediaQuery} {
+ font-size: 18px;
+ }
+ `,
+ paragraph200: (disableMargin?: boolean) => css`
+ font-size: 16px;
+ line-height: 30px;
+ font-weight: 400;
+ margin-bottom: ${disableMargin ? 0 : "18px"};
+ `,
+ ...
+```
+
+
+
+### Spacing
+
+One major part for consistent look and easy styling is defined spacing. Dynamic and Static are useful categories:
+
+
+
+```ts
+const spacingValues: SpacingValues = {
+ none: {
+ xs: 0,
+ s: 0,
+ m: 0,
+ l: 0,
+ xl: 0,
+ xxl: 0,
+ },
+ //dynamic
+ d150: {
+ xs: 4,
+ s: 4,
+ m: 4,
+ l: 8,
+ xl: 8,
+ xxl: 8,
+ },
+ ...
+ //static
+ s150: 4,
+ s200: 8,
+ s250: 12,
+ ...
+```
+
+
+
+## Modern CSS3 Stuff / Browser Support
+
+Check support with [CanIUse.com](https://caniuse.com).
+
+Relevant value: **"All Users/Europe"**
+
+
+
+### Frontend/Site
+
+Anything with a usage share of **>= 93%** can be used freely.
+
+Anything with a usage share of **>= 90%** can be used if the basic functionality is ensured. This means: The site must still work if this feature is not supported, but styling may
+slightly differ or behavior may not feel perfect. Depending on the feature or deviation in behavior, this threshold may be lower. The final decision lies with the responsible stylist.
+
+### Admin
+
+Everything supported by Chrome, Firefox, and Safari can be used.
+
+### Grid and Flex
+
+Use CSS Grid and Flexbox to align elements. But only use them when necessary — it's not required to set `display: flex` on every `div`.
+
+
+
+```ts
+export const Wrapper = styled.div`
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ ...
+```
+
+
+
+### List and ListItem Styling
+
+When styling a list to columns you should take the styling to the list and not to the item-block.
+
+
+
+```tsx
+// List.tsx
+
+ {blocks.map((block) => (
+
+ ))}
+
;
+
+export const List = styled.div`
+ display: flex;
+ flex-wrap: wrap;
+`;
+
+// Button.tsx
+export const ButtonBlock = styled.div`
+ width: 25%;
+`;
+```
+
+
+
+
+
+```tsx
+// List.tsx
+
+ {blocks.map((block) => (
+ -
+
+
+ ))}
+
;
+
+export const List = styled.div`
+ display: flex;
+ flex-wrap: wrap;
+`;
+
+export const Item = styled.div`
+ width: 25%;
+`;
+```
+
+
+
+### Recommendation: Empty Lines
+
+For better code readability, it is recommended to make a empty line between css and every form of selector:
+
+
+
+```tsx
+const ImageWrapper = styled.div`
+ display: inline-block;
+ max-height: 200px;
+ max-width: 200px;
+ cursor: pointer;
+ ${({ theme }) => theme.breakpoints.m.mediaQuery} {
+ max-width: 160px;
+ max-height: 160px;
+ }
+ ${({ theme }) => theme.breakpoints.l.mediaQuery} {
+ max-width: 200px;
+ max-height: 200px;
+ }
+ &:hover {
+ opacity: 0.5;
+ }
+`;
+```
+
+
+
+
+
+```tsx
+const ImageWrapper = styled.div`
+ display: inline-block;
+ max-height: 200px;
+ max-width: 200px;
+ cursor: pointer;
+
+ ${({ theme }) => theme.breakpoints.m.mediaQuery} {
+ max-width: 160px;
+ max-height: 160px;
+ }
+
+ ${({ theme }) => theme.breakpoints.l.mediaQuery} {
+ max-width: 200px;
+ max-height: 200px;
+ }
+
+ &:hover {
+ opacity: 0.5;
+ }
+`;
+```
+
+
+
+### Mobile First Approach
+
+When styling a site, block or component, always start with the mobile layout. [The Mobile First approach](https://css-tricks.com/how-to-develop-and-test-a-mobile-first-design-in-2021/) helps us to reach the majority of users and provides them with a good-looking page.
+
+### Inline Styles
+
+If possible, don't use inline styles, use Emotion or Styled Components instead.
+
+
+
+```tsx
+ handleDelete(key)} style={{ padding: "0 0 8px 8px" }}>
+```
+
+
+
+
+
+```tsx
+import { IconButton as MuiIconButton } from "@mui/material";
+
+const IconButton = styled(MuiIconButton)(() => ({
+ padding: "0 0 8px 8px",
+}));
+
+ handleDelete(key)} />;
+```
+
+
+
+or even better name the button after its function.
+
+
+
+```tsx
+import { IconButton } from "@mui/material";
+
+const DeleteButton = styled(IconButton)(() => ({
+ padding: "0 0 8px 8px",
+}));
+
+ handleDelete(key)} />;
+```
+
+
diff --git a/spec/standards/coding-guidelines/typescript.md b/spec/standards/coding-guidelines/typescript.md
new file mode 100644
index 0000000000..49a591a62b
--- /dev/null
+++ b/spec/standards/coding-guidelines/typescript.md
@@ -0,0 +1,97 @@
+# Typescript
+
+Everything from [Clean Code concepts adapted for TypeScript](https://github.com/labs42io/clean-code-typescript)
+
+## General
+
+Prefer using an options object instead of multiple parameters
+(Explanation: [Clean Code concepts adapted for TypeScript](https://github.com/labs42io/clean-code-typescript#function-arguments-2-or-fewer-ideally))
+
+
+
+```ts
+const getSortedJobs = (orderBy: string, includeSoftDeleted: boolean, limit: number): Job[] => {};
+
+getSortedJobs("createdAt", true, 20);
+```
+
+
+
+
+
+```ts
+const getSortedJobs = (options: { orderBy: string; includeSoftDeleted: boolean; limit: number }): Job[] => {};
+
+getSortedJobs({
+ orderBy: "createdAt",
+ includeSoftDeleted: true,
+ limit: 20,
+});
+```
+
+
+
+- Use named exports only (Exception: Default exports are allowed only if technically required)
+ **Reason:** They are harder to locate and refactor.
+
+- Use relative imports only for sibling or child files within a module (for anything else, use imports via @src)
+
+- Prefer async/await over callbacks
+
+- Prefer for...of loops
+ Supports all iterators, async/await, and control statements
+ (See: [Should one use for-of or forEach when iterating through an array?](https://stackoverflow.com/questions/50844095/should-one-use-for-of-or-foreach-when-iterating-through-an-array/50844413#50844413))
+
+- Use default arguments instead of short-circuiting or conditional logic
+
+
+
+```ts
+function createMicrobrewery(name) {
+ const breweryName = name || "Hipster Brew Co.";
+ // ...
+}
+```
+
+
+
+
+
+```ts
+function createMicrobrewery(name = "Hipster Brew Co.") {
+ // ...
+}
+```
+
+
+
+## 3rd Party NPM packages
+
+See [Libraries and Techniques](libraries.md)
+
+## Further Reading / Sources
+
+- [Google TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html)
+- [Clean Code concepts adapted for TypeScript – GitHub by labs42io](https://github.com/labs42io/clean-code-typescript#function-arguments-2-or-fewer-ideally)
+- [oida.dev | TypeScript, JavaScript, Rust](https://fettblog.eu/)
+
+## Naming Conventions
+
+### Enums
+
+Use `camelCase` for the **keys** and **values** of your enums.
+
+#### Example:
+
+```ts
+enum Direction {
+ north = "north",
+ northEast = "northEast",
+ east = "east",
+ southEast = "southEast",
+ south = "south",
+ southWest = "southWest",
+ west = "west",
+ northWest = "northWest",
+}
+```