---
title: "Website"
description: "Sidor och formulär. Varje app är en modul i en gemensam datamodell."
canonical: "https://obop.dev/sv/apps/website/"
lang: "sv"
---

# Website

## Vad den är till för

Hold the content of a public website: pages, menus, blog posts and the form submissions visitors send. This app stores and organises content; something else renders it. Publishing needs approval.

## Vad paketet gör och inte gör

Content for a public website: pages with a slug and a draft, published, archived flow, navigation menu items, blog posts with a byline and a publish date, translations of both, and the form submissions visitors send in. When the instance runs with the public site enabled it serves the published content to visitors as a server-rendered website with SEO and no login; only the fields marked public are ever visible to them. Publishing makes content public and needs a human approval, agents may only propose it. Senders are personal data and are never public.

## Modeller

### `website_page`

A page of the website

Läsgrupp: `website.user`. Skrivgrupp: `website.user`.

| Fält | Typ | Dataklass | Personuppgift | Grupp | Agenter ser | Beskrivning |
|---|---|---|---|---|---|---|
| `title` | text | `none` | nej | `website.user` | i klartext | Page title |
| `slug` | text | `none` | nej | `website.user` | i klartext | URL path of the page without slashes at the ends, lowercase with dashes, for example about-us. The page with slug home is the front page |
| `body` | longtext | `none` | nej | `website.user` | i klartext | Page content in Markdown (a safe subset: headings, lists, links, emphasis, code, quotes, tables) |
| `seo_title` | text | `none` | nej | `website.user` | i klartext | Title shown in search results; empty means the page title |
| `seo_description` | text | `none` | nej | `website.user` | i klartext | Description shown in search results |
| `published_on` | date | `none` | nej | `website.user` | i klartext | Day the page went public (YYYY-MM-DD) |
| `state` | select (draft, published, archived) | `none` | nej | `website.user` | i klartext | Page status: draft, published, archived |

### `website_menu_item`

An entry of the site navigation

Läsgrupp: `website.user`. Skrivgrupp: `website.manager`.

| Fält | Typ | Dataklass | Personuppgift | Grupp | Agenter ser | Beskrivning |
|---|---|---|---|---|---|---|
| `label` | text | `none` | nej | `website.user` | i klartext | Text shown in the menu |
| `url` | text | `none` | nej | `website.user` | i klartext | Where the entry leads: a page slug starting with a slash or a full address |
| `parent_id` | ref → website_menu_item | `none` | nej | `website.user` | i klartext | The entry this one is nested under; empty for a top-level entry |
| `sequence` | number | `none` | nej | `website.user` | i klartext | Order among its siblings, lowest first |
| `visible` | bool | `none` | nej | `website.user` | i klartext | Whether the entry is shown |
| `new_window` | bool | `none` | nej | `website.user` | i klartext | Whether the link opens in a new window |

### `website_blog_post`

A blog post

Läsgrupp: `website.user`. Skrivgrupp: `website.user`.

| Fält | Typ | Dataklass | Personuppgift | Grupp | Agenter ser | Beskrivning |
|---|---|---|---|---|---|---|
| `title` | text | `none` | nej | `website.user` | i klartext | Post title |
| `slug` | text | `none` | nej | `website.user` | i klartext | URL part of the post, lowercase with dashes |
| `author_name` | text | `public_directory` | ja | `website.user` | maskerad | Name of the author, for the team's own records |
| `byline` | text | `none` | nej | `website.user` | i klartext | Author line shown publicly, for example the team or brand name; use a name here only if the person agreed to it |
| `summary` | text | `none` | nej | `website.user` | i klartext | Teaser shown in listings |
| `body` | longtext | `none` | nej | `website.user` | i klartext | Post content in Markdown (a safe subset: headings, lists, links, emphasis, code, quotes, tables) |
| `tags` | text | `none` | nej | `website.user` | i klartext | Comma-separated tags, for example news,product |
| `published_on` | date | `none` | nej | `website.user` | i klartext | Day the post is dated (YYYY-MM-DD) |
| `state` | select (draft, published, archived) | `none` | nej | `website.user` | i klartext | Post status: draft, published, archived |

### `website_form_submission`

A message a visitor sent through a form on the site

Läsgrupp: `website.user`. Skrivgrupp: `website.user`.

| Fält | Typ | Dataklass | Personuppgift | Grupp | Agenter ser | Beskrivning |
|---|---|---|---|---|---|---|
| `form_name` | text | `none` | nej | `website.user` | i klartext | Which form it came from, for example contact |
| `sender_name` | text | `internal` | ja | `website.user` | maskerad | Name the visitor gave |
| `sender_email` | text | `internal` | ja | `website.user` | maskerad | Email address the visitor gave |
| `sender_phone` | text | `internal` | ja | `website.user` | maskerad | Phone number the visitor gave |
| `message` | longtext | `internal` | ja | `website.user` | maskerad | What the visitor wrote |
| `source_page` | text | `none` | nej | `website.user` | i klartext | Slug of the page the form was on |
| `submitted_on` | date | `none` | nej | `website.user` | i klartext | Day of the submission (YYYY-MM-DD) |
| `consent_given` | bool | `none` | nej | `website.user` | i klartext | Whether the visitor ticked the consent box for being contacted |
| `state` | select (new, handled, spam) | `none` | nej | `website.user` | i klartext | Handling status: new, handled, spam |

### `website_page_translation`

A page translated into another language; the public site shows it to visitors who read that language

Läsgrupp: `website.user`. Skrivgrupp: `website.user`.

| Fält | Typ | Dataklass | Personuppgift | Grupp | Agenter ser | Beskrivning |
|---|---|---|---|---|---|---|
| `page_id` | ref → website_page | `none` | nej | `website.user` | i klartext | The page this translates |
| `lang` | select (en, de, fr, pl, fi, sv, es) | `none` | nej | `website.user` | i klartext | Language of the translation: en, de, fr, pl, fi, sv or es |
| `title` | text | `none` | nej | `website.user` | i klartext | Translated page title |
| `body` | longtext | `none` | nej | `website.user` | i klartext | Translated page content in Markdown |
| `seo_title` | text | `none` | nej | `website.user` | i klartext | Translated title shown in search results |
| `seo_description` | text | `none` | nej | `website.user` | i klartext | Translated description shown in search results |
| `published` | bool | `none` | nej | `website.user` | i klartext | Whether the translation is shown; it is only reachable while its page is published |

### `website_blog_post_translation`

A blog post translated into another language

Läsgrupp: `website.user`. Skrivgrupp: `website.user`.

| Fält | Typ | Dataklass | Personuppgift | Grupp | Agenter ser | Beskrivning |
|---|---|---|---|---|---|---|
| `post_id` | ref → website_blog_post | `none` | nej | `website.user` | i klartext | The post this translates |
| `lang` | select (en, de, fr, pl, fi, sv, es) | `none` | nej | `website.user` | i klartext | Language of the translation: en, de, fr, pl, fi, sv or es |
| `title` | text | `none` | nej | `website.user` | i klartext | Translated post title |
| `summary` | text | `none` | nej | `website.user` | i klartext | Translated teaser |
| `body` | longtext | `none` | nej | `website.user` | i klartext | Translated post content in Markdown |
| `published` | bool | `none` | nej | `website.user` | i klartext | Whether the translation is shown; it is only reachable while its post is published |

## Arbetsflöden

### `website_page`

| Åtgärd | Flyttar | Vem får köra den | Godkännande |
|---|---|---|---|
| `website_page.publish` | state: draft → published | `website.manager` | ja |
| `website_page.unpublish` | state: published → draft | `website.manager` | nej |
| `website_page.archive` | state: published → archived | `website.manager` | nej |

### `website_blog_post`

| Åtgärd | Flyttar | Vem får köra den | Godkännande |
|---|---|---|---|
| `website_blog_post.publish` | state: draft → published | `website.manager` | ja |
| `website_blog_post.unpublish` | state: published → draft | `website.manager` | nej |
| `website_blog_post.archive` | state: published → archived | `website.manager` | nej |

### `website_form_submission`

| Åtgärd | Flyttar | Vem får köra den | Godkännande |
|---|---|---|---|
| `website_form_submission.handle` | state: new → handled | `website.user` | nej |
| `website_form_submission.mark_spam` | state: new → spam | `website.user` | nej |

## Behörighetsgrupper

Grupper som den här appen använder:

- `website.manager`
- `website.user`

## Steg som kräver godkännande

Steg som en agent bara kan föreslå:

- `website_page.publish`
- `website_blog_post.publish`

## Vad agenter kan och inte kan göra

En agent kan läsa, söka, skapa och uppdatera poster i den här appen, och köra de åtgärder som inte kräver godkännande, inom behörighetsgrupperna för sin token.

Den kan bara föreslå de här stegen, och en person måste godkänna dem: `website_page.publish`, `website_blog_post.publish`, `website_page.delete`, `website_menu_item.delete`, `website_blog_post.delete`, `website_form_submission.delete`, `website_page_translation.delete`, `website_blog_post_translation.delete`.

Personuppgifter maskeras som platshållare: `website_blog_post.author_name`, `website_form_submission.sender_name`, `website_form_submission.sender_email`, `website_form_submission.sender_phone`, `website_form_submission.message`.

## Beroenden

Inga.

## Installera

Installera den från appen Customize (Marknadsplats), eller från kommandoraden:

```bash
obop modules install-from website
```

Kräver en databas och administratörsbehörighet.

## Bygg din egen

[Modulguiden visar hur appar som den här skrivs](/sv/docs/reference/module-manifest/)
