diff --git a/alfa-client/.prettierignore b/alfa-client/.prettierignore
index ee7824bd9c6d18d685c77479a451c9554c111e9d..0eb1899d00dd4018fa9605a6b746a08a07174333 100644
--- a/alfa-client/.prettierignore
+++ b/alfa-client/.prettierignore
@@ -6,4 +6,5 @@ packages/workspace/src/generators/**/files/**/*.json
 /.nx/cache
 .angular
 
-/.nx/workspace-data
\ No newline at end of file
+/.nx/workspace-data
+*.md
\ No newline at end of file
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer-zu-oe-hinzufuegen.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer-zu-oe-hinzufuegen.cy.ts
index 3735e511e5eb33b45987bbf61fb4aa757d02025c..9095c63279a17ffe2cbada1f4de9f956593c0638 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer-zu-oe-hinzufuegen.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer-zu-oe-hinzufuegen.cy.ts
@@ -13,7 +13,7 @@ describe('Organisationseinheit zu Benutzer hinzufügen', () => {
   const zustaendigeStelleSearchComponent: ZustaendigeStelleDialogE2EComponent = new ZustaendigeStelleDialogE2EComponent();
   const organistationsEinheitOrdnungsamt: string = 'Ordnungsamt';
   const organisationsEinheitDenkmalpflege: string = 'Denkmalpflege';
-  const organisationsEinheitWentorf: string = 'grundschule wentorf';
+  const organisationsEinheitLiegenschaften: string = 'Liegenschaften';
   const organisationsEinheitNone: string = 'keine zuständige Stelle zugewiesen';
   const vorname: string = 'Theo';
   const nachname: string = 'Testuser';
@@ -91,7 +91,7 @@ describe('Organisationseinheit zu Benutzer hinzufügen', () => {
   it('should enable new Organisationseinheit for users after adding it', () => {
     mainPage.clickOrganisationsEinheitenNavigationItem();
     organisationsEinheitenComponent.clickHinzufuegen();
-    zustaendigeStelleSearchComponent.enterSearchTerm(organisationsEinheitWentorf);
+    zustaendigeStelleSearchComponent.enterSearchTerm(organisationsEinheitLiegenschaften);
     zustaendigeStelleSearchComponent.getZustaendigeStelleTitle(0).then((title: string) => {
       zustaendigeStelleSearchComponent.clickFoundItem(0);
     });
@@ -99,12 +99,12 @@ describe('Organisationseinheit zu Benutzer hinzufügen', () => {
     mainPage.clickBenutzerNavigationItem();
     benutzerPage.clickUserEntry(benutzername2);
 
-    exist(benutzerPage.getOrganisationsEinheitCheckbox(organisationsEinheitWentorf));
+    exist(benutzerPage.getOrganisationsEinheitCheckbox(organisationsEinheitLiegenschaften));
   });
 
   it('should add new Organisationseinheit to existing user', () => {
-    benutzerPage.clickOrganisationsEinheitCheckbox(organistationsEinheitOrdnungsamt);
+    benutzerPage.clickOrganisationsEinheitCheckbox(organisationsEinheitLiegenschaften);
     benutzerPage.saveUser();
-    benutzerPage.stringExistsInUserEntry(organisationsEinheitWentorf, benutzername2);
+    benutzerPage.stringExistsInUserEntry(organisationsEinheitLiegenschaften, benutzername2);
   });
 });
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/organisationseinheiten/organisationseinheiten-laden.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/organisationseinheiten/organisationseinheiten-laden.cy.ts
index ed230c60ca0575070181bc4c680f2876b231f808..91a1673e96e41b8dbdae4e4338e864a0527f816e 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/organisationseinheiten/organisationseinheiten-laden.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/organisationseinheiten/organisationseinheiten-laden.cy.ts
@@ -48,7 +48,7 @@ describe.skip('TODO: activate after fix for OZG-7391: show Organisationsheiten',
 
   it('should show table of Organisationseinheiten', () => {
     waitForSpinnerToDisappear();
-    mainPage.openOrganisationsEinheiten();
+    mainPage.clickOrganisationsEinheitenNavigationItem();
 
     exist(organisationsEinheitenTab.getOrganisationsEinheitList());
   });
diff --git a/alfa-client/apps/admin/src/app/app.component.ts b/alfa-client/apps/admin/src/app/app.component.ts
index fe6c276c6df933b4df3e29605271a7cf31380042..6de5c0ab4da5fed7ffc763b86cdb18e253c44528 100644
--- a/alfa-client/apps/admin/src/app/app.component.ts
+++ b/alfa-client/apps/admin/src/app/app.component.ts
@@ -27,13 +27,19 @@ import { ROUTES } from '@admin-client/shared';
 import { KeycloakTokenService } from '@admin/keycloak-shared';
 import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared';
 import { BuildInfoComponent } from '@alfa-client/common';
-import { isLoaded, isNotUndefined, mapToResource, StateResource, TechSharedModule } from '@alfa-client/tech-shared';
+import { HasLinkPipe, isLoaded, isNotUndefined, mapToResource, StateResource } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, inject, OnInit } from '@angular/core';
 import { Router, RouterLink, RouterOutlet } from '@angular/router';
 import { AuthenticationService } from '@authentication';
 import { hasLink } from '@ngxp/rest';
-import { AdminLogoIconComponent, NavbarComponent, NavItemComponent, OrgaUnitIconComponent, UsersIconComponent, } from '@ods/system';
+import {
+  AdminLogoIconComponent,
+  NavbarComponent,
+  NavItemComponent,
+  OrgaUnitIconComponent,
+  UsersIconComponent,
+} from '@ods/system';
 import { filter, Observable, Subscription } from 'rxjs';
 import { UserProfileButtonContainerComponent } from '../common/user-profile-button-container/user-profile.button-container.component';
 import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/unavailable-page.component';
@@ -54,9 +60,9 @@ import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/
     RouterOutlet,
     UnavailablePageComponent,
     BuildInfoComponent,
-    TechSharedModule,
     MenuContainerComponent,
     RouterLink,
+    HasLinkPipe,
   ],
 })
 export class AppComponent implements OnInit {
diff --git a/alfa-client/apps/admin/src/main.ts b/alfa-client/apps/admin/src/main.ts
index 517ab0538bea573be67b1b8184ec7bb50695c242..de7bed8ea66ac6e222311d9d8c185b4cad477b85 100644
--- a/alfa-client/apps/admin/src/main.ts
+++ b/alfa-client/apps/admin/src/main.ts
@@ -21,18 +21,23 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { EnvironmentModule, loadEnvironment } from '@alfa-client/environment-shared';
-import { enableProdMode, importProvidersFrom, Injectable } from '@angular/core';
-import { isNil } from 'lodash-es';
-
+import { AggregationMappingProvider } from '@admin-client/reporting-shared';
 import { ApiRootModule } from '@alfa-client/api-root-shared';
+import { EnvironmentModule, loadEnvironment } from '@alfa-client/environment-shared';
 import { NavigationSharedModule } from '@alfa-client/navigation-shared';
 import { registerLocaleData } from '@angular/common';
 import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
 import localeDe from '@angular/common/locales/de';
+import { enableProdMode, importProvidersFrom, Injectable } from '@angular/core';
 import { bootstrapApplication, BrowserModule } from '@angular/platform-browser';
 import { provideAnimations } from '@angular/platform-browser/animations';
-import { ActivatedRouteSnapshot, BaseRouteReuseStrategy, provideRouter, RouteReuseStrategy, withRouterConfig, } from '@angular/router';
+import {
+  ActivatedRouteSnapshot,
+  BaseRouteReuseStrategy,
+  provideRouter,
+  RouteReuseStrategy,
+  withRouterConfig,
+} from '@angular/router';
 import { HttpUnauthorizedInterceptor } from '@authentication';
 import { EffectsModule } from '@ngrx/effects';
 import { StoreRouterConnectingModule } from '@ngrx/router-store';
@@ -43,6 +48,10 @@ import { ConfigurationsProviders } from 'libs/admin/configuration-shared/src/lib
 import { PostfachProviders } from 'libs/admin/postfach-shared/src/lib/postfach.providers';
 import { SettingsProviders } from 'libs/admin/settings-shared/src/lib/settings.providers';
 import { UserProviders } from 'libs/admin/user/src/lib/user.providers';
+import { isNil } from 'lodash-es';
+import { HttpBinaryFileInterceptor } from '../../../libs/tech-shared/src/lib/interceptor/http-binary-file.interceptor';
+import { HttpXsrfInterceptor } from '../../../libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor';
+import { XhrInterceptor } from '../../../libs/tech-shared/src/lib/interceptor/xhr.interceptor';
 import { AppComponent } from './app/app.component';
 import { appRoutes } from './app/app.routes';
 import { environment } from './environments/environment';
@@ -69,10 +78,26 @@ loadEnvironment(environment.environmentUrl).then((env) => {
   bootstrapApplication(AppComponent, {
     providers: [
       { provide: RouteReuseStrategy, useClass: NoRouteReuseStrategy },
+      {
+        provide: HTTP_INTERCEPTORS,
+        useClass: XhrInterceptor,
+        multi: true,
+      },
+      {
+        provide: HTTP_INTERCEPTORS,
+        useClass: HttpXsrfInterceptor,
+        multi: true,
+      },
+      {
+        provide: HTTP_INTERCEPTORS,
+        useClass: HttpBinaryFileInterceptor,
+        multi: true,
+      },
       ConfigurationsProviders,
       PostfachProviders,
       SettingsProviders,
       UserProviders,
+      AggregationMappingProvider,
       importProvidersFrom(
         NavigationSharedModule,
         BrowserModule,
diff --git a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.ts b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.ts
index d2d9e1334032279c2fd0aa5b32ffc76a89944534..431f26bb8d2aa1913a5a8b67563aa75466d13ce3 100644
--- a/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component.ts
@@ -22,12 +22,13 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { OrganisationsEinheitContainerComponent } from '@admin-client/organisations-einheit';
+import { HasLinkPipe } from '@alfa-client/tech-shared';
 import { Component } from '@angular/core';
 
 @Component({
   selector: 'organisationseinheit-page',
   templateUrl: './organisationseinheit-page.component.html',
   standalone: true,
-  imports: [OrganisationsEinheitContainerComponent],
+  imports: [ OrganisationsEinheitContainerComponent, HasLinkPipe],
 })
 export class OrganisationsEinheitPageComponent {}
diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts
index a861afd0728827a45330d8d5d2d78f63e6dfc5d1..938cc1b0061d2194105629ca70c1e5f8619d881c 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.spec.ts
@@ -1,7 +1,7 @@
+import { AdminStatistikFieldsFormComponent } from '@admin-client/statistik';
 import { existsAsHtmlElement } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MockComponent } from 'ng-mocks';
-import { AdminStatistikFieldsFormComponent } from '../../../../../../libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component';
 import { getDataTestIdOf } from '../../../../../../libs/tech-shared/test/data-test';
 import { StatistikFieldsFormPageComponent } from './statistik-fields-form-page.component';
 
diff --git a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts
index e249c034417fc7133d8cc2c5db690ddcb94ea50f..c4122b72d148865b4219d5446a3c2060574b23e7 100644
--- a/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component.ts
@@ -1,6 +1,6 @@
+import { AdminStatistikFieldsFormComponent } from '@admin-client/statistik';
 import { CommonModule } from '@angular/common';
 import { Component } from '@angular/core';
-import { AdminStatistikFieldsFormComponent } from '../../../../../../libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component';
 
 @Component({
   selector: 'statistik-fields-form-page',
diff --git a/alfa-client/apps/alfa-e2e/docker-compose.yml b/alfa-client/apps/alfa-e2e/docker-compose.yml
index efbb27de9070db53e35dc0e0c7c3d41ed9015966..cb3cff0ebb701a6600ea2204ea18b3928a0ddbbd 100644
--- a/alfa-client/apps/alfa-e2e/docker-compose.yml
+++ b/alfa-client/apps/alfa-e2e/docker-compose.yml
@@ -154,7 +154,7 @@ services:
         soft: 65536
         hard: 65536
     healthcheck:
-      test: [ 'CMD-SHELL', "curl -s 'http://localhost:9200/_cat/health?h=status' | egrep -q '(green|yellow)'" ]
+      test: ['CMD-SHELL', "curl -s 'http://localhost:9200/_cat/health?h=status' | egrep -q '(green|yellow)'"]
       interval: 10s
       timeout: 10s
       retries: 5
@@ -195,7 +195,7 @@ services:
       - 7080:8080
       - 7081:8081
     healthcheck:
-      test: [ 'CMD-SHELL', 'wget --spider localhost:8081/version' ]
+      test: ['CMD-SHELL', 'wget --spider localhost:8081/version']
       interval: 5s
       timeout: 5s
       retries: 5
diff --git a/alfa-client/apps/alfa-e2e/src/components/ui/button-with-spinner.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/ui/button-with-spinner.e2e.component.ts
deleted file mode 100644
index 4ac9816e675cd64b552f97c41b05a685dd8307d1..0000000000000000000000000000000000000000
--- a/alfa-client/apps/alfa-e2e/src/components/ui/button-with-spinner.e2e.component.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-export class ButtonWithSpinnerE2EComponent {
-  private readonly locatorButton: string = 'icon-button';
-
-  public findButton(root) {
-    return root.findTestElementWithClass(this.locatorButton);
-  }
-
-  //TODO Methode aus der MeinPage verwenden
-  public waitToDisappear(root) {
-    root.should('not.have.descendants', '[data-test-class=spinner]');
-  }
-}
diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-bescheid-wizard.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-bescheid-wizard.e2e.component.ts
index f2ee0ef04a1a37219a85db48a5b894dd0229123b..057b39b29c7de8819c69e745af44cda24e300859 100644
--- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-bescheid-wizard.e2e.component.ts
+++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-bescheid-wizard.e2e.component.ts
@@ -24,6 +24,7 @@
 import { contains, enterWith } from '../../support/cypress.util';
 import { uploadFile } from '../../support/file-upload';
 import { getAdjustedDateGerman } from '../../support/tech.util';
+import Chainable = Cypress.Chainable;
 
 export class VorgangBescheidWizardE2EComponent {
   private readonly bewilligtButton: string = 'button-bewilligt';
@@ -43,10 +44,8 @@ export class VorgangBescheidWizardE2EComponent {
   private readonly closeButton: string = 'close-bescheid';
   private readonly closeDialog: string = 'bescheid-close-dialog';
   private readonly bescheidResultBox: string = 'bescheiden-result';
-  private readonly bescheidVerwerfenButton: string =
-    'bescheiderstellung-abbrechen-entwurf-verwerfen';
-  private readonly bescheidSpeichernButton: string =
-    'bescheiderstellung-abbrechen-entwurf-speichern';
+  private readonly bescheidVerwerfenButton: string = 'bescheiderstellung-abbrechen-entwurf-verwerfen';
+  private readonly bescheidSpeichernButton: string = 'bescheiderstellung-abbrechen-entwurf-speichern';
   private readonly uploadBescheidFileButton: string = '-single-file-upload-button';
   private readonly uploadAttachmentButton: string = 'Anhang_hochladen-file-upload-button';
   private readonly uploadAutomaticBescheid: string = 'create-bescheid-document-button';
@@ -60,18 +59,15 @@ export class VorgangBescheidWizardE2EComponent {
 
   private readonly fileBescheidValid: string = 'Bescheid_validpdf-file-item';
   private readonly fileAnhangValid: string = 'Anhang_validpdf-file-item';
-  private readonly fileAutomaticBescheid: string =
-    'KFAS_LIVE_KI_10_Haltverbot_befristetpdf-file-item';
+  private readonly fileAutomaticBescheid: string = 'KFAS_LIVE_KI_10_Haltverbot_befristetpdf-file-item';
 
   private readonly bescheidDocument: string = 'bescheid-document';
   private readonly attachmentDocument: string = 'bescheid-attachments';
-  private readonly bescheidUploadSpinner: string =
-    '[data-test-id="bescheid-document"] ods-spinner-icon';
-  private readonly attachmentUploadSpinner: string =
-    '[data-test-id="bescheid-attachments"] ods-spinner-icon';
-  private readonly bescheidSaveSpinner: string =
-    '[data-test-id="confirm-and-save-button"] ods-spinner-icon';
+  private readonly bescheidUploadSpinner: string = '[data-test-id="bescheid-document"] ods-spinner-icon';
+  private readonly attachmentUploadSpinner: string = '[data-test-id="bescheid-attachments"] ods-spinner-icon';
+  private readonly bescheidSaveSpinner: string = '[data-test-id="confirm-and-save-button"] ods-spinner-icon';
   private readonly sendenSpinner: string = '[data-test-id="send-button"] ods-spinner-icon';
+  private readonly missingBescheidDocumentMessage: string = 'missing-bescheid-document-error-message';
 
   private locatorRoot: string = 'bescheid-wizard';
 
@@ -93,6 +89,7 @@ export class VorgangBescheidWizardE2EComponent {
   public getUeberspringenButton(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.ueberspringenButton);
   }
+
   public getStatusText(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.statusText);
   }
@@ -112,6 +109,7 @@ export class VorgangBescheidWizardE2EComponent {
   public getDateInput(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.dateInput);
   }
+
   public getDateError(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.dateError);
   }
@@ -292,4 +290,8 @@ export class VorgangBescheidWizardE2EComponent {
   public closeDialogIsShown(): void {
     this.getCloseDialog().should('exist');
   }
+
+  public getMissingBescheidDocumentMessage(): Chainable<Element> {
+    return cy.getTestElement(this.missingBescheidDocumentMessage);
+  }
 }
diff --git a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-page.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-page.e2e.component.ts
index 4be7b6532108923566044183f5591b1a175ee2d8..e17043afdfaa7c7de564ec7b244ff85b1761985a 100644
--- a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-page.e2e.component.ts
+++ b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-page.e2e.component.ts
@@ -22,7 +22,6 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { AttachmentContainerE2EComponent } from '../attachment/attachment.e2e.component';
-import { ButtonWithSpinnerE2EComponent } from '../ui/button-with-spinner.e2e.component';
 
 export class WiedervorlageE2EComponent {
   private readonly locatorBetreffInput: string = 'Betreff-text-input';
@@ -33,10 +32,7 @@ export class WiedervorlageE2EComponent {
   private readonly locatorStatusDot: string = 'dot';
   private readonly locatorSpeichernButton: string = 'speichern-button';
 
-  private readonly buttonWithSpinnerComponent: ButtonWithSpinnerE2EComponent =
-    new ButtonWithSpinnerE2EComponent();
-  private readonly attachmentContainer: AttachmentContainerE2EComponent =
-    new AttachmentContainerE2EComponent();
+  private readonly attachmentContainer: AttachmentContainerE2EComponent = new AttachmentContainerE2EComponent();
 
   public getBetreff() {
     return cy.getTestElement(this.locatorBetreffInput);
@@ -63,9 +59,7 @@ export class WiedervorlageE2EComponent {
   }
 
   public getSpeichernButton() {
-    return this.buttonWithSpinnerComponent.findButton(
-      cy.getTestElement(this.locatorSpeichernButton),
-    );
+    return cy.getTestElement(this.locatorSpeichernButton);
   }
 
   public getAttachmentContainer(): AttachmentContainerE2EComponent {
diff --git a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component.ts
index 93801c671d44ca75f7473867689c7941d6efa611..91718623842de6e64bb8c0a863ba2146606d68c4 100644
--- a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component.ts
+++ b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component.ts
@@ -21,15 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ButtonWithSpinnerE2EComponent } from '../ui/button-with-spinner.e2e.component';
 import { WiedervorlageInVorgangE2EComponent } from './wiedervorlage-in-vorgang.e2e.component';
 
 export class WiedervorlagenInVorgangE2EComponent {
   private readonly locatorCreateWiedervorlageButton: string = 'create-wiedervorlage';
-
-  private readonly buttonWithSpinnerComponent: ButtonWithSpinnerE2EComponent =
-    new ButtonWithSpinnerE2EComponent();
-
   private readonly locatorRoot: string = 'wiedervorlagen-in-vorgang';
 
   public getRoot() {
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-abbrechen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-abbrechen.cy.ts
index 85aceeb252469b106e0ff87864712d178b2b5797..7292aa333e4233b18c846485f02d316a080b6dc4 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-abbrechen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-abbrechen.cy.ts
@@ -26,11 +26,7 @@ import localeDe from '@angular/common/locales/de';
 import localeDeExtra from '@angular/common/locales/extra/de';
 import { VorgangBescheidWizardE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-bescheid-wizard.e2e.component';
 import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components';
-import {
-  VorgangE2E,
-  VorgangStatusE2E,
-  vorgangStatusLabelE2E,
-} from 'apps/alfa-e2e/src/model/vorgang';
+import { VorgangE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from 'apps/alfa-e2e/src/model/vorgang';
 import { uploadFile } from 'apps/alfa-e2e/src/support/file-upload';
 import { getAdjustedDateGerman } from 'apps/alfa-e2e/src/support/tech.util';
 import 'cypress-real-events/support';
@@ -39,10 +35,7 @@ import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.
 import { VorgangPage } from '../../../page-objects/vorgang.po';
 import { dropCollections } from '../../../support/cypress-helper';
 import { contains, exist, haveText, notExist } from '../../../support/cypress.util';
-import {
-  TEST_FILE_BESCHEID_ANHANG_VALID,
-  TEST_FILE_BESCHEID_VALID,
-} from '../../../support/data.util';
+import { TEST_FILE_BESCHEID_ANHANG_VALID, TEST_FILE_BESCHEID_VALID } from '../../../support/data.util';
 import { initUsermanagerUsers, loginAsSabine } from '../../../support/user-util';
 import { buildVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util';
 
@@ -64,8 +57,7 @@ describe('Vorgang - Bescheid abbrechen', () => {
     status: VorgangStatusE2E.IN_BEARBEITUNG,
   };
 
-  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent =
-    vorgangPage.getFormularButtons();
+  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons();
 
   before(() => {
     initVorgaenge([bescheidVorgang]);
@@ -81,7 +73,7 @@ describe('Vorgang - Bescheid abbrechen', () => {
     dropCollections();
   });
 
-  describe.skip('Sollte gefixt sein nach OZG-6185 - Discard changes after click on Verwerfen', () => {
+  describe('Discard changes after click on Verwerfen', () => {
     it('should click abgelehnt, enter date, and continue to step 2', () => {
       vorgangList.getListItem(bescheidVorgang.name).getRoot().click();
       waitForSpinnerToDisappear();
@@ -118,14 +110,18 @@ describe('Vorgang - Bescheid abbrechen', () => {
     });
 
     it('should show status In Bearbeitung', () => {
-      haveText(
-        vorgangPage.getVorgangDetailHeader().getStatus(),
-        vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG],
-      );
+      haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]);
     });
   });
 
   describe('Keep changes after click on Entwurf speichern', () => {
+    it('should navigate to vorgang list page', () => {
+      vorgangPage.getSubnavigation().getBackButton().click();
+      waitForSpinnerToDisappear();
+
+      exist(vorgangList.getRoot());
+    });
+
     it('click Vorgang', () => {
       vorgangList.getListItem(bescheidVorgang.name).getRoot().click();
       waitForSpinnerToDisappear();
@@ -160,10 +156,7 @@ describe('Vorgang - Bescheid abbrechen', () => {
     });
 
     it('should show status In Bearbeitung', () => {
-      haveText(
-        vorgangPage.getVorgangDetailHeader().getStatus(),
-        vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG],
-      );
+      haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]);
     });
 
     it('should keep date and status from current Bescheid in progress', () => {
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-dokumente-hochladen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-dokumente-hochladen.cy.ts
index 5fa34c5a3e560c4f2a343c38e071550be99856a2..2f0235885f20f005854b6a72df819534cbd15c6c 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-dokumente-hochladen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-dokumente-hochladen.cy.ts
@@ -33,16 +33,8 @@ import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-lis
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
 import { VorgangPage } from '../../../page-objects/vorgang.po';
 import { dropCollections, getTestElement } from '../../../support/cypress-helper';
-import { contains, exist, haveValue, notContains, notExist } from '../../../support/cypress.util';
-import {
-  TEST_FILE_BESCHEID_ANHANG_BIG,
-  TEST_FILE_BESCHEID_ANHANG_VALID,
-  TEST_FILE_BESCHEID_VALID,
-  TEST_FILE_JPEG,
-  TEST_FILE_JPG,
-  TEST_FILE_PNG,
-  TEST_FILE_WITH_CONTENT,
-} from '../../../support/data.util';
+import { contains, exist, haveText, haveValue, notContains, notExist } from '../../../support/cypress.util';
+import { TEST_FILE_BESCHEID_ANHANG_BIG, TEST_FILE_BESCHEID_ANHANG_VALID, TEST_FILE_BESCHEID_VALID, TEST_FILE_JPEG, TEST_FILE_JPG, TEST_FILE_PNG, TEST_FILE_WITH_CONTENT, } from '../../../support/data.util';
 import { initUsermanagerUsers, loginAsSabine } from '../../../support/user-util';
 import { buildVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util';
 
@@ -60,12 +52,11 @@ describe('Bescheid Dokumente hochladen', () => {
     status: VorgangStatusE2E.IN_BEARBEITUNG,
   };
 
-  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent =
-    vorgangPage.getFormularButtons();
+  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons();
 
   const documentError: string = 'Erlaubte Dateiendungen';
   const sizeError: string = 'Anhänge größer';
-  const missingBescheidError: string = 'Bitte fügen Sie';
+  const missingBescheidError: string = 'Bitte fügen Sie ein Bescheiddokument hinzu.';
   const nachrichtHeader: string = 'Neue Nachricht';
   const antragstellerName: string = 'An: Max Testermann';
   const betreffText: string = 'Ihr Bescheid zum Antrag';
@@ -127,17 +118,11 @@ describe('Bescheid Dokumente hochladen', () => {
     });
 
     it('should delete files on clicking X button', () => {
-      bescheidWizard
-        .getDeleteButtonOfElement(
-          bescheidWizard.getElementFromFileName(TEST_FILE_BESCHEID_ANHANG_VALID),
-        )
-        .click();
+      bescheidWizard.getDeleteButtonOfElement(bescheidWizard.getElementFromFileName(TEST_FILE_BESCHEID_ANHANG_VALID)).click();
       notExist(bescheidWizard.getFileAnhangValidInWizard());
       exist(bescheidWizard.getFileBescheidValidInWizard());
 
-      bescheidWizard
-        .getDeleteButtonOfElement(bescheidWizard.getElementFromFileName(TEST_FILE_BESCHEID_VALID))
-        .click();
+      bescheidWizard.getDeleteButtonOfElement(bescheidWizard.getElementFromFileName(TEST_FILE_BESCHEID_VALID)).click();
       notExist(bescheidWizard.getFileBescheidValidInWizard());
     });
 
@@ -169,7 +154,8 @@ describe('Bescheid Dokumente hochladen', () => {
   describe('do not continue without attached Bescheid', () => {
     it('should show error if no Bescheid is attached and step 3 is clicked', () => {
       bescheidWizard.getWeiterButton().click();
-      contains(bescheidWizard.getBescheidDocument(), missingBescheidError);
+      exist(bescheidWizard.getMissingBescheidDocumentMessage());
+      haveText(bescheidWizard.getMissingBescheidDocumentMessage(), missingBescheidError);
     });
   });
 
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-historie.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-historie.cy.ts
index 30031db94e06f4edfbd0d265a38d3d04bdd78069..0507e30112e6638ca225665737c64002a6ec99f0 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-historie.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-historie.cy.ts
@@ -29,16 +29,10 @@ import { VorgangBescheideE2EComponent } from 'apps/alfa-e2e/src/components/vorga
 import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components';
 import { VorgangFormularDatenE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular.e2e.component';
 import { VorgangSubnavigationE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-subnavigation';
-import {
-  BescheidHistorieItemE2EComponent,
-  VorgangFormularDatenHistorieItemE2EComponent,
-} from 'apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component';
+import { BescheidHistorieItemE2EComponent, VorgangFormularDatenHistorieItemE2EComponent, } from 'apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component';
 import { HistorieHeadlineE2E } from 'apps/alfa-e2e/src/model/historie';
 import { VorgangE2E, VorgangStatusE2E } from 'apps/alfa-e2e/src/model/vorgang';
-import {
-  TEST_FILE_BESCHEID_ANHANG_VALID,
-  TEST_FILE_BESCHEID_VALID,
-} from 'apps/alfa-e2e/src/support/data.util';
+import { TEST_FILE_BESCHEID_ANHANG_VALID, TEST_FILE_BESCHEID_VALID } from 'apps/alfa-e2e/src/support/data.util';
 import { uploadFile } from 'apps/alfa-e2e/src/support/file-upload';
 import { getAdjustedDateGerman } from 'apps/alfa-e2e/src/support/tech.util';
 import 'cypress-real-events/support';
@@ -79,14 +73,11 @@ describe('Bescheid History', () => {
     status: VorgangStatusE2E.IN_BEARBEITUNG,
   };
 
-  const vorgangDatenFormular: VorgangFormularDatenE2EComponent =
-    vorgangPage.getFormularDatenContainer();
+  const vorgangDatenFormular: VorgangFormularDatenE2EComponent = vorgangPage.getFormularDatenContainer();
 
-  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent =
-    vorgangPage.getFormularButtons();
+  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons();
 
-  const vorgangSubnavigationButtons: VorgangSubnavigationE2EComponent =
-    vorgangPage.getSubnavigation();
+  const vorgangSubnavigationButtons: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation();
 
   const bescheide: VorgangBescheideE2EComponent = vorgangPage.getBescheide();
 
@@ -125,16 +116,14 @@ describe('Bescheid History', () => {
         waitForSpinnerToDisappear();
         vorgangDatenFormular.getHistorieTab().click();
 
-        const historieItem: VorgangFormularDatenHistorieItemE2EComponent =
-          vorgangDatenFormular.getHistorieItemByIndex(0);
+        const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieItemByIndex(0);
 
         contains(historieItem.getHeadline(), HistorieHeadlineE2E.BESCHEID_ERSTELLT);
         contains(historieItem.getUser(), userName);
       });
 
       it('should show detailed info after click on arrow', () => {
-        const historieItem: VorgangFormularDatenHistorieItemE2EComponent =
-          vorgangDatenFormular.getHistorieItemByIndex(0);
+        const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieItemByIndex(0);
         const bescheidItem: BescheidHistorieItemE2EComponent = historieItem.getBescheid();
         historieItem.getExpandButton().click();
 
@@ -160,8 +149,7 @@ describe('Bescheid History', () => {
         waitForSpinnerToDisappear();
         vorgangDatenFormular.getHistorieTab().click();
 
-        const historieItem: VorgangFormularDatenHistorieItemE2EComponent =
-          vorgangDatenFormular.getHistorieItemByIndex(0);
+        const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieItemByIndex(0);
         const bescheidItem: BescheidHistorieItemE2EComponent = historieItem.getBescheid();
         historieItem.getExpandButton().click();
 
@@ -172,7 +160,7 @@ describe('Bescheid History', () => {
       });
     });
 
-    describe.skip('Show history entry after sending Bescheid', () => {
+    describe('Show history entry after sending Bescheid', () => {
       it('should show Bescheid entry on history tab after sending message', () => {
         vorgangSubnavigationButtons.getBackButton().click();
         vorgangList.getListItem(bescheidSendenVorgang.name).getRoot().click();
@@ -194,8 +182,7 @@ describe('Bescheid History', () => {
         notExist(bescheidWizard.getSendenSpinner());
 
         vorgangDatenFormular.getHistorieTab().click();
-        const historieItemExpand: VorgangFormularDatenHistorieItemE2EComponent =
-          vorgangDatenFormular.getHistorieItemByIndex(0);
+        const historieItemExpand: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieItemByIndex(0);
         const bescheidItem: BescheidHistorieItemE2EComponent = historieItemExpand.getBescheid();
         historieItemExpand.getExpandButton().click();
 
@@ -206,13 +193,11 @@ describe('Bescheid History', () => {
       });
 
       it('should show history entries for sent Bescheid and message', () => {
-        const historieItemSent: VorgangFormularDatenHistorieItemE2EComponent =
-          vorgangDatenFormular.getHistorieItemByIndex(1);
+        const historieItemSent: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieItemByIndex(1);
         contains(historieItemSent.getHeadline(), HistorieHeadlineE2E.BESCHEID_VERSCHICKT);
         contains(historieItemSent.getUser(), userName);
 
-        const historieItemMessage: VorgangFormularDatenHistorieItemE2EComponent =
-          vorgangDatenFormular.getHistorieItemByIndex(3);
+        const historieItemMessage: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieItemByIndex(3);
         contains(historieItemMessage.getHeadline(), HistorieHeadlineE2E.SEND_POSTFACH_NACHRICHT);
         contains(historieItemMessage.getUser(), userName);
       });
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-nur-speichern.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-nur-speichern.cy.ts
index b75f8c43401365ded80a0f22ae2571b78f9dd6d5..d2e2df9695234a26ff907b7cdde54563df9ca977 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-nur-speichern.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-nur-speichern.cy.ts
@@ -26,11 +26,7 @@ import localeDe from '@angular/common/locales/de';
 import localeDeExtra from '@angular/common/locales/extra/de';
 import { VorgangBescheidWizardE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-bescheid-wizard.e2e.component';
 import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components';
-import {
-  VorgangE2E,
-  VorgangStatusE2E,
-  vorgangStatusLabelE2E,
-} from 'apps/alfa-e2e/src/model/vorgang';
+import { VorgangE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from 'apps/alfa-e2e/src/model/vorgang';
 import { uploadFile } from 'apps/alfa-e2e/src/support/file-upload';
 import { getAdjustedDateGerman } from 'apps/alfa-e2e/src/support/tech.util';
 import 'cypress-real-events/support';
@@ -39,10 +35,7 @@ import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.
 import { VorgangPage } from '../../../page-objects/vorgang.po';
 import { dropCollections } from '../../../support/cypress-helper';
 import { contains, enterWith, exist, haveText, notExist } from '../../../support/cypress.util';
-import {
-  TEST_FILE_BESCHEID_ANHANG_VALID,
-  TEST_FILE_BESCHEID_VALID,
-} from '../../../support/data.util';
+import { TEST_FILE_BESCHEID_ANHANG_VALID, TEST_FILE_BESCHEID_VALID } from '../../../support/data.util';
 import { initUsermanagerUsers, loginAsSabine } from '../../../support/user-util';
 import { buildVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util';
 
@@ -53,7 +46,7 @@ describe('Bescheid speichern', () => {
   const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
 
   const abgelehntText: string = 'Abgelehnt am';
-  const manuellText: string = 'Bescheid muss manuell';
+  const manuellText: string = 'Der Bescheid muss manuell versendet werden.';
 
   const vorgangPage: VorgangPage = new VorgangPage();
   const bescheidWizard: VorgangBescheidWizardE2EComponent = vorgangPage.getBescheidWizard();
@@ -63,8 +56,7 @@ describe('Bescheid speichern', () => {
     status: VorgangStatusE2E.IN_BEARBEITUNG,
   };
 
-  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent =
-    vorgangPage.getFormularButtons();
+  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons();
 
   before(() => {
     initVorgaenge([bescheidVorgang]);
@@ -108,10 +100,7 @@ describe('Bescheid speichern', () => {
       notExist(bescheidWizard.getRoot());
 
       waitForSpinnerToDisappear();
-      haveText(
-        vorgangPage.getVorgangDetailHeader().getStatus(),
-        vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN],
-      );
+      haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN]);
     });
   });
 });
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts
index 81bbd0cdfbe44f1480fcd852caa3f0ae3657e701..e7cbc9d44df2099c5443729d0bb2b1187dd4e5f9 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts
@@ -27,7 +27,7 @@ import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-lis
 import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang';
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
 import { VorgangPage } from '../../../page-objects/vorgang.po';
-import { dropCollections, wait } from '../../../support/cypress-helper';
+import { dropCollections } from '../../../support/cypress-helper';
 import { contains, exist, haveText, notExist } from '../../../support/cypress.util';
 import { loginAsSabine } from '../../../support/user-util';
 import { buildVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util';
@@ -132,15 +132,12 @@ describe('Vorgang abschliessen', () => {
 
       it('should close snackbar on revoke', () => {
         snackBar.getRevokeButton().click();
-        wait(500);
         waitForSpinnerToDisappear();
-
         notExist(snackBar.getMessage());
       });
 
-      it.skip('UNSTABLE: should show status Beschieden', () => {
+      it('should show status Beschieden', () => {
         notExist(vorgangPage.getProgressBar());
-
         haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN]);
       });
 
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-formdata.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-formdata.cy.ts
index 893f7d2d803a5ba3b368af963a296f6dc494620c..a7912650d925a0159a8ec3793d6cca2449715311 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-formdata.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-formdata.cy.ts
@@ -39,6 +39,7 @@ import {
   initVorgaenge,
   objectIds,
 } from '../../../support/vorgang-util';
+import { VorgangSubnavigationE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-subnavigation';
 
 registerLocaleData(localeDe, 'de', localeDeExtra);
 
@@ -51,6 +52,7 @@ describe('Vorgang Detailansicht with formData', () => {
     vorgangPage.getFormularDatenContainer();
 
   const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader();
+  const vorgangSubnavigation: VorgangSubnavigationE2EComponent = new VorgangSubnavigationE2EComponent();
 
   const ort: string = 'Ort';
   const sh_strasse: string = 'Strasse';
@@ -135,33 +137,12 @@ describe('Vorgang Detailansicht with formData', () => {
         contains(vorgangDatenFormular.getRoot(), 'sh_strasse');
       });
     });
-
-    // SKIP: Metadaten sind aktuell aus
-    describe('click on "Metadaten" tab', () => {
-      it.skip('should show on click on tab', () => {
-        vorgangDatenFormular.getMetadatenTab().click();
-
-        exist(vorgangDatenFormular.getMetadaten());
-      });
-
-      it.skip('should show "emailadresse"', () => {
-        contains(vorgangDatenFormular.getRoot(), 'emailadresse');
-      });
-
-      it.skip('should show "postleitzahl"', () => {
-        contains(vorgangDatenFormular.getRoot(), 'postleitzahl');
-      });
-
-      it('should navigate back to Vorgang List', () => {
-        vorgangPage.getSubnavigation().getBackButton().click();
-        waitForSpinnerToDisappear();
-      });
-    });
   });
 
   describe('navigate to vorgang detail (with labels)', () => {
     describe('click on vorgang in list', () => {
       it('should show header', () => {
+        vorgangSubnavigation.back();
         vorgangList.getListItem(vorgangWithLabels.name).getRoot().click();
         waitForSpinnerToDisappear();
 
@@ -193,20 +174,5 @@ describe('Vorgang Detailansicht with formData', () => {
       });
     });
 
-    describe.skip('click on "Metadaten" tab', () => {
-      it('should show on click on tab', () => {
-        vorgangDatenFormular.getMetadatenTab().click();
-
-        exist(vorgangDatenFormular.getMetadaten());
-      });
-
-      it('should show "E-Mail Adresse"', () => {
-        contains(vorgangDatenFormular.getRoot(), emailadresse);
-      });
-
-      it('should show "PLZ"', () => {
-        contains(vorgangDatenFormular.getRoot(), postleitzahl);
-      });
-    });
   });
 });
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.cy.ts
index 7fa1b271ad7f923a8757a96e1e73854837fe101c..435e7106eda6a88a896ac03e25fe1cc75f1132e7 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.cy.ts
@@ -107,19 +107,6 @@ describe('Vorgang Detailansicht', () => {
       });
     });
 
-    // SKIP: Metada sind aktuell disabled
-    describe.skip('metadaten in tab', () => {
-      it('should show on click on tab', () => {
-        vorgangDatenFormular.getMetadatenTab().click();
-
-        exist(vorgangDatenFormular.getMetadaten());
-      });
-
-      it('should show "empfangendestelle"', () => {
-        contains(vorgangDatenFormular.getRoot(), vorgang.eingangs[0].formData.empfangendestelle.emailadresse);
-      });
-    });
-
     describe('antragdaten in tab', () => {
       it('should show on click on tab', () => {
         vorgangDatenFormular.getAntragdatenTab().click();
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-vorpruefen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-vorpruefen.cy.ts
index 2b9956e17ae93200b66f44edd95bca083813ea1f..ca02f561b4be2aa40d3a8dc9c65feeff9dfe6269 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-vorpruefen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-vorpruefen.cy.ts
@@ -115,40 +115,23 @@ describe.skip('Vorgang vorprüfen', () => {
       });
 
       it('should open "more menu"', () => {
-        //nur testweise
-        //kommentarContainer.getHinzufuegenButton().click();
-        //kommentarContainer.getTextInput().clear().type(kommentarText);
-        //kommentarContainer.getFormularSpeichernButton().click();
         waitForSpinnerToDisappear();
-        //
-
         vorgangMoreMenu.getButton().click();
 
         exist(vorgangMoreMenu.getRoot());
       });
 
-      it('should show Prüfung item', () => {
-        //exist(menuItem.getRoot());?
-      });
-
       it('should show "Vorgang vorpüfen" button', () => {
         exist(menuItem.getButton());
       });
 
-      it('should have a positive comment after Prüfung', () => {
+      it.skip('AKTUELL FEHLER: should have a positive comment after Prüfung', () => {
         menuItem.getButton().click();
-        //waitForSpinnerToDisappear();
-
         exist(kommentarContainer.getKommentar(kommentarText).getRoot());
-        //check for positive comment
       });
 
       it('should close menu after Prüfung', () => {
-        //am Ende entfernen
         vorgangMoreMenu.getButton().click();
-
-        //notExist(menuItem.getRoot());
-
         vorgangPage.getSubnavigation().getBackButton().click();
       });
     });
@@ -165,22 +148,10 @@ describe.skip('Vorgang vorprüfen', () => {
         exist(vorgangPage.getVorgangDetailHeader().getRoot());
       });
 
-      it('should have a negative comment after Prüfung', () => {
+      it.skip('AKTUELL FEHLER: should have a negative comment after Prüfung', () => {
         vorgangMoreMenu.getButton().click();
-
         menuItem.getButton().click();
-
-        //nur testweise
-        //kommentarContainer.getHinzufuegenButton().click();
-        //kommentarContainer.getTextInput().clear().type(kommentarText);
-        //kommentarContainer.getFormularSpeichernButton().click();
-        waitForSpinnerToDisappear();
-        //
-
-        waitForSpinnerToDisappear();
-
         exist(kommentarContainer.getKommentar(kommentarText).getRoot());
-        //check for negative comment
       });
 
       it('should close menu after Prüfung', () => {
@@ -190,20 +161,12 @@ describe.skip('Vorgang vorprüfen', () => {
       });
     });
 
-    describe('button not available on other Vorgänge', () => {
-      const menuItem: VorgangMoreMenuVorpruefenItemE2EComponent =
-        vorgangMoreMenu.getVorpruefenItem();
-
-      it('should open Vorgang-Detail-Page', () => {
+    describe('menu not available on other Vorgänge', () => {
+      it('should not show more menu on other Vorgänge', () => {
         vorgangList.getListItem(vorgangOhnePruefung.name).getRoot().click();
         waitForSpinnerToDisappear();
 
-        exist(vorgangPage.getVorgangDetailHeader().getRoot());
-      });
-
-      it('more menu should not contain Vorprüfen button', () => {
-        vorgangMoreMenu.getButton().click();
-        notExist(menuItem.getRoot());
+        notExist(vorgangMoreMenu.getRoot());
       });
     });
   });
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts
index c86efc5d90992c7d5eb14b126554bc3b1872cac1..a589537f1b6c1ebc75b77173ca51aa829824bc8a 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts
@@ -27,7 +27,7 @@ import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-lis
 import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang';
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
 import { VorgangPage } from '../../../page-objects/vorgang.po';
-import { dropCollections, wait } from '../../../support/cypress-helper';
+import { dropCollections } from '../../../support/cypress-helper';
 import { contains, exist, haveText, notExist } from '../../../support/cypress.util';
 import { loginAsSabine } from '../../../support/user-util';
 import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util';
@@ -137,8 +137,6 @@ describe('Vorgang wiedereroeffnen', () => {
 
       describe('by icon-button', () => {
         it('should have status Beschieden', () => {
-          wait(500);
-
           haveText(
             vorgangPage.getVorgangDetailHeader().getStatus(),
             vorgangStatusLabelE2E[vorgangBeschiedenWiedereroeffnenRevoke.status],
@@ -153,7 +151,7 @@ describe('Vorgang wiedereroeffnen', () => {
           contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET);
         });
 
-        it('should close snackbar on revoke', () => {
+        it('should click on snackbar revoke', () => {
           snackbar.getRevokeButton().click();
           waitForSpinnerToDisappear();
 
@@ -258,9 +256,8 @@ describe('Vorgang wiedereroeffnen', () => {
           contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET);
         });
 
-        it('should close snackbar on revoke', () => {
+        it('should click snackbar revoke', () => {
           snackbar.getRevokeButton().click();
-          wait(500);
           waitForSpinnerToDisappear();
 
           notExist(snackbar.getMessage());
diff --git a/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts b/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts
index 69e7bccdfc44a17993598e6c49a8e81bd066db33..3dbd6155939b778a411f9b2fd18822286feaf958 100644
--- a/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts
+++ b/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts
@@ -46,10 +46,9 @@ export function notExist(element: any): void {
 }
 
 export function haveText(element: any, text: string): void {
-  element
-    .invoke('text')
-    .then((elementText) => elementText.trim())
-    .should('equal', text);
+  element.invoke('text').should(($text) => {
+    expect($text.trim()).to.equal(text);
+  });
 }
 
 export function haveTextWithoutChildren(element: any, text: string): void {
diff --git a/alfa-client/apps/alfa/src/app/app.component.ts b/alfa-client/apps/alfa/src/app/app.component.ts
index 559dcfd6e2a53319d2a3710cddbf06c168e8a112..6a4820c7036735d0a1fd127463805e28aacad058 100644
--- a/alfa-client/apps/alfa/src/app/app.component.ts
+++ b/alfa-client/apps/alfa/src/app/app.component.ts
@@ -24,7 +24,7 @@
 import { ApiRootFacade, ApiRootResource } from '@alfa-client/api-root-shared';
 import { ENVIRONMENT_CONFIG } from '@alfa-client/environment-shared';
 import { NavigationService } from '@alfa-client/navigation-shared';
-import { StateResource, isNotNull } from '@alfa-client/tech-shared';
+import { InjectorService, StateResource, isNotNull } from '@alfa-client/tech-shared';
 import { IconService } from '@alfa-client/ui';
 import { buildPathSegmentsFromLocalStorage } from '@alfa-client/vorgang-shared';
 import { Component, Inject, OnInit } from '@angular/core';
@@ -49,6 +49,7 @@ export class AppComponent implements OnInit {
     private iconService: IconService,
     private oAuthService: OAuthService,
     private navigationService: NavigationService,
+    private injectorService: InjectorService,
   ) {
     this.iconService.registerIcons();
   }
diff --git a/alfa-client/apps/alfa/src/app/app.module.ts b/alfa-client/apps/alfa/src/app/app.module.ts
index d8e90a9d20917ac50f4056a53fe9d18825cde65d..566ebc0b3fd03aa04506016be0d3c16aa1bf1fd9 100644
--- a/alfa-client/apps/alfa/src/app/app.module.ts
+++ b/alfa-client/apps/alfa/src/app/app.module.ts
@@ -29,11 +29,14 @@ import { HintSharedModule } from '@alfa-client/hint-shared';
 import { NavigationModule } from '@alfa-client/navigation';
 import { OzgCloudUrlSerializer } from '@alfa-client/navigation-shared';
 import { ResourceRedirectComponent } from '@alfa-client/resource-redirect';
-import { UiModule } from '@alfa-client/ui';
+import { SpinnerComponent } from '@alfa-client/ui';
 import { registerLocaleData } from '@angular/common';
-import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
+import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
 import localeDe from '@angular/common/locales/de';
 import { LOCALE_ID, NgModule } from '@angular/core';
+import { DateFnsAdapter } from '@angular/material-date-fns-adapter';
+import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
+import { MatIconModule } from '@angular/material/icon';
 import { BrowserModule } from '@angular/platform-browser';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 import { RouterModule, Routes, UrlSerializer } from '@angular/router';
@@ -42,11 +45,29 @@ import { StoreRouterConnectingModule } from '@ngrx/router-store';
 import { StoreModule } from '@ngrx/store';
 import { StoreDevtoolsModule } from '@ngrx/store-devtools';
 import { OAuthModule } from 'angular-oauth2-oidc';
+import { de } from 'date-fns/locale';
+import { HttpBinaryFileInterceptor } from '../../../../libs/tech-shared/src/lib/interceptor/http-binary-file.interceptor';
+import { HttpXsrfInterceptor } from '../../../../libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor';
+import { XhrInterceptor } from '../../../../libs/tech-shared/src/lib/interceptor/xhr.interceptor';
+import { HttpConnectionTimeoutInterceptor } from '../../../../libs/ui/src/lib/interceptor/http-connection-timeout.interceptor';
+import { HttpErrorInterceptor } from '../../../../libs/ui/src/lib/interceptor/http-error.interceptor';
 import { environment } from '../environments/environment';
 import { AppComponent } from './app.component';
 
 registerLocaleData(localeDe);
 
+export const CUSTOM_DATE_FORMATS = {
+  parse: {
+    dateInput: 'dd.MM.yyyy',
+  },
+  display: {
+    dateInput: 'dd.MM.yyyy',
+    monthYearLabel: 'MMM yyyy',
+    dateA11yLabel: 'dd.MM.yyyy',
+    monthYearA11yLabel: 'MM yyyy',
+  },
+};
+
 const routes: Routes = [
   {
     path: '',
@@ -61,13 +82,13 @@ const routes: Routes = [
 @NgModule({
   declarations: [AppComponent],
   imports: [
+    MatIconModule,
     BrowserModule,
     BrowserAnimationsModule,
     RouterModule.forRoot(routes, {
       initialNavigation: 'disabled',
       onSameUrlNavigation: 'reload',
     }),
-    UiModule,
     EnvironmentModule,
     OAuthModule.forRoot({
       resourceServer: {
@@ -94,10 +115,49 @@ const routes: Routes = [
     // Workaround: load any module depending on ApiRootActions.loadApiRootSuccess
     // TODO Check if a future NgRx version will solve Lazy Loading + Effects.forFeature()
     HintSharedModule,
+    SpinnerComponent,
   ],
   providers: [
     { provide: LOCALE_ID, useValue: 'de' },
     { provide: UrlSerializer, useClass: OzgCloudUrlSerializer },
+    {
+      provide: HTTP_INTERCEPTORS,
+      useClass: HttpErrorInterceptor,
+      multi: true,
+    },
+    {
+      provide: HTTP_INTERCEPTORS,
+      useClass: HttpConnectionTimeoutInterceptor,
+      multi: true,
+    },
+    {
+      provide: HTTP_INTERCEPTORS,
+      useClass: XhrInterceptor,
+      multi: true,
+    },
+    {
+      provide: HTTP_INTERCEPTORS,
+      useClass: HttpXsrfInterceptor,
+      multi: true,
+    },
+    {
+      provide: HTTP_INTERCEPTORS,
+      useClass: HttpBinaryFileInterceptor,
+      multi: true,
+    },
+    {
+      provide: MAT_DATE_LOCALE,
+      useValue: de,
+    },
+    {
+      provide: MAT_DATE_FORMATS,
+      useValue: CUSTOM_DATE_FORMATS,
+    },
+    {
+      provide: DateAdapter,
+      useClass: DateFnsAdapter,
+      deps: [MAT_DATE_LOCALE],
+    },
     provideHttpClient(withInterceptorsFromDi()),
   ],
   bootstrap: [AppComponent],
diff --git a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.spec.ts b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.spec.ts
index 1f417e5febf09fcf523cd7c2d01a273d65630e79..6fe7f6ec6a78e51ef53b8f5b3e8c5f4fc7d129b1 100644
--- a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.spec.ts
+++ b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.spec.ts
@@ -17,8 +17,8 @@ describe('MenuComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [MenuComponent],
-      declarations: [HasLinkPipe, MockComponent(NavItemComponent), MockComponent(MailboxIconComponent)],
+      imports: [MenuComponent, HasLinkPipe],
+      declarations: [MockComponent(NavItemComponent), MockComponent(MailboxIconComponent)],
     }).compileComponents();
 
     fixture = TestBed.createComponent(MenuComponent);
diff --git a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.ts b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.ts
index 19cc60bab45d9e098ace89450e3c7efa50e96c30..0c9cddefff0b13b58d8dd915f44352b78bd60f2b 100644
--- a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.ts
+++ b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.ts
@@ -1,5 +1,5 @@
 import { ConfigurationLinkRel, ConfigurationResource } from '@admin-client/configuration-shared';
-import { StateResource, TechSharedModule } from '@alfa-client/tech-shared';
+import { HasLinkPipe, StateResource } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { MailboxIconComponent, NavItemComponent, StatisticIconComponent } from '@ods/system';
@@ -7,7 +7,7 @@ import { MailboxIconComponent, NavItemComponent, StatisticIconComponent } from '
 @Component({
   selector: 'admin-menu',
   standalone: true,
-  imports: [CommonModule, NavItemComponent, MailboxIconComponent, TechSharedModule, StatisticIconComponent],
+  imports: [CommonModule, NavItemComponent, MailboxIconComponent, StatisticIconComponent, HasLinkPipe],
   templateUrl: './menu.component.html',
 })
 export class MenuComponent {
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts
index 043e5c2e056bb11eb29983c5eef09ce0fa17a74e..43bc3d38565e870585b2ba846b8c2d681d977014 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts
@@ -39,6 +39,7 @@ describe('AdminOrganisationsEinheitRepository', () => {
         (group: GroupRepresentation): AdminOrganisationsEinheit => ({
           name: group.name,
           id: group.id,
+          attributes: group.attributes,
         }),
       );
 
@@ -63,6 +64,7 @@ describe('AdminOrganisationsEinheitRepository', () => {
     const organisationsEinheit: AdminOrganisationsEinheit = {
       name: groupRep.name,
       id: groupRep.id,
+      attributes: groupRep.attributes,
     };
 
     beforeEach(() => {
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts
index 5dc1b0ee3bf1ea39b1668edf2fa7379a6836f81f..c2d454434e07562492f0c929bc710d7793a70403 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts
@@ -40,6 +40,7 @@ export class AdminOrganisationsEinheitRepository {
     return {
       id: group.id,
       name: group.name,
+      attributes: group.attributes,
     };
   }
 }
diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.model.ts b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.model.ts
index 8a4b105a948caf4f288a8639468d888d2fb3c255..3a93c42e6b0042f02dd9f509969444431ce6c374 100644
--- a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.model.ts
+++ b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.model.ts
@@ -24,4 +24,5 @@
 export interface AdminOrganisationsEinheit {
   id?: string;
   name: string;
+  attributes: { [key: string]: string[] };
 }
diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/test/organisations-einheit.ts b/alfa-client/libs/admin/organisations-einheit-shared/src/test/organisations-einheit.ts
index 6bb1baad301e83997665d96347628cf092f1d5ea..aac833df1f46a18a007d4c780e5673dbe5a7ec19 100644
--- a/alfa-client/libs/admin/organisations-einheit-shared/src/test/organisations-einheit.ts
+++ b/alfa-client/libs/admin/organisations-einheit-shared/src/test/organisations-einheit.ts
@@ -29,6 +29,9 @@ export function createAdminOrganisationsEinheit(): AdminOrganisationsEinheit {
   return {
     id: faker.string.uuid(),
     name: faker.lorem.word(),
+    attributes: {
+      organisationseinheitId: [faker.string.uuid()],
+    },
   };
 }
 
diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts
index 5fd68cc789206b701f2adad2c2d0f5280917b55d..2f207e5573f8398234d5d01e201430a4c4e34303 100644
--- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts
+++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts
@@ -25,7 +25,7 @@ import { OrganisationsEinheitContainerComponent } from '@admin-client/organisati
 import { AdminOrganisationsEinheit, AdminOrganisationsEinheitService } from '@admin-client/organisations-einheit-shared';
 import { createStateResource, StateResource, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared';
 import { existsAsHtmlElement, getMockComponent, Mock, mock } from '@alfa-client/test-utils';
-import { OzgcloudDialogService, UiModule } from '@alfa-client/ui';
+import { OzgcloudDialogService } from '@alfa-client/ui';
 import { OrganisationsEinheitResource } from '@alfa-client/zustaendige-stelle-shared';
 import { CommonModule } from '@angular/common';
 import { ViewContainerRef } from '@angular/core';
@@ -66,7 +66,7 @@ describe('OrganisationsEinheitContainerComponent', () => {
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       declarations: [ToEmbeddedResourcesPipe],
-      imports: [CommonModule, UiModule, OrganisationsEinheitContainerComponent, MockComponent(OrganisationsEinheitListComponent)],
+      imports: [CommonModule, OrganisationsEinheitContainerComponent, MockComponent(OrganisationsEinheitListComponent)],
       providers: [
         { provide: AdminOrganisationsEinheitService, useValue: organisationsEinheitService },
         { provide: OzgcloudDialogService, useValue: dialogService },
@@ -85,7 +85,16 @@ describe('OrganisationsEinheitContainerComponent', () => {
 
   describe('component', () => {
     describe('ngOnInit', () => {
-      it('should call organisationsEinheitService getAll', (done) => {
+      it('should call organisationsEinheitService getList', (done) => {
+        component.ngOnInit();
+
+        component.organisationsEinheitenStateResource$.subscribe(() => {
+          expect(organisationsEinheitService.getAll).toHaveBeenCalled();
+          done();
+        });
+      });
+
+      it('should set organisationsEinheitListStateResource$', (done) => {
         component.ngOnInit();
 
         component.organisationsEinheitenStateResource$.subscribe(() => {
@@ -143,7 +152,10 @@ describe('OrganisationsEinheitContainerComponent', () => {
       it('should call organisationsEinheitService create', () => {
         component.handleDialogResponse(organisationsEinheitResource);
 
-        expect(organisationsEinheitService.create).toHaveBeenCalledWith({ name: organisationsEinheitResource.name });
+        expect(organisationsEinheitService.create).toHaveBeenCalledWith({
+          name: organisationsEinheitResource.name,
+          attributes: { organisationseinheitId: [organisationsEinheitResource.organisationEinheitId] },
+        });
       });
 
       it('should set createOrganisationsEinheitProgress$', () => {
diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.ts
index a1b124b07e83e6496d5409cef4cdd271e826b842..31e3a25fa7f482c8b85cf9de2a97e8623596d555 100644
--- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.ts
+++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.ts
@@ -7,9 +7,8 @@ import {
   ResourceSearchService,
   SearchResourceServiceConfig,
   StateResource,
-  TechSharedModule,
 } from '@alfa-client/tech-shared';
-import { OzgcloudDialogService, UiModule } from '@alfa-client/ui';
+import { OzgcloudDialogService, SpinnerComponent } from '@alfa-client/ui';
 import { ZustaendigeStelleModule } from '@alfa-client/zustaendige-stelle';
 import {
   OrganisationsEinheitListResource,
@@ -31,12 +30,11 @@ import { OrganisationsEinheitListComponent } from './organisations-einheit-list/
   standalone: true,
   imports: [
     CommonModule,
-    UiModule,
     ZustaendigeStelleModule,
     ZustaendigeStelleSharedModule,
     OrganisationsEinheitListComponent,
-    TechSharedModule,
     ButtonComponent,
+    SpinnerComponent,
   ],
   providers: [
     {
@@ -82,6 +80,9 @@ export class OrganisationsEinheitContainerComponent implements OnInit, OnDestroy
   mapToAdminOrganisationsEinheit(organisationsEinheitResource: OrganisationsEinheitResource): AdminOrganisationsEinheit {
     return {
       name: organisationsEinheitResource.name,
+      attributes: {
+        organisationseinheitId: [organisationsEinheitResource.organisationEinheitId],
+      },
     };
   }
 }
diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts
index 6fd9e1d7f938b76081a00e071efe41067de9273b..dd2fba6125d358ef26de554cdf79d2afdc40cf9b 100644
--- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts
+++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts
@@ -22,14 +22,14 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { AdminOrganisationsEinheit } from '@admin-client/organisations-einheit-shared';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { existsAsHtmlElement, getElementFromFixture, mock } from '@alfa-client/test-utils';
 import { CommonModule } from '@angular/common';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MatTooltipModule } from '@angular/material/tooltip';
 import { ActivatedRoute } from '@angular/router';
 import { ExclamationIconComponent, ListComponent, ListItemComponent } from '@ods/system';
 import { getConvertedDataTestIdOf, getDataTestIdOf } from 'libs/tech-shared/test/data-test';
-import { MockComponent, MockModule } from 'ng-mocks';
+import { MockComponent } from 'ng-mocks';
 import { createAdminOrganisationsEinheit } from '../../../../../organisations-einheit-shared/src/test/organisations-einheit';
 import { OrganisationsEinheitListComponent } from './organisations-einheit-list.component';
 
@@ -48,13 +48,12 @@ describe('OrganisationsEinheitListComponent', () => {
           useValue: mock(ActivatedRoute),
         },
       ],
-      imports: [
-        CommonModule,
+      imports: [CommonModule, ConvertForDataTestPipe],
+      declarations: [
         OrganisationsEinheitListComponent,
         MockComponent(ListComponent),
         MockComponent(ListItemComponent),
         MockComponent(ExclamationIconComponent),
-        MockModule(MatTooltipModule),
       ],
     }).compileComponents();
 
diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts
index 349085056be2fdeda545dda9849cac09822254c0..7efc0bbbe6727d1d558c63bad8ffe6a2d08b9d35 100644
--- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts
+++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts
@@ -22,7 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { AdminOrganisationsEinheit } from '@admin-client/organisations-einheit-shared';
-import { TechSharedModule } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe, ToResourceUriPipe } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { ExclamationIconComponent, ListComponent, ListItemComponent, TooltipDirective } from '@ods/system';
@@ -31,7 +31,15 @@ import { ExclamationIconComponent, ListComponent, ListItemComponent, TooltipDire
   selector: 'admin-organisations-einheit-list',
   templateUrl: './organisations-einheit-list.component.html',
   standalone: true,
-  imports: [CommonModule, ListComponent, ListItemComponent, ExclamationIconComponent, TooltipDirective, TechSharedModule],
+  imports: [
+    CommonModule,
+    ListComponent,
+    ListItemComponent,
+    ExclamationIconComponent,
+    TooltipDirective,
+    ToResourceUriPipe,
+    ConvertForDataTestPipe,
+  ],
 })
 export class OrganisationsEinheitListComponent {
   @Input() public organisationsEinheitList: AdminOrganisationsEinheit[] = [];
diff --git a/alfa-client/libs/admin/postfach-shared/project.json b/alfa-client/libs/admin/postfach-shared/project.json
index 6489dc23d02f10a0660d03ccd39ccebae8dadc5d..e02554623fc02a4f2929efea43c8669d24ecdf3a 100644
--- a/alfa-client/libs/admin/postfach-shared/project.json
+++ b/alfa-client/libs/admin/postfach-shared/project.json
@@ -10,7 +10,7 @@
       "executor": "@nx/jest:jest",
       "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
       "options": {
-        "tsConfig": "libs/admin//postfach-shared/tsconfig.spec.json",
+        "tsConfig": "libs/admin/postfach-shared/tsconfig.spec.json",
         "jestConfig": "libs/admin/postfach-shared/jest.config.ts"
       }
     },
diff --git a/alfa-client/libs/admin/postfach-shared/src/lib/postfach-resource.service.ts b/alfa-client/libs/admin/postfach-shared/src/lib/postfach-resource.service.ts
index 48043163dea114eba85fa881d9047ec90f8ef24a..a617ed3abf3f31d102889877f0d10a8117bb23b2 100644
--- a/alfa-client/libs/admin/postfach-shared/src/lib/postfach-resource.service.ts
+++ b/alfa-client/libs/admin/postfach-shared/src/lib/postfach-resource.service.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { SettingsService } from '@admin-client/settings-shared';
+import { SettingName, SettingsService } from '@admin-client/settings-shared';
 import { ApiResourceService, ResourceRepository, ResourceServiceConfig } from '@alfa-client/tech-shared';
 import { PostfachLinkRel } from './postfach.linkrel';
 import { PostfachResource } from './postfach.model';
@@ -34,7 +34,7 @@ export function createPostfachResourceService(repository: ResourceRepository, se
 
 function buildConfig(settingService: SettingsService): ResourceServiceConfig<PostfachResource> {
   return {
-    resource: settingService.getPostfach(),
+    resource: settingService.get(SettingName.POSTFACH),
     getLinkRel: PostfachLinkRel.SELF,
     edit: { linkRel: PostfachLinkRel.SELF },
   };
diff --git a/alfa-client/libs/admin/postfach-shared/src/lib/postfach.model.ts b/alfa-client/libs/admin/postfach-shared/src/lib/postfach.model.ts
index c592dec3e6621543ca69e9ee23abdeea1ec6f4ec..e3ce2fb8bd6153796bea9bf82422718d2324721e 100644
--- a/alfa-client/libs/admin/postfach-shared/src/lib/postfach.model.ts
+++ b/alfa-client/libs/admin/postfach-shared/src/lib/postfach.model.ts
@@ -21,8 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Resource } from '@ngxp/rest';
-import { SettingName } from 'libs/admin/settings-shared/src/lib/settings.model';
+import { SettingItemResource } from 'libs/admin/settings-shared/src/lib/settings.model';
 
 export interface Absender {
   name: string;
@@ -37,9 +36,4 @@ export interface Postfach {
   signatur: string;
 }
 
-export declare type PostfachSettingsItem = {
-  name: SettingName.POSTFACH;
-  settingBody: Postfach;
-};
-
-export declare type PostfachResource = Resource & PostfachSettingsItem;
+export declare type PostfachResource = SettingItemResource<Postfach>;
diff --git a/alfa-client/libs/admin/postfach-shared/src/lib/postfach.service.spec.ts b/alfa-client/libs/admin/postfach-shared/src/lib/postfach.service.spec.ts
index d779cb50dc2173e7dee4dc929a7e11f5d259724d..2441dc06db2b787fe3f33389d1fb2daae412e3bf 100644
--- a/alfa-client/libs/admin/postfach-shared/src/lib/postfach.service.spec.ts
+++ b/alfa-client/libs/admin/postfach-shared/src/lib/postfach.service.spec.ts
@@ -21,6 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { SettingItem } from '@admin-client/settings-shared';
 import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared';
 import { Mock, mock } from '@alfa-client/test-utils';
 import { SnackBarService } from '@alfa-client/ui';
@@ -31,7 +32,7 @@ import { singleCold, singleHot } from 'libs/tech-shared/test/marbles';
 import { Observable, of } from 'rxjs';
 import { createPostfachResource, createPostfachSettingItem } from '../test/postfach';
 import { PostfachResourceService } from './postfach-resource.service';
-import { PostfachResource, PostfachSettingsItem } from './postfach.model';
+import { Postfach, PostfachResource } from './postfach.model';
 import { PostfachService } from './postfach.service';
 
 describe('PostfachService', () => {
@@ -78,7 +79,7 @@ describe('PostfachService', () => {
   });
 
   describe('save', () => {
-    const postfachSettingsItem: PostfachSettingsItem = createPostfachSettingItem();
+    const postfachSettingsItem: SettingItem<Postfach> = createPostfachSettingItem();
     const postfachResource: PostfachResource = createPostfachResource();
     const postfachStateResource: StateResource<PostfachResource> = createStateResource(postfachResource);
 
diff --git a/alfa-client/libs/admin/postfach-shared/src/lib/postfach.service.ts b/alfa-client/libs/admin/postfach-shared/src/lib/postfach.service.ts
index 19cf4ef6cf561586b44f3afee70e4c716ec54052..3321cfc1690bd504a1e0f94ac6eda627170a29c9 100644
--- a/alfa-client/libs/admin/postfach-shared/src/lib/postfach.service.ts
+++ b/alfa-client/libs/admin/postfach-shared/src/lib/postfach.service.ts
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { SettingName } from '@admin-client/settings-shared';
+import { SettingItem, SettingName } from '@admin-client/settings-shared';
 import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
 import { SnackBarService } from '@alfa-client/ui';
 import { inject, Injectable } from '@angular/core';
 import { Observable, startWith, tap } from 'rxjs';
 import { PostfachResourceService } from './postfach-resource.service';
-import { Postfach, PostfachResource, PostfachSettingsItem } from './postfach.model';
+import { Postfach, PostfachResource } from './postfach.model';
 
 @Injectable()
 export class PostfachService {
@@ -51,7 +51,7 @@ export class PostfachService {
     }
   }
 
-  private buildPostfachSettingItem(postfach: Postfach): PostfachSettingsItem {
+  private buildPostfachSettingItem(postfach: Postfach): SettingItem<Postfach> {
     return {
       name: SettingName.POSTFACH,
       settingBody: postfach,
diff --git a/alfa-client/libs/admin/postfach-shared/src/test/postfach.ts b/alfa-client/libs/admin/postfach-shared/src/test/postfach.ts
index 93d7492c32b0e0b595a447757952ee358b0e1345..88132bc3d88c73d130f50caed0da9aa15ae68d5b 100644
--- a/alfa-client/libs/admin/postfach-shared/src/test/postfach.ts
+++ b/alfa-client/libs/admin/postfach-shared/src/test/postfach.ts
@@ -22,9 +22,9 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { faker } from '@faker-js/faker';
-import { SettingItemResource, SettingName } from 'libs/admin/settings-shared/src/lib/settings.model';
+import { SettingItem, SettingName } from 'libs/admin/settings-shared/src/lib/settings.model';
 import { toResource } from 'libs/tech-shared/test/resource';
-import { Postfach, PostfachResource, PostfachSettingsItem } from '../lib/postfach.model';
+import { Postfach, PostfachResource } from '../lib/postfach.model';
 
 export function createPostfach(): Postfach {
   return {
@@ -39,7 +39,7 @@ export function createPostfach(): Postfach {
   };
 }
 
-export function createPostfachSettingItem(): PostfachSettingsItem {
+export function createPostfachSettingItem(): SettingItem<Postfach> {
   return {
     name: SettingName.POSTFACH,
     settingBody: createPostfach(),
@@ -49,10 +49,3 @@ export function createPostfachSettingItem(): PostfachSettingsItem {
 export function createPostfachResource(): PostfachResource {
   return toResource(createPostfachSettingItem());
 }
-
-export function createSettingItemResource(): SettingItemResource {
-  return toResource({
-    name: faker.word.sample(),
-    settingBody: {},
-  });
-}
diff --git a/alfa-client/libs/admin/reporting-shared/.eslintrc.json b/alfa-client/libs/admin/reporting-shared/.eslintrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..7474579d583c598ae092a906b3e6cf1ad3c08a50
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/.eslintrc.json
@@ -0,0 +1,33 @@
+{
+  "extends": ["../../../.eslintrc.json"],
+  "ignorePatterns": ["!**/*"],
+  "overrides": [
+    {
+      "files": ["*.ts"],
+      "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"],
+      "rules": {
+        "@angular-eslint/directive-selector": [
+          "error",
+          {
+            "type": "attribute",
+            "prefix": "admin",
+            "style": "camelCase"
+          }
+        ],
+        "@angular-eslint/component-selector": [
+          "error",
+          {
+            "type": "element",
+            "prefix": "admin",
+            "style": "kebab-case"
+          }
+        ]
+      }
+    },
+    {
+      "files": ["*.html"],
+      "extends": ["plugin:@nx/angular-template"],
+      "rules": {}
+    }
+  ]
+}
diff --git a/alfa-client/libs/admin/reporting-shared/README.md b/alfa-client/libs/admin/reporting-shared/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..be5bb22469ec116a5b8b3d498db669555c92da4e
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/README.md
@@ -0,0 +1,7 @@
+# admin-reporting-shared
+
+This library was generated with [Nx](https://nx.dev).
+
+## Running unit tests
+
+Run `nx test admin-reporting-shared` to execute the unit tests.
diff --git a/alfa-client/libs/admin/reporting-shared/jest.config.ts b/alfa-client/libs/admin/reporting-shared/jest.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b4f392a061baff74cb98d86a02f0100960384315
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/jest.config.ts
@@ -0,0 +1,21 @@
+export default {
+  displayName: 'admin-reporting-shared',
+  preset: '../../../jest.preset.js',
+  setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
+  coverageDirectory: '../../../coverage/libs/admin/reporting-shared',
+  transform: {
+    '^.+\\.(ts|mjs|js|html)$': [
+      'jest-preset-angular',
+      {
+        tsconfig: '<rootDir>/tsconfig.spec.json',
+        stringifyContentPathRegex: '\\.(html|svg)$',
+      },
+    ],
+  },
+  transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
+  snapshotSerializers: [
+    'jest-preset-angular/build/serializers/no-ng-attributes',
+    'jest-preset-angular/build/serializers/ng-snapshot',
+    'jest-preset-angular/build/serializers/html-comment',
+  ],
+};
diff --git a/alfa-client/libs/admin/reporting-shared/project.json b/alfa-client/libs/admin/reporting-shared/project.json
new file mode 100644
index 0000000000000000000000000000000000000000..f7a760900530aff273dc117494292f1e2b028824
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/project.json
@@ -0,0 +1,22 @@
+{
+  "name": "admin-reporting-shared",
+  "$schema": "../../../node_modules/nx/schemas/project-schema.json",
+  "sourceRoot": "libs/admin/reporting-shared/src",
+  "prefix": "admin",
+  "projectType": "library",
+  "tags": [],
+  "targets": {
+    "test": {
+      "executor": "@nx/jest:jest",
+      "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
+      "options": {
+        "tsConfig": "libs/admin/reporting-shared/tsconfig.spec.json",
+        "jestConfig": "libs/admin/reporting-shared/jest.config.ts"
+      }
+    },
+    "lint": {
+      "executor": "@nx/eslint:lint",
+      "outputs": ["{options.outputFile}"]
+    }
+  }
+}
diff --git a/alfa-client/libs/admin/reporting-shared/src/index.ts b/alfa-client/libs/admin/reporting-shared/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..44ab78233d97deaf497e327e28f71c431ae6960e
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/src/index.ts
@@ -0,0 +1,4 @@
+export * from './lib/aggregation-mapping-resource.service';
+export * from './lib/aggregation-mapping.model';
+export * from './lib/aggregation-mapping.provider';
+export * from './lib/aggregation-mapping.service';
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..65eb7a8e1680b97f12cdba2556ae8d9d9041883c
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping-resource.service.ts
@@ -0,0 +1,26 @@
+import { ConfigurationLinkRel, ConfigurationResource, ConfigurationService } from '@admin-client/configuration-shared';
+import { ListResourceServiceConfig, ResourceListService, ResourceRepository } from '@alfa-client/tech-shared';
+import { AggregationMappingListLinkRel } from './aggregation-mapping.linkrel';
+import { AggregationMappingListResource, AggregationMappingResource } from './aggregation-mapping.model';
+
+export class AggregationMappingListResourceService extends ResourceListService<
+  ConfigurationResource,
+  AggregationMappingListResource,
+  AggregationMappingResource
+> {}
+
+export function createAggregationMappingResourceService(
+  repository: ResourceRepository,
+  configurationService: ConfigurationService,
+) {
+  return new ResourceListService(buildConfig(configurationService), repository);
+}
+
+function buildConfig(configurationService: ConfigurationService): ListResourceServiceConfig<ConfigurationResource> {
+  return {
+    baseResource: configurationService.get(),
+    listLinkRel: ConfigurationLinkRel.AGGREGATION_MAPPINGS,
+    listResourceListLinkRel: AggregationMappingListLinkRel.LIST,
+    createLinkRel: AggregationMappingListLinkRel.SELF,
+  };
+}
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.linkrel.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.linkrel.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a4a02bfd7087b105a9d0d2dd816aa2b180a4db9c
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.linkrel.ts
@@ -0,0 +1,4 @@
+export enum AggregationMappingListLinkRel {
+  LIST = 'aggregationMappings',
+  SELF = 'self',
+}
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.model.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0db6cb4e397768b10781b3c34c9379fc866cec2b
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.model.ts
@@ -0,0 +1,20 @@
+import { ListResource } from '@alfa-client/tech-shared';
+import { Resource } from '@ngxp/rest';
+
+export interface AggregationMapping {
+  formIdentifier: FormIdentifier;
+  mappings: FieldMapping[];
+}
+
+export interface FormIdentifier {
+  formEngineName: string;
+  formId: string;
+}
+
+export interface FieldMapping {
+  sourcePath: string;
+  targetPath: string;
+}
+
+export interface AggregationMappingResource extends AggregationMapping, Resource {}
+export interface AggregationMappingListResource extends ListResource {}
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.provider.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.provider.ts
new file mode 100644
index 0000000000000000000000000000000000000000..888d7154e81dbfe53fb7476e4de8835463de6d25
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.provider.ts
@@ -0,0 +1,17 @@
+import { ResourceRepository } from '@alfa-client/tech-shared';
+import { Provider } from '@angular/core';
+import { ConfigurationService } from 'libs/admin/configuration-shared/src/lib/configuration.service';
+import {
+  AggregationMappingListResourceService,
+  createAggregationMappingResourceService,
+} from './aggregation-mapping-resource.service';
+import { AggregationMappingService } from './aggregation-mapping.service';
+
+export const AggregationMappingProvider: Provider[] = [
+  {
+    provide: AggregationMappingListResourceService,
+    useFactory: createAggregationMappingResourceService,
+    deps: [ResourceRepository, ConfigurationService],
+  },
+  AggregationMappingService,
+];
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ecf4387ceee6a3dbdd6775f8ef4fa3a306144002
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.spec.ts
@@ -0,0 +1,79 @@
+import { StateResource, createStateResource } from '@alfa-client/tech-shared';
+import { Mock, mock } from '@alfa-client/test-utils';
+import { TestBed } from '@angular/core/testing';
+import { singleCold } from 'libs/tech-shared/test/marbles';
+import { Observable } from 'rxjs';
+import {
+  createAggregationMapping,
+  createAggregationMappingListResource,
+  createAggregationMappingResource,
+} from '../../test/aggregation-mapping';
+import { AggregationMappingListResourceService } from './aggregation-mapping-resource.service';
+import { AggregationMapping, AggregationMappingListResource, AggregationMappingResource } from './aggregation-mapping.model';
+import { AggregationMappingService } from './aggregation-mapping.service';
+
+describe('AggregationMappingService', () => {
+  let service: AggregationMappingService;
+  let listResourceService: Mock<AggregationMappingListResourceService>;
+
+  beforeEach(() => {
+    listResourceService = mock(AggregationMappingListResourceService);
+
+    TestBed.configureTestingModule({
+      providers: [AggregationMappingService, { provide: AggregationMappingListResourceService, useValue: listResourceService }],
+    });
+
+    service = TestBed.inject(AggregationMappingService);
+  });
+
+  it('should create', () => {
+    expect(service).toBeTruthy();
+  });
+
+  describe('get list', () => {
+    const aggregationMappingListResource: AggregationMappingListResource = createAggregationMappingListResource();
+    const aggregationMappingListStateResource: StateResource<AggregationMappingListResource> =
+      createStateResource(aggregationMappingListResource);
+
+    beforeEach(() => {
+      listResourceService.getList = jest.fn().mockReturnValue(singleCold(aggregationMappingListStateResource));
+    });
+
+    it('should call listResourceService', () => {
+      service.getList();
+
+      expect(listResourceService.getList).toHaveBeenCalled();
+    });
+
+    it('should return value', () => {
+      const loadedAggregationMappingListResource: Observable<StateResource<AggregationMappingListResource>> = service.getList();
+
+      expect(loadedAggregationMappingListResource).toBeObservable(singleCold(aggregationMappingListStateResource));
+    });
+  });
+
+  describe('create', () => {
+    const aggregationMappingResource: AggregationMappingResource = createAggregationMappingResource();
+    const aggregationMappingStateResource: StateResource<AggregationMappingResource> =
+      createStateResource(aggregationMappingResource);
+
+    const aggregationMapping: AggregationMapping = createAggregationMapping();
+
+    beforeEach(() => {
+      listResourceService.create = jest.fn().mockReturnValue(singleCold(aggregationMappingStateResource));
+    });
+
+    it('should call resourceService', () => {
+      service.create(aggregationMapping);
+
+      expect(listResourceService.create).toHaveBeenCalledWith(aggregationMapping);
+    });
+
+    it('should return value', () => {
+      const loadedAggregationMappingResource: Observable<StateResource<AggregationMappingResource>> =
+        service.create(aggregationMapping);
+
+      expect(loadedAggregationMappingResource).toBeObservable(singleCold(aggregationMappingStateResource));
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..20a8ce6c1ccda133323bac99a671d887e77afb8e
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/src/lib/aggregation-mapping.service.ts
@@ -0,0 +1,18 @@
+import { StateResource } from '@alfa-client/tech-shared';
+import { Injectable, inject } from '@angular/core';
+import { Observable } from 'rxjs';
+import { AggregationMappingListResourceService } from './aggregation-mapping-resource.service';
+import { AggregationMapping, AggregationMappingListResource, AggregationMappingResource } from './aggregation-mapping.model';
+
+@Injectable()
+export class AggregationMappingService {
+  readonly listService = inject(AggregationMappingListResourceService);
+
+  public getList(): Observable<StateResource<AggregationMappingListResource>> {
+    return this.listService.getList();
+  }
+
+  public create(toCreate: AggregationMapping): Observable<StateResource<AggregationMappingResource>> {
+    return this.listService.create(toCreate);
+  }
+}
diff --git a/alfa-client/libs/admin/reporting-shared/src/test-setup.ts b/alfa-client/libs/admin/reporting-shared/src/test-setup.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c408668266d2fec3a9803c0ec044bc163fb987fe
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/src/test-setup.ts
@@ -0,0 +1,12 @@
+import '@testing-library/jest-dom';
+import 'jest-preset-angular/setup-jest';
+
+import { getTestBed } from '@angular/core/testing';
+import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
+
+getTestBed().resetTestEnvironment();
+getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
+  teardown: { destroyAfterEach: false },
+  errorOnUnknownProperties: true,
+  errorOnUnknownElements: true,
+});
diff --git a/alfa-client/libs/admin/reporting-shared/test/aggregation-mapping.ts b/alfa-client/libs/admin/reporting-shared/test/aggregation-mapping.ts
new file mode 100644
index 0000000000000000000000000000000000000000..acbcc9fa75722396e4a410ea77e9157a2a8ce8fc
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/test/aggregation-mapping.ts
@@ -0,0 +1,35 @@
+import { faker } from '@faker-js/faker';
+import { times } from 'lodash-es';
+import { LinkRelationName } from '../../../tech-shared/src';
+import { toResource } from '../../../tech-shared/test/resource';
+import { AggregationMapping, AggregationMappingListResource, AggregationMappingResource } from '../src';
+import { AggregationMappingListLinkRel } from '../src/lib/aggregation-mapping.linkrel';
+
+export function createAggregationMapping(): AggregationMapping {
+  return {
+    formIdentifier: {
+      formEngineName: faker.lorem.word(),
+      formId: faker.string.uuid(),
+    },
+    mappings: [
+      {
+        sourcePath: faker.lorem.word(),
+        targetPath: faker.lorem.word(),
+      },
+    ],
+  };
+}
+
+export function createAggregationMappingResource(linkRelations: LinkRelationName[] = []): AggregationMappingResource {
+  return toResource(createAggregationMapping(), linkRelations);
+}
+
+export function createAggregationMappingResources(linkRelations: LinkRelationName[] = []): AggregationMappingResource[] {
+  return times(10, () => createAggregationMappingResource(linkRelations));
+}
+
+export function createAggregationMappingListResource(linkRelations: LinkRelationName[] = []): AggregationMappingListResource {
+  return toResource({}, linkRelations, {
+    [AggregationMappingListLinkRel.LIST]: createAggregationMappingResources(),
+  });
+}
diff --git a/alfa-client/libs/admin/reporting-shared/tsconfig.json b/alfa-client/libs/admin/reporting-shared/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..8ca9ad312c2bd4dc364383853ddd91a2ed8f86fd
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/tsconfig.json
@@ -0,0 +1,16 @@
+{
+  "extends": "../../../tsconfig.base.json",
+  "files": [],
+  "include": [],
+  "references": [
+    {
+      "path": "./tsconfig.lib.json"
+    },
+    {
+      "path": "./tsconfig.spec.json"
+    }
+  ],
+  "compilerOptions": {
+    "target": "es2022"
+  }
+}
diff --git a/alfa-client/libs/admin/reporting-shared/tsconfig.lib.json b/alfa-client/libs/admin/reporting-shared/tsconfig.lib.json
new file mode 100644
index 0000000000000000000000000000000000000000..8441346f6e5858b2ef4235cb3c3160eda256f94a
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/tsconfig.lib.json
@@ -0,0 +1,12 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../../../dist/out-tsc",
+    "declaration": true,
+    "declarationMap": true,
+    "inlineSources": true,
+    "types": []
+  },
+  "exclude": ["src/**/*.spec.ts", "src/test-setup.ts", "jest.config.ts", "src/**/*.test.ts"],
+  "include": ["src/**/*.ts"]
+}
diff --git a/alfa-client/libs/admin/reporting-shared/tsconfig.spec.json b/alfa-client/libs/admin/reporting-shared/tsconfig.spec.json
new file mode 100644
index 0000000000000000000000000000000000000000..723782fbd367969806c5992aea882773ab65af8b
--- /dev/null
+++ b/alfa-client/libs/admin/reporting-shared/tsconfig.spec.json
@@ -0,0 +1,12 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../../../dist/out-tsc",
+    "module": "commonjs",
+    "types": ["jest", "node"],
+    "target": "ES2022",
+    "useDefineForClassFields": false
+  },
+  "files": ["src/test-setup.ts"],
+  "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"]
+}
diff --git a/alfa-client/libs/admin/settings-shared/jest.config.ts b/alfa-client/libs/admin/settings-shared/jest.config.ts
index e9e4c0e81848959b2203b3551b8a0e999c127500..9c940034939a689a0f138e47d5c3a5c34d2bb92e 100644
--- a/alfa-client/libs/admin/settings-shared/jest.config.ts
+++ b/alfa-client/libs/admin/settings-shared/jest.config.ts
@@ -1,9 +1,8 @@
 export default {
-  displayName: 'admin-settings',
+  displayName: 'admin-settings-shared',
   preset: '../../../jest.preset.js',
   setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
-  globals: {},
-  coverageDirectory: '../../coverage/libs/admin/settings-shared',
+  coverageDirectory: '../../../coverage/libs/admin/settings-shared',
   transform: {
     '^.+\\.(ts|mjs|js|html)$': [
       'jest-preset-angular',
@@ -13,7 +12,7 @@ export default {
       },
     ],
   },
-  transformIgnorePatterns: ['node_modules/(?!.pnpm|.*\\.mjs$)'],
+  transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
   snapshotSerializers: [
     'jest-preset-angular/build/serializers/no-ng-attributes',
     'jest-preset-angular/build/serializers/ng-snapshot',
diff --git a/alfa-client/libs/admin/settings-shared/project.json b/alfa-client/libs/admin/settings-shared/project.json
index 702a27446f83db42dc97ec9409c8f3d323dcbb65..02e461c6816868190ac3b45dea543a934a1d6d1d 100644
--- a/alfa-client/libs/admin/settings-shared/project.json
+++ b/alfa-client/libs/admin/settings-shared/project.json
@@ -1,15 +1,11 @@
 {
-  "name": "admin-settings",
+  "name": "admin-settings-shared",
   "$schema": "../../../node_modules/nx/schemas/project-schema.json",
   "sourceRoot": "libs/admin/settings-shared/src",
-  "projectType": "library",
   "prefix": "admin",
+  "projectType": "library",
   "tags": [],
   "targets": {
-    "lint": {
-      "executor": "@nx/eslint:lint",
-      "outputs": ["{options.outputFile}"]
-    },
     "test": {
       "executor": "@nx/jest:jest",
       "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
@@ -17,6 +13,10 @@
         "tsConfig": "libs/admin/settings-shared/tsconfig.spec.json",
         "jestConfig": "libs/admin/settings-shared/jest.config.ts"
       }
+    },
+    "lint": {
+      "executor": "@nx/eslint:lint",
+      "outputs": ["{options.outputFile}"]
     }
   }
 }
diff --git a/alfa-client/libs/admin/settings-shared/src/lib/settings-resource.service.ts b/alfa-client/libs/admin/settings-shared/src/lib/settings-resource.service.ts
index a75f91afec901a8c969c00ede9a8631766421f1f..7e9df14e6ec13929f720978ada7ebcb3e74c5ef9 100644
--- a/alfa-client/libs/admin/settings-shared/src/lib/settings-resource.service.ts
+++ b/alfa-client/libs/admin/settings-shared/src/lib/settings-resource.service.ts
@@ -4,7 +4,11 @@ import { Resource } from '@ngxp/rest';
 import { SettingListLinkRel } from './settings.linkrel';
 import { SettingItemResource, SettingListResource } from './settings.model';
 
-export class SettingListResourceService extends ResourceListService<Resource, SettingListResource, SettingItemResource> {}
+export class SettingListResourceService extends ResourceListService<
+  Resource,
+  SettingListResource,
+  SettingItemResource<unknown>
+> {}
 
 export function createSettingListResourceService(repository: ResourceRepository, configurationService: ConfigurationService) {
   return new ResourceListService(buildConfig(configurationService), repository);
diff --git a/alfa-client/libs/admin/settings-shared/src/lib/settings.model.ts b/alfa-client/libs/admin/settings-shared/src/lib/settings.model.ts
index 263fca126d53eb889e1701e931a8b32a38899145..2e97584b7934ea105c828cbb2523c0d16ce431a1 100644
--- a/alfa-client/libs/admin/settings-shared/src/lib/settings.model.ts
+++ b/alfa-client/libs/admin/settings-shared/src/lib/settings.model.ts
@@ -25,16 +25,16 @@ import { ListResource } from '@alfa-client/tech-shared';
 import { Resource } from '@ngxp/rest';
 
 export interface SettingListResource extends ListResource {
-  _embedded: { settings: SettingItemResource[] };
+  _embedded: { settings: SettingItemResource<unknown>[] };
 }
 
 export enum SettingName {
   POSTFACH = 'Postfach',
 }
 
-export interface SettingItem {
+export interface SettingItem<T> {
   name: SettingName;
-  settingBody: unknown;
+  settingBody: T;
 }
 
-export declare type SettingItemResource = Resource & SettingItem;
+export interface SettingItemResource<T> extends SettingItem<T>, Resource {}
diff --git a/alfa-client/libs/admin/settings-shared/src/lib/settings.service.spec.ts b/alfa-client/libs/admin/settings-shared/src/lib/settings.service.spec.ts
index 9b24d56767a9f5de93f738638d976333cfa93af7..1cf23c357186c0480ce12a349497c2c1f66139e5 100644
--- a/alfa-client/libs/admin/settings-shared/src/lib/settings.service.spec.ts
+++ b/alfa-client/libs/admin/settings-shared/src/lib/settings.service.spec.ts
@@ -21,16 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { PostfachResource } from '@admin-client/postfach-shared';
 import { StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared';
 import { Mock, mock } from '@alfa-client/test-utils';
 import { TestBed } from '@angular/core/testing';
 import { singleCold } from 'libs/tech-shared/test/marbles';
 import { Observable, of } from 'rxjs';
-import { createPostfachResource, createSettingItemResource } from '../../../postfach-shared/src/test/postfach';
-import { createSettingsListResource } from '../../test/settings';
+import { createSettingItemResource, createSettingsListResource } from '../../test/settings';
 import { SettingListResourceService } from './settings-resource.service';
-import { SettingListResource } from './settings.model';
+import { SettingItemResource, SettingListResource, SettingName } from './settings.model';
 import { SettingsService } from './settings.service';
 
 describe('SettingsService', () => {
@@ -51,11 +49,12 @@ describe('SettingsService', () => {
     expect(service).toBeTruthy();
   });
 
-  describe('get Postfach', () => {
-    const postfachResource = createPostfachResource();
-    const postfachStateResource: StateResource<PostfachResource> = createStateResource(postfachResource);
+  describe('get by setting name', () => {
+    const settingItemName: SettingName = <SettingName>'DUMMY';
+    const settingItemResource: SettingItemResource<unknown> = { ...createSettingItemResource(), name: settingItemName };
+    const settingItemStateResource: StateResource<SettingItemResource<unknown>> = createStateResource(settingItemResource);
     const settingsListResource: StateResource<SettingListResource> = createStateResource(
-      createSettingsListResource([postfachResource]),
+      createSettingsListResource([settingItemResource]),
     );
 
     beforeEach(() => {
@@ -63,28 +62,28 @@ describe('SettingsService', () => {
     });
 
     it('should call resource service', () => {
-      service.getPostfach();
+      service.get(settingItemName);
 
       expect(settingListResourceService.getList).toHaveBeenCalled();
     });
 
-    it('should return null for non postfach resource', () => {
+    it('should return null for non existing setting item resource', () => {
       const emptySettingsListResource: StateResource<SettingListResource> = createStateResource(
         createSettingsListResource([createSettingItemResource()]),
       );
-
       settingListResourceService.getList = jest.fn().mockReturnValue(singleCold(emptySettingsListResource));
 
-      const postfach: Observable<StateResource<PostfachResource>> = service.getPostfach();
-      expect(postfach).toBeObservable(singleCold(createEmptyStateResource()));
+      const settingItemStateResource$: Observable<StateResource<SettingItemResource<unknown>>> = service.get(settingItemName);
+
+      expect(settingItemStateResource$).toBeObservable(singleCold(createEmptyStateResource()));
     });
 
-    it('should return item resource as postfach resource', () => {
+    it('should return item resource as setting item resource', () => {
       settingListResourceService.getList = jest.fn().mockReturnValue(singleCold(settingsListResource));
 
-      const postfach: Observable<StateResource<PostfachResource>> = service.getPostfach();
+      const settingItemStateResource$: Observable<StateResource<SettingItemResource<unknown>>> = service.get(settingItemName);
 
-      expect(postfach).toBeObservable(singleCold(postfachStateResource));
+      expect(settingItemStateResource$).toBeObservable(singleCold(settingItemStateResource));
     });
   });
 });
diff --git a/alfa-client/libs/admin/settings-shared/src/lib/settings.service.ts b/alfa-client/libs/admin/settings-shared/src/lib/settings.service.ts
index 51faa2be7ea9aa2a9f878de233ad56d32ec0f81c..770c9d7da6230f67e7d92c553e97e062277b5994 100644
--- a/alfa-client/libs/admin/settings-shared/src/lib/settings.service.ts
+++ b/alfa-client/libs/admin/settings-shared/src/lib/settings.service.ts
@@ -1,15 +1,17 @@
-import { PostfachResource } from '@admin-client/postfach-shared';
 import { StateResource } from '@alfa-client/tech-shared';
 import { inject, Injectable } from '@angular/core';
 import { map, Observable } from 'rxjs';
 import { SettingListResourceService } from './settings-resource.service';
-import { getPostfachResource } from './settings.util';
+import { SettingItemResource, SettingListResource, SettingName } from './settings.model';
+import { getSettingItemResource } from './settings.util';
 
 @Injectable()
 export class SettingsService {
   private settingListResourceService = inject(SettingListResourceService);
 
-  public getPostfach(): Observable<StateResource<PostfachResource>> {
-    return this.settingListResourceService.getList().pipe(map(getPostfachResource));
+  public get<T>(name: SettingName): Observable<StateResource<SettingItemResource<T>>> {
+    return this.settingListResourceService
+      .getList()
+      .pipe(map((list: StateResource<SettingListResource>) => getSettingItemResource<T>(list, name)));
   }
 }
diff --git a/alfa-client/libs/admin/settings-shared/src/lib/settings.util.spec.ts b/alfa-client/libs/admin/settings-shared/src/lib/settings.util.spec.ts
index 5b78df34aa506c8180878416054cd11bb4164d14..fe8480f147ba265070096e70d6fe54f817324397 100644
--- a/alfa-client/libs/admin/settings-shared/src/lib/settings.util.spec.ts
+++ b/alfa-client/libs/admin/settings-shared/src/lib/settings.util.spec.ts
@@ -21,30 +21,31 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { PostfachResource } from '@admin-client/postfach-shared';
-import { SettingListResource } from '@admin-client/settings-shared';
 import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared';
-import { createPostfachResource } from 'libs/admin/postfach-shared/src/test/postfach';
-import { createFilledSettingsListResource } from '../../test/settings';
-import { getPostfachResource } from './settings.util';
+import { Resource } from '@ngxp/rest';
+import { createFilledSettingsListResource, createSettingItemResource } from '../../test/settings';
+import { SettingItemResource, SettingListResource, SettingName } from './settings.model';
+import { getSettingItemResource } from './settings.util';
 
-describe('get postfach resource', () => {
-  it('should return state resource with postfach resource if exists', () => {
-    const postfachResource: PostfachResource = createPostfachResource();
+describe('get setting item resource', () => {
+  const settingName: SettingName = <SettingName>'DUMMY';
+
+  it('should return matching setting resource as state resource if exists', () => {
+    const settingItemResource: SettingItemResource<unknown> = { ...createSettingItemResource(), name: settingName };
     const settingsListResource: StateResource<SettingListResource> = createStateResource(
-      createFilledSettingsListResource([postfachResource]),
+      createFilledSettingsListResource([settingItemResource]),
     );
 
-    const postfachStateResource: StateResource<PostfachResource> = getPostfachResource(settingsListResource);
+    const stateResource: StateResource<Resource> = getSettingItemResource(settingsListResource, settingName);
 
-    expect(postfachStateResource.resource).toEqual(postfachResource);
+    expect(stateResource.resource).toEqual(settingItemResource);
   });
 
-  it('should return empty state resource if postfach resource NOT exists', () => {
+  it('should return empty state resource if no matching resource exists', () => {
     const settingsListResource: StateResource<SettingListResource> = createStateResource(createFilledSettingsListResource([]));
 
-    const postfachStateResource: StateResource<PostfachResource> = getPostfachResource(settingsListResource);
+    const stateResource: StateResource<Resource> = getSettingItemResource(settingsListResource, settingName);
 
-    expect(postfachStateResource).toEqual(createEmptyStateResource());
+    expect(stateResource).toEqual(createEmptyStateResource());
   });
 });
diff --git a/alfa-client/libs/admin/settings-shared/src/lib/settings.util.ts b/alfa-client/libs/admin/settings-shared/src/lib/settings.util.ts
index d5cf7605cada028e253a26d1e3641eee5856e2c7..2a00f86b2a84fef05b45ccfde06c3ff8a6321745 100644
--- a/alfa-client/libs/admin/settings-shared/src/lib/settings.util.ts
+++ b/alfa-client/libs/admin/settings-shared/src/lib/settings.util.ts
@@ -21,7 +21,6 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { PostfachResource } from '@admin-client/postfach-shared';
 import {
   createEmptyStateResource,
   createStateResource,
@@ -32,14 +31,11 @@ import {
 import { SettingListLinkRel } from './settings.linkrel';
 import { SettingItemResource, SettingListResource, SettingName } from './settings.model';
 
-export function getPostfachResource(settingsListResource: StateResource<SettingListResource>): StateResource<PostfachResource> {
-  const entries: SettingItemResource[] = getEmbeddedResources(settingsListResource, SettingListLinkRel.LIST);
-  const postfachSettingItemResource: SettingItemResource = entries.find(isPostfachSettingItem);
-  return isNotNil(postfachSettingItemResource) ?
-      createStateResource(postfachSettingItemResource as PostfachResource)
-    : createEmptyStateResource();
-}
-
-function isPostfachSettingItem(item: SettingItemResource): boolean {
-  return item.name === SettingName.POSTFACH;
+export function getSettingItemResource<T>(
+  settingsListResource: StateResource<SettingListResource>,
+  itemName: SettingName,
+): StateResource<SettingItemResource<T>> {
+  const entries: SettingItemResource<T>[] = getEmbeddedResources(settingsListResource, SettingListLinkRel.LIST);
+  const entry: SettingItemResource<T> = entries.find((item: SettingItemResource<T>) => item.name === itemName);
+  return isNotNil(entry) ? createStateResource(entry) : createEmptyStateResource<SettingItemResource<T>>();
 }
diff --git a/alfa-client/libs/admin/settings-shared/test/settings.ts b/alfa-client/libs/admin/settings-shared/test/settings.ts
index c3b9478ea57d373b18ad6315c0e5161fd7d9b008..a7bf1ded5bac477efcce579bd74f1646d8664a2d 100644
--- a/alfa-client/libs/admin/settings-shared/test/settings.ts
+++ b/alfa-client/libs/admin/settings-shared/test/settings.ts
@@ -1,9 +1,10 @@
+import { faker } from '@faker-js/faker/.';
 import { Resource } from '@ngxp/rest';
 import { toResource } from 'libs/tech-shared/test/resource';
 import { SettingListLinkRel } from '../src/lib/settings.linkrel';
 import { SettingItemResource, SettingListResource } from '../src/lib/settings.model';
 
-export function createSettingsListResource(settingsItems: SettingItemResource[]): SettingListResource {
+export function createSettingsListResource(settingsItems: SettingItemResource<unknown>[]): SettingListResource {
   return toResource({}, [], {
     settings: settingsItems,
   });
@@ -14,3 +15,10 @@ export function createFilledSettingsListResource(resources: Resource[], linkRela
     [SettingListLinkRel.LIST]: resources,
   });
 }
+
+export function createSettingItemResource(): SettingItemResource<unknown> {
+  return toResource({
+    name: faker.word.sample(),
+    settingBody: {},
+  });
+}
diff --git a/alfa-client/libs/admin/shared/src/index.ts b/alfa-client/libs/admin/shared/src/index.ts
index ece2c025dc3e05d4b26ad131fc7e419331e301d2..8f0992f8376dfb02cbd0096e33f516ac819f3d97 100644
--- a/alfa-client/libs/admin/shared/src/index.ts
+++ b/alfa-client/libs/admin/shared/src/index.ts
@@ -1 +1,4 @@
+export * from './lib/admin-cancel-button/admin-cancel-button.component';
+export * from './lib/admin-save-button/admin-save-button.component';
 export * from './lib/routes';
+export * from './lib/token';
diff --git a/alfa-client/libs/admin/shared/src/lib/admin-cancel-button/admin-cancel-button.component.html b/alfa-client/libs/admin/shared/src/lib/admin-cancel-button/admin-cancel-button.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..3125fbdfd9242e48e3a30a5891e445bb6d8b8498
--- /dev/null
+++ b/alfa-client/libs/admin/shared/src/lib/admin-cancel-button/admin-cancel-button.component.html
@@ -0,0 +1,3 @@
+<ods-routing-button [linkPath]="linkPath" text="Abbrechen" variant="outline" dataTestId="cancel-button">
+  <ods-close-icon icon class="fill-primary" />
+</ods-routing-button>
diff --git a/alfa-client/libs/admin/shared/src/lib/admin-cancel-button/admin-cancel-button.component.spec.ts b/alfa-client/libs/admin/shared/src/lib/admin-cancel-button/admin-cancel-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..253650b230fb8be30ddb854fe3ad62351b058e5b
--- /dev/null
+++ b/alfa-client/libs/admin/shared/src/lib/admin-cancel-button/admin-cancel-button.component.spec.ts
@@ -0,0 +1,36 @@
+import { AdminCancelButtonComponent } from '@admin-client/shared';
+import { getMockComponent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RoutingButtonComponent } from '@ods/component';
+import { CloseIconComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+
+describe('AdminCancelButtonComponent', () => {
+  let component: AdminCancelButtonComponent;
+  let fixture: ComponentFixture<AdminCancelButtonComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [AdminCancelButtonComponent],
+      declarations: [MockComponent(RoutingButtonComponent), MockComponent(CloseIconComponent)],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(AdminCancelButtonComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('button', () => {
+    it('should be called with linkPath', () => {
+      component.linkPath = 'dummyLinkPath';
+
+      fixture.detectChanges();
+
+      expect(getMockComponent(fixture, RoutingButtonComponent).linkPath).toBe('dummyLinkPath');
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/shared/src/lib/admin-cancel-button/admin-cancel-button.component.ts b/alfa-client/libs/admin/shared/src/lib/admin-cancel-button/admin-cancel-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8c284f05c61e3d545025c8447d4d302a0fc3db85
--- /dev/null
+++ b/alfa-client/libs/admin/shared/src/lib/admin-cancel-button/admin-cancel-button.component.ts
@@ -0,0 +1,14 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { RoutingButtonComponent } from '@ods/component';
+import { CloseIconComponent } from '@ods/system';
+
+@Component({
+  selector: 'admin-cancel-button',
+  templateUrl: './admin-cancel-button.component.html',
+  standalone: true,
+  imports: [CommonModule, RoutingButtonComponent, CloseIconComponent],
+})
+export class AdminCancelButtonComponent {
+  @Input() linkPath: string;
+}
diff --git a/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.html b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..8bd6a5f92932e22006b3b8e2cb353a9c3fa93eb1
--- /dev/null
+++ b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.html
@@ -0,0 +1,6 @@
+<ods-button-with-spinner
+  (clickEmitter)="submit()"
+  text="Speichern"
+  dataTestId="save-button"
+  [stateResource]="stateResource$ | async"
+/>
diff --git a/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.spec.ts b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..52a303f378e824677dd6518126ae838ebd416e3a
--- /dev/null
+++ b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.spec.ts
@@ -0,0 +1,71 @@
+import { ADMIN_FORMSERVICE } from '@admin-client/shared';
+import { AbstractFormService, createStateResource, StateResource } from '@alfa-client/tech-shared';
+import { dispatchEventFromFixture, getMockComponent, Mock, MockEvent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { Resource } from '@ngxp/rest';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { getDataTestIdAttributeOf } from 'libs/tech-shared/test/data-test';
+import { singleCold } from 'libs/tech-shared/test/marbles';
+import { createDummyResource } from 'libs/tech-shared/test/resource';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { AdminSaveButtonComponent } from './admin-save-button.component';
+
+describe('AdminSaveButtonComponent', () => {
+  let component: AdminSaveButtonComponent;
+  let fixture: ComponentFixture<AdminSaveButtonComponent>;
+
+  let formService: Mock<AbstractFormService<Resource>>;
+
+  const saveButton: string = getDataTestIdAttributeOf('save-button');
+
+  const stateResource: StateResource<Resource> = createStateResource(createDummyResource());
+
+  beforeEach(async () => {
+    formService = <any>{ submit: jest.fn().mockReturnValue(singleCold(stateResource)) };
+
+    await TestBed.configureTestingModule({
+      imports: [AdminSaveButtonComponent],
+      declarations: [MockComponent(ButtonWithSpinnerComponent)],
+      providers: [
+        {
+          provide: ADMIN_FORMSERVICE,
+          useValue: formService,
+        },
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(AdminSaveButtonComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('on submit', () => {
+    it('should call formService', () => {
+      dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
+
+      expect(formService.submit).toHaveBeenCalled();
+    });
+
+    it('should assign state resource', () => {
+      dispatchEventFromFixture(fixture, saveButton, MockEvent.CLICK);
+
+      expect(component.stateResource$).toBeObservable(singleCold(stateResource));
+    });
+  });
+
+  describe('button', () => {
+    it('should call with stateResource', () => {
+      component.stateResource$ = of(stateResource);
+
+      fixture.detectChanges();
+
+      const comp: ButtonWithSpinnerComponent = getMockComponent(fixture, ButtonWithSpinnerComponent);
+      expect(comp.stateResource).toBe(stateResource);
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.ts b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..60abd08c7f311ecabe6d56ecc47fbfcd16412877
--- /dev/null
+++ b/alfa-client/libs/admin/shared/src/lib/admin-save-button/admin-save-button.component.ts
@@ -0,0 +1,23 @@
+import { ADMIN_FORMSERVICE } from '@admin-client/shared';
+import { AbstractFormService, createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
+import { CommonModule } from '@angular/common';
+import { Component, inject } from '@angular/core';
+import { Resource } from '@ngxp/rest';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { Observable, of } from 'rxjs';
+
+@Component({
+  selector: 'admin-save-button',
+  standalone: true,
+  imports: [CommonModule, ButtonWithSpinnerComponent],
+  templateUrl: './admin-save-button.component.html',
+})
+export class AdminSaveButtonComponent {
+  private formService: AbstractFormService<Resource> = inject(ADMIN_FORMSERVICE);
+
+  public stateResource$: Observable<StateResource<Resource>> = of(createEmptyStateResource<Resource>());
+
+  public submit(): void {
+    this.stateResource$ = this.formService.submit();
+  }
+}
diff --git a/alfa-client/libs/admin/shared/src/lib/token.ts b/alfa-client/libs/admin/shared/src/lib/token.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f19e2c875946591ba08470c654f91c80664176aa
--- /dev/null
+++ b/alfa-client/libs/admin/shared/src/lib/token.ts
@@ -0,0 +1,5 @@
+import { AbstractFormService } from '@alfa-client/tech-shared';
+import { InjectionToken } from '@angular/core';
+import { Resource } from '@ngxp/rest';
+
+export const ADMIN_FORMSERVICE = new InjectionToken<AbstractFormService<Resource>>('adminFormService');
diff --git a/alfa-client/libs/admin/statistik/src/index.ts b/alfa-client/libs/admin/statistik/src/index.ts
index cdc5d7b64f24d50920b721f3ab01c5b69cb41b99..157271feb3bf8625864f12faec9623307c3b7690 100644
--- a/alfa-client/libs/admin/statistik/src/index.ts
+++ b/alfa-client/libs/admin/statistik/src/index.ts
@@ -1 +1,2 @@
 export * from './lib/statistik-container/statistik-container.component';
+export * from './lib/statistik-fields-form/admin-statistik-fields-form.component';
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
index 77c10ae229f5d8c6430d82349d6f2d213fa72054..1fd0441a39d71372d0c65fd84d0ce5386ac52fd2 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.html
@@ -24,10 +24,12 @@
 
 -->
 <h1 class="heading-1" data-test-id="statistik-header-text">Statistik</h1>
-<div class="mt-4">
-  <ods-button
+<div class="mt-4 w-fit">
+  <ods-routing-button
+    [linkPath]="ROUTES.STATISTIK_NEU"
     text="Weitere Felder auswerten"
-    (clickEmitter)="navigateToStatistikFieldsForm()"
     dataTestId="weitere-felder-auswerten-button"
-  ></ods-button>
+  ></ods-routing-button>
 </div>
+
+<ng-container *ngIf="listStateResource$ | async"></ng-container>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
index b4390c03face2557262e05f6964e02dc40e4cd7a..a2bc7e4bfe5efdec1af21b9ad1da7deaccf1a21f 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.spec.ts
@@ -21,11 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ROUTES } from '@admin-client/shared';
-import { NavigationService } from '@alfa-client/navigation-shared';
-import { existsAsHtmlElement, mock, Mock, triggerEvent } from '@alfa-client/test-utils';
+import { AggregationMappingListResource, AggregationMappingService } from '@admin-client/reporting-shared';
+import { createStateResource, StateResource } from '@alfa-client/tech-shared';
+import { existsAsHtmlElement, mock, Mock } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RoutingButtonComponent } from '@ods/component';
+import { singleCold } from 'libs/tech-shared/test/marbles';
+import { MockComponent } from 'ng-mocks';
 import { getDataTestIdAttributeOf } from '../../../../../tech-shared/test/data-test';
+import { createAggregationMappingListResource } from '../../../../reporting-shared/test/aggregation-mapping';
 import { StatistikContainerComponent } from './statistik-container.component';
 
 describe('StatistikContainerComponent', () => {
@@ -34,43 +38,34 @@ describe('StatistikContainerComponent', () => {
 
   const evaluateAdditionalFieldsTestId: string = getDataTestIdAttributeOf('weitere-felder-auswerten-button');
 
-  let navigationService: Mock<NavigationService>;
-
-  beforeEach(() => {
-    navigationService = mock(NavigationService);
-  });
+  let aggregationMappingService: Mock<AggregationMappingService>;
 
   beforeEach(async () => {
+    aggregationMappingService = mock(AggregationMappingService);
+
     await TestBed.configureTestingModule({
       imports: [StatistikContainerComponent],
-      providers: [
-        {
-          provide: NavigationService,
-          useValue: navigationService,
+      declarations: [MockComponent(RoutingButtonComponent)],
+    })
+      .overrideComponent(StatistikContainerComponent, {
+        set: {
+          providers: [
+            {
+              provide: AggregationMappingService,
+              useValue: aggregationMappingService,
+            },
+          ],
         },
-      ],
-    });
-  });
+      })
+      .compileComponents();
 
-  beforeEach(() => {
     fixture = TestBed.createComponent(StatistikContainerComponent);
     component = fixture.componentInstance;
-
     fixture.detectChanges();
   });
 
-  describe('component', () => {
-    it('should create', () => {
-      expect(component).toBeTruthy();
-    });
-
-    describe('navigateToStatistikFieldsForm', () => {
-      it('should call navigation service', () => {
-        component.navigateToStatistikFieldsForm();
-
-        expect(navigationService.navigate).toHaveBeenCalledWith(ROUTES.STATISTIK_NEU);
-      });
-    });
+  it('should create', () => {
+    expect(component).toBeTruthy();
   });
 
   describe('template', () => {
@@ -80,23 +75,28 @@ describe('StatistikContainerComponent', () => {
 
         existsAsHtmlElement(fixture, evaluateAdditionalFieldsTestId);
       });
+    });
+  });
 
-      describe('output', () => {
-        describe('clickEmitter', () => {
-          it('should call handler', () => {
-            component.navigateToStatistikFieldsForm = jest.fn();
-            fixture.detectChanges();
+  describe('on init', () => {
+    const stateResource: StateResource<AggregationMappingListResource> = createStateResource(
+      createAggregationMappingListResource(),
+    );
 
-            triggerEvent({
-              fixture,
-              elementSelector: evaluateAdditionalFieldsTestId,
-              name: 'clickEmitter',
-            });
+    beforeEach(() => {
+      aggregationMappingService.getList.mockReturnValue(singleCold(stateResource));
+    });
 
-            expect(component.navigateToStatistikFieldsForm).toHaveBeenCalled();
-          });
-        });
-      });
+    it('should call service to get list', () => {
+      component.ngOnInit();
+
+      expect(aggregationMappingService.getList).toHaveBeenCalled();
+    });
+
+    it('should assign stateResource', () => {
+      component.ngOnInit();
+
+      expect(component.listStateResource$).toBeObservable(singleCold(stateResource));
     });
   });
 });
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
index a00051de29e86232f267891b6f6c8324a726993a..90c3515896348b1c1d6ee77ba4f247428e79c4bf 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-container/statistik-container.component.ts
@@ -21,22 +21,29 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { AggregationMappingListResource, AggregationMappingService } from '@admin-client/reporting-shared';
 import { ROUTES } from '@admin-client/shared';
-import { NavigationService } from '@alfa-client/navigation-shared';
+import { StateResource } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
-import { Component, inject } from '@angular/core';
-import { ButtonComponent } from '@ods/system';
+import { Component, inject, OnInit } from '@angular/core';
+import { RoutingButtonComponent } from '@ods/component';
+import { Observable } from 'rxjs';
 
 @Component({
   selector: 'admin-statistik-container',
   templateUrl: './statistik-container.component.html',
   standalone: true,
-  imports: [CommonModule, ButtonComponent],
+  imports: [CommonModule, RoutingButtonComponent],
+  providers: [AggregationMappingService],
 })
-export class StatistikContainerComponent {
-  private readonly navigationService = inject(NavigationService);
+export class StatistikContainerComponent implements OnInit {
+  private service = inject(AggregationMappingService);
 
-  public navigateToStatistikFieldsForm(): void {
-    this.navigationService.navigate(ROUTES.STATISTIK_NEU);
+  public listStateResource$: Observable<StateResource<AggregationMappingListResource>>;
+
+  public readonly ROUTES = ROUTES;
+
+  ngOnInit(): void {
+    this.listStateResource$ = this.service.getList();
   }
 }
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.html
index cef302fc15f148000041c0c968f1ccbefc446e83..27805c87fe074bae41311083bc1aed20d5aaeaef 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.html
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.html
@@ -1,37 +1,29 @@
 <h2 class="heading-2" data-test-id="statistik-fields-form-header-text">Felder zur Auswertung hinzufügen</h2>
 
 <div class="flex max-w-4xl flex-col gap-4">
-  <ods-text-input
-    [fieldControl]="formEngineFormControl"
-    label="Formengine"
-    placeholder="Tragen Sie hier die Formengine des Formulars ein."
-    data-test-id="form-engine-input"
-  ></ods-text-input>
-
-  <ods-text-input
-    [fieldControl]="formIdFormControl"
-    label="FormID"
-    placeholder="Tragen Sie hier die FormID des Formulars ein."
-    data-test-id="form-id-input"
-  ></ods-text-input>
-
-  @for (dataFieldControl of dataFieldsFormControls; track $index) {
-    <ods-text-input
-      [fieldControl]="dataFieldControl"
-      label="Pfad des Datenfeldes"
-      placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
-      [attr.data-test-id]="'data-statistik-field-' + $index"
-    ></ods-text-input>
-  }
-
-  <ods-button text="Datenfeld hinzufügen" (clickEmitter)="addDataField()" dataTestId="add-data-field-button">
-    <ods-plus-icon icon class="fill-whitetext"/>
+  <form class="form flex-col" [formGroup]="formService.form" class="flex flex-col gap-4">
+    <div [formGroupName]="StatistikFieldsFormService.FIELD_FORM_IDENTIFIER" class="flex flex-col gap-4">
+      <ods-text-editor
+        [formControlName]="StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME"
+        label="Formengine"
+        placeholder="Tragen Sie hier die Formengine des Formulars ein."
+        data-test-id="form-engine-name-input"
+      ></ods-text-editor>
+      <ods-text-editor
+        [formControlName]="StatistikFieldsFormService.FIELD_FORM_ID"
+        label="FormID"
+        placeholder="Tragen Sie hier die FormID des Formulars ein."
+        data-test-id="form-id-input"
+      ></ods-text-editor>
+    </div>
+    <statistik-fields-form-mapping />
+  </form>
+  <ods-button text="Datenfeld hinzufügen" dataTestId="add-mapping-button" (clickEmitter)="formService.addMapping()">
+    <ods-plus-icon icon class="fill-whitetext" />
   </ods-button>
 
   <div class="mt-4 flex gap-4">
-    <ods-button text="Speichern" dataTestId="save-statistik-fields-button"></ods-button>
-    <ods-button text="Abbrechen" variant="outline" (clickEmitter)="onCancel()" dataTestId="cancel-statistik-fields-button">
-      <ods-close-icon icon class="fill-primary"/>
-    </ods-button>
+    <admin-save-button />
+    <admin-cancel-button [linkPath]="Routes.STATISTIK" />
   </div>
 </div>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.spec.ts
index 54502497cd68edcdec0876e2aad378126c2c28e3..a0154fd3137315cfbfd12187d70f0ffb43635df5 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.spec.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.spec.ts
@@ -1,86 +1,75 @@
-import { ROUTES } from '@admin-client/shared';
-import { NavigationService } from '@alfa-client/navigation-shared';
-import { existsAsHtmlElement, getElementComponentFromFixtureByCss, mock, Mock, triggerEvent } from '@alfa-client/test-utils';
+import { ADMIN_FORMSERVICE } from '@admin-client/shared';
+import { EMPTY_STRING } from '@alfa-client/tech-shared';
+import { dispatchEventFromFixture, existsAsHtmlElement, mock, Mock, MockEvent } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { FormBuilder } from '@angular/forms';
-import { TextInputComponent } from '@ods/system';
+import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
+import { TextEditorComponent } from '@ods/component';
+import { ButtonComponent, PlusIconComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
 import { getDataTestIdAttributeOf, getDataTestIdOf } from '../../../../../tech-shared/test/data-test';
+import { AdminCancelButtonComponent } from '../../../../shared/src/lib/admin-cancel-button/admin-cancel-button.component';
+import { AdminSaveButtonComponent } from '../../../../shared/src/lib/admin-save-button/admin-save-button.component';
 import { AdminStatistikFieldsFormComponent } from './admin-statistik-fields-form.component';
+import { AdminStatistikFieldsFormMappingComponent } from './statistik-fields-form-mapping/statistik-fields-form-mapping.component';
 import { StatistikFieldsFormService } from './statistik-fields.formservice';
 
 describe('AdminStatistikFieldsFormComponent', () => {
   let component: AdminStatistikFieldsFormComponent;
   let fixture: ComponentFixture<AdminStatistikFieldsFormComponent>;
 
-  const formEngineInputTestId: string = getDataTestIdOf('form-engine-input');
+  const formEngineNameInputTestId: string = getDataTestIdOf('form-engine-name-input');
   const formIdInputTestId: string = getDataTestIdOf('form-id-input');
-  const addDataFieldButtonTestId: string = getDataTestIdAttributeOf('add-data-field-button');
-  const saveButtonTestId: string = getDataTestIdAttributeOf('save-statistik-fields-button');
-  const cancelButtonTestId: string = getDataTestIdAttributeOf('cancel-statistik-fields-button');
-  const dataField1TestId: string = getDataTestIdOf('data-statistik-field-0');
+  const addMappingButton: string = getDataTestIdAttributeOf('add-mapping-button');
 
-  let formService: StatistikFieldsFormService;
-  let navigationService: Mock<NavigationService>;
+  const formBuilder: FormBuilder = new FormBuilder();
 
-  beforeEach(() => {
-    formService = new StatistikFieldsFormService(new FormBuilder());
-    navigationService = mock(NavigationService);
-  });
+  let formService: Mock<StatistikFieldsFormService>;
 
   beforeEach(async () => {
-    TestBed.overrideComponent(AdminStatistikFieldsFormComponent, {
-      set: {
-        providers: [
-          {
-            provide: StatistikFieldsFormService,
-            useValue: formService,
-          },
-          {
-            provide: NavigationService,
-            useValue: navigationService,
-          },
-        ],
-      },
+    const form: FormGroup = formBuilder.group({
+      [StatistikFieldsFormService.FIELD_FORM_IDENTIFIER]: formBuilder.group({
+        [StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
+        [StatistikFieldsFormService.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
+      }),
     });
 
+    formService = <any>{ ...mock(StatistikFieldsFormService), form };
+
     await TestBed.configureTestingModule({
-      imports: [AdminStatistikFieldsFormComponent],
-      providers: [{ provide: StatistikFieldsFormService, useValue: formService }],
-    }).compileComponents();
+      declarations: [
+        AdminStatistikFieldsFormComponent,
+        MockComponent(TextEditorComponent),
+        MockComponent(ButtonComponent),
+        MockComponent(PlusIconComponent),
+        MockComponent(AdminSaveButtonComponent),
+        MockComponent(AdminCancelButtonComponent),
+        MockComponent(AdminStatistikFieldsFormMappingComponent),
+      ],
+      imports: [ReactiveFormsModule],
+    })
+      .overrideComponent(AdminStatistikFieldsFormComponent, {
+        set: {
+          providers: [
+            {
+              provide: StatistikFieldsFormService,
+              useValue: formService,
+            },
+            {
+              provide: ADMIN_FORMSERVICE,
+              useValue: formService,
+            },
+          ],
+        },
+      })
+      .compileComponents();
 
     fixture = TestBed.createComponent(AdminStatistikFieldsFormComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
 
-  describe('component', () => {
-    it('should create', () => {
-      expect(component).toBeTruthy();
-    });
-
-    it('should set form controls', () => {
-      expect(component.formEngineFormControl).toBeDefined();
-      expect(component.formIdFormControl).toBeDefined();
-      expect(component.dataFieldsFormControls).toBeDefined();
-    });
-
-    describe('addDataField', () => {
-      it('should call form service', () => {
-        formService.addDataField = jest.fn();
-
-        component.addDataField();
-
-        expect(formService.addDataField).toHaveBeenCalled();
-      });
-    });
-
-    describe('onCancel', () => {
-      it('should call navigation service', () => {
-        component.onCancel();
-
-        expect(navigationService.navigate).toHaveBeenCalledWith(ROUTES.STATISTIK);
-      });
-    });
+  it('should create', () => {
+    expect(component).toBeTruthy();
   });
 
   describe('template', () => {
@@ -88,18 +77,7 @@ describe('AdminStatistikFieldsFormComponent', () => {
       it('should exists', () => {
         fixture.detectChanges();
 
-        existsAsHtmlElement(fixture, formEngineInputTestId);
-      });
-
-      it('should have been called with inputs', () => {
-        fixture.detectChanges();
-
-        const formEngineInput: TextInputComponent = getElementComponentFromFixtureByCss<TextInputComponent>(
-          fixture,
-          formEngineInputTestId,
-        );
-
-        expect(formEngineInput.fieldControl).toEqual(component.formEngineFormControl);
+        existsAsHtmlElement(fixture, formEngineNameInputTestId);
       });
     });
 
@@ -109,91 +87,23 @@ describe('AdminStatistikFieldsFormComponent', () => {
 
         existsAsHtmlElement(fixture, formIdInputTestId);
       });
-
-      it('should have been called with inputs', () => {
-        fixture.detectChanges();
-
-        const formIdInput: TextInputComponent = getElementComponentFromFixtureByCss<TextInputComponent>(
-          fixture,
-          formIdInputTestId,
-        );
-
-        expect(formIdInput.fieldControl).toEqual(component.formIdFormControl);
-      });
-    });
-
-    describe('data field input', () => {
-      it('should exists', () => {
-        fixture.detectChanges();
-
-        existsAsHtmlElement(fixture, dataField1TestId);
-      });
-
-      it('should have been called with inputs', () => {
-        fixture.detectChanges();
-
-        const dataFieldInput: TextInputComponent = getElementComponentFromFixtureByCss<TextInputComponent>(
-          fixture,
-          dataField1TestId,
-        );
-
-        expect(dataFieldInput.fieldControl).toEqual(component.dataFieldsFormControls[0]);
-      });
-    });
-
-    describe('add data field button', () => {
-      it('should exists', () => {
-        fixture.detectChanges();
-
-        existsAsHtmlElement(fixture, addDataFieldButtonTestId);
-      });
-
-      describe('output', () => {
-        describe('clickEmitter', () => {
-          it('should call handler', () => {
-            fixture.detectChanges();
-            component.addDataField = jest.fn();
-
-            triggerEvent({
-              fixture,
-              elementSelector: addDataFieldButtonTestId,
-              name: 'clickEmitter',
-            });
-
-            expect(component.addDataField).toHaveBeenCalled();
-          });
-        });
-      });
-    });
-
-    describe('save button', () => {
-      it('should exists', () => {
-        fixture.detectChanges();
-
-        existsAsHtmlElement(fixture, saveButtonTestId);
-      });
     });
 
-    describe('cancel button', () => {
+    describe('add mapping button', () => {
       it('should exists', () => {
         fixture.detectChanges();
 
-        existsAsHtmlElement(fixture, cancelButtonTestId);
+        existsAsHtmlElement(fixture, addMappingButton);
       });
 
       describe('output', () => {
         describe('clickEmitter', () => {
-          it('should call handler', () => {
-            component.onCancel = jest.fn();
+          it('should call formService', () => {
             fixture.detectChanges();
 
-            triggerEvent({
-              fixture,
-              elementSelector: cancelButtonTestId,
-              name: 'clickEmitter',
-            });
+            dispatchEventFromFixture(fixture, addMappingButton, MockEvent.CLICK);
 
-            expect(component.onCancel).toHaveBeenCalled();
+            expect(formService.addMapping).toHaveBeenCalled();
           });
         });
       });
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.ts
index 59d083f34a2f5f727734c29c02f6b8de13c7d2d6..0298196202e623a3d080468c792f3c1c800a8750 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/admin-statistik-fields-form.component.ts
@@ -1,37 +1,30 @@
-import { ROUTES } from '@admin-client/shared';
-import { NavigationService } from '@alfa-client/navigation-shared';
-import { CommonModule } from '@angular/common';
+import { ADMIN_FORMSERVICE, AdminCancelButtonComponent, AdminSaveButtonComponent, ROUTES } from '@admin-client/shared';
 import { Component, inject } from '@angular/core';
-import { FormArray, FormControl, ReactiveFormsModule } from '@angular/forms';
-import { ButtonComponent, CloseIconComponent, PlusIconComponent, TextInputComponent } from '@ods/system';
+import { ReactiveFormsModule } from '@angular/forms';
+import { TextEditorComponent } from '@ods/component';
+import { ButtonComponent, DeleteIconComponent, PlusIconComponent } from '@ods/system';
+import { AdminStatistikFieldsFormMappingComponent } from './statistik-fields-form-mapping/statistik-fields-form-mapping.component';
 import { StatistikFieldsFormService } from './statistik-fields.formservice';
 
 @Component({
   selector: 'admin-statistik-fields-form',
-  standalone: true,
-  imports: [CommonModule, TextInputComponent, ButtonComponent, CloseIconComponent, ReactiveFormsModule, PlusIconComponent],
-  providers: [StatistikFieldsFormService],
   templateUrl: './admin-statistik-fields-form.component.html',
+  standalone: true,
+  imports: [
+    ButtonComponent,
+    PlusIconComponent,
+    ReactiveFormsModule,
+    TextEditorComponent,
+    DeleteIconComponent,
+    AdminSaveButtonComponent,
+    AdminCancelButtonComponent,
+    AdminStatistikFieldsFormMappingComponent,
+  ],
+  providers: [{ provide: ADMIN_FORMSERVICE, useClass: StatistikFieldsFormService }],
 })
 export class AdminStatistikFieldsFormComponent {
-  private readonly formService = inject(StatistikFieldsFormService);
-  private readonly navigationService = inject(NavigationService);
-
-  public readonly formEngineFormControl: FormControl = this.formService.form.controls[
-    StatistikFieldsFormService.FIELD_FORM_ENGINE
-  ] as FormControl;
-  public readonly formIdFormControl: FormControl = this.formService.form.controls[
-    StatistikFieldsFormService.FIELD_FORM_ID
-  ] as FormControl;
-  public readonly dataFieldsFormControls: FormControl[] = (
-    this.formService.form.controls[StatistikFieldsFormService.FIELD_DATA_FIELDS] as FormArray
-  ).controls as FormControl[];
-
-  public addDataField(): void {
-    this.formService.addDataField();
-  }
+  public readonly formService = <StatistikFieldsFormService>inject(ADMIN_FORMSERVICE);
 
-  public onCancel(): void {
-    this.navigationService.navigate(ROUTES.STATISTIK);
-  }
+  public readonly StatistikFieldsFormService = StatistikFieldsFormService;
+  public readonly Routes = ROUTES;
 }
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.html b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..2ce86b545b1039b795911cf172f154b9e2b97871
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.html
@@ -0,0 +1,27 @@
+<form [formGroup]="formService.form">
+  <div class="flex flex-col gap-4" [formArrayName]="StatistikFieldsFormService.FIELD_MAPPINGS">
+    <div
+      *ngFor="let mappingControl of formService.mappings.controls; let i = index"
+      [formGroupName]="i"
+      class="flex w-full gap-2"
+    >
+      <ods-text-editor
+        class="flex-1"
+        formControlName="sourcePath"
+        label="Pfad des Datenfeldes"
+        placeholder="Tragen Sie hier den gesamten Pfad des Datenfeldes ein, das Sie auswerten möchten."
+        [attr.data-test-id]="'mapping-field-' + i"
+      ></ods-text-editor>
+      <ods-button
+        class="self-end"
+        variant="ghost"
+        size="fit"
+        destructive="true"
+        (clickEmitter)="formService.removeMapping(i)"
+        [dataTestId]="'remove-mapping-button-' + i"
+      >
+        <ods-delete-icon icon />
+      </ods-button>
+    </div>
+  </div>
+</form>
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..61cd006e429951cde3657be7688b30063cc2e6eb
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.spec.ts
@@ -0,0 +1,90 @@
+import { ADMIN_FORMSERVICE } from '@admin-client/shared';
+import { EMPTY_STRING } from '@alfa-client/tech-shared';
+import { dispatchEventFromFixture, existsAsHtmlElement, mock, Mock, MockEvent, mockGetValue } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
+import { TextEditorComponent } from '@ods/component';
+import { ButtonComponent, DeleteIconComponent } from '@ods/system';
+import { getDataTestIdOf, getDynamicDataTestIdAttributOf } from 'libs/tech-shared/test/data-test';
+import { MockComponent } from 'ng-mocks';
+import { StatistikFieldsFormService } from '../statistik-fields.formservice';
+import { AdminStatistikFieldsFormMappingComponent } from './statistik-fields-form-mapping.component';
+
+describe('AdminStatistikFieldsFormMappingComponent', () => {
+  let component: AdminStatistikFieldsFormMappingComponent;
+  let fixture: ComponentFixture<AdminStatistikFieldsFormMappingComponent>;
+
+  const mappingField: string = getDataTestIdOf('mapping-field-0');
+  const removeMappingButton: string = getDynamicDataTestIdAttributOf('remove-mapping-button-0');
+
+  const formBuilder: FormBuilder = new FormBuilder();
+
+  let formService: Mock<StatistikFieldsFormService>;
+
+  beforeEach(async () => {
+    const form: FormGroup = formBuilder.group({
+      [StatistikFieldsFormService.FIELD_MAPPINGS]: formBuilder.array([
+        new FormGroup({ sourcePath: new FormControl(EMPTY_STRING) }),
+      ]),
+    });
+
+    formService = <any>{
+      ...mock(StatistikFieldsFormService),
+      form,
+      addMapping: jest.fn(),
+      removeMapping: jest.fn(),
+    };
+
+    mockGetValue(
+      formService,
+      StatistikFieldsFormService.FIELD_MAPPINGS,
+      form.controls[StatistikFieldsFormService.FIELD_MAPPINGS],
+    );
+
+    await TestBed.configureTestingModule({
+      declarations: [
+        AdminStatistikFieldsFormMappingComponent,
+        MockComponent(TextEditorComponent),
+        MockComponent(ButtonComponent),
+        MockComponent(DeleteIconComponent),
+      ],
+      imports: [ReactiveFormsModule],
+      providers: [
+        {
+          provide: StatistikFieldsFormService,
+          useValue: formService,
+        },
+        {
+          provide: ADMIN_FORMSERVICE,
+          useValue: formService,
+        },
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(AdminStatistikFieldsFormMappingComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('template', () => {
+    describe('mapping input', () => {
+      it('should exists', () => {
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, mappingField);
+      });
+    });
+
+    describe('remove mapping button', () => {
+      it('should call formservice', () => {
+        dispatchEventFromFixture(fixture, removeMappingButton, MockEvent.CLICK);
+
+        expect(formService.removeMapping).toHaveBeenCalledWith(0);
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..48bc3eaddd2a2fe51b983939dd8920b02e7f8dae
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields-form-mapping/statistik-fields-form-mapping.component.ts
@@ -0,0 +1,29 @@
+import { ADMIN_FORMSERVICE, AdminCancelButtonComponent, AdminSaveButtonComponent, ROUTES } from '@admin-client/shared';
+import { CommonModule } from '@angular/common';
+import { Component, inject } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { TextEditorComponent } from '@ods/component';
+import { ButtonComponent, DeleteIconComponent, PlusIconComponent } from '@ods/system';
+import { StatistikFieldsFormService } from '../statistik-fields.formservice';
+
+@Component({
+  selector: 'statistik-fields-form-mapping',
+  templateUrl: './statistik-fields-form-mapping.component.html',
+  standalone: true,
+  imports: [
+    CommonModule,
+    ButtonComponent,
+    PlusIconComponent,
+    ReactiveFormsModule,
+    TextEditorComponent,
+    DeleteIconComponent,
+    AdminSaveButtonComponent,
+    AdminCancelButtonComponent,
+  ],
+})
+export class AdminStatistikFieldsFormMappingComponent {
+  public readonly formService = <StatistikFieldsFormService>inject(ADMIN_FORMSERVICE);
+
+  public readonly StatistikFieldsFormService = StatistikFieldsFormService;
+  public readonly Routes = ROUTES;
+}
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..58a2273cb692762c4f930e583c8c49f210099517
--- /dev/null
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.spec.ts
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { AggregationMappingResource, AggregationMappingService } from '@admin-client/reporting-shared';
+import { EMPTY_STRING, StateResource, createStateResource } from '@alfa-client/tech-shared';
+import { Mock, mock } from '@alfa-client/test-utils';
+import { TestBed } from '@angular/core/testing';
+import { FormArray, FormControl, FormGroup } from '@angular/forms';
+import { createAggregationMapping, createAggregationMappingResource } from 'libs/admin/reporting-shared/test/aggregation-mapping';
+import { of } from 'rxjs';
+import { StatistikFieldsFormService } from './statistik-fields.formservice';
+
+describe('StatistikFieldsFormService', () => {
+  let formService: StatistikFieldsFormService;
+
+  let service: Mock<AggregationMappingService>;
+
+  beforeEach(() => {
+    service = mock(AggregationMappingService);
+
+    TestBed.configureTestingModule({
+      providers: [StatistikFieldsFormService, { provide: AggregationMappingService, useValue: service }],
+    });
+
+    formService = TestBed.inject(StatistikFieldsFormService);
+  });
+
+  it('should create', () => {
+    expect(formService).toBeTruthy();
+  });
+
+  describe('on do submit', () => {
+    const stateResource: StateResource<AggregationMappingResource> = createStateResource(createAggregationMappingResource());
+
+    beforeEach(() => {
+      service.create.mockReturnValue(of(stateResource));
+    });
+
+    it('should call service', () => {
+      formService.form = <any>createAggregationMapping();
+
+      formService.submit();
+
+      expect(service.create).toHaveBeenCalledWith(formService.form.value);
+    });
+  });
+
+  describe('add mapping', () => {
+    it('should add mapping control', () => {
+      formService.addMapping();
+
+      const mappingFormArray: FormArray = <FormArray>formService.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS];
+      expect(mappingFormArray).toHaveLength(2);
+      expect(mappingFormArray.controls[0].value).toEqual({ sourcePath: EMPTY_STRING });
+    });
+  });
+
+  describe('remove mapping', () => {
+    it('should remove mapping control', () => {
+      (<FormArray>formService.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS]).push(
+        new FormGroup({ sourcePath: new FormControl('controlToRemove') }),
+      );
+
+      formService.removeMapping(1);
+
+      const mappingFormArray: FormArray = <FormArray>formService.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS];
+      expect(mappingFormArray).toHaveLength(1);
+      expect(mappingFormArray.controls[0].value).toEqual({ sourcePath: EMPTY_STRING });
+    });
+  });
+
+  describe('get mappings', () => {
+    it('should return mappings as array', () => {
+      const mappings: FormArray = formService.mappings;
+
+      expect(mappings).toHaveLength(1);
+      expect(mappings.controls[0].value).toEqual({ sourcePath: EMPTY_STRING });
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
index 229a7147d1b785c937d46c45c3ae65070a8b2608..1b746e12f42b44cc1261ce6de543380ea61d9ec4 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
@@ -1,32 +1,50 @@
+import { AggregationMappingResource, AggregationMappingService } from '@admin-client/reporting-shared';
 import { AbstractFormService, EMPTY_STRING, StateResource } from '@alfa-client/tech-shared';
-import { Injectable } from '@angular/core';
-import { FormArray, FormControl, UntypedFormGroup } from '@angular/forms';
-import { Resource } from '@ngxp/rest';
-import { EMPTY, Observable } from 'rxjs';
+import { inject, Injectable } from '@angular/core';
+import { FormArray, FormControl, FormGroup, UntypedFormGroup } from '@angular/forms';
+import { Observable } from 'rxjs';
 
 @Injectable()
-export class StatistikFieldsFormService extends AbstractFormService<Resource> {
-  public static readonly FIELD_FORM_ENGINE: string = 'formEngine';
+export class StatistikFieldsFormService extends AbstractFormService<AggregationMappingResource> {
+  private service = inject(AggregationMappingService);
+
+  public static readonly FIELD_FORM_IDENTIFIER: string = 'formIdentifier';
+  public static readonly FIELD_FORM_ENGINE_NAME: string = 'formEngineName';
   public static readonly FIELD_FORM_ID: string = 'formId';
-  public static readonly FIELD_DATA_FIELDS: string = 'dataFields';
+
+  public static readonly FIELD_MAPPINGS: string = 'mappings';
 
   protected initForm(): UntypedFormGroup {
     return this.formBuilder.group({
-      [StatistikFieldsFormService.FIELD_FORM_ENGINE]: new FormControl(EMPTY_STRING),
-      [StatistikFieldsFormService.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
-      [StatistikFieldsFormService.FIELD_DATA_FIELDS]: new FormArray([new FormControl(EMPTY_STRING)]),
+      [StatistikFieldsFormService.FIELD_FORM_IDENTIFIER]: this.formBuilder.group({
+        [StatistikFieldsFormService.FIELD_FORM_ENGINE_NAME]: new FormControl(EMPTY_STRING),
+        [StatistikFieldsFormService.FIELD_FORM_ID]: new FormControl(EMPTY_STRING),
+      }),
+      [StatistikFieldsFormService.FIELD_MAPPINGS]: new FormArray([this.createArrayControl()]),
     });
   }
 
-  protected doSubmit(): Observable<StateResource<Resource>> {
-    return EMPTY;
+  protected doSubmit(): Observable<StateResource<AggregationMappingResource>> {
+    return this.service.create(this.getFormValue());
   }
 
   protected getPathPrefix(): string {
     return 'settingBody';
   }
 
-  public addDataField(): void {
-    (this.form.controls[StatistikFieldsFormService.FIELD_DATA_FIELDS] as FormArray).push(new FormControl(EMPTY_STRING));
+  public addMapping(): void {
+    this.mappings.push(this.createArrayControl());
+  }
+
+  private createArrayControl(): FormGroup {
+    return new FormGroup({ sourcePath: new FormControl(EMPTY_STRING) });
+  }
+
+  public removeMapping(index: number): void {
+    this.mappings.removeAt(index);
+  }
+
+  public get mappings(): FormArray {
+    return this.form.controls[StatistikFieldsFormService.FIELD_MAPPINGS] as FormArray;
   }
 }
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.spec.ts b/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.spec.ts
index 92031a721d4ebb9e879f75308b003848c82d6cc0..8e823be03c1f064fe2cd152da724bb3e0fcdc001 100644
--- a/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.spec.ts
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.spec.ts
@@ -438,7 +438,7 @@ describe('UserFormService', () => {
     });
 
     it('should return bauamt group when active', () => {
-      const organisationsEinheit: AdminOrganisationsEinheit = { name: 'bauamt' };
+      const organisationsEinheit: AdminOrganisationsEinheit = createAdminOrganisationsEinheit();
       organisationsEinheitenGroup.addControl(organisationsEinheit.name, new FormControl(true));
 
       const result: string[] = formService._getActiveOrganisationsEinheiten();
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.html b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.html
index bffb14da6bda5e9ae083f25f445a12b3d6854ae5..153e3e19deecd0653b83ae9fc7e516f85b6a8716 100644
--- a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.html
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.html
@@ -24,9 +24,9 @@
 
 -->
 <h1 class="heading-1 mb-4">Benutzer & Rollen</h1>
-<ods-routing-button [linkPath]="ROUTES.BENUTZER_NEU" text="Benutzer hinzufügen" class="mb-4" dataTestId="add-user-button" />
+<ods-routing-button [linkPath]="ROUTES.BENUTZER_NEU" text="Benutzer hinzufügen" class="mb-4 w-fit" dataTestId="add-user-button" />
 <ods-list>
   @for (user of usersStateResource.resource; track $index) {
     <admin-user [user]="user" class="block w-full" />
   }
-</ods-list>
\ No newline at end of file
+</ods-list>
diff --git a/alfa-client/libs/authentication/src/lib/http-unauthorized.interceptor.spec.ts b/alfa-client/libs/authentication/src/lib/http-unauthorized.interceptor.spec.ts
index bf426ac9299c13c5440929e9b54d276e35f6be8e..8e32931929aab5f151b00cc4b14b3aaacc5c9142 100644
--- a/alfa-client/libs/authentication/src/lib/http-unauthorized.interceptor.spec.ts
+++ b/alfa-client/libs/authentication/src/lib/http-unauthorized.interceptor.spec.ts
@@ -22,12 +22,12 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Mock, mock } from '@alfa-client/test-utils';
+import { HttpErrorResponse, HttpHandler, HttpRequest } from '@angular/common/http';
 import { TestBed } from '@angular/core/testing';
 import { MatDialogModule } from '@angular/material/dialog';
-import { HttpUnauthorizedInterceptor } from './http-unauthorized.interceptor';
-import { HttpErrorResponse, HttpHandler, HttpRequest } from '@angular/common/http';
 import { Subject, isEmpty } from 'rxjs';
 import { AuthenticationService } from './authentication.service';
+import { HttpUnauthorizedInterceptor } from './http-unauthorized.interceptor';
 
 describe('HttpUnauthorizedInterceptor', () => {
   let interceptor: HttpUnauthorizedInterceptor;
@@ -96,7 +96,7 @@ describe('HttpUnauthorizedInterceptor', () => {
     it('should rethrow error if not unauthorized status', () => {
       const anyError: any = new HttpErrorResponse({ status: 500 });
 
-      expect(() => interceptor.handleError(anyError)).toThrowError();
+      expect(() => interceptor.handleError(anyError)).toThrow();
     });
   });
 });
diff --git a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.spec.ts
index 5a6c54ccfacecba703c2c89e30cc7fac777ec114..35a608b28271ff395579092f156f23ad0fc1f445 100644
--- a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.spec.ts
+++ b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.spec.ts
@@ -22,10 +22,10 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { CommandOrder, CommandResource } from '@alfa-client/command-shared';
-import { ApiError } from '@alfa-client/tech-shared';
+import { ApiError, createEmptyStateResource } from '@alfa-client/tech-shared';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { Action } from '@ngrx/store';
-import { createCommandResource } from 'libs/command-shared/test/command';
+import { createCommandResource, createSuccessfullyDoneCommandStateResource } from 'libs/command-shared/test/command';
 import { createApiError } from 'libs/tech-shared/test/error';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { BescheidState, initialState, reducer } from './bescheid.reducer';
@@ -55,7 +55,21 @@ describe('Bescheid Reducer', () => {
 
         const state: BescheidState = reducer(initialState, action);
 
-        expect(state.bescheidCommand.loading).toBeTruthy();
+        expect(state.bescheidCommand).toEqual(createEmptyStateResource(true));
+      });
+
+      it('should replace state resource with loading', () => {
+        const initialState: BescheidState = { bescheidCommand: createSuccessfullyDoneCommandStateResource() };
+        const resource: VorgangWithEingangResource = createVorgangWithEingangResource();
+        const action: Action = CommandActions.createCommand({
+          resource,
+          linkRel: VorgangWithEingangLinkRel.CREATE_BESCHEID_DRAFT,
+          command: { ...createCommandResource(), order: CommandOrder.CREATE_BESCHEID },
+        });
+
+        const state: BescheidState = reducer(initialState, action);
+
+        expect(state.bescheidCommand).toEqual(createEmptyStateResource(true));
       });
     });
 
diff --git a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.ts b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.ts
index 0e804a1d07360070a1b3eaab5411a9c841c0e473..870d54c9df087e333cb44249f93ab9f133562396 100644
--- a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.ts
+++ b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.ts
@@ -21,19 +21,8 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import {
-  CommandProps,
-  CommandResource,
-  CreateCommandFailureProps,
-  CreateCommandProps,
-} from '@alfa-client/command-shared';
-import {
-  ApiError,
-  StateResource,
-  createEmptyStateResource,
-  createErrorStateResource,
-  createStateResource,
-} from '@alfa-client/tech-shared';
+import { CommandProps, CommandResource, CreateCommandFailureProps, CreateCommandProps } from '@alfa-client/command-shared';
+import { ApiError, createEmptyStateResource, createErrorStateResource, createStateResource, StateResource, } from '@alfa-client/tech-shared';
 import { HttpErrorResponse } from '@angular/common/http';
 import { Action, ActionReducer, createReducer, on } from '@ngrx/store';
 import { isCreateBescheidCommand } from '../bescheid.util';
@@ -56,35 +45,22 @@ export const initialState: BescheidState = {
 
 const bescheidReducer: ActionReducer<BescheidState, Action> = createReducer(
   initialState,
-  on(
-    CommandActions.createCommand,
-    (state: BescheidState, props: CreateCommandProps): BescheidState => {
-      return isCreateBescheidCommand(props.command.order) ?
-          { ...state, bescheidCommand: { ...state.bescheidCommand, loading: true } }
-        : state;
-    },
-  ),
-  on(
-    CommandActions.createCommandSuccess,
-    (state: BescheidState, props: CommandProps): BescheidState => {
-      return isCreateBescheidCommand(props.command.order) ?
-          { ...state, bescheidCommand: createStateResource(props.command) }
-        : state;
-    },
-  ),
-  on(
-    CommandActions.createCommandFailure,
-    (state: BescheidState, props: CreateCommandFailureProps): BescheidState => {
-      return isCreateBescheidCommand(props.command.order) ?
-          {
-            ...state,
-            bescheidCommand: createErrorStateResource(
-              <ApiError>(<HttpErrorResponse>props.error).error,
-            ),
-          }
-        : state;
-    },
-  ),
+  on(CommandActions.createCommand, (state: BescheidState, props: CreateCommandProps): BescheidState => {
+    return isCreateBescheidCommand(props.command.order) ? { ...state, bescheidCommand: createEmptyStateResource(true) } : state;
+  }),
+  on(CommandActions.createCommandSuccess, (state: BescheidState, props: CommandProps): BescheidState => {
+    return isCreateBescheidCommand(props.command.order) ?
+        { ...state, bescheidCommand: createStateResource(props.command) }
+      : state;
+  }),
+  on(CommandActions.createCommandFailure, (state: BescheidState, props: CreateCommandFailureProps): BescheidState => {
+    return isCreateBescheidCommand(props.command.order) ?
+        {
+          ...state,
+          bescheidCommand: createErrorStateResource(<ApiError>(<HttpErrorResponse>props.error).error),
+        }
+      : state;
+  }),
 );
 
 export function reducer(state: BescheidState, action: Action): BescheidState {
diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid-resource-service.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid-resource-service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ab266d7734797b1e6fdf8b845ba8793696893a8e
--- /dev/null
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid-resource-service.ts
@@ -0,0 +1,25 @@
+import { CommandOrder, CommandResourceService, CommandService } from '@alfa-client/command-shared';
+import { ResourceRepository, ResourceServiceConfig } from '@alfa-client/tech-shared';
+import { VorgangService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { BescheidLinkRel } from './bescheid.linkrel';
+import { BescheidResource } from './bescheid.model';
+
+export class BescheidResourceService extends CommandResourceService<VorgangWithEingangResource, BescheidResource> {}
+
+export function createBescheidResourceService(
+  repository: ResourceRepository,
+  commandService: CommandService,
+  vorgangService: VorgangService,
+): CommandResourceService<VorgangWithEingangResource, BescheidResource> {
+  console.info('Create Bescheid Resource Service');
+  return new CommandResourceService(buildConfig(vorgangService), repository, commandService);
+}
+
+function buildConfig(vorgangService: VorgangService): ResourceServiceConfig<VorgangWithEingangResource> {
+  return {
+    resource: vorgangService.getVorgangWithEingang(),
+    getLinkRel: VorgangWithEingangLinkRel.BESCHEID_DRAFT,
+    delete: { linkRel: BescheidLinkRel.DELETE, order: CommandOrder.DELETE_BESCHEID },
+    edit: { linkRel: BescheidLinkRel.UPDATE, order: CommandOrder.UPDATE_BESCHEID },
+  };
+}
diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.model.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.model.ts
index b661c130f51fb8e2e2239a68a525b6f25d24c598..6fee5ec006a52da9172c6491cc0bf38c4a0ba0df 100644
--- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.model.ts
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.model.ts
@@ -21,8 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { HttpError, ListResource } from '@alfa-client/tech-shared';
-import { Resource } from '@ngxp/rest';
+import { BinaryFileResource } from '@alfa-client/binary-file-shared';
+import { CommandResource } from '@alfa-client/command-shared';
+import { createEmptyStateResource, HttpError, ListResource, StateResource } from '@alfa-client/tech-shared';
+import { Resource, ResourceUri } from '@ngxp/rest';
 
 export enum BescheidStatus {
   DRAFT = 'DRAFT',
@@ -64,3 +66,55 @@ export enum BescheidWizardStep {
 export interface BescheidWizardDialogResult {
   reloadVorgang: boolean;
 }
+
+export interface BescheidDocument {
+  upload: UploadFileInProgress;
+  create: StateResource<CommandResource>;
+  documentUri?: ResourceUri;
+  resource?: BinaryFileResource;
+}
+
+export function createEmptyBescheidDocument(): BescheidDocument {
+  return {
+    upload: createEmptyUploadInProgress(),
+    create: createEmptyStateResource(),
+  };
+}
+
+export interface BescheidAttachments {
+  upload: UploadFileInProgress;
+  uploadStateResource: StateResource<BinaryFileResource>;
+  items: BinaryFileResource[];
+}
+
+export function createEmptyBescheidAttachments(): BescheidAttachments {
+  return {
+    upload: createEmptyUploadInProgress(),
+    uploadStateResource: createEmptyStateResource(),
+    items: [],
+  };
+}
+
+export function createEmptyUploadInProgress(): UploadFileInProgress {
+  return {
+    loading: false,
+    fileName: null,
+  };
+}
+
+export interface Wizard {
+  activeStep: BescheidWizardStep;
+  sendBy: BescheidSendBy;
+  canBeSend: boolean;
+  bescheidCreated: boolean;
+  empfaenger?: string;
+}
+
+export function createInitialWizard(): Wizard {
+  return {
+    activeStep: BescheidWizardStep.AntragBescheiden,
+    sendBy: BescheidSendBy.NACHRICHT,
+    canBeSend: true,
+    bescheidCreated: false,
+  };
+}
diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
index d799453d615d41bd0e21b7940461d59c7131adf0..ab845cf6b4f7e3156ebb7a940e418780e9a410d2 100644
--- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
@@ -23,6 +23,7 @@
  */
 import { BinaryFileListResource, BinaryFileResource, BinaryFileService } from '@alfa-client/binary-file-shared';
 import { CommandOrder, CommandResource, CommandService, CreateCommandProps } from '@alfa-client/command-shared';
+import { PostfachService } from '@alfa-client/postfach-shared';
 import {
   ApiError,
   EMPTY_ARRAY,
@@ -80,7 +81,6 @@ import { BescheidService } from './bescheid.service';
 import { DocumentLinkRel } from './document.linkrel';
 import { DocumentResource } from './document.model';
 
-import { PostfachService } from '@alfa-client/postfach-shared';
 import * as DateUtil from '../../../tech-shared/src/lib/date.util';
 import * as BescheidUtil from './bescheid.util';
 
@@ -89,7 +89,7 @@ describe('BescheidService', () => {
 
   let facade: Mock<BescheidFacade>;
   let vorgangService: Mock<VorgangService>;
-  let resourceRepository: Mock<ResourceRepository>;
+  let resourceRepository: Mock<ResourceRepository<BescheidResource>>;
   let commandService: Mock<CommandService>;
   let vorgangCommandService: Mock<VorgangCommandService>;
   let binaryFileService: Mock<BinaryFileService>;
diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
index 3426c36b0868b332b4324580b8eadf6fcbab37f0..7b8a2f737d688302a3a9f30e218b126a9fad285e 100644
--- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
@@ -124,7 +124,7 @@ export class BescheidService {
     private readonly commandService: CommandService,
     private readonly vorgangCommandService: VorgangCommandService,
     private readonly binaryFileService: BinaryFileService,
-    private readonly repository: ResourceRepository,
+    private readonly repository: ResourceRepository<BescheidResource>,
     private readonly postfachService: PostfachService,
   ) {
     this.bescheidResourceService = new CommandResourceService(
@@ -132,7 +132,11 @@ export class BescheidService {
       repository,
       this.commandService,
     );
-    this.bescheidListResourceService = new ResourceListService(this.buildBescheidListServiceConfig(), repository);
+    this.bescheidListResourceService = new ResourceListService<
+      VorgangWithEingangResource,
+      BescheidListResource,
+      BescheidResource
+    >(this.buildBescheidListServiceConfig(), repository);
   }
 
   public getActiveStep(): Observable<BescheidWizardStep> {
diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid2.service.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid2.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..977ca30abc3c3200416749391b488b397e75731c
--- /dev/null
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid2.service.spec.ts
@@ -0,0 +1,975 @@
+/*
+ * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { BinaryFileListLinkRel, BinaryFileListResource, BinaryFileResource, BinaryFileService, } from '@alfa-client/binary-file-shared';
+import { CommandOrder, CommandResource, CommandResourceService, CommandService, CreateCommandProps, getEffectedResourceUrl, } from '@alfa-client/command-shared';
+import { PostfachService } from '@alfa-client/postfach-shared';
+import { createEmptyStateResource, createErrorStateResource, createLoadingStateResource, createStateResource, EMPTY_STRING, getEmbeddedResources, StateResource, } from '@alfa-client/tech-shared';
+import { Mock, mock } from '@alfa-client/test-utils';
+import { VorgangCommandService, VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { TestBed } from '@angular/core/testing';
+import { faker } from '@faker-js/faker';
+import { getUrl, LinkRel, ResourceUri } from '@ngxp/rest';
+import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel';
+import { createProblemDetail } from 'libs/tech-shared/test/error';
+import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
+import { EMPTY, Observable, of } from 'rxjs';
+import { createBinaryFileListResource, createBinaryFileResource } from '../../../binary-file-shared/test/binary-file';
+import { createCommandErrorStateResource, createCommandResource, createCommandStateResource, createCreateCommandProps, createSuccessfullyDoneCommandStateResource, } from '../../../command-shared/test/command';
+import { ResourceRepository } from '../../../tech-shared/src/lib/resource/resource.repository';
+import { createFile } from '../../../tech-shared/test/file';
+import { singleCold, singleColdCompleted } from '../../../tech-shared/test/marbles';
+import { createBescheid, createBescheidAttachments, createBescheidDocument, createBescheidResource } from '../test/bescheid';
+import { createDocumentResource } from '../test/document';
+import { BescheidFacade } from './+state/bescheid.facade';
+import { BescheidResourceService } from './bescheid-resource-service';
+import { BescheidLinkRel } from './bescheid.linkrel';
+import { Bescheid, BescheidAttachments, BescheidDocument, BescheidResource, BescheidWizardStep, createEmptyBescheidAttachments, createEmptyBescheidDocument, createEmptyUploadInProgress, createInitialWizard, } from './bescheid.model';
+import { BescheidService2 } from './bescheid2.service';
+import { DocumentLinkRel } from './document.linkrel';
+import { DocumentResource } from './document.model';
+
+import { expect } from '@jest/globals';
+import * as BescheidUtil from './bescheid.util';
+
+describe('BescheidService', () => {
+  let service: BescheidService2;
+
+  let facade: Mock<BescheidFacade>;
+  let vorgangService: Mock<VorgangService>;
+  let resourceRepository: Mock<ResourceRepository>;
+  let commandService: Mock<CommandService>;
+  let vorgangCommandService: Mock<VorgangCommandService>;
+  let binaryFileService: Mock<BinaryFileService>;
+  let postfachService: Mock<PostfachService>;
+  let bescheidResourceService: Mock<BescheidResourceService>;
+
+  const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource();
+  const vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource> =
+    createStateResource(vorgangWithEingangResource);
+  const bescheidResource: BescheidResource = createBescheidResource();
+  const commandStateResource: StateResource<CommandResource> = createCommandStateResource();
+
+  beforeEach(() => {
+    facade = mock(BescheidFacade);
+    resourceRepository = mock(ResourceRepository);
+    commandService = mock(CommandService);
+    vorgangCommandService = mock(VorgangCommandService);
+    vorgangService = mock(VorgangService);
+    vorgangService.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource));
+    binaryFileService = mock(BinaryFileService);
+    postfachService = mock(PostfachService);
+    bescheidResourceService = mock(CommandResourceService);
+
+    TestBed.configureTestingModule({
+      providers: [
+        { provide: BescheidFacade, useValue: facade },
+        { provide: VorgangService, useValue: vorgangService },
+        { provide: ResourceRepository, useValue: resourceRepository },
+        { provide: CommandService, useValue: commandService },
+        { provide: VorgangCommandService, useValue: vorgangCommandService },
+        { provide: BinaryFileService, useValue: binaryFileService },
+        {
+          provide: PostfachService,
+          useValue: postfachService,
+        },
+        { provide: BescheidResourceService, useValue: bescheidResourceService },
+        BescheidService2,
+      ],
+    });
+
+    service = TestBed.inject(BescheidService2);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+
+  describe('init', () => {
+    it('should init state', () => {
+      service.setActiveStep(2);
+
+      service.init();
+
+      expect(service.getWizard()).toBeObservable(singleCold(createInitialWizard()));
+      expect(service.getActiveStep()).toBeObservable(singleCold(BescheidWizardStep.AntragBescheiden));
+      expect(service.getBescheidCreated()).toBeObservable(singleCold(false));
+      expect(service.getBescheidDocument()).toBeObservable(singleCold(createEmptyBescheidDocument()));
+      expect(service.getAttachments()).toBeObservable(singleCold(createEmptyBescheidAttachments()));
+    });
+  });
+
+  describe('exit', () => {
+    it('should reload postfach list', () => {
+      service.exit();
+
+      expect(postfachService.setPostfachMailOnReload).toHaveBeenCalled();
+    });
+  });
+
+  describe('skipBescheidCreation', () => {
+    beforeEach(() => {
+      service.deleteBescheidAndCompleteVorgang = jest.fn().mockReturnValue(of(commandStateResource));
+    });
+
+    it('should complete vorgang', () => {
+      service.skipBescheidCreation(vorgangWithEingangResource, null);
+
+      expect(vorgangCommandService.abschliessen).toHaveBeenCalledWith(vorgangWithEingangResource);
+    });
+
+    it('should NOT complete vorgang', () => {
+      service.skipBescheidCreation(vorgangWithEingangResource, bescheidResource);
+
+      expect(vorgangCommandService.abschliessen).not.toHaveBeenCalled();
+    });
+
+    it('should delete bescheid and complete vorgang', () => {
+      service.skipBescheidCreation(vorgangWithEingangResource, bescheidResource).subscribe();
+
+      expect(service.deleteBescheidAndCompleteVorgang).toHaveBeenCalledWith(vorgangWithEingangResource);
+    });
+
+    it('should return command', () => {
+      const command$: Observable<StateResource<CommandResource>> = service.skipBescheidCreation(
+        vorgangWithEingangResource,
+        bescheidResource,
+      );
+
+      expect(command$).toBeObservable(singleColdCompleted(commandStateResource));
+    });
+  });
+
+  describe('deleteBescheidAndCompleteVorgang', () => {
+    beforeEach(() => {
+      service.deleteBescheid = jest.fn().mockReturnValue(of(createCommandStateResource));
+      vorgangCommandService.abschliessen.mockReturnValue(EMPTY);
+    });
+
+    it('should complete vorgang', () => {
+      service.deleteBescheidAndCompleteVorgang(vorgangWithEingangResource).subscribe();
+
+      expect(vorgangCommandService.abschliessen).toHaveBeenCalledWith(vorgangWithEingangResource);
+    });
+
+    it('should delete bescheid', () => {
+      vorgangCommandService.abschliessen.mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+
+      service.deleteBescheidAndCompleteVorgang(vorgangWithEingangResource).subscribe();
+
+      expect(service.deleteBescheid).toHaveBeenCalled();
+    });
+
+    it('should NOT delete bescheid on loading', () => {
+      vorgangCommandService.abschliessen.mockReturnValue(of(createEmptyStateResource(true)));
+
+      service.deleteBescheidAndCompleteVorgang(vorgangWithEingangResource).subscribe();
+
+      expect(service.deleteBescheid).not.toHaveBeenCalled();
+    });
+
+    it('should NOT delete bescheid on error', () => {
+      vorgangCommandService.abschliessen.mockReturnValue(of(createErrorStateResource(createProblemDetail())));
+
+      service.deleteBescheidAndCompleteVorgang(vorgangWithEingangResource).subscribe();
+
+      expect(service.deleteBescheid).not.toHaveBeenCalled();
+    });
+
+    it('should return vorgang abschliessen command', () => {
+      const command: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+      vorgangCommandService.abschliessen.mockReturnValue(of(command));
+
+      const command$: Observable<StateResource<CommandResource>> =
+        service.deleteBescheidAndCompleteVorgang(vorgangWithEingangResource);
+
+      expect(command$).toBeObservable(singleColdCompleted(command));
+    });
+  });
+
+  describe('delete bescheid', () => {
+    it('should create command', () => {
+      service.deleteBescheid();
+
+      expect(bescheidResourceService.delete).toHaveBeenCalled();
+    });
+
+    it('should return command', () => {
+      const commandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+      bescheidResourceService.delete.mockReturnValue(of(commandStateResource));
+
+      const createdCommand$: Observable<StateResource<CommandResource>> = service.deleteBescheid();
+
+      expect(createdCommand$).toBeObservable(singleColdCompleted(commandStateResource));
+    });
+  });
+
+  describe('loadFiles', () => {
+    beforeEach(() => {
+      service.loadBescheidDocument = jest.fn();
+      service.loadAttachments = jest.fn();
+    });
+
+    it('should bescheid document', () => {
+      service.loadFiles(bescheidResource);
+
+      expect(service.loadBescheidDocument).toHaveBeenCalledWith(bescheidResource);
+    });
+
+    it('should load attachments', () => {
+      service.loadFiles(bescheidResource);
+
+      expect(service.loadAttachments).toHaveBeenCalledWith(bescheidResource);
+    });
+  });
+
+  describe('create bescheid document', () => {
+    beforeEach(() => {
+      service.doCreateBescheidDocument = jest.fn().mockReturnValue(EMPTY);
+      service.handleCreateBescheidDocumentResponse = jest.fn();
+    });
+
+    it('should emit bescheid document', () => {
+      service.createBescheidDocument(bescheidResource);
+
+      expect(service.getBescheidDocument()).toBeObservable(
+        singleCold({ ...createEmptyBescheidDocument(), create: createEmptyStateResource(true) }),
+      );
+    });
+
+    it('should do create bescheid document', () => {
+      service.createBescheidDocument(bescheidResource);
+
+      expect(service.doCreateBescheidDocument).toHaveBeenCalledWith(bescheidResource);
+    });
+
+    it('should handle create response on loaded', () => {
+      service.doCreateBescheidDocument = jest.fn().mockReturnValue(of(commandStateResource));
+
+      service.createBescheidDocument(bescheidResource);
+
+      expect(service.handleCreateBescheidDocumentResponse).toHaveBeenCalledWith(commandStateResource);
+    });
+
+    it('should handle create response on error', () => {
+      const commandError: StateResource<CommandResource> = createCommandErrorStateResource();
+      service.doCreateBescheidDocument = jest.fn().mockReturnValue(of(commandError));
+
+      service.createBescheidDocument(bescheidResource);
+
+      expect(service.handleCreateBescheidDocumentResponse).toHaveBeenCalledWith(commandError);
+    });
+  });
+
+  describe('doCreateBescheidDocument', () => {
+    it('should create command by props', () => {
+      service.doCreateBescheidDocument(bescheidResource);
+
+      expect(commandService.createCommandByProps).toHaveBeenCalledWith({
+        resource: bescheidResource,
+        linkRel: BescheidLinkRel.CREATE_DOCUMENT,
+        command: {
+          order: CommandOrder.CREATE_BESCHEID_DOCUMENT,
+          body: null,
+        },
+        snackBarMessage: EMPTY_STRING,
+      });
+    });
+  });
+
+  describe('handleCreateBescheidDocumentResponse', () => {
+    const commandStateResource: StateResource<CommandResource> = createStateResource(
+      createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]),
+    );
+
+    beforeEach(() => {
+      service.loadBescheidDocumentByUri = jest.fn();
+      service.emitBescheidDocumentError = jest.fn();
+    });
+
+    it('should emit error', () => {
+      const commandErrorStateResource: StateResource<CommandResource> = createCommandErrorStateResource();
+
+      service.handleCreateBescheidDocumentResponse(commandErrorStateResource);
+
+      expect(service.getBescheidDocument()).toBeObservable(
+        singleCold({ ...createEmptyBescheidDocument(), create: commandErrorStateResource } as BescheidDocument),
+      );
+    });
+
+    it('should emit bescheid document state', () => {
+      service.handleCreateBescheidDocumentResponse(commandStateResource);
+
+      expect(service.getBescheidDocument()).toBeObservable(
+        singleCold({
+          ...createEmptyBescheidDocument(),
+          documentUri: getEffectedResourceUrl(commandStateResource.resource),
+        }),
+      );
+    });
+
+    it('should load document by uri', () => {
+      service.handleCreateBescheidDocumentResponse(commandStateResource);
+
+      expect(service.loadBescheidDocumentByUri).toHaveBeenCalledWith(getEffectedResourceUrl(commandStateResource.resource));
+    });
+  });
+
+  describe('emitBescheidDocumentError', () => {
+    it('should emit', () => {
+      const commandError: StateResource<CommandResource> = createCommandErrorStateResource();
+
+      service.emitBescheidDocumentError(commandError);
+
+      expect(service.getBescheidDocument()).toBeObservable(
+        singleCold({
+          ...createEmptyBescheidDocument(),
+          upload: { ...createEmptyUploadInProgress(), loading: false, error: commandError.error },
+        }),
+      );
+    });
+  });
+
+  describe('loadBescheidDocument', () => {
+    beforeEach(() => {
+      service.loadBescheidDocumentByUri = jest.fn();
+    });
+
+    it('should load by uri', () => {
+      const bescheidResource: BescheidResource = createBescheidResource([BescheidLinkRel.BESCHEID_DOCUMENT]);
+
+      service.loadBescheidDocument(bescheidResource);
+
+      expect(service.loadBescheidDocumentByUri).toHaveBeenCalledWith(getUrl(bescheidResource, BescheidLinkRel.BESCHEID_DOCUMENT));
+    });
+
+    it('should NOT load by uri', () => {
+      service.loadBescheidDocument(bescheidResource);
+
+      expect(service.loadBescheidDocumentByUri).not.toHaveBeenCalled();
+    });
+  });
+
+  describe('loadBescheidDocumentByUri', () => {
+    const resourceUri: ResourceUri = faker.internet.url();
+
+    beforeEach(() => {
+      resourceRepository.getResource.mockReturnValue(EMPTY);
+      service.loadBescheidDocumentFile = jest.fn();
+    });
+
+    it('should get resource', () => {
+      service.loadBescheidDocumentByUri(resourceUri);
+
+      expect(resourceRepository.getResource).toHaveBeenCalledWith(resourceUri);
+    });
+
+    it('should load bescheid document file', () => {
+      const documentResource: DocumentResource = createDocumentResource();
+      resourceRepository.getResource.mockReturnValue(of(documentResource));
+
+      service.loadBescheidDocumentByUri(resourceUri);
+
+      expect(service.loadBescheidDocumentFile).toHaveBeenCalledWith(documentResource);
+    });
+  });
+
+  describe('load bescheid document file', () => {
+    const document: DocumentResource = createDocumentResource([DocumentLinkRel.FILE]);
+    const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource());
+
+    beforeEach(() => {
+      binaryFileService.getFile.mockReturnValue(of(binaryFileStateResource));
+    });
+
+    it('should call binary file service', () => {
+      service.loadBescheidDocumentFile(document);
+
+      expect(binaryFileService.getFile).toHaveBeenCalledWith(getUrl(document, DocumentLinkRel.FILE));
+    });
+
+    it('should emit bescheid document state', () => {
+      service.loadBescheidDocumentFile(document);
+
+      expect(service.getBescheidDocument()).toBeObservable(
+        singleCold({
+          upload: createEmptyUploadInProgress(),
+          create: createEmptyStateResource(),
+          resource: binaryFileStateResource.resource,
+          documentUri: getUrl(document, LinkRel.Self),
+        }),
+      );
+    });
+  });
+
+  describe('loadAttachments', () => {
+    const bescheidResourceWithAttachments: BescheidResource = createBescheidResource([BescheidLinkRel.ATTACHMENTS]);
+
+    beforeEach(() => {
+      binaryFileService.getFiles.mockReturnValue(EMPTY);
+    });
+
+    it('should call binary file service', () => {
+      service.loadAttachments(bescheidResourceWithAttachments);
+
+      expect(binaryFileService.getFiles).toHaveBeenCalledWith(bescheidResourceWithAttachments, BescheidLinkRel.ATTACHMENTS);
+    });
+
+    it('should NOT call binary file service', () => {
+      service.loadAttachments(bescheidResource);
+
+      expect(binaryFileService.getFiles).not.toHaveBeenCalled();
+    });
+
+    it('should emit attachments state', () => {
+      const binaryFileListStateResource: StateResource<BinaryFileListResource> =
+        createStateResource(createBinaryFileListResource());
+      binaryFileService.getFiles.mockReturnValue(of(binaryFileListStateResource));
+      service.loadAttachments(bescheidResourceWithAttachments);
+
+      expect(binaryFileService.getFiles).toHaveBeenCalledWith(bescheidResourceWithAttachments, BescheidLinkRel.ATTACHMENTS);
+
+      expect(service.getAttachments()).toBeObservable(
+        singleCold({
+          ...createEmptyBescheidAttachments(),
+          items: getEmbeddedResources(binaryFileListStateResource, BinaryFileListLinkRel.FILE_LIST),
+        }),
+      );
+    });
+  });
+
+  describe('uploadAttachment', () => {
+    const attachment: File = createFile();
+
+    beforeEach(() => {
+      binaryFileService.uploadFile.mockReturnValue(EMPTY);
+      service.handleAttachmentUpload = jest.fn();
+    });
+
+    it('should emit upload loading', () => {
+      service.uploadAttachment(attachment, bescheidResource);
+
+      expect(service.getAttachments()).toBeObservable(
+        singleCold({
+          ...createEmptyBescheidAttachments(),
+          upload: { fileName: attachment.name, loading: true },
+          uploadStateResource: createLoadingStateResource(),
+        } as BescheidAttachments),
+      );
+    });
+
+    it('should call binary file service', () => {
+      service.uploadAttachment(attachment, bescheidResource);
+
+      expect(binaryFileService.uploadFile).toHaveBeenCalledWith(
+        bescheidResource,
+        BescheidLinkRel.UPLOAD_ATTACHMENT,
+        attachment,
+        false,
+      );
+    });
+
+    it('should handle attachment upload', () => {
+      const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource());
+      binaryFileService.uploadFile.mockReturnValue(of(binaryFileStateResource));
+
+      service.uploadAttachment(attachment, bescheidResource);
+
+      expect(service.handleAttachmentUpload).toHaveBeenCalledWith(binaryFileStateResource);
+    });
+  });
+
+  describe('handleAttachmentUpload', () => {
+    it('should emit state on success', () => {
+      const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource());
+
+      service.handleAttachmentUpload(binaryFileStateResource);
+
+      expect(service.getAttachments()).toBeObservable(
+        singleCold({
+          ...createEmptyBescheidAttachments(),
+          items: [binaryFileStateResource.resource],
+          uploadStateResource: binaryFileStateResource,
+          upload: {
+            ...createEmptyUploadInProgress(),
+            error: binaryFileStateResource.error,
+            loading: binaryFileStateResource.loading,
+          },
+        } as BescheidAttachments),
+      );
+    });
+
+    it('should emit state on error', () => {
+      const binaryFileStateResource: StateResource<BinaryFileResource> = createErrorStateResource(createProblemDetail());
+
+      service.handleAttachmentUpload(binaryFileStateResource);
+
+      expect(service.getAttachments()).toBeObservable(
+        singleCold({
+          ...createEmptyBescheidAttachments(),
+          items: [],
+          uploadStateResource: binaryFileStateResource,
+          upload: {
+            ...createEmptyUploadInProgress(),
+            error: binaryFileStateResource.error,
+            loading: binaryFileStateResource.loading,
+          },
+        }),
+      );
+    });
+  });
+
+  describe('deleteAttachment', () => {
+    it('should delete', () => {
+      const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource());
+      service.handleAttachmentUpload(binaryFileStateResource);
+
+      service.deleteAttachment(binaryFileStateResource.resource);
+
+      expect(service.getAttachments()).toBeObservable(
+        singleCold({ ...createEmptyBescheidAttachments(), uploadStateResource: binaryFileStateResource } as BescheidAttachments),
+      );
+    });
+  });
+
+  describe('upload bescheid document', () => {
+    const documentFile: File = createFile();
+
+    beforeEach(() => {
+      binaryFileService.uploadFile.mockReturnValue(EMPTY);
+      service.handleUploadBescheidDocumentResponse = jest.fn();
+    });
+
+    it('should emit bescheid document state', () => {
+      service.uploadBescheidDocument(documentFile, bescheidResource);
+
+      expect(service.getBescheidDocument()).toBeObservable(
+        singleCold({ ...createEmptyBescheidDocument(), upload: { fileName: documentFile.name, loading: true } }),
+      );
+    });
+
+    it('should call binary file service', () => {
+      service.uploadBescheidDocument(documentFile, bescheidResource);
+
+      expect(binaryFileService.uploadFile).toHaveBeenCalledWith(
+        bescheidResource,
+        BescheidLinkRel.UPLOAD_BESCHEID_FILE,
+        documentFile,
+        false,
+      );
+    });
+
+    it('should handle upload response', () => {
+      const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource());
+      binaryFileService.uploadFile.mockReturnValue(of(binaryFileStateResource));
+
+      service.uploadBescheidDocument(documentFile, bescheidResource);
+
+      expect(service.handleUploadBescheidDocumentResponse).toHaveBeenCalledWith(bescheidResource, binaryFileStateResource);
+    });
+  });
+
+  describe('handleUploadBescheidDocumentResponse', () => {
+    beforeEach(() => {
+      service.emitBescheidDocumentError = jest.fn();
+      service.createBescheidDocumentFromFile = jest.fn();
+    });
+
+    it('should emit error', () => {
+      const errorStateResource: StateResource<BinaryFileResource> = createErrorStateResource(createProblemDetail());
+
+      service.handleUploadBescheidDocumentResponse(bescheidResource, errorStateResource);
+
+      expect(service.emitBescheidDocumentError).toHaveBeenCalledWith(errorStateResource);
+    });
+
+    it('should create bescheid document from file', () => {
+      const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource());
+
+      service.handleUploadBescheidDocumentResponse(bescheidResource, binaryFileStateResource);
+
+      expect(service.createBescheidDocumentFromFile).toHaveBeenCalledWith(bescheidResource, binaryFileStateResource.resource);
+    });
+  });
+
+  describe('create bescheid document from file', () => {
+    const bescheid: BescheidResource = createBescheidResource();
+    const binaryFile: BinaryFileResource = createBinaryFileResource();
+
+    const createCommandProps: CreateCommandProps = createCreateCommandProps();
+    let buildCreateBescheidDocumentFromFilePropsSpy;
+
+    const commandStateResource: StateResource<CommandResource> = createCommandStateResource();
+
+    beforeEach(() => {
+      buildCreateBescheidDocumentFromFilePropsSpy = jest
+        .spyOn(BescheidUtil, 'buildCreateBescheidDocumentFromFileProps')
+        .mockReturnValue(createCommandProps);
+      commandService.createCommandByProps.mockReturnValue(of(commandStateResource));
+    });
+
+    it('should call command sevice', () => {
+      service.createBescheidDocumentFromFile(bescheid, binaryFile);
+
+      expect(commandService.createCommandByProps).toHaveBeenCalledWith(createCommandProps);
+    });
+
+    it('should build create command document from file props', () => {
+      service.createBescheidDocumentFromFile(bescheid, binaryFile);
+
+      expect(buildCreateBescheidDocumentFromFilePropsSpy).toHaveBeenCalledWith(bescheid, binaryFile);
+    });
+
+    it('should call handle create bescheid document from file response', () => {
+      service.handleCreateBescheidDocumentFromFileResponse = jest.fn();
+
+      service.createBescheidDocumentFromFile(bescheid, binaryFile);
+
+      expect(service.handleCreateBescheidDocumentFromFileResponse).toHaveBeenCalledWith(commandStateResource, binaryFile);
+    });
+  });
+
+  describe('handleCreateBescheidDocumentFromFileResponse', () => {
+    const commandStateResource: StateResource<CommandResource> = createStateResource(
+      createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]),
+    );
+
+    beforeEach(() => {
+      service.emitBescheidDocumentError = jest.fn();
+    });
+
+    it('should emit error', () => {
+      const errorStateResource: StateResource<CommandResource> = createErrorStateResource(createProblemDetail());
+
+      service.handleCreateBescheidDocumentFromFileResponse(errorStateResource, createBinaryFileResource());
+
+      expect(service.emitBescheidDocumentError).toHaveBeenCalledWith(errorStateResource);
+    });
+
+    it('should NOT emit error', () => {
+      const binaryFileResource: BinaryFileResource = createBinaryFileResource();
+
+      service.handleCreateBescheidDocumentFromFileResponse(commandStateResource, binaryFileResource);
+
+      expect(service.emitBescheidDocumentError).not.toHaveBeenCalled();
+    });
+
+    it('should emit bescheid document state', () => {
+      const binaryFileResource: BinaryFileResource = createBinaryFileResource();
+
+      service.handleCreateBescheidDocumentFromFileResponse(commandStateResource, binaryFileResource);
+
+      expect(service.getBescheidDocument()).toBeObservable(
+        singleCold({
+          ...createEmptyBescheidDocument(),
+          documentUri: getEffectedResourceUrl(commandStateResource.resource),
+          upload: createEmptyUploadInProgress(),
+          resource: binaryFileResource,
+        }),
+      );
+    });
+
+    it('should NOT emit bescheid document state', () => {
+      const errorStateResource: StateResource<CommandResource> = createErrorStateResource(createProblemDetail());
+
+      service.handleCreateBescheidDocumentFromFileResponse(errorStateResource, createBinaryFileResource());
+
+      expect(service.getBescheidDocument()).toBeObservable(singleCold(createEmptyBescheidDocument()));
+    });
+  });
+
+  describe('createBescheid', () => {
+    const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource();
+    const command: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]);
+    const commandStateResource: StateResource<CommandResource> = createStateResource(command);
+
+    beforeEach(() => {
+      service.updateBescheidDraft = jest.fn();
+    });
+
+    beforeEach(() => {
+      facade.getBescheidCommand.mockReturnValue(of(commandStateResource));
+      (service as any).bescheidResourceService.loadByResourceUri = jest.fn();
+    });
+
+    it('should call facade', () => {
+      service.createBescheid(vorgangWithEingang).subscribe();
+
+      expect(facade.createBescheidDraft).toHaveBeenCalledWith(vorgangWithEingang, {
+        order: CommandOrder.CREATE_BESCHEID,
+        body: null,
+      });
+    });
+
+    it('should update bescheid draft', () => {
+      service.createBescheid(vorgangWithEingang).subscribe();
+
+      expect(service.updateBescheidDraft).toHaveBeenCalledWith(commandStateResource.resource);
+    });
+  });
+
+  describe('updateBescheidDraft', () => {
+    const command: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]);
+
+    beforeEach(() => {
+      (service as any).bescheidResourceService.loadByResourceUri = jest.fn();
+    });
+
+    it('should load resource by uri', () => {
+      service.updateBescheidDraft(command);
+
+      expect((service as any).bescheidResourceService.loadByResourceUri).toHaveBeenCalledWith(
+        getUrl(command, CommandLinkRel.EFFECTED_RESOURCE),
+      );
+    });
+
+    it('should emit bescheid created', () => {
+      service.updateBescheidDraft({ ...command, order: CommandOrder.CREATE_BESCHEID });
+
+      expect(service.getBescheidCreated()).toBeObservable(singleCold(true));
+    });
+  });
+
+  describe('updateBescheid', () => {
+    const bescheid: Bescheid = createBescheid();
+    const commandResource: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]);
+    const commandStateResource: StateResource<CommandResource> = createStateResource(commandResource);
+
+    beforeEach(() => {
+      service.doUpdateBescheid = jest.fn().mockReturnValue(EMPTY);
+      service.updateBescheidDraft = jest.fn().mockReturnValue(EMPTY);
+    });
+
+    it('should do update bescheid', () => {
+      service.updateBescheid(bescheidResource, bescheid);
+
+      expect(service.doUpdateBescheid).toHaveBeenCalledWith(bescheidResource, bescheid);
+    });
+
+    it('should update bescheid draft', () => {
+      service.doUpdateBescheid = jest.fn().mockReturnValue(of(commandStateResource));
+
+      service.updateBescheid(bescheidResource, bescheid).subscribe();
+
+      expect(service.updateBescheidDraft).toHaveBeenCalledWith(commandResource);
+    });
+  });
+
+  describe('do update bescheid', () => {
+    const bescheid: Bescheid = createBescheid();
+    const bescheidResource: BescheidResource = createBescheidResource();
+
+    const createCommandProps: CreateCommandProps = createCreateCommandProps();
+    let buildUpdateBescheidCommandPropsSpy: jest.SpyInstance;
+
+    beforeEach(() => {
+      buildUpdateBescheidCommandPropsSpy = jest
+        .spyOn(BescheidUtil, 'buildUpdateBescheidCommandProps')
+        .mockReturnValue(createCommandProps);
+      commandService.createCommandByProps.mockClear();
+      commandService.createCommandByProps.mockReturnValue(of(createCommandStateResource()));
+    });
+
+    it('should build update bescheid command props', () => {
+      service.doUpdateBescheid(bescheidResource, bescheid);
+
+      expect(buildUpdateBescheidCommandPropsSpy).toHaveBeenCalledWith(bescheidResource, bescheid);
+    });
+
+    it('should call command service', () => {
+      service.doUpdateBescheid(bescheidResource, bescheid).subscribe();
+
+      expect(commandService.createCommandByProps).toHaveBeenCalledWith(createCommandProps);
+    });
+  });
+
+  describe('sendBescheidManually', () => {
+    beforeEach(() => {
+      service.sendBescheid = jest.fn().mockReturnValue(EMPTY);
+    });
+
+    it('should send bescheid', () => {
+      service.sendBescheidManually().subscribe();
+
+      expect(service.sendBescheid).toHaveBeenCalledWith(BescheidLinkRel.BESCHEIDEN);
+    });
+
+    it('should return send bescheid command', () => {
+      const commandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+      service.sendBescheid = jest.fn().mockReturnValue(of(commandStateResource));
+
+      const sendCommandStateResource$: Observable<StateResource<CommandResource>> = service.sendBescheidManually();
+
+      expect(sendCommandStateResource$).toBeObservable(singleColdCompleted(commandStateResource));
+    });
+  });
+
+  describe('sendBescheid', () => {
+    beforeEach(() => {
+      service.getBescheidDraft = jest.fn().mockReturnValue(of(createStateResource(bescheidResource)));
+      commandService.createCommandByProps.mockReturnValue(EMPTY);
+    });
+
+    it('should get bescheid draft', () => {
+      service.sendBescheidManually().subscribe();
+
+      expect(service.getBescheidDraft).toHaveBeenCalled();
+    });
+
+    it('should create command', () => {
+      service.sendBescheid(BescheidLinkRel.BESCHEIDEN).subscribe();
+
+      expect(commandService.createCommandByProps).toHaveBeenCalledWith({
+        resource: bescheidResource,
+        linkRel: BescheidLinkRel.BESCHEIDEN,
+        command: {
+          order: CommandOrder.SEND_BESCHEID,
+          body: null,
+        },
+        snackBarMessage: EMPTY_STRING,
+      } as CreateCommandProps);
+    });
+
+    it('should return send bescheid command', () => {
+      const commandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+      commandService.createCommandByProps = jest.fn().mockReturnValue(of(commandStateResource));
+
+      const sendCommandStateResource$: Observable<StateResource<CommandResource>> = service.sendBescheid(
+        BescheidLinkRel.BESCHEIDEN,
+      );
+
+      expect(sendCommandStateResource$).toBeObservable(singleColdCompleted(commandStateResource));
+    });
+  });
+
+  describe('sendBescheidMessage', () => {
+    beforeEach(() => {
+      service.getBescheidDraft = jest.fn().mockReturnValue(createStateResource(bescheidResource));
+      service.sendBescheid = jest.fn().mockReturnValue(EMPTY);
+    });
+
+    it('should send bescheid', () => {
+      service.sendBescheidMessage().subscribe();
+
+      expect(service.sendBescheid).toHaveBeenCalledWith(BescheidLinkRel.BESCHEIDEN_UND_SENDEN);
+    });
+
+    it('should return send bescheid command', () => {
+      const commandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+      service.sendBescheid = jest.fn().mockReturnValue(of(commandStateResource));
+
+      const sendCommandStateResource$: Observable<StateResource<CommandResource>> = service.sendBescheidMessage();
+
+      expect(sendCommandStateResource$).toBeObservable(singleColdCompleted(commandStateResource));
+    });
+  });
+
+  describe('setActiveStep', () => {
+    it('should emit changed active step', () => {
+      service.setActiveStep(BescheidWizardStep.DokumenteHochladen);
+
+      expect(service.getActiveStep()).toBeObservable(singleCold(BescheidWizardStep.DokumenteHochladen));
+    });
+  });
+
+  describe('getBescheidDraft', () => {
+    const bescheidDraft: BescheidResource = createBescheidResource();
+    const bescheidDraftStateResource: StateResource<BescheidResource> = createStateResource(bescheidDraft);
+
+    it('should call resource service', () => {
+      bescheidResourceService.get = jest.fn();
+
+      service.getBescheidDraft();
+
+      expect(bescheidResourceService.get).toHaveBeenCalled();
+    });
+
+    it('should return value', () => {
+      bescheidResourceService.get = jest.fn().mockReturnValue(singleCold(bescheidDraftStateResource));
+
+      const bescheidStateResource$: Observable<StateResource<BescheidResource>> = service.getBescheidDraft();
+
+      expect(bescheidStateResource$).toBeObservable(singleCold(bescheidDraftStateResource));
+    });
+  });
+
+  describe('setNachrichtEmpfaenger', () => {
+    it('should change wizard state', () => {
+      const empfaenger: string = faker.person.fullName();
+
+      service.setNachrichtEmpfaenger(empfaenger);
+
+      expect(service.getWizard()).toBeObservable(singleCold({ ...createInitialWizard(), empfaenger }));
+    });
+  });
+
+  describe('lockBescheidSending', () => {
+    it('should change wizard state', () => {
+      service.lockBescheidSending();
+
+      expect(service.getWizard()).toBeObservable(singleCold({ ...createInitialWizard(), canBeSend: false }));
+    });
+  });
+
+  describe('unlockBescheidSending', () => {
+    it('should change wizard state', () => {
+      service.unlockBescheidSending();
+
+      expect(service.getWizard()).toBeObservable(singleCold({ ...createInitialWizard(), canBeSend: true }));
+    });
+  });
+
+  describe('finishAddingAttachments', () => {
+    it('should update state', () => {
+      const attachments: BescheidAttachments = createBescheidAttachments();
+      service._attachments$.next(attachments);
+
+      service.finishAddingAttachments();
+
+      expect(service.getAttachments()).toBeObservable(
+        singleCold({
+          ...attachments,
+          upload: createEmptyUploadInProgress(),
+          uploadStateResource: createEmptyStateResource(),
+        } as BescheidAttachments),
+      );
+    });
+  });
+
+  describe('finishAddingBescheidDocument', () => {
+    it('should update state', () => {
+      const bescheidDocument: BescheidDocument = createBescheidDocument();
+      service._bescheidDocument$.next(bescheidDocument);
+
+      service.finishAddingBescheidDocument();
+
+      expect(service.getBescheidDocument()).toBeObservable(
+        singleCold({
+          ...bescheidDocument,
+          create: createEmptyStateResource(),
+          upload: createEmptyUploadInProgress(),
+        } as BescheidDocument),
+      );
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid2.service.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid2.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3c5d8191390993f76b6456a8577d895b57dd6f55
--- /dev/null
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid2.service.ts
@@ -0,0 +1,387 @@
+import {
+  Bescheid,
+  BescheidAttachments,
+  BescheidDocument,
+  BescheidLinkRel,
+  BescheidResource,
+  BescheidSendBy,
+  BescheidWizardStep,
+  buildCreateBescheidCommand,
+  buildCreateBescheidDocumentCommandProps,
+  buildCreateBescheidDocumentFromFileProps,
+  buildSendBescheidCommandProps,
+  buildUpdateBescheidCommandProps,
+  createEmptyBescheidAttachments,
+  createEmptyBescheidDocument,
+  createEmptyUploadInProgress,
+  createInitialWizard,
+  DocumentResource,
+  Wizard,
+} from '@alfa-client/bescheid-shared';
+import {
+  BinaryFileListLinkRel,
+  BinaryFileListResource,
+  BinaryFileResource,
+  BinaryFileService,
+} from '@alfa-client/binary-file-shared';
+import {
+  CommandOrder,
+  CommandResource,
+  CommandService,
+  getEffectedResourceUrl,
+  notHasCommandError,
+  tapOnCommandSuccessfullyDone,
+} from '@alfa-client/command-shared';
+import { PostfachService } from '@alfa-client/postfach-shared';
+import {
+  createEmptyStateResource,
+  createLoadingStateResource,
+  filterIsLoadedOrHasError,
+  getEmbeddedResources,
+  hasStateResourceError,
+  isLoaded,
+  ResourceRepository,
+  StateResource,
+} from '@alfa-client/tech-shared';
+import { VorgangCommandService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { inject, Injectable } from '@angular/core';
+import { getUrl, hasLink, LinkRel, Resource, ResourceUri } from '@ngxp/rest';
+import { isNil } from 'lodash-es';
+import { BehaviorSubject, filter, first, map, Observable, switchMap } from 'rxjs';
+import { BescheidFacade } from './+state/bescheid.facade';
+import { BescheidResourceService } from './bescheid-resource-service';
+import { DocumentLinkRel } from './document.linkrel';
+
+@Injectable()
+export class BescheidService2 {
+  private readonly bescheidFacade = inject(BescheidFacade);
+  private readonly commandService = inject(CommandService);
+  private readonly vorgangCommandService = inject(VorgangCommandService);
+  private readonly binaryFileService = inject(BinaryFileService);
+  private readonly resourceRepository = inject(ResourceRepository);
+  private readonly postfachService = inject(PostfachService);
+  private readonly bescheidResourceService = inject(BescheidResourceService);
+
+  readonly _bescheidDocument$: BehaviorSubject<BescheidDocument> = new BehaviorSubject(createEmptyBescheidDocument());
+  readonly _attachments$: BehaviorSubject<BescheidAttachments> = new BehaviorSubject(createEmptyBescheidAttachments());
+  readonly _wizard$: BehaviorSubject<Wizard> = new BehaviorSubject(createInitialWizard());
+
+  public init(): void {
+    this._wizard$.next(createInitialWizard());
+    this._bescheidDocument$.next(createEmptyBescheidDocument());
+    this._attachments$.next(createEmptyBescheidAttachments());
+  }
+
+  public exit(): void {
+    this.postfachService.setPostfachMailOnReload();
+  }
+
+  public skipBescheidCreation(
+    vorgangWithEingangResource: VorgangWithEingangResource,
+    bescheidResource: BescheidResource,
+  ): Observable<StateResource<CommandResource>> {
+    if (isNil(bescheidResource)) {
+      return this.vorgangCommandService.abschliessen(vorgangWithEingangResource);
+    }
+    return this.deleteBescheidAndCompleteVorgang(vorgangWithEingangResource);
+  }
+
+  deleteBescheidAndCompleteVorgang(
+    vorgangWithEingangResource: VorgangWithEingangResource,
+  ): Observable<StateResource<CommandResource>> {
+    return this.vorgangCommandService
+      .abschliessen(vorgangWithEingangResource)
+      .pipe(tapOnCommandSuccessfullyDone(() => this.deleteBescheid()));
+  }
+
+  public deleteBescheid(): Observable<StateResource<CommandResource>> {
+    return this.bescheidResourceService.delete();
+  }
+
+  public loadFiles(bescheidResource: BescheidResource): void {
+    this.loadBescheidDocument(bescheidResource);
+    this.loadAttachments(bescheidResource);
+  }
+
+  public createBescheidDocument(bescheidResource: BescheidResource): void {
+    this._bescheidDocument$.next({ ...createEmptyBescheidDocument(), create: createEmptyStateResource(true) });
+    this.doCreateBescheidDocument(bescheidResource)
+      .pipe(filterIsLoadedOrHasError(), first())
+      .subscribe((commandStateResource: StateResource<CommandResource>) =>
+        this.handleCreateBescheidDocumentResponse(commandStateResource),
+      );
+  }
+
+  doCreateBescheidDocument(bescheidResource: BescheidResource): Observable<StateResource<CommandResource>> {
+    return this.commandService.createCommandByProps(buildCreateBescheidDocumentCommandProps(bescheidResource));
+  }
+
+  handleCreateBescheidDocumentResponse(commandStateResource: StateResource<CommandResource>): void {
+    if (notHasCommandError(commandStateResource.resource)) {
+      const documentUri: ResourceUri = getEffectedResourceUrl(commandStateResource.resource);
+      this._bescheidDocument$.next({ ...this._bescheidDocument$.value, documentUri });
+      this.loadBescheidDocumentByUri(documentUri);
+    } else {
+      this._bescheidDocument$.next({ ...this._bescheidDocument$.value, create: commandStateResource });
+    }
+  }
+
+  emitBescheidDocumentError(stateResource: StateResource<Resource>): void {
+    const value: BescheidDocument = this._bescheidDocument$.value;
+    this._bescheidDocument$.next({
+      ...value,
+      upload: { ...value.upload, loading: false, error: stateResource.error },
+    });
+  }
+
+  loadBescheidDocument(bescheidResource: BescheidResource): void {
+    if (hasLink(bescheidResource, BescheidLinkRel.BESCHEID_DOCUMENT)) {
+      this.loadBescheidDocumentByUri(getUrl(bescheidResource, BescheidLinkRel.BESCHEID_DOCUMENT));
+    }
+  }
+
+  public loadBescheidDocumentByUri(resourceUri: ResourceUri): void {
+    this.resourceRepository
+      .getResource(resourceUri)
+      .pipe(first())
+      .subscribe((document: DocumentResource) => this.loadBescheidDocumentFile(document));
+  }
+
+  loadBescheidDocumentFile(document: DocumentResource): void {
+    this.binaryFileService
+      .getFile(getUrl(document, DocumentLinkRel.FILE))
+      .pipe(filterIsLoadedOrHasError(), first())
+      .subscribe((binaryFile: StateResource<BinaryFileResource>) => {
+        this._bescheidDocument$.next({
+          ...this._bescheidDocument$.value,
+          upload: createEmptyUploadInProgress(),
+          create: createEmptyStateResource(),
+          resource: binaryFile.resource,
+          documentUri: getUrl(document, LinkRel.Self),
+        });
+      });
+  }
+
+  loadAttachments(bescheidResource: BescheidResource): void {
+    if (hasLink(bescheidResource, BescheidLinkRel.ATTACHMENTS)) {
+      this.binaryFileService
+        .getFiles(bescheidResource, BescheidLinkRel.ATTACHMENTS)
+        .pipe(
+          filterIsLoadedOrHasError(),
+          first(),
+          map((stateResource: StateResource<BinaryFileListResource>) =>
+            getEmbeddedResources<BinaryFileResource>(stateResource, BinaryFileListLinkRel.FILE_LIST),
+          ),
+        )
+        .subscribe((files: BinaryFileResource[]) => this._attachments$.next({ ...this._attachments$.value, items: files }));
+    }
+  }
+
+  public uploadAttachment(attachment: File, bescheidResource: BescheidResource): void {
+    this._attachments$.next({
+      ...this._attachments$.value,
+      upload: { fileName: attachment.name, loading: true },
+      uploadStateResource: createLoadingStateResource(),
+    });
+    this.binaryFileService
+      .uploadFile(bescheidResource, BescheidLinkRel.UPLOAD_ATTACHMENT, attachment, false)
+      .pipe(filterIsLoadedOrHasError(), first())
+      .subscribe((binaryFileStateResource: StateResource<BinaryFileResource>) =>
+        this.handleAttachmentUpload(binaryFileStateResource),
+      );
+  }
+
+  handleAttachmentUpload(binaryFileStateResource: StateResource<BinaryFileResource>) {
+    const value: BescheidAttachments = this._attachments$.value;
+    if (hasStateResourceError(binaryFileStateResource)) {
+      this._attachments$.next({
+        ...value,
+        uploadStateResource: binaryFileStateResource,
+        upload: { ...value.upload, error: binaryFileStateResource.error, loading: binaryFileStateResource.loading },
+      });
+    } else {
+      this._attachments$.next({
+        ...value,
+        uploadStateResource: binaryFileStateResource,
+        items: [...value.items, binaryFileStateResource.resource],
+        upload: { ...value.upload, error: binaryFileStateResource.error, loading: binaryFileStateResource.loading },
+      });
+    }
+  }
+
+  public deleteAttachment(attachment: BinaryFileResource): void {
+    const value: BescheidAttachments = this._attachments$.value;
+    this._attachments$.next({
+      ...value,
+      items: value.items.filter((each: BinaryFileResource) => getUrl(each) !== getUrl(attachment)),
+    });
+  }
+
+  public uploadBescheidDocument(document: File, bescheid: BescheidResource): void {
+    this._bescheidDocument$.next({ ...this._bescheidDocument$.value, upload: { fileName: document.name, loading: true } });
+    this.binaryFileService
+      .uploadFile(bescheid, BescheidLinkRel.UPLOAD_BESCHEID_FILE, document, false)
+      .pipe(filterIsLoadedOrHasError(), first())
+      .subscribe((binaryFileStateResource: StateResource<BinaryFileResource>) =>
+        this.handleUploadBescheidDocumentResponse(bescheid, binaryFileStateResource),
+      );
+  }
+
+  handleUploadBescheidDocumentResponse(
+    bescheid: BescheidResource,
+    binaryFileStateResource: StateResource<BinaryFileResource>,
+  ): void {
+    if (hasStateResourceError(binaryFileStateResource)) {
+      this.emitBescheidDocumentError(binaryFileStateResource);
+    } else {
+      this.createBescheidDocumentFromFile(bescheid, binaryFileStateResource.resource);
+    }
+  }
+
+  createBescheidDocumentFromFile(bescheid: BescheidResource, binaryFile: BinaryFileResource): void {
+    this.commandService
+      .createCommandByProps(buildCreateBescheidDocumentFromFileProps(bescheid, binaryFile))
+      .pipe(filterIsLoadedOrHasError(), first())
+      .subscribe((commandStateResource: StateResource<CommandResource>) =>
+        this.handleCreateBescheidDocumentFromFileResponse(commandStateResource, binaryFile),
+      );
+  }
+
+  handleCreateBescheidDocumentFromFileResponse(
+    commandStateResource: StateResource<CommandResource>,
+    binaryFile: BinaryFileResource,
+  ): void {
+    if (hasStateResourceError(commandStateResource)) {
+      this.emitBescheidDocumentError(commandStateResource);
+    } else {
+      this._bescheidDocument$.next({
+        ...this._bescheidDocument$.value,
+        documentUri: getEffectedResourceUrl(commandStateResource.resource),
+        upload: createEmptyUploadInProgress(),
+        resource: binaryFile,
+      });
+    }
+  }
+
+  public createBescheid(
+    vorgangWithEingang: VorgangWithEingangResource,
+    bescheid?: Bescheid,
+  ): Observable<StateResource<CommandResource>> {
+    this.bescheidFacade.createBescheidDraft(vorgangWithEingang, buildCreateBescheidCommand(bescheid));
+    return this.bescheidFacade
+      .getBescheidCommand()
+      .pipe(
+        tapOnCommandSuccessfullyDone((commandStateResource: StateResource<CommandResource>) =>
+          this.updateBescheidDraft(commandStateResource.resource),
+        ),
+      );
+  }
+
+  updateBescheidDraft(command: CommandResource): void {
+    this.bescheidResourceService.loadByResourceUri(getEffectedResourceUrl(command));
+    if (command.order === CommandOrder.CREATE_BESCHEID) {
+      this._wizard$.next({ ...this._wizard$.value, bescheidCreated: true });
+    }
+  }
+
+  public updateBescheid(
+    bescheidResource: BescheidResource,
+    updatedBescheid: Bescheid,
+  ): Observable<StateResource<CommandResource>> {
+    return this.doUpdateBescheid(bescheidResource, updatedBescheid).pipe(
+      tapOnCommandSuccessfullyDone((commandStateResource: StateResource<CommandResource>) => {
+        this.updateBescheidDraft(commandStateResource.resource);
+      }),
+    );
+  }
+
+  doUpdateBescheid(bescheidResource: BescheidResource, bescheid: Bescheid): Observable<StateResource<CommandResource>> {
+    return this.commandService.createCommandByProps(buildUpdateBescheidCommandProps(bescheidResource, bescheid));
+  }
+
+  public sendBescheidManually(): Observable<StateResource<CommandResource>> {
+    return this.sendBescheid(BescheidLinkRel.BESCHEIDEN);
+  }
+
+  public sendBescheidMessage(): Observable<StateResource<CommandResource>> {
+    return this.sendBescheid(BescheidLinkRel.BESCHEIDEN_UND_SENDEN);
+  }
+
+  sendBescheid(linkRel: BescheidLinkRel): Observable<StateResource<CommandResource>> {
+    return this.getBescheidDraft().pipe(
+      filter(isLoaded),
+      map((stateResource: StateResource<BescheidResource>) => stateResource.resource),
+      switchMap((bescheidResource: BescheidResource) =>
+        this.commandService.createCommandByProps(buildSendBescheidCommandProps(bescheidResource, linkRel)),
+      ),
+    );
+  }
+
+  public getBescheidDraft(): Observable<StateResource<BescheidResource>> {
+    return this.bescheidResourceService.get();
+  }
+
+  public getAttachments(): Observable<BescheidAttachments> {
+    return this._attachments$.asObservable();
+  }
+
+  public getBescheidDocument(): Observable<BescheidDocument> {
+    return this._bescheidDocument$.asObservable();
+  }
+
+  public deleteBescheidDocument(): void {
+    this._bescheidDocument$.next(createEmptyBescheidDocument());
+  }
+
+  public getActiveStep(): Observable<BescheidWizardStep> {
+    return this._wizard$.asObservable().pipe(map((wizard: Wizard) => wizard.activeStep));
+  }
+
+  public setActiveStep(step: BescheidWizardStep): void {
+    this._wizard$.next({ ...this._wizard$.value, activeStep: step });
+  }
+
+  public getBescheidCreated(): Observable<boolean> {
+    return this._wizard$.asObservable().pipe(map((wizard: Wizard) => wizard.bescheidCreated));
+  }
+
+  public selectBescheidResource(): Observable<StateResource<BescheidResource>> {
+    return this.bescheidResourceService.selectResource();
+  }
+
+  public getWizard(): Observable<Wizard> {
+    return this._wizard$.asObservable();
+  }
+
+  public setSendBy(sendBy: BescheidSendBy): void {
+    this._wizard$.next({ ...this._wizard$.value, sendBy: sendBy });
+  }
+
+  public setNachrichtEmpfaenger(empfaenger: string): void {
+    this._wizard$.next({ ...this._wizard$.value, empfaenger: empfaenger });
+  }
+
+  public lockBescheidSending(): void {
+    this._wizard$.next({ ...this._wizard$.value, canBeSend: false });
+  }
+
+  public unlockBescheidSending(): void {
+    this._wizard$.next({ ...this._wizard$.value, canBeSend: true });
+  }
+
+  public finishAddingAttachments(): void {
+    this._attachments$.next({
+      ...this._attachments$.value,
+      upload: createEmptyUploadInProgress(),
+      uploadStateResource: createEmptyStateResource(),
+    });
+  }
+
+  public finishAddingBescheidDocument(): void {
+    this._bescheidDocument$.next({
+      ...this._bescheidDocument$.value,
+      upload: createEmptyUploadInProgress(),
+      create: createEmptyStateResource(),
+    });
+  }
+}
diff --git a/alfa-client/libs/bescheid-shared/src/test/bescheid.ts b/alfa-client/libs/bescheid-shared/src/test/bescheid.ts
index d9140137173742b27c72af02134df8c57475f2e1..b8f118a56164cfd5fd06c7b6e2db02c9bac57471 100644
--- a/alfa-client/libs/bescheid-shared/src/test/bescheid.ts
+++ b/alfa-client/libs/bescheid-shared/src/test/bescheid.ts
@@ -25,16 +25,11 @@ import { createStateResource, StateResource } from '@alfa-client/tech-shared';
 import { faker } from '@faker-js/faker';
 import { toResource } from 'libs/tech-shared/test/resource';
 import { times } from 'lodash-es';
-import { createApiError } from '../../../tech-shared/test/error';
+import { createBinaryFileResource } from '../../../binary-file-shared/test/binary-file';
+import { createSuccessfullyDoneCommandStateResource } from '../../../command-shared/test/command';
+import { createProblemDetail } from '../../../tech-shared/test/error';
 import { BescheidListLinkRel } from '../lib/bescheid.linkrel';
-import {
-  Bescheid,
-  BescheidListResource,
-  BescheidResource,
-  BescheidSendBy,
-  BescheidStatus,
-  UploadFileInProgress,
-} from '../lib/bescheid.model';
+import { Bescheid, BescheidAttachments, BescheidDocument, BescheidListResource, BescheidResource, BescheidSendBy, BescheidStatus, BescheidWizardStep, UploadFileInProgress, Wizard, } from '../lib/bescheid.model';
 
 export function createBescheid(): Bescheid {
   return {
@@ -53,14 +48,12 @@ export function createBescheidResource(linkRel: string[] = []): BescheidResource
   return toResource(createBescheid(), linkRel);
 }
 
-export function createBescheidStateResource(
-  linkRel: string[] = [],
-): StateResource<BescheidResource> {
+export function createBescheidStateResource(linkRel: string[] = []): StateResource<BescheidResource> {
   return createStateResource(createBescheidResource(linkRel));
 }
 
 export function createUploadFileInProgress(): UploadFileInProgress {
-  return { loading: true, fileName: faker.person.firstName(), error: createApiError() };
+  return { loading: true, fileName: faker.person.firstName(), error: createProblemDetail() };
 }
 
 export function createBescheidResources(linkRelations: string[] = []): BescheidResource[] {
@@ -75,3 +68,54 @@ export function createBescheidListResource(
     [BescheidListLinkRel.BESCHEID_LIST]: bescheide,
   });
 }
+
+export function createBescheidAttachments(): BescheidAttachments {
+  return {
+    upload: createUploadFileInProgress(),
+    items: [createBinaryFileResource()],
+    uploadStateResource: createStateResource(createBinaryFileResource()),
+  };
+}
+
+export function createBescheidDocument(): BescheidDocument {
+  return {
+    upload: createUploadFileInProgress(),
+    create: createSuccessfullyDoneCommandStateResource(),
+    documentUri: faker.internet.url(),
+    resource: createBinaryFileResource(),
+  };
+}
+
+export function createSuccessfulUpload(): UploadFileInProgress {
+  return {
+    loading: false,
+    error: null,
+    fileName: faker.system.fileName(),
+  };
+}
+
+export function createPendingUpload(): UploadFileInProgress {
+  return {
+    loading: true,
+    fileName: faker.system.fileName(),
+    error: null,
+  };
+}
+
+export function createErrorUpload(): UploadFileInProgress {
+  return {
+    loading: false,
+    error: createProblemDetail(),
+    fileName: faker.system.fileName(),
+  };
+}
+
+export function createWizard(): Wizard {
+  return {
+    empfaenger: faker.person.fullName(),
+    sendBy: BescheidSendBy.MANUAL,
+    bescheidCreated: false,
+    canBeSend: true,
+    activeStep: BescheidWizardStep.BescheidVersenden,
+  };
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.html
index dd3c548c5ab8b1d8b0811314cc637153af596aab..d63d7046e6e03287fae28cd1e019ff1fe55ce0f6 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.html
@@ -27,28 +27,25 @@
   <div class="fixed inset-0 z-10 w-screen overflow-y-auto">
     <div class="flex h-full items-center justify-center p-8">
       <div
-        class="relative h-full w-full max-w-7xl transform overflow-hidden rounded-lg bg-background-200 px-6 py-10 text-left shadow-xl transition-all"
+        class="relative h-full w-full max-w-7xl transform overflow-hidden rounded-lg bg-background-200 py-9 pl-6 pr-9 text-left shadow-xl transition-all"
       >
-        <ng-container *ngIf="bescheidDraftStateResource$ | async as bescheidStateResource">
-          <ods-button
-            variant="ghost"
-            size="fit"
-            class="absolute right-0 top-0 text-text"
-            (clickEmitter)="cancelWizard(bescheidStateResource.resource)"
-            data-test-id="close-bescheid"
-          >
-            <ods-close-icon icon />
-          </ods-button>
-          <alfa-bescheid-wizard
-            [vorgangWithEingangResource]="vorgangWithEingangResource"
-            [activeStep]="bescheidService.getActiveStep() | async"
-            [bescheidStateResource]="bescheidStateResource"
-            [submitStateResource]="submitStateResource$ | async"
-            (weiterClickEmitter)="onWeiter($event)"
-            (vorgangAbgeschlossen)="onVorgangAbgeschlossen()"
-            data-test-id="bescheid-wizard"
-          ></alfa-bescheid-wizard>
-        </ng-container>
+        @let bescheidStateResource = bescheidDraftStateResource$ | async;
+        <ods-button
+          variant="ghost"
+          size="fit"
+          class="absolute right-0 top-0 text-text"
+          (clickEmitter)="cancelWizard(bescheidStateResource.resource)"
+          dataTestId="close-bescheid"
+        >
+          <ods-close-icon icon />
+        </ods-button>
+        <alfa-bescheid-wizard
+          [vorgangWithEingangResource]="vorgangWithEingangResource"
+          [activeStep]="activeStep$ | async"
+          [bescheidStateResource]="bescheidStateResource"
+          (vorgangAbgeschlossen)="onVorgangAbgeschlossen()"
+          data-test-id="bescheid-wizard"
+        ></alfa-bescheid-wizard>
       </div>
     </div>
   </div>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.spec.ts
index 55cca698c53bc342a4a2546ce9bde17a57b5e889..1fe204ade444f7609bea459484de54ed0ab5a829 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.spec.ts
@@ -21,21 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { BescheidResource, BescheidService, BescheidWizardDialogResult, BescheidWizardStep } from '@alfa-client/bescheid-shared';
+import { BescheidResource, BescheidWizardDialogResult, BescheidWizardStep } from '@alfa-client/bescheid-shared';
 import { CommandOrder, CommandResource } from '@alfa-client/command-shared';
+import { createEmptyStateResource, createStateResource, ESCAPE_KEY, StateResource } from '@alfa-client/tech-shared';
 import {
-  ESCAPE_KEY,
-  StateResource,
-  createEmptyStateResource,
-  createErrorStateResource,
-  createStateResource,
-} from '@alfa-client/tech-shared';
-import {
-  DialogRefMock,
-  Mock,
   createDialogRefMock,
+  DialogRefMock,
   existsAsHtmlElement,
   getElementFromFixtureByType,
+  Mock,
   mock,
   triggerEvent,
   useFromMock,
@@ -47,15 +41,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ButtonComponent, CloseIconComponent } from '@ods/system';
 import { MockComponent } from 'ng-mocks';
 import { EMPTY, of } from 'rxjs';
+import { BescheidService2 } from '../../../../bescheid-shared/src/lib/bescheid2.service';
 import { createBescheidResource, createBescheidStateResource } from '../../../../bescheid-shared/src/test/bescheid';
-import {
-  createCommandErrorResource,
-  createCommandResource,
-  createSuccessfullyDoneCommandResource,
-  createSuccessfullyDoneCommandStateResource,
-} from '../../../../command-shared/test/command';
-import { getDataTestIdOf } from '../../../../tech-shared/test/data-test';
-import { createApiError } from '../../../../tech-shared/test/error';
+import { createCommandErrorResource, createSuccessfullyDoneCommandResource } from '../../../../command-shared/test/command';
+import { getDataTestIdAttributeOf, getDataTestIdOf } from '../../../../tech-shared/test/data-test';
 import { singleColdCompleted } from '../../../../tech-shared/test/marbles';
 import { createKeydownKeyboardEvent } from '../../../../test-utils/src/lib/keyboard';
 import { createVorgangWithEingangResource } from '../../../../vorgang-shared/test/vorgang';
@@ -73,9 +62,9 @@ describe('BescheidWizardContainerComponent', () => {
   let fixture: ComponentFixture<BescheidWizardContainerComponent>;
 
   const bescheidWizard: string = getDataTestIdOf('bescheid-wizard');
-  const closeButton: string = getDataTestIdOf('close-bescheid');
+  const closeButton: string = getDataTestIdAttributeOf('close-bescheid');
 
-  let bescheidService: Mock<BescheidService>;
+  let bescheidService: Mock<BescheidService2>;
   let ozgcloudDialogService: Mock<OzgcloudDialogService>;
   let formService: Mock<BescheidFormService>;
   let wizardDialogRef: DialogRefMock<BescheidWizardDialogResult>;
@@ -83,7 +72,8 @@ describe('BescheidWizardContainerComponent', () => {
   const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource();
 
   beforeEach(() => {
-    bescheidService = mock(BescheidService);
+    bescheidService = mock(BescheidService2);
+    bescheidService.getBescheidCreated.mockReturnValue(EMPTY);
     ozgcloudDialogService = mock(OzgcloudDialogService);
     formService = mock(BescheidFormService);
     wizardDialogRef = createDialogRefMock();
@@ -115,7 +105,7 @@ describe('BescheidWizardContainerComponent', () => {
           useValue: { vorgangWithEingangResource },
         },
         {
-          provide: BescheidService,
+          provide: BescheidService2,
           useValue: bescheidService,
         },
         {
@@ -160,6 +150,14 @@ describe('BescheidWizardContainerComponent', () => {
         expect(formService.setVorgangWithEingangResource).toHaveBeenCalledWith(vorgangWithEingangResource);
       });
 
+      it('should set active step', () => {
+        bescheidService.getActiveStep.mockReturnValue(of(BescheidWizardStep.BescheidVersenden));
+
+        component.ngOnInit();
+
+        expect(component.activeStep$).toBeObservable(singleColdCompleted(BescheidWizardStep.BescheidVersenden));
+      });
+
       it('should subscribe to bescheid resource', () => {
         component.subscribeToBescheidResourceIfExists = jest.fn();
 
@@ -231,74 +229,6 @@ describe('BescheidWizardContainerComponent', () => {
       });
     });
 
-    describe('onWeiter', () => {
-      beforeEach(() => {
-        formService.submit = jest.fn().mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
-        component.isBescheidSuccessfullyCreated = jest.fn().mockReturnValue(true);
-        bescheidService.getBescheidDraft.mockReturnValue(of(createBescheidStateResource()));
-      });
-
-      it('should submit form', () => {
-        component.onWeiter(BescheidWizardStep.DokumenteHochladen);
-
-        expect(formService.submit).toHaveBeenCalled();
-      });
-
-      it('should increment step on created bescheid', () => {
-        component.onWeiter(BescheidWizardStep.DokumenteHochladen);
-
-        component.submitStateResource$.subscribe();
-        expect(bescheidService.setActiveStep).toHaveBeenCalledWith(BescheidWizardStep.DokumenteHochladen);
-      });
-
-      it('should increment step on updated bescheid', () => {
-        component.isBescheidSuccessfullyCreated = jest.fn().mockReturnValue(false);
-
-        component.onWeiter(BescheidWizardStep.DokumenteHochladen);
-
-        component.submitStateResource$.subscribe();
-        expect(bescheidService.setActiveStep).toHaveBeenCalledWith(BescheidWizardStep.DokumenteHochladen);
-      });
-
-      it('should not increment step on command resource error', () => {
-        component.isBescheidSuccessfullyCreated = jest.fn().mockReturnValue(false);
-        formService.submit = jest.fn().mockReturnValue(of(createErrorStateResource(createApiError())));
-
-        component.onWeiter(BescheidWizardStep.DokumenteHochladen);
-
-        component.submitStateResource$.subscribe();
-        expect(bescheidService.setActiveStep).not.toHaveBeenCalled();
-      });
-
-      it('should not increment step on command resource loading', () => {
-        component.isBescheidSuccessfullyCreated = jest.fn().mockReturnValue(false);
-        formService.submit = jest.fn().mockReturnValue(of(createStateResource(createCommandResource(), true)));
-
-        component.onWeiter(BescheidWizardStep.DokumenteHochladen);
-
-        component.submitStateResource$.subscribe();
-        expect(bescheidService.setActiveStep).not.toHaveBeenCalled();
-      });
-
-      it('should not increment step on bescheid resource error', () => {
-        bescheidService.getBescheidDraft.mockReturnValue(of(createErrorStateResource(createApiError())));
-
-        component.onWeiter(BescheidWizardStep.DokumenteHochladen);
-
-        component.submitStateResource$.subscribe();
-        expect(bescheidService.setActiveStep).not.toHaveBeenCalled();
-      });
-
-      it('should not increment step on bescheid loading', () => {
-        bescheidService.getBescheidDraft.mockReturnValue(of(createStateResource(null, true)));
-
-        component.onWeiter(BescheidWizardStep.DokumenteHochladen);
-
-        component.submitStateResource$.subscribe();
-        expect(bescheidService.setActiveStep).not.toHaveBeenCalled();
-      });
-    });
-
     describe('isBescheidSuccessfullyCreated', () => {
       it('should return true', () => {
         const createBescheidCommandResource: CommandResource = {
@@ -498,81 +428,60 @@ describe('BescheidWizardContainerComponent', () => {
   });
 
   describe('template', () => {
-    describe('alfa-bescheid-wizard', () => {
+    describe('wizard', () => {
       function getElementComponent(): BescheidWizardComponent {
         return getElementFromFixtureByType(fixture, BescheidWizardComponent);
       }
 
-      describe('input', () => {
-        it('should set vorgangWithEingangResource', () => {
-          component.vorgangWithEingangResource = createVorgangWithEingangResource();
-
-          fixture.detectChanges();
-
-          expect(getElementComponent().vorgangWithEingangResource).toBe(component.vorgangWithEingangResource);
-        });
-
-        it('should set activeStep', () => {
-          bescheidService.getActiveStep.mockReturnValue(of(2));
-
-          fixture.detectChanges();
-
-          expect(getElementComponent().activeStep).toBe(2);
-        });
-
-        it('should set bescheidStateResource', () => {
-          const bescheidStateResource: StateResource<BescheidResource> = createBescheidStateResource();
-          component.bescheidDraftStateResource$ = of(bescheidStateResource);
+      it('should have been called with inputs', () => {
+        component.vorgangWithEingangResource = createVorgangWithEingangResource();
+        bescheidService.getActiveStep.mockReturnValue(of(BescheidWizardStep.DokumenteHochladen));
+        const bescheidStateResource: StateResource<BescheidResource> = createBescheidStateResource();
+        component.bescheidDraftStateResource$ = of(bescheidStateResource);
+        component.ngOnInit();
 
-          fixture.detectChanges();
+        fixture.detectChanges();
 
-          expect(getElementComponent().bescheidStateResource).toBe(bescheidStateResource);
-        });
+        expect(getElementComponent().vorgangWithEingangResource).toEqual(component.vorgangWithEingangResource);
+        expect(getElementComponent().activeStep).toEqual(2);
+        expect(getElementComponent().bescheidStateResource).toEqual(bescheidStateResource);
       });
 
       describe('output', () => {
-        it('should call onWeiter', () => {
-          component.onWeiter = jest.fn();
+        describe('vorgangAbgeschlossen', () => {
+          it('should call onVorgangAbgeschlossen', () => {
+            component.onVorgangAbgeschlossen = jest.fn();
 
-          triggerEvent({
-            fixture,
-            name: 'weiterClickEmitter',
-            elementSelector: bescheidWizard,
-          });
-
-          expect(component.onWeiter).toHaveBeenCalled();
-        });
-
-        it('should call onVorgangAbgeschlossen', () => {
-          component.onVorgangAbgeschlossen = jest.fn();
+            triggerEvent({
+              fixture,
+              name: 'vorgangAbgeschlossen',
+              elementSelector: bescheidWizard,
+            });
 
-          triggerEvent({
-            fixture,
-            name: 'vorgangAbgeschlossen',
-            elementSelector: bescheidWizard,
+            expect(component.onVorgangAbgeschlossen).toHaveBeenCalled();
           });
-
-          expect(component.onVorgangAbgeschlossen).toHaveBeenCalled();
         });
       });
     });
 
-    describe('ods-button close', () => {
-      it('should show', () => {
+    describe('close button', () => {
+      it('should exists', () => {
         existsAsHtmlElement(fixture, closeButton);
       });
 
       describe('output', () => {
-        it('should call cancelWizard', () => {
-          component.cancelWizard = jest.fn();
+        describe('clickEmitter', () => {
+          it('should call cancelWizard', () => {
+            component.cancelWizard = jest.fn();
 
-          triggerEvent({
-            fixture,
-            name: 'clickEmitter',
-            elementSelector: closeButton,
-          });
+            triggerEvent({
+              fixture,
+              name: 'clickEmitter',
+              elementSelector: closeButton,
+            });
 
-          expect(component.cancelWizard).toHaveBeenCalled();
+            expect(component.cancelWizard).toHaveBeenCalled();
+          });
         });
       });
     });
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.ts
index d3be996f4a86c3236bbc64cfb9ec74baa5f9b761..cba4185d1a3d6805f5291ad6972c11965ed40fc5 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.ts
@@ -21,28 +21,19 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { BescheidResource, BescheidService, BescheidWizardDialogResult, BescheidWizardStep } from '@alfa-client/bescheid-shared';
-import { CommandOrder, CommandResource, isSuccessfulDone } from '@alfa-client/command-shared';
-import {
-  StateResource,
-  createEmptyStateResource,
-  hasStateResourceError,
-  isEscapeKey,
-  isLoaded,
-  isNotLoading,
-  isNotNil,
-} from '@alfa-client/tech-shared';
+import { BescheidResource, BescheidWizardDialogResult, BescheidWizardStep } from '@alfa-client/bescheid-shared';
+import { CommandOrder, CommandResource, CommandService, isSuccessfulDone } from '@alfa-client/command-shared';
+import { createEmptyStateResource, isEscapeKey, isNotLoading, isNotNil, ResourceRepository, StateResource, } from '@alfa-client/tech-shared';
 import { OzgcloudDialogService } from '@alfa-client/ui';
-import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { VorgangService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { getEmpfaenger } from '@alfa-client/vorgang-shared-ui';
 import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';
-import { Component, Inject, OnDestroy, OnInit, ViewContainerRef } from '@angular/core';
-import { Resource, hasLink } from '@ngxp/rest';
-import { Observable, Subscription, filter, first, of, switchMap, tap } from 'rxjs';
-import {
-  BescheidWizardCancelDialogContainerComponent,
-  CancelWizardDialogData,
-  CancelWizardDialogResult,
-} from './bescheid-wizard/cancel-dialog-container/bescheid-wizard-cancel-dialog-container.component';
+import { Component, inject, OnDestroy, OnInit, ViewContainerRef } from '@angular/core';
+import { hasLink } from '@ngxp/rest';
+import { BescheidResourceService, createBescheidResourceService } from 'libs/bescheid-shared/src/lib/bescheid-resource-service';
+import { filter, first, Observable, of, Subscription, switchMap } from 'rxjs';
+import { BescheidService2 } from '../../../../bescheid-shared/src/lib/bescheid2.service';
+import { BescheidWizardCancelDialogContainerComponent, CancelWizardDialogData, CancelWizardDialogResult, } from './bescheid-wizard/cancel-dialog-container/bescheid-wizard-cancel-dialog-container.component';
 import { BescheidFormService } from './bescheid.formservice';
 
 export interface BescheidWizardDialogData {
@@ -52,42 +43,63 @@ export interface BescheidWizardDialogData {
 @Component({
   selector: 'alfa-bescheid-wizard-container',
   templateUrl: './bescheid-wizard-container.component.html',
-  providers: [BescheidFormService],
+  providers: [
+    BescheidFormService,
+    BescheidService2,
+    {
+      provide: BescheidResourceService,
+      useFactory: createBescheidResourceService,
+      deps: [ResourceRepository, CommandService, VorgangService],
+    },
+  ],
 })
 export class BescheidWizardContainerComponent implements OnInit, OnDestroy {
+  private readonly bescheidService = inject(BescheidService2);
+  private readonly ozgcloudDialogService = inject(OzgcloudDialogService);
+  private readonly dialogData: BescheidWizardDialogData = inject(DIALOG_DATA);
+  private readonly dialogRef = inject(DialogRef<BescheidWizardDialogResult>);
+  private readonly formService = inject(BescheidFormService);
+  readonly viewContainerRef = inject(ViewContainerRef);
+
   public bescheidDraftStateResource$: Observable<StateResource<BescheidResource>> =
     of(createEmptyStateResource<BescheidResource>());
-  public submitStateResource$: Observable<StateResource<Resource>> = of(createEmptyStateResource<Resource>());
+  public activeStep$: Observable<BescheidWizardStep>;
 
   cancelDialogRef: DialogRef<CancelWizardDialogResult>;
   vorgangWithEingangResource: VorgangWithEingangResource;
   keydownEventsSubscription: Subscription;
 
-  constructor(
-    @Inject(DIALOG_DATA) private readonly dialogData: BescheidWizardDialogData,
-    private readonly dialogRef: DialogRef<BescheidWizardDialogResult>,
-    readonly viewContainerRef: ViewContainerRef,
-    public readonly formService: BescheidFormService,
-    readonly bescheidService: BescheidService,
-    private readonly ozgcloudDialogService: OzgcloudDialogService,
-  ) {
-    this.vorgangWithEingangResource = dialogData.vorgangWithEingangResource;
+  constructor() {
+    this.vorgangWithEingangResource = this.dialogData.vorgangWithEingangResource;
   }
 
   ngOnInit(): void {
     this.bescheidService.init();
+    this.bescheidService.setNachrichtEmpfaenger(getEmpfaenger(this.vorgangWithEingangResource));
     this.formService.setVorgangWithEingangResource(this.vorgangWithEingangResource);
+    this.activeStep$ = this.bescheidService.getActiveStep();
     this.subscribeToBescheidResourceIfExists();
     this.handleEscapeKey();
   }
 
   ngOnDestroy(): void {
     this.keydownEventsSubscription.unsubscribe();
+    this.bescheidService.exit();
   }
 
   subscribeToBescheidResourceIfExists(): void {
     if (hasLink(this.vorgangWithEingangResource, VorgangWithEingangLinkRel.BESCHEID_DRAFT)) {
       this.bescheidDraftStateResource$ = this.bescheidService.getBescheidDraft();
+    } else {
+      this.bescheidService
+        .getBescheidCreated()
+        .pipe(
+          filter((created: boolean) => created),
+          first(),
+        )
+        .subscribe(() => {
+          this.bescheidDraftStateResource$ = this.bescheidService.selectBescheidResource();
+        });
     }
   }
 
@@ -103,23 +115,6 @@ export class BescheidWizardContainerComponent implements OnInit, OnDestroy {
       });
   }
 
-  public onWeiter(nextStep: BescheidWizardStep): void {
-    this.submitStateResource$ = this.formService.submit().pipe(
-      switchMap((commandStateResource: StateResource<CommandResource>) => {
-        if (this.isBescheidSuccessfullyCreated(commandStateResource.resource)) {
-          this.bescheidDraftStateResource$ = this.bescheidService.getBescheidDraft();
-          return this.bescheidDraftStateResource$;
-        }
-        return of(commandStateResource);
-      }),
-      tap((stateResource: StateResource<Resource>) => {
-        if (isLoaded(stateResource) && !hasStateResourceError(stateResource)) {
-          this.bescheidService.setActiveStep(nextStep);
-        }
-      }),
-    );
-  }
-
   isBescheidSuccessfullyCreated(commandResource: CommandResource): boolean {
     return isSuccessfulDone(commandResource) && commandResource.order === CommandOrder.CREATE_BESCHEID;
   }
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-button/bescheid-wizard-abschliessen-button.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-button/bescheid-wizard-abschliessen-button.component.html
similarity index 100%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-button/bescheid-wizard-abschliessen-button.component.html
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-button/bescheid-wizard-abschliessen-button.component.html
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-button/bescheid-wizard-abschliessen-button.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-button/bescheid-wizard-abschliessen-button.component.spec.ts
similarity index 82%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-button/bescheid-wizard-abschliessen-button.component.spec.ts
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-button/bescheid-wizard-abschliessen-button.component.spec.ts
index 82b7402b1b2792d8ddd554934d8b9a5fb8071811..52f9b2e3270123a2dbf0204ef563ba4a38ab5e9c 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-button/bescheid-wizard-abschliessen-button.component.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-button/bescheid-wizard-abschliessen-button.component.spec.ts
@@ -21,31 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import {
-  createDialogRefMock,
-  DialogRefMock,
-  existsAsHtmlElement,
-  mock,
-  Mock,
-  triggerEvent,
-  useFromMock,
-} from '@alfa-client/test-utils';
-import { OzgcloudDialogService } from '@alfa-client/ui';
+import { BescheidResource } from '@alfa-client/bescheid-shared';
+import { createDialogRefMock, DialogRefMock, existsAsHtmlElement, mock, Mock, triggerEvent, useFromMock, } from '@alfa-client/test-utils';
+import { createDialogResult, OzgcloudDialogCommandResult, OzgcloudDialogService } from '@alfa-client/ui';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { EventEmitter } from '@angular/core';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { of } from 'rxjs';
-import { createSuccessfullyDoneCommandStateResource } from '../../../../../../command-shared/test/command';
-import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
-import {
-  createDialogResult,
-  OzgcloudDialogCommandResult,
-} from '../../../../../../ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.result';
-import { createVorgangWithEingangResource } from '../../../../../../vorgang-shared/test/vorgang';
-import {
-  AbschliessenDialogData,
-  BescheidWizardAbschliessenDialogContainerComponent,
-} from '../abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component';
+import { createBescheidResource } from '../../../../../../../bescheid-shared/src/test/bescheid';
+import { createSuccessfullyDoneCommandStateResource } from '../../../../../../../command-shared/test/command';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { createVorgangWithEingangResource } from '../../../../../../../vorgang-shared/test/vorgang';
+import { AbschliessenDialogData, BescheidWizardAbschliessenDialogContainerComponent, } from '../abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component';
 import { BescheidWizardAbschliessenButtonComponent } from './bescheid-wizard-abschliessen-button.component';
 
 describe('BescheidWizardAbschliessenButtonComponent', () => {
@@ -89,14 +76,16 @@ describe('BescheidWizardAbschliessenButtonComponent', () => {
 
       it('should open dialog', () => {
         const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource();
+        const bescheidResource: BescheidResource = createBescheidResource();
         component.vorgangWithEingangResource = vorgangWithEingangResource;
+        component.bescheidResource = bescheidResource;
 
         component.onClick();
 
         expect(ozgcloudDialogService.openInCallingComponentContext).toHaveBeenCalledWith(
           BescheidWizardAbschliessenDialogContainerComponent,
           component.viewContainerRef,
-          { vorgangWithEingangResource } as AbschliessenDialogData,
+          { vorgangWithEingangResource, bescheidResource } as AbschliessenDialogData,
         );
       });
 
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-button/bescheid-wizard-abschliessen-button.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-button/bescheid-wizard-abschliessen-button.component.ts
similarity index 70%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-button/bescheid-wizard-abschliessen-button.component.ts
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-button/bescheid-wizard-abschliessen-button.component.ts
index 506fee1b6090c5bfcaf238d866b95b8cf284c711..c6622e64f1f3ee3dce37cef72ed5371892a7893c 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-button/bescheid-wizard-abschliessen-button.component.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-button/bescheid-wizard-abschliessen-button.component.ts
@@ -21,15 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { BescheidResource } from '@alfa-client/bescheid-shared';
 import { OzgcloudDialogService } from '@alfa-client/ui';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { DialogRef } from '@angular/cdk/dialog';
-import { Component, EventEmitter, Input, Output, ViewContainerRef } from '@angular/core';
+import { Component, EventEmitter, inject, Input, Output, ViewContainerRef } from '@angular/core';
 import { filter } from 'rxjs';
 import {
-  OzgcloudDialogCommandResult,
   isDialogSuccessfullyCompleted,
-} from '../../../../../../ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.result';
+  OzgcloudDialogCommandResult,
+} from '../../../../../../../ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.result';
 import {
   AbschliessenDialogData,
   BescheidWizardAbschliessenDialogContainerComponent,
@@ -38,35 +39,33 @@ import {
 @Component({
   selector: 'alfa-bescheid-wizard-abschliessen-button',
   templateUrl: './bescheid-wizard-abschliessen-button.component.html',
+  styles: [':host {@apply flex-1 flex items-end}'],
 })
 export class BescheidWizardAbschliessenButtonComponent {
   @Input() vorgangWithEingangResource: VorgangWithEingangResource;
+  @Input() bescheidResource: BescheidResource;
 
   @Output() vorgangAbgeschlossen: EventEmitter<void> = new EventEmitter<void>();
 
-  constructor(
-    private readonly ozgclouDialogService: OzgcloudDialogService,
-    readonly viewContainerRef: ViewContainerRef,
-  ) {}
+  private readonly ozgcloudDialogService = inject(OzgcloudDialogService);
+  readonly viewContainerRef = inject(ViewContainerRef);
 
   public onClick(): void {
     const dialogData: AbschliessenDialogData = {
       vorgangWithEingangResource: this.vorgangWithEingangResource,
+      bescheidResource: this.bescheidResource,
     };
 
-    const dialogRef: DialogRef<OzgcloudDialogCommandResult> =
-      this.ozgclouDialogService.openInCallingComponentContext(
-        BescheidWizardAbschliessenDialogContainerComponent,
-        this.viewContainerRef,
-        dialogData,
-      );
+    const dialogRef: DialogRef<OzgcloudDialogCommandResult> = this.ozgcloudDialogService.openInCallingComponentContext(
+      BescheidWizardAbschliessenDialogContainerComponent,
+      this.viewContainerRef,
+      dialogData,
+    );
 
     this.handleDialogClosed(dialogRef);
   }
 
   handleDialogClosed(dialogRef: DialogRef<OzgcloudDialogCommandResult>): void {
-    dialogRef.closed
-      .pipe(filter(isDialogSuccessfullyCompleted))
-      .subscribe(() => this.vorgangAbgeschlossen.emit());
+    dialogRef.closed.pipe(filter(isDialogSuccessfullyCompleted)).subscribe(() => this.vorgangAbgeschlossen.emit());
   }
 }
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.html
similarity index 100%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.html
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.html
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.spec.ts
similarity index 75%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.spec.ts
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.spec.ts
index 01d76234027235a6d5417fd1ec6758d5d6c4f24b..df6b0e09d088b27f5601ba9b12abf43363b8a0a7 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.spec.ts
@@ -21,33 +21,24 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { BescheidService } from '@alfa-client/bescheid-shared';
+import { BescheidResource } from '@alfa-client/bescheid-shared';
 import { CommandResource } from '@alfa-client/command-shared';
 import { StateResource } from '@alfa-client/tech-shared';
-import {
-  createDialogRefMock,
-  DialogRefMock,
-  getElementComponentFromFixtureByCss,
-  mock,
-  Mock,
-  triggerEvent,
-} from '@alfa-client/test-utils';
-import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
+import { createDialogRefMock, DialogRefMock, getElementComponentFromFixtureByCss, mock, Mock, triggerEvent, } from '@alfa-client/test-utils';
+import { createDialogResult, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatIcon } from '@angular/material/icon';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
-import { createSuccessfullyDoneCommandStateResource } from '../../../../../../command-shared/test/command';
-import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
-import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
-import { createDialogResult } from '../../../../../../ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.result';
-import { createVorgangWithEingangResource } from '../../../../../../vorgang-shared/test/vorgang';
-import {
-  AbschliessenDialogData,
-  BescheidWizardAbschliessenDialogContainerComponent,
-} from './bescheid-wizard-abschliessen-dialog-container.component';
+import { BescheidService2 } from '../../../../../../../bescheid-shared/src/lib/bescheid2.service';
+import { createBescheidResource } from '../../../../../../../bescheid-shared/src/test/bescheid';
+import { createSuccessfullyDoneCommandStateResource } from '../../../../../../../command-shared/test/command';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { singleColdCompleted } from '../../../../../../../tech-shared/test/marbles';
+import { createVorgangWithEingangResource } from '../../../../../../../vorgang-shared/test/vorgang';
+import { AbschliessenDialogData, BescheidWizardAbschliessenDialogContainerComponent, } from './bescheid-wizard-abschliessen-dialog-container.component';
 
 describe('BescheidWizardAbschliessenDialogContainerComponent', () => {
   let component: BescheidWizardAbschliessenDialogContainerComponent;
@@ -57,13 +48,14 @@ describe('BescheidWizardAbschliessenDialogContainerComponent', () => {
   const confirmButtonDataTestId: string = getDataTestIdOf('ueberspringen-abschliessen-button');
   const cancelButtonDataTestId: string = getDataTestIdOf('ueberspringen-abbrechen-button');
   const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource();
-  const dialogData: AbschliessenDialogData = { vorgangWithEingangResource };
+  const bescheidResource: BescheidResource = createBescheidResource();
+  const dialogData: AbschliessenDialogData = { vorgangWithEingangResource, bescheidResource };
 
   let dialogRef: DialogRefMock;
-  let bescheidService: Mock<BescheidService>;
+  let bescheidService: Mock<BescheidService2>;
 
   beforeEach(() => {
-    bescheidService = mock(BescheidService);
+    bescheidService = mock(BescheidService2);
     dialogRef = createDialogRefMock();
   });
 
@@ -84,7 +76,7 @@ describe('BescheidWizardAbschliessenDialogContainerComponent', () => {
           useValue: dialogRef,
         },
         {
-          provide: BescheidService,
+          provide: BescheidService2,
           useValue: bescheidService,
         },
       ],
@@ -111,16 +103,16 @@ describe('BescheidWizardAbschliessenDialogContainerComponent', () => {
     describe('onConfirm', () => {
       it('should call bescheid service', () => {
         const commandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
-        bescheidService.bescheidErstellungUeberspringen.mockReturnValue(of(commandStateResource));
+        bescheidService.skipBescheidCreation.mockReturnValue(of(commandStateResource));
 
         component.onConfirm();
 
-        expect(bescheidService.bescheidErstellungUeberspringen).toHaveBeenCalledWith(vorgangWithEingangResource);
+        expect(bescheidService.skipBescheidCreation).toHaveBeenCalledWith(vorgangWithEingangResource, bescheidResource);
       });
 
       it('should set abschliessen$', () => {
         const commandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
-        bescheidService.bescheidErstellungUeberspringen.mockReturnValue(of(commandStateResource));
+        bescheidService.skipBescheidCreation.mockReturnValue(of(commandStateResource));
 
         component.onConfirm();
 
@@ -129,7 +121,7 @@ describe('BescheidWizardAbschliessenDialogContainerComponent', () => {
 
       it('should close dialog', () => {
         const commandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
-        bescheidService.bescheidErstellungUeberspringen.mockReturnValue(of(commandStateResource));
+        bescheidService.skipBescheidCreation.mockReturnValue(of(commandStateResource));
 
         component.onConfirm();
         component.abschliessen$.subscribe();
@@ -140,7 +132,7 @@ describe('BescheidWizardAbschliessenDialogContainerComponent', () => {
   });
 
   describe('template', () => {
-    describe('button close', () => {
+    describe('close button', () => {
       describe('output', () => {
         it('should call onClose', () => {
           component.onClose = jest.fn();
@@ -152,7 +144,7 @@ describe('BescheidWizardAbschliessenDialogContainerComponent', () => {
       });
     });
 
-    describe('ozgcloud-stroked-button-with-spinner Überspringen und abschließen', () => {
+    describe('überspringen und abschließen button', () => {
       function getElementComponent(): OzgcloudStrokedButtonWithSpinnerComponent {
         return getElementComponentFromFixtureByCss(fixture, confirmButtonDataTestId);
       }
@@ -172,18 +164,14 @@ describe('BescheidWizardAbschliessenDialogContainerComponent', () => {
         it('should call onConfirm', () => {
           component.onConfirm = jest.fn();
 
-          triggerEvent({
-            fixture,
-            name: 'click',
-            elementSelector: confirmButtonDataTestId,
-          });
+          triggerEvent({ fixture, name: 'click', elementSelector: confirmButtonDataTestId });
 
           expect(component.onConfirm).toHaveBeenCalled();
         });
       });
     });
 
-    describe('ozgcloud-stroked-button-with-spinner Abbrechen', () => {
+    describe('abbrechen button', () => {
       it('should call onClose', () => {
         component.onClose = jest.fn();
 
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.ts
similarity index 78%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.ts
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.ts
index f147cfea08b03a214884c2d4d5d5c8414df4b4be..5a8ace4040ce03c2e7cff5f2efc3f24877d0f201 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component.ts
@@ -21,17 +21,19 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { BescheidService } from '@alfa-client/bescheid-shared';
+import { BescheidResource } from '@alfa-client/bescheid-shared';
 import { CommandResource, tapOnCommandSuccessfullyDone } from '@alfa-client/command-shared';
 import { StateResource } from '@alfa-client/tech-shared';
 import { createDialogResult } from '@alfa-client/ui';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';
-import { Component, Inject } from '@angular/core';
+import { Component, inject } from '@angular/core';
 import { Observable } from 'rxjs';
+import { BescheidService2 } from '../../../../../../../bescheid-shared/src/lib/bescheid2.service';
 
 export interface AbschliessenDialogData {
   vorgangWithEingangResource: VorgangWithEingangResource;
+  bescheidResource: BescheidResource;
 }
 
 @Component({
@@ -39,21 +41,20 @@ export interface AbschliessenDialogData {
   templateUrl: './bescheid-wizard-abschliessen-dialog-container.component.html',
 })
 export class BescheidWizardAbschliessenDialogContainerComponent {
-  public abschliessen$: Observable<StateResource<CommandResource>>;
+  private readonly dialogData: AbschliessenDialogData = inject(DIALOG_DATA);
+  private readonly dialogRef = inject(DialogRef);
+  private readonly bescheidService = inject(BescheidService2);
 
-  constructor(
-    @Inject(DIALOG_DATA) private readonly dialogData: AbschliessenDialogData,
-    private readonly dialogRef: DialogRef,
-    private readonly bescheidService: BescheidService,
-  ) {}
+  public abschliessen$: Observable<StateResource<CommandResource>>;
 
   public onClose(): void {
     this.dialogRef.close();
   }
 
   public onConfirm(): void {
+    // @ts-ignore
     this.abschliessen$ = this.bescheidService
-      .bescheidErstellungUeberspringen(this.dialogData.vorgangWithEingangResource)
+      .skipBescheidCreation(this.dialogData.vorgangWithEingangResource, this.dialogData.bescheidResource)
       .pipe(
         tapOnCommandSuccessfullyDone((commandStateResource: StateResource<CommandResource>) =>
           this.dialogRef.close(createDialogResult(commandStateResource)),
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden-container.component.html
similarity index 75%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden.component.html
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden-container.component.html
index 6d9e44922fc835eaffab2615c9a54659f928a195..025f01d04b1065869baaffd5dc7814c956f6850f 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden-container.component.html
@@ -23,29 +23,25 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<div class="mt-2 grid h-full grid-cols-[min-content_1fr_1fr] gap-7">
-  <alfa-bescheid-wizard-stepper
-    [activeStep]="bescheidWizardStep.AntragBescheiden"
-    data-test-id="wizard-stepper"
-  ></alfa-bescheid-wizard-stepper>
-  <div>
-    <alfa-bescheid-wizard-step-title label="Antrag bescheiden" data-test-id="wizard-step-title"></alfa-bescheid-wizard-step-title>
+<alfa-step-content-layout [activeStep]="BescheidWizardStep.AntragBescheiden">
+  <ng-container stepPanel>
+    <alfa-bescheid-wizard-step-title label="Antrag bescheiden" data-test-id="wizard-step-title" />
     <alfa-bescheid-wizard-antrag-bescheiden-form
       [vorgangWithEingangResource]="vorgangWithEingangResource"
       [bescheidResource]="bescheidResource"
-      [submitStateResource]="submitStateResource"
-      (weiterClickEmitter)="weiterClickEmitter.emit(bescheidWizardStep.DokumenteHochladen)"
+      (weiterClickEmitter)="onWeiterClick()"
       data-test-id="antrag-bescheiden-form"
     ></alfa-bescheid-wizard-antrag-bescheiden-form>
     <alfa-bescheid-wizard-abschliessen-button
       [vorgangWithEingangResource]="vorgangWithEingangResource"
+      [bescheidResource]="bescheidResource"
       (vorgangAbgeschlossen)="vorgangAbgeschlossen.emit()"
       data-test-id="wizard-abschliessen-button"
     ></alfa-bescheid-wizard-abschliessen-button>
-  </div>
-  <alfa-bescheid-wizard-summary data-test-id="wizard-summary">
+  </ng-container>
+  <ng-container summary>
     <alfa-bescheid-wizard-antrag-bescheiden-summary
       data-test-id="antrag-bescheiden-summary"
     ></alfa-bescheid-wizard-antrag-bescheiden-summary>
-  </alfa-bescheid-wizard-summary>
-</div>
+  </ng-container>
+</alfa-step-content-layout>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden-container.component.spec.ts
similarity index 54%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden.component.spec.ts
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden-container.component.spec.ts
index a2a12395ea886598dae1607d5836a41dc2602097..d3452acaabaa91d8cced04afc925138dd1d2d546 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden.component.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden-container.component.spec.ts
@@ -21,44 +21,43 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { BescheidService, BescheidWizardStep } from '@alfa-client/bescheid-shared';
-import { Mock, existsAsHtmlElement, getElementFromFixtureByType, mock, triggerEvent, useFromMock } from '@alfa-client/test-utils';
+import { existsAsHtmlElement, getElementFromFixtureByType, Mock, mock, triggerEvent, useFromMock } from '@alfa-client/test-utils';
 import { EventEmitter } from '@angular/core';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MockComponent } from 'ng-mocks';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
 import { createBescheidResource } from '../../../../../../bescheid-shared/src/test/bescheid';
-import { createCommandStateResource } from '../../../../../../command-shared/test/command';
 import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from '../../../../../../vorgang-shared/test/vorgang';
-import { BescheidWizardAbschliessenButtonComponent } from '../abschliessen-button/bescheid-wizard-abschliessen-button.component';
+import { StepContentLayoutComponent } from '../step-content-layout/step-content-layout.component';
 import { BescheidWizardStepTitleComponent } from '../step-title/bescheid-wizard-step-title.component';
 import { BescheidWizardStepperComponent } from '../stepper/bescheid-wizard-stepper.component';
 import { BescheidWizardSummaryComponent } from '../summary/bescheid-wizard-summary.component';
-import { BescheidWizardAntragBescheidenComponent } from './bescheid-wizard-antrag-bescheiden.component';
+import { BescheidWizardAbschliessenButtonComponent } from './abschliessen-button/bescheid-wizard-abschliessen-button.component';
+import { BescheidWizardAntragBescheidenContainerComponent } from './bescheid-wizard-antrag-bescheiden-container.component';
 import { BescheidWizardAntragBescheidenFormComponent } from './form/bescheid-wizard-antrag-bescheiden-form.component';
 import { BescheidWizardAntragBescheidenSummaryComponent } from './summary/bescheid-wizard-antrag-bescheiden-summary.component';
 
 describe('BescheidWizardAntragBescheidenComponent', () => {
-  let component: BescheidWizardAntragBescheidenComponent;
-  let fixture: ComponentFixture<BescheidWizardAntragBescheidenComponent>;
+  let component: BescheidWizardAntragBescheidenContainerComponent;
+  let fixture: ComponentFixture<BescheidWizardAntragBescheidenContainerComponent>;
 
-  const wizardStepper: string = getDataTestIdOf('wizard-stepper');
   const wizardStepTitle: string = getDataTestIdOf('wizard-step-title');
   const antragBescheidenForm: string = getDataTestIdOf('antrag-bescheiden-form');
   const abschliessenButton: string = getDataTestIdOf('wizard-abschliessen-button');
-  const wizardSummary: string = getDataTestIdOf('wizard-summary');
   const antragBescheidenSummary: string = getDataTestIdOf('antrag-bescheiden-summary');
 
-  let bescheidService: Mock<BescheidService>;
+  let bescheidService: Mock<BescheidService2>;
 
   beforeEach(() => {
-    bescheidService = mock(BescheidService);
+    bescheidService = mock(BescheidService2);
   });
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       declarations: [
-        BescheidWizardAntragBescheidenComponent,
+        BescheidWizardAntragBescheidenContainerComponent,
+        MockComponent(StepContentLayoutComponent),
         MockComponent(BescheidWizardStepTitleComponent),
         MockComponent(BescheidWizardAntragBescheidenFormComponent),
         MockComponent(BescheidWizardSummaryComponent),
@@ -68,15 +67,14 @@ describe('BescheidWizardAntragBescheidenComponent', () => {
       ],
       providers: [
         {
-          provide: BescheidService,
+          provide: BescheidService2,
           useValue: bescheidService,
         },
       ],
     }).compileComponents();
 
-    fixture = TestBed.createComponent(BescheidWizardAntragBescheidenComponent);
+    fixture = TestBed.createComponent(BescheidWizardAntragBescheidenContainerComponent);
     component = fixture.componentInstance;
-    component.weiterClickEmitter = useFromMock(mock(EventEmitter<BescheidWizardStep>));
     component.vorgangAbgeschlossen = useFromMock(mock(EventEmitter<void>));
     fixture.detectChanges();
   });
@@ -86,121 +84,75 @@ describe('BescheidWizardAntragBescheidenComponent', () => {
   });
 
   describe('template', () => {
-    describe('alfa-bescheid-wizard-stepper', () => {
-      function getElementComponent(): BescheidWizardStepperComponent {
-        return getElementFromFixtureByType(fixture, BescheidWizardStepperComponent);
+    describe('wizard step title', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, wizardStepTitle);
+      });
+    });
+
+    describe('antrag bescheiden form', () => {
+      function getElementComponent(): BescheidWizardAntragBescheidenFormComponent {
+        return getElementFromFixtureByType(fixture, BescheidWizardAntragBescheidenFormComponent);
       }
 
       it('should exists', () => {
-        fixture.detectChanges();
-
-        existsAsHtmlElement(fixture, wizardStepper);
+        existsAsHtmlElement(fixture, antragBescheidenForm);
       });
 
-      describe('input', () => {
-        it('should set activeStep', () => {
-          fixture.detectChanges();
+      it('should have been called with inputs', () => {
+        component.vorgangWithEingangResource = createVorgangWithEingangResource();
+        component.bescheidResource = createBescheidResource();
 
-          expect(getElementComponent().activeStep).toBe(BescheidWizardStep.AntragBescheiden);
-        });
-      });
-    });
+        fixture.detectChanges();
 
-    describe('alfa-bescheid-wizard-step-title', () => {
-      it('should show', () => {
-        existsAsHtmlElement(fixture, wizardStepTitle);
+        expect(getElementComponent().vorgangWithEingangResource).toBe(component.vorgangWithEingangResource);
+        expect(getElementComponent().bescheidResource).toBe(component.bescheidResource);
       });
-    });
 
-    describe('alfa-bescheid-wizard-summary', () => {
-      it('should show', () => {
-        existsAsHtmlElement(fixture, wizardSummary);
-      });
-    });
+      describe('output', () => {
+        describe('weiterClickEmitter', () => {
+          it('should call handler', () => {
+            component.onWeiterClick = jest.fn();
 
-    describe('alfa-bescheid-wizard-antrag-bescheiden-summary', () => {
-      it('should show', () => {
-        existsAsHtmlElement(fixture, antragBescheidenSummary);
+            triggerEvent({ fixture, name: 'weiterClickEmitter', elementSelector: antragBescheidenForm });
+
+            expect(component.onWeiterClick).toHaveBeenCalled();
+          });
+        });
       });
     });
 
-    describe('alfa-bescheid-wizard-abschliessen-button', () => {
+    describe('abschliessen button', () => {
       function getElementComponent(): BescheidWizardAbschliessenButtonComponent {
         return getElementFromFixtureByType(fixture, BescheidWizardAbschliessenButtonComponent);
       }
 
-      it('should show', () => {
+      it('should exists', () => {
         existsAsHtmlElement(fixture, abschliessenButton);
       });
 
-      describe('input', () => {
-        it('should set vorgangWithEingangResource', () => {
-          component.vorgangWithEingangResource = createVorgangWithEingangResource();
+      it('should have been called with inputs', () => {
+        component.vorgangWithEingangResource = createVorgangWithEingangResource();
+        component.bescheidResource = createBescheidResource();
 
-          fixture.detectChanges();
+        fixture.detectChanges();
 
-          expect(getElementComponent().vorgangWithEingangResource).toBe(component.vorgangWithEingangResource);
-        });
+        expect(getElementComponent().vorgangWithEingangResource).toBe(component.vorgangWithEingangResource);
+        expect(getElementComponent().bescheidResource).toBe(component.bescheidResource);
       });
 
       describe('output', () => {
-        it('should call onVorgangAbgeschlossen', () => {
-          triggerEvent({
-            fixture,
-            name: 'vorgangAbgeschlossen',
-            elementSelector: abschliessenButton,
-          });
+        it('should call handler', () => {
+          triggerEvent({ fixture, name: 'vorgangAbgeschlossen', elementSelector: abschliessenButton });
 
           expect(component.vorgangAbgeschlossen.emit).toHaveBeenCalled();
         });
       });
     });
 
-    describe('alfa-bescheid-wizard-antrag-bescheiden-form', () => {
-      function getElementComponent(): BescheidWizardAntragBescheidenFormComponent {
-        return getElementFromFixtureByType(fixture, BescheidWizardAntragBescheidenFormComponent);
-      }
-
-      it('should show', () => {
-        existsAsHtmlElement(fixture, antragBescheidenForm);
-      });
-
-      describe('input', () => {
-        it('should set vorgangWithEingangResource', () => {
-          component.vorgangWithEingangResource = createVorgangWithEingangResource();
-
-          fixture.detectChanges();
-
-          expect(getElementComponent().vorgangWithEingangResource).toBe(component.vorgangWithEingangResource);
-        });
-
-        it('should set bescheidResource', () => {
-          component.bescheidResource = createBescheidResource();
-
-          fixture.detectChanges();
-
-          expect(getElementComponent().bescheidResource).toBe(component.bescheidResource);
-        });
-
-        it('should set submitStateResource', () => {
-          component.submitStateResource = createCommandStateResource();
-
-          fixture.detectChanges();
-
-          expect(getElementComponent().submitStateResource).toBe(component.submitStateResource);
-        });
-      });
-
-      describe('output', () => {
-        it('should emit weiterClickEmitter', () => {
-          triggerEvent({
-            fixture,
-            name: 'weiterClickEmitter',
-            elementSelector: antragBescheidenForm,
-          });
-
-          expect(component.weiterClickEmitter.emit).toHaveBeenCalledWith(BescheidWizardStep.DokumenteHochladen);
-        });
+    describe('antrag bescheiden summary', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, antragBescheidenSummary);
       });
     });
   });
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden-container.component.ts
similarity index 68%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden.component.ts
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden-container.component.ts
index 2dcbf71a91305c14e8c10cd4b8c4130f1609f715..9837cbe2bca5ed1e8ff4f9674d10895c476d7faf 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden.component.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden-container.component.ts
@@ -22,22 +22,25 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { BescheidResource, BescheidWizardStep } from '@alfa-client/bescheid-shared';
-import { StateResource } from '@alfa-client/tech-shared';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
-import { Component, EventEmitter, Input, Output } from '@angular/core';
-import { Resource } from '@ngxp/rest';
+import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
 
 @Component({
-  selector: 'alfa-bescheid-wizard-antrag-bescheiden',
-  templateUrl: './bescheid-wizard-antrag-bescheiden.component.html',
+  selector: 'alfa-bescheid-wizard-antrag-bescheiden-container',
+  templateUrl: './bescheid-wizard-antrag-bescheiden-container.component.html',
 })
-export class BescheidWizardAntragBescheidenComponent {
+export class BescheidWizardAntragBescheidenContainerComponent {
   @Input() vorgangWithEingangResource: VorgangWithEingangResource;
   @Input() bescheidResource: BescheidResource;
-  @Input() submitStateResource: StateResource<Resource>;
 
-  @Output() weiterClickEmitter: EventEmitter<BescheidWizardStep> = new EventEmitter<BescheidWizardStep>();
   @Output() vorgangAbgeschlossen: EventEmitter<void> = new EventEmitter<void>();
 
-  public readonly bescheidWizardStep = BescheidWizardStep;
+  private readonly bescheidService = inject(BescheidService2);
+
+  public readonly BescheidWizardStep = BescheidWizardStep;
+
+  public onWeiterClick(): void {
+    this.bescheidService.setActiveStep(BescheidWizardStep.DokumenteHochladen);
+  }
 }
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.html
index 5d3a471c46056ef89c8d3995ce0591519fd97bbc..8861db5df5fd7745a5061fecd7fead4301583384 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.html
@@ -24,7 +24,7 @@
 
 -->
 <div [formGroup]="formService.form" role="radiogroup" aria-label="Bescheidstatus">
-  <div class="my-10 flex max-w-2xl gap-8">
+  <div class="my-10 flex flex-wrap gap-8">
     <ods-radio-button-card
       label="bewilligt"
       [name]="formServiceClass.FIELD_BEWILLIGT"
@@ -52,12 +52,13 @@
     </ozgcloud-date-editor>
   </div>
 </div>
-<alfa-bescheid-wizard-weiter-button
-  *ngIf="
-    (vorgangWithEingangResource | hasLink: vorgangWithEingangLinkRel.CREATE_BESCHEID_DRAFT) ||
-    (bescheidResource | hasLink: bescheidLinkRel.UPDATE)
-  "
-  [submitStateResource]="submitStateResource"
-  (clickEmitter)="weiterClickEmitter.emit()"
-  data-test-id="weiter-button"
-></alfa-bescheid-wizard-weiter-button>
+@if (
+  (vorgangWithEingangResource | hasLink: vorgangWithEingangLinkRel.CREATE_BESCHEID_DRAFT) ||
+  (bescheidResource | hasLink: bescheidLinkRel.UPDATE)
+) {
+  <alfa-bescheid-wizard-weiter-button
+    [submitStateResource]="submitStateResource$ | async"
+    (clickEmitter)="submit()"
+    data-test-id="weiter-button"
+  ></alfa-bescheid-wizard-weiter-button>
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.spec.ts
index fb9b631931e637501aefed12255c8b44284b0167..fc15a7f9282febbd25179f0b255a5781234bfb86 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.spec.ts
@@ -21,9 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { BescheidLinkRel, BescheidService } from '@alfa-client/bescheid-shared';
-import { HasLinkPipe } from '@alfa-client/tech-shared';
-import { existsAsHtmlElement, mock, notExistsAsHtmlElement, triggerEvent, useFromMock } from '@alfa-client/test-utils';
+import { BescheidLinkRel } from '@alfa-client/bescheid-shared';
+import { CommandResource } from '@alfa-client/command-shared';
+import { createEmptyStateResource, HasLinkPipe, StateResource } from '@alfa-client/tech-shared';
+import { existsAsHtmlElement, getElementFromFixtureByType, mock, notExistsAsHtmlElement, triggerEvent, useFromMock, } from '@alfa-client/test-utils';
 import { DateEditorComponent } from '@alfa-client/ui';
 import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
 import { EventEmitter } from '@angular/core';
@@ -31,8 +32,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
 import { CloseIconComponent, RadioButtonCardComponent, StampIconComponent } from '@ods/system';
 import { MockComponent } from 'ng-mocks';
+import { EMPTY, of } from 'rxjs';
+import { BescheidService2 } from '../../../../../../../bescheid-shared/src/lib/bescheid2.service';
 import { createBescheidResource } from '../../../../../../../bescheid-shared/src/test/bescheid';
+import { createSuccessfullyDoneCommandStateResource } from '../../../../../../../command-shared/test/command';
 import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { singleColdCompleted } from '../../../../../../../tech-shared/test/marbles';
 import { createVorgangWithEingangResource } from '../../../../../../../vorgang-shared/test/vorgang';
 import { BescheidFormService } from '../../../bescheid.formservice';
 import { BescheidWizardWeiterButtonComponent } from '../../weiter-button/bescheid-wizard-weiter-button.component';
@@ -47,7 +52,8 @@ describe('BescheidWizardAntragBescheidenFormComponent', () => {
   let formService: BescheidFormService;
 
   beforeEach(async () => {
-    formService = new BescheidFormService(new UntypedFormBuilder(), useFromMock(mock(BescheidService)));
+    formService = new BescheidFormService(new UntypedFormBuilder(), useFromMock(mock(BescheidService2)));
+    formService.submit = jest.fn().mockReturnValue(EMPTY);
 
     await TestBed.configureTestingModule({
       declarations: [
@@ -74,12 +80,35 @@ describe('BescheidWizardAntragBescheidenFormComponent', () => {
     fixture.detectChanges();
   });
 
-  it('should create', () => {
-    expect(component).toBeTruthy();
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      expect(component.submitStateResource$).toBeObservable(singleColdCompleted(createEmptyStateResource()));
+    });
+
+    describe('submit', () => {
+      it('should call form service', () => {
+        component.submit();
+
+        expect(formService.submit).toHaveBeenCalled();
+      });
+
+      it('should emit weiter click', () => {
+        formService.submit = jest.fn().mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(component.weiterClickEmitter.emit).toHaveBeenCalled();
+      });
+    });
   });
 
   describe('template', () => {
-    describe('alfa-bescheid-wizard-weiter-button', () => {
+    describe('weiter button', () => {
       it('should exists if bescheid update link exists', () => {
         component.bescheidResource = createBescheidResource([BescheidLinkRel.UPDATE]);
 
@@ -98,7 +127,7 @@ describe('BescheidWizardAntragBescheidenFormComponent', () => {
         existsAsHtmlElement(fixture, weiterButton);
       });
 
-      it('should not exists if update and create links missing', () => {
+      it('should NOT exists if update and create links missing', () => {
         component.vorgangWithEingangResource = createVorgangWithEingangResource();
         component.bescheidResource = createBescheidResource();
 
@@ -107,7 +136,7 @@ describe('BescheidWizardAntragBescheidenFormComponent', () => {
         notExistsAsHtmlElement(fixture, weiterButton);
       });
 
-      it('should not exists if update link missing', () => {
+      it('should NOT exists if update link missing', () => {
         component.bescheidResource = createBescheidResource();
 
         fixture.detectChanges();
@@ -115,19 +144,36 @@ describe('BescheidWizardAntragBescheidenFormComponent', () => {
         notExistsAsHtmlElement(fixture, weiterButton);
       });
 
+      it('should have been called with inputs', (done) => {
+        component.vorgangWithEingangResource = createVorgangWithEingangResource([
+          VorgangWithEingangLinkRel.CREATE_BESCHEID_DRAFT,
+        ]);
+
+        fixture.detectChanges();
+
+        const weiterButtonComponent: BescheidWizardWeiterButtonComponent = getElementFromFixtureByType(
+          fixture,
+          BescheidWizardWeiterButtonComponent,
+        );
+
+        component.submitStateResource$.subscribe((submitStateResource: StateResource<CommandResource>) => {
+          expect(weiterButtonComponent.submitStateResource).toEqual(submitStateResource);
+          done();
+        });
+      });
+
       describe('output', () => {
-        it('should emit weiterClickEmitter', () => {
-          component.bescheidResource = createBescheidResource([BescheidLinkRel.UPDATE]);
+        describe('clickEmitter', () => {
+          it('should submit', () => {
+            component.submit = jest.fn();
+            component.bescheidResource = createBescheidResource([BescheidLinkRel.UPDATE]);
 
-          fixture.detectChanges();
+            fixture.detectChanges();
 
-          triggerEvent({
-            fixture,
-            name: 'clickEmitter',
-            elementSelector: weiterButton,
-          });
+            triggerEvent({ fixture, name: 'clickEmitter', elementSelector: weiterButton });
 
-          expect(component.weiterClickEmitter.emit).toHaveBeenCalled();
+            expect(component.submit).toHaveBeenCalled();
+          });
         });
       });
     });
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.ts
index 5806f5dcf9a2ecb1cf45d737419fe19da8f546ec..5c9c0ab6365f39586a6b9809fbd41ecba860a869 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component.ts
@@ -22,10 +22,11 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { BescheidLinkRel, BescheidResource } from '@alfa-client/bescheid-shared';
-import { StateResource } from '@alfa-client/tech-shared';
+import { CommandResource, tapOnCommandSuccessfullyDone } from '@alfa-client/command-shared';
+import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
-import { Component, EventEmitter, Input, Output } from '@angular/core';
-import { Resource } from '@ngxp/rest';
+import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
+import { Observable, of } from 'rxjs';
 import { BescheidFormService } from '../../../bescheid.formservice';
 
 @Component({
@@ -35,13 +36,20 @@ import { BescheidFormService } from '../../../bescheid.formservice';
 export class BescheidWizardAntragBescheidenFormComponent {
   @Input() vorgangWithEingangResource: VorgangWithEingangResource;
   @Input() bescheidResource: BescheidResource;
-  @Input() submitStateResource: StateResource<Resource>;
 
   @Output() weiterClickEmitter = new EventEmitter<void>();
 
+  public readonly formService = inject(BescheidFormService);
+
+  public submitStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
+
   public readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel;
   public readonly bescheidLinkRel = BescheidLinkRel;
   public readonly formServiceClass = BescheidFormService;
 
-  constructor(public readonly formService: BescheidFormService) {}
+  public submit(): void {
+    this.submitStateResource$ = this.formService
+      .submit()
+      .pipe(tapOnCommandSuccessfullyDone(() => this.weiterClickEmitter.emit()));
+  }
 }
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/summary/bescheid-wizard-antrag-bescheiden-summary.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/summary/bescheid-wizard-antrag-bescheiden-summary.component.spec.ts
index e4d89586aec9b233d612f87877efdd1298a8c318..571478e90cb9e5e00e8f79f7d695c475416cf95e 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/summary/bescheid-wizard-antrag-bescheiden-summary.component.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/summary/bescheid-wizard-antrag-bescheiden-summary.component.spec.ts
@@ -60,18 +60,20 @@ describe('BescheidWizardAntragBescheidenSummaryComponent', () => {
   });
 
   describe('template', () => {
-    describe('ods-bescheid-status-text', () => {
+    describe('status text', () => {
       function getElementComponent(): BescheidStatusTextComponent {
         return getElementFromFixtureByType(fixture, BescheidStatusTextComponent);
       }
 
-      it('should subscribe to bescheid value form changes', () => {
+      it('should exists', () => {
+        formService.getBescheidFormValueChanges.mockReturnValue(of(createBescheid()));
+
         fixture.detectChanges();
 
-        expect(formService.getBescheidFormValueChanges).toHaveBeenCalled();
+        existsAsHtmlElement(fixture, bescheidStatusText);
       });
 
-      it('should NOT show', () => {
+      it('should NOT exists', () => {
         formService.getBescheidFormValueChanges.mockReturnValue(EMPTY);
 
         fixture.detectChanges();
@@ -79,41 +81,21 @@ describe('BescheidWizardAntragBescheidenSummaryComponent', () => {
         notExistsAsHtmlElement(fixture, bescheidStatusText);
       });
 
-      it('should show', () => {
-        formService.getBescheidFormValueChanges.mockReturnValue(of(createBescheid()));
-
+      it('should subscribe to bescheid value form changes', () => {
         fixture.detectChanges();
 
-        existsAsHtmlElement(fixture, bescheidStatusText);
+        expect(formService.getBescheidFormValueChanges).toHaveBeenCalled();
       });
 
-      describe('input', () => {
-        it('should set bewilligt', () => {
-          const bescheid: Bescheid = createBescheid();
-          formService.getBescheidFormValueChanges.mockReturnValue(of(bescheid));
-
-          fixture.detectChanges();
-
-          expect(getElementComponent().bewilligt).toBe(bescheid.bewilligt);
-        });
-
-        it('should set dateText', () => {
-          const bescheid: Bescheid = { ...createBescheid(), beschiedenAm: '2024-01-01' };
-          formService.getBescheidFormValueChanges.mockReturnValue(of(bescheid));
+      it('should have been called with inputs', () => {
+        const bescheid: Bescheid = createBescheid();
+        formService.getBescheidFormValueChanges.mockReturnValue(of(bescheid));
 
-          fixture.detectChanges();
-
-          expect(getElementComponent().dateText).toBe('01.01.2024');
-        });
-
-        it('should set hasBescheidDraft', () => {
-          const bescheid: Bescheid = createBescheid();
-          formService.getBescheidFormValueChanges.mockReturnValue(of(bescheid));
-
-          fixture.detectChanges();
+        fixture.detectChanges();
 
-          expect(getElementComponent().hasBescheidDraft).toBeFalsy();
-        });
+        expect(getElementComponent().bewilligt).toBe(bescheid.bewilligt);
+        expect(getElementComponent().dateText).toBe('01.01.2024');
+        expect(getElementComponent().hasBescheidDraft).toBeFalsy();
       });
     });
   });
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/attachment-files/bescheid-wizard-attachment-files.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/attachment-files/bescheid-wizard-attachment-files.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..622107cd6a88a6410e8c7bcdc7e08fd262f1635b
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/attachment-files/bescheid-wizard-attachment-files.component.html
@@ -0,0 +1,21 @@
+<ods-attachment-wrapper>
+  @for (attachment of attachments; track $index) {
+    <alfa-binary-file2-container
+      [file]="attachment"
+      [deletable]="deletable"
+      (startDelete)="delete.emit($event)"
+      [attr.data-test-id]="(attachment.name | convertForDataTest) + '-file2-container'"
+    >
+    </alfa-binary-file2-container>
+  }
+  @if (upload.loading || upload.error) {
+    <ods-attachment
+      [loadingCaption]="upload.fileName"
+      errorCaption="Fehler beim Hochladen"
+      [errorMessages]="upload.error | convertProblemDetailToErrorMessages"
+      description="Anhang wird hochgeladen"
+      [isLoading]="upload.loading"
+      data-test-id="attachment-upload-in-progress"
+    ></ods-attachment>
+  }
+</ods-attachment-wrapper>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/attachment-files/bescheid-wizard-attachment-files.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/attachment-files/bescheid-wizard-attachment-files.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..92f027903e7ddb01410294bcced6f60759882b68
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/attachment-files/bescheid-wizard-attachment-files.component.spec.ts
@@ -0,0 +1,165 @@
+import { BescheidAttachments, createEmptyBescheidAttachments, createEmptyUploadInProgress } from '@alfa-client/bescheid-shared';
+import { BinaryFile2ContainerComponent } from '@alfa-client/binary-file';
+import { ConvertForDataTestPipe, ConvertProblemDetailToErrorMessagesPipe, ProblemDetail } from '@alfa-client/tech-shared';
+import {
+  existsAsHtmlElement,
+  getElementComponentFromFixtureByCss,
+  notExistsAsHtmlElement,
+  triggerEvent,
+} from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { AttachmentComponent, AttachmentWrapperComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+import { createBescheidAttachments } from '../../../../../../../bescheid-shared/src/test/bescheid';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { createProblemDetail } from '../../../../../../../tech-shared/test/error';
+import { BescheidWizardAttachmentFilesComponent } from './bescheid-wizard-attachment-files.component';
+
+describe('BescheidWizardAttachmentFileComponent', () => {
+  let component: BescheidWizardAttachmentFilesComponent;
+  let fixture: ComponentFixture<BescheidWizardAttachmentFilesComponent>;
+
+  const convertForDataTest: ConvertForDataTestPipe = new ConvertForDataTestPipe();
+  const convertProblemDetailsToErrorMessage: ConvertProblemDetailToErrorMessagesPipe =
+    new ConvertProblemDetailToErrorMessagesPipe();
+
+  const attachments: BescheidAttachments = createBescheidAttachments();
+
+  const binaryFileContainerTestId: string = getDataTestIdOf(
+    convertForDataTest.transform(attachments.items[0].name) + '-file2-container',
+  );
+  const attachmentUploadTestId: string = getDataTestIdOf('attachment-upload-in-progress');
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardAttachmentFilesComponent,
+        MockComponent(BinaryFile2ContainerComponent),
+        MockComponent(AttachmentComponent),
+        MockComponent(AttachmentWrapperComponent),
+        ConvertForDataTestPipe,
+        ConvertProblemDetailToErrorMessagesPipe,
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardAttachmentFilesComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      expect(component.upload).toEqual(createEmptyUploadInProgress());
+      expect(component.attachments).toEqual(createEmptyBescheidAttachments().items);
+    });
+
+    describe('set attachments', () => {
+      it('should set attachments', () => {
+        component.attachments = attachments;
+
+        expect(component.attachments).toEqual(attachments.items);
+      });
+
+      it('should set upload', () => {
+        component.attachments = attachments;
+
+        expect(component.upload).toEqual(attachments.upload);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('attachment binary file container', () => {
+      it('should exists', () => {
+        component.attachments = attachments;
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, binaryFileContainerTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        component.attachments = attachments;
+
+        fixture.detectChanges();
+        const binaryFileComponent: BinaryFile2ContainerComponent =
+          getElementComponentFromFixtureByCss<BinaryFile2ContainerComponent>(fixture, binaryFileContainerTestId);
+
+        expect(binaryFileComponent.file).toEqual(attachments.items[0]);
+        expect(binaryFileComponent.deletable).toEqual(component.deletable);
+      });
+
+      describe('output', () => {
+        describe('startDelete', () => {
+          it('should emit', () => {
+            component.attachments = attachments;
+            component.delete.emit = jest.fn();
+
+            fixture.detectChanges();
+
+            triggerEvent({
+              fixture,
+              elementSelector: binaryFileContainerTestId,
+              name: 'startDelete',
+              data: attachments.items[0],
+            });
+
+            expect(component.delete.emit).toHaveBeenCalledWith(attachments.items[0]);
+          });
+        });
+      });
+    });
+
+    describe('upload attachment', () => {
+      it('should exists on loading', () => {
+        component.attachments = { ...attachments, upload: { ...attachments.upload, loading: true, error: null } };
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, attachmentUploadTestId);
+      });
+
+      it('should exists on error', () => {
+        component.attachments = {
+          ...attachments,
+          upload: { ...attachments.upload, loading: false, error: createProblemDetail() },
+        };
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, attachmentUploadTestId);
+      });
+
+      it('should NOT exists', () => {
+        component.attachments = {
+          ...attachments,
+          upload: { ...attachments.upload, loading: false, error: null },
+        };
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, attachmentUploadTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        component.attachments = attachments;
+
+        fixture.detectChanges();
+        const attachmentComponent: AttachmentComponent = getElementComponentFromFixtureByCss<AttachmentComponent>(
+          fixture,
+          attachmentUploadTestId,
+        );
+
+        expect(attachmentComponent.loadingCaption).toEqual(attachments.upload.fileName);
+        expect(attachmentComponent.errorMessages).toEqual(
+          convertProblemDetailsToErrorMessage.transform(attachments.upload.error as ProblemDetail),
+        );
+        expect(attachmentComponent.isLoading).toEqual(attachments.upload.loading);
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/attachment-files/bescheid-wizard-attachment-files.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/attachment-files/bescheid-wizard-attachment-files.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b5a60cd795a7f6b7b918ce39a5fd5b45c1b3cb63
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/attachment-files/bescheid-wizard-attachment-files.component.ts
@@ -0,0 +1,30 @@
+import {
+  BescheidAttachments,
+  createEmptyBescheidAttachments,
+  createEmptyUploadInProgress,
+  UploadFileInProgress,
+} from '@alfa-client/bescheid-shared';
+import { BinaryFileResource } from '@alfa-client/binary-file-shared';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-attachment-files',
+  templateUrl: './bescheid-wizard-attachment-files.component.html',
+})
+export class BescheidWizardAttachmentFilesComponent {
+  @Input() set attachments(value: BescheidAttachments) {
+    this._attachments = value;
+    this.upload = value.upload;
+  }
+
+  get attachments(): BinaryFileResource[] {
+    return this._attachments.items;
+  }
+
+  @Input() deletable: boolean;
+
+  @Output() delete: EventEmitter<BinaryFileResource> = new EventEmitter();
+
+  public upload: UploadFileInProgress = createEmptyUploadInProgress();
+  private _attachments: BescheidAttachments = createEmptyBescheidAttachments();
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/bescheid-wizard-attachment-files-container.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/bescheid-wizard-attachment-files-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..c34bfce43f0959f56aa16e8a993f31b61bec0839
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/bescheid-wizard-attachment-files-container.component.html
@@ -0,0 +1,6 @@
+<alfa-bescheid-wizard-attachment-files
+  [attachments]="attachments$ | async"
+  [deletable]="(activeStep$ | async) === bescheidWizardStep.DokumenteHochladen"
+  (delete)="deleteAttachment($event)"
+  data-test-id="bescheid-attachments"
+></alfa-bescheid-wizard-attachment-files>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/bescheid-wizard-attachment-files-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/bescheid-wizard-attachment-files-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9c2cdd8df598bfddfb8b6fc3512066f44d58cc65
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/bescheid-wizard-attachment-files-container.component.spec.ts
@@ -0,0 +1,123 @@
+import { BescheidAttachments, BescheidWizardStep } from '@alfa-client/bescheid-shared';
+import { BinaryFileResource } from '@alfa-client/binary-file-shared';
+import { existsAsHtmlElement, getElementComponentFromFixtureByCss, mock, Mock, triggerEvent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+import { createBescheidAttachments } from '../../../../../../bescheid-shared/src/test/bescheid';
+import { createBinaryFileResource } from '../../../../../../binary-file-shared/test/binary-file';
+import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
+import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
+import { BescheidWizardAttachmentFilesComponent } from './attachment-files/bescheid-wizard-attachment-files.component';
+import { BescheidWizardAttachmentFilesContainerComponent } from './bescheid-wizard-attachment-files-container.component';
+
+describe('BescheidWizardAttachmentFileContainerComponent', () => {
+  let component: BescheidWizardAttachmentFilesContainerComponent;
+  let fixture: ComponentFixture<BescheidWizardAttachmentFilesContainerComponent>;
+
+  const attachmentsFilesTestId: string = getDataTestIdOf('bescheid-attachments');
+
+  const attachments: BescheidAttachments = createBescheidAttachments();
+
+  let bescheidService: Mock<BescheidService2>;
+
+  beforeEach(() => {
+    bescheidService = mock(BescheidService2);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [BescheidWizardAttachmentFilesContainerComponent, MockComponent(BescheidWizardAttachmentFilesComponent)],
+      providers: [{ provide: BescheidService2, useValue: bescheidService }],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardAttachmentFilesContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    describe('ngOnInit', () => {
+      it('should set attachments', () => {
+        bescheidService.getAttachments.mockReturnValue(of(attachments));
+
+        component.ngOnInit();
+
+        expect(component.attachments$).toBeObservable(singleColdCompleted(attachments));
+      });
+
+      it('should set active step', () => {
+        bescheidService.getActiveStep.mockReturnValue(of(BescheidWizardStep.BescheidVersenden));
+
+        component.ngOnInit();
+
+        expect(component.activeStep$).toBeObservable(singleColdCompleted(BescheidWizardStep.BescheidVersenden));
+      });
+    });
+
+    describe('deleteAttachment', () => {
+      it('should call service', () => {
+        component.deleteAttachment = jest.fn();
+        const binaryFileResource: BinaryFileResource = createBinaryFileResource();
+
+        component.deleteAttachment(binaryFileResource);
+
+        expect(component.deleteAttachment).toHaveBeenCalledWith(binaryFileResource);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('attachment files', () => {
+      function getComponent(): BescheidWizardAttachmentFilesComponent {
+        return getElementComponentFromFixtureByCss<BescheidWizardAttachmentFilesComponent>(fixture, attachmentsFilesTestId);
+      }
+
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, attachmentsFilesTestId);
+      });
+
+      it('should have been called with attachments', () => {
+        component.attachments$ = of(attachments);
+
+        fixture.detectChanges();
+
+        expect(getComponent().attachments).toEqual(attachments);
+      });
+
+      it('should have been called with deletable true', () => {
+        component.activeStep$ = of(BescheidWizardStep.DokumenteHochladen);
+
+        fixture.detectChanges();
+
+        expect(getComponent().deletable).toEqual(true);
+      });
+
+      it('should have been called with deletable false', () => {
+        component.activeStep$ = of(BescheidWizardStep.BescheidVersenden);
+
+        fixture.detectChanges();
+
+        expect(getComponent().deletable).toEqual(false);
+      });
+
+      describe('output', () => {
+        describe('delete', () => {
+          it('should call handler', () => {
+            const binaryFileResource: BinaryFileResource = createBinaryFileResource();
+            component.deleteAttachment = jest.fn();
+
+            triggerEvent({ fixture, elementSelector: attachmentsFilesTestId, name: 'delete', data: binaryFileResource });
+
+            expect(component.deleteAttachment).toHaveBeenCalledWith(binaryFileResource);
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/bescheid-wizard-attachment-files-container.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/bescheid-wizard-attachment-files-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..50d2dea88ea12ba5fec926d895ff47044f017409
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/attachment-files-container/bescheid-wizard-attachment-files-container.component.ts
@@ -0,0 +1,27 @@
+import { BescheidAttachments, BescheidWizardStep } from '@alfa-client/bescheid-shared';
+import { BinaryFileResource } from '@alfa-client/binary-file-shared';
+import { Component, inject, OnInit } from '@angular/core';
+import { Observable } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-attachment-files-container',
+  templateUrl: './bescheid-wizard-attachment-files-container.component.html',
+})
+export class BescheidWizardAttachmentFilesContainerComponent implements OnInit {
+  public readonly bescheidService = inject(BescheidService2);
+
+  public attachments$: Observable<BescheidAttachments>;
+  public activeStep$: Observable<BescheidWizardStep>;
+
+  public readonly bescheidWizardStep = BescheidWizardStep;
+
+  ngOnInit(): void {
+    this.attachments$ = this.bescheidService.getAttachments();
+    this.activeStep$ = this.bescheidService.getActiveStep();
+  }
+
+  public deleteAttachment(binaryFileResource: BinaryFileResource): void {
+    this.bescheidService.deleteAttachment(binaryFileResource);
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/bescheid-wizard-bescheid-versenden-container.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/bescheid-wizard-bescheid-versenden-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..ebb663b568ce2cddf824bba0988d46ed38c3c6e8
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/bescheid-wizard-bescheid-versenden-container.component.html
@@ -0,0 +1,30 @@
+<alfa-step-content-layout
+  [activeStep]="bescheidWizardStep.BescheidVersenden"
+  (stepChange)="onStepChange($event)"
+  data-test-id="step-content-layout"
+>
+  <ng-container stepPanel>
+    <alfa-bescheid-wizard-step-title
+      label="Antrag bescheiden"
+      [inactiveStep]="true"
+      data-test-id="antrag-bescheiden-step-title"
+    />
+    <alfa-bescheid-wizard-step-title
+      label="Dokumente hinzufügen"
+      [inactiveStep]="true"
+      data-test-id="dokumente-hochladen-step-title"
+    />
+    <alfa-bescheid-wizard-step-title label="Bescheid versenden" />
+    <alfa-bescheid-wizard-bescheid-versenden-form
+      [bescheidResource]="bescheidResource"
+      (sendBy)="onSendBy($event)"
+      data-test-id="bescheid-wizard-bescheid-versenden-form"
+    />
+  </ng-container>
+  <ng-container summary>
+    <alfa-bescheid-wizard-bescheid-versenden-summary
+      [bescheidResource]="bescheidResource"
+      [wizard]="wizard$ | async"
+      data-test-id="bescheiden-result"
+    /> </ng-container
+></alfa-step-content-layout>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/bescheid-wizard-bescheid-versenden-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/bescheid-wizard-bescheid-versenden-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..abdb3be7cef699e775c5bbc324911d1ef71b7127
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/bescheid-wizard-bescheid-versenden-container.component.spec.ts
@@ -0,0 +1,184 @@
+import { BescheidResource, BescheidSendBy, BescheidWizardStep, Wizard } from '@alfa-client/bescheid-shared';
+import { existsAsHtmlElement, getElementComponentFromFixtureByCss, mock, Mock, triggerEvent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+import { createBescheidResource, createWizard } from '../../../../../../bescheid-shared/src/test/bescheid';
+import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
+import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
+import { StepContentLayoutComponent } from '../step-content-layout/step-content-layout.component';
+import { BescheidWizardStepTitleComponent } from '../step-title/bescheid-wizard-step-title.component';
+import { BescheidWizardSummaryComponent } from '../summary/bescheid-wizard-summary.component';
+import { BescheidWizardBescheidVersendenContainerComponent } from './bescheid-wizard-bescheid-versenden-container.component';
+import { BescheidWizardBescheidVersendenFormComponent } from './form/bescheid-wizard-bescheid-versenden-form.component';
+import { BescheidWizardBescheidVersendenSummaryComponent } from './summary/bescheid-wizard-bescheid-versenden-summary.component';
+
+describe('BescheidWizardBescheidVersendenComponent', () => {
+  let component: BescheidWizardBescheidVersendenContainerComponent;
+  let fixture: ComponentFixture<BescheidWizardBescheidVersendenContainerComponent>;
+
+  const stepContentLayout: string = getDataTestIdOf('step-content-layout');
+  const antragBescheidenStepTitleTestId: string = getDataTestIdOf('antrag-bescheiden-step-title');
+  const dokumenteHochladenStepTitleTestId: string = getDataTestIdOf('dokumente-hochladen-step-title');
+  const formTestId: string = getDataTestIdOf('bescheid-wizard-bescheid-versenden-form');
+  const versendenSummaryTestId: string = getDataTestIdOf('bescheiden-result');
+
+  const bescheidResource: BescheidResource = createBescheidResource();
+
+  let bescheidService: Mock<BescheidService2>;
+
+  beforeEach(() => {
+    bescheidService = mock(BescheidService2);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardBescheidVersendenContainerComponent,
+        MockComponent(StepContentLayoutComponent),
+        MockComponent(BescheidWizardStepTitleComponent),
+        MockComponent(BescheidWizardBescheidVersendenFormComponent),
+        MockComponent(BescheidWizardSummaryComponent),
+        MockComponent(BescheidWizardBescheidVersendenSummaryComponent),
+      ],
+      providers: [{ provide: BescheidService2, useValue: bescheidService }],
+    }).compileComponents();
+
+    createComponent();
+  });
+
+  function createComponent() {
+    fixture = TestBed.createComponent(BescheidWizardBescheidVersendenContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      const wizard: Wizard = createWizard();
+      bescheidService.getWizard.mockReturnValue(of(wizard));
+
+      createComponent();
+
+      expect(component.wizard$).toBeObservable(singleColdCompleted(wizard));
+    });
+
+    it('should set bescheid resource', () => {
+      component.bescheidResource = bescheidResource;
+
+      expect(component.bescheidResource).toEqual(bescheidResource);
+    });
+
+    it('should set send by', () => {
+      component.bescheidResource = bescheidResource;
+
+      expect(bescheidService.setSendBy).toHaveBeenCalledWith(bescheidResource.sendBy);
+    });
+
+    describe('onSendBy', () => {
+      it('should call service', () => {
+        component.onSendBy(BescheidSendBy.MANUAL);
+
+        expect(bescheidService.setSendBy).toHaveBeenCalledWith(BescheidSendBy.MANUAL);
+      });
+    });
+
+    describe('onStepChange', () => {
+      it('should call service', () => {
+        component.onStepChange(BescheidWizardStep.DokumenteHochladen);
+
+        expect(bescheidService.setActiveStep).toHaveBeenCalledWith(BescheidWizardStep.DokumenteHochladen);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('step content layout', () => {
+      describe('output', () => {
+        describe('stepChange', () => {
+          it('should call handler', () => {
+            component.onStepChange = jest.fn();
+
+            triggerEvent({
+              fixture,
+              elementSelector: stepContentLayout,
+              name: 'stepChange',
+              data: BescheidWizardStep.DokumenteHochladen,
+            });
+
+            expect(component.onStepChange).toHaveBeenCalledWith(BescheidWizardStep.DokumenteHochladen);
+          });
+        });
+      });
+    });
+
+    describe('antrag bescheid step title', () => {
+      it('should have inputs', () => {
+        const stepTitleComponent: BescheidWizardStepTitleComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardStepTitleComponent>(fixture, antragBescheidenStepTitleTestId);
+
+        expect(stepTitleComponent.inactiveStep).toEqual(true);
+      });
+    });
+
+    describe('dokumente hochladen step title', () => {
+      it('should have inputs', () => {
+        const stepTitleComponent: BescheidWizardStepTitleComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardStepTitleComponent>(fixture, dokumenteHochladenStepTitleTestId);
+
+        expect(stepTitleComponent.inactiveStep).toEqual(true);
+      });
+    });
+
+    describe('bescheid versenden form', () => {
+      it('should have inputs', () => {
+        component.bescheidResource = createBescheidResource();
+
+        fixture.detectChanges();
+        const formComponent: BescheidWizardBescheidVersendenFormComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardBescheidVersendenFormComponent>(fixture, formTestId);
+
+        expect(formComponent.bescheidResource).toEqual(component.bescheidResource);
+      });
+
+      describe('output', () => {
+        describe('sendBy', () => {
+          it('should call handler', () => {
+            component.onSendBy = jest.fn();
+
+            triggerEvent({ fixture, elementSelector: formTestId, name: 'sendBy', data: BescheidSendBy.MANUAL });
+
+            expect(component.onSendBy).toHaveBeenCalledWith(BescheidSendBy.MANUAL);
+          });
+        });
+      });
+    });
+
+    describe('bescheid versenden summary', () => {
+      it('should exists', () => {
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, versendenSummaryTestId);
+      });
+
+      it('should have inputs', () => {
+        const wizard: Wizard = createWizard();
+        bescheidService.getWizard.mockReturnValue(of(wizard));
+        createComponent();
+        component.bescheidResource = bescheidResource;
+
+        fixture.detectChanges();
+        const summaryComponent: BescheidWizardBescheidVersendenSummaryComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardBescheidVersendenSummaryComponent>(fixture, versendenSummaryTestId);
+
+        expect(summaryComponent.bescheidResource).toEqual(bescheidResource);
+        expect(summaryComponent.wizard).toEqual(wizard);
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/bescheid-wizard-bescheid-versenden-container.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/bescheid-wizard-bescheid-versenden-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..70408d0b23afb74630248f0a140e07f8f0ccf60a
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/bescheid-wizard-bescheid-versenden-container.component.ts
@@ -0,0 +1,35 @@
+import { BescheidResource, BescheidSendBy, BescheidWizardStep, Wizard } from '@alfa-client/bescheid-shared';
+import { Component, inject, Input } from '@angular/core';
+import { Observable } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-bescheid-versenden-container',
+  templateUrl: './bescheid-wizard-bescheid-versenden-container.component.html',
+})
+export class BescheidWizardBescheidVersendenContainerComponent {
+  @Input() set bescheidResource(value: BescheidResource) {
+    this._bescheidResource = value;
+    this.bescheidService.setSendBy(value.sendBy);
+  }
+
+  get bescheidResource(): BescheidResource {
+    return this._bescheidResource;
+  }
+
+  private readonly bescheidService: BescheidService2 = inject(BescheidService2);
+
+  public readonly wizard$: Observable<Wizard> = this.bescheidService.getWizard();
+
+  private _bescheidResource: BescheidResource;
+
+  public readonly bescheidWizardStep = BescheidWizardStep;
+
+  public onSendBy(sendBy: BescheidSendBy): void {
+    this.bescheidService.setSendBy(sendBy);
+  }
+
+  public onStepChange(step: BescheidWizardStep): void {
+    this.bescheidService.setActiveStep(step);
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/form/bescheid-wizard-bescheid-versenden-form.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/form/bescheid-wizard-bescheid-versenden-form.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..b9ebc81cb5beee11821a7ecdba7e340bc1883fbe
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/form/bescheid-wizard-bescheid-versenden-form.component.html
@@ -0,0 +1,33 @@
+<div
+  [formGroup]="formService.form"
+  class="mt-5 flex w-full max-w-72 flex-col gap-4"
+  role="radiogroup"
+  aria-level="Bescheid versenden"
+>
+  @if (bescheidResource | hasLink: bescheidLinkRel.BESCHEIDEN_UND_SENDEN) {
+    <ods-radio-button-card
+      label="Als neue Nachricht an den Antragsteller senden"
+      [value]="bescheidSendBy.NACHRICHT"
+      [name]="formServiceClass.FIELD_SEND_BY"
+      variant="bescheid_save"
+      [fullWidthText]="true"
+      (change)="changeSendBy(bescheidSendBy.NACHRICHT)"
+      data-test-id="send-to-antragsteller-button"
+    >
+      <ods-send-icon size="large"></ods-send-icon>
+    </ods-radio-button-card>
+    @if (bescheidResource | hasLink: bescheidLinkRel.BESCHEIDEN) {
+      <ods-radio-button-card
+        label="Nur speichern"
+        [value]="bescheidSendBy.MANUAL"
+        [name]="formServiceClass.FIELD_SEND_BY"
+        variant="bescheid_save"
+        [fullWidthText]="true"
+        (change)="changeSendBy(bescheidSendBy.MANUAL)"
+        data-test-id="save-button"
+      >
+        <ods-save-icon size="large"></ods-save-icon>
+      </ods-radio-button-card>
+    }
+  }
+</div>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/form/bescheid-wizard-bescheid-versenden-form.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/form/bescheid-wizard-bescheid-versenden-form.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fc058c004dce9f0e1c8e22efc3960498c03e0d90
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/form/bescheid-wizard-bescheid-versenden-form.component.spec.ts
@@ -0,0 +1,177 @@
+import { BescheidLinkRel, BescheidSendBy } from '@alfa-client/bescheid-shared';
+import { HasLinkPipe } from '@alfa-client/tech-shared';
+import {
+  existsAsHtmlElement,
+  getElementComponentFromFixtureByCss,
+  notExistsAsHtmlElement,
+  triggerEvent,
+} from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
+import { RadioButtonCardComponent, SaveIconComponent, SendIconComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+import { createBescheidResource } from '../../../../../../../bescheid-shared/src/test/bescheid';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { BescheidFormService } from '../../../bescheid.formservice';
+import { BescheidWizardBescheidVersendenFormComponent } from './bescheid-wizard-bescheid-versenden-form.component';
+
+describe('BescheidWizardBescheidVersendenFormComponent', () => {
+  let component: BescheidWizardBescheidVersendenFormComponent;
+  let fixture: ComponentFixture<BescheidWizardBescheidVersendenFormComponent>;
+
+  const sendBescheidMessageTestId: string = getDataTestIdOf('send-to-antragsteller-button');
+  const saveBeschedTestId: string = getDataTestIdOf('save-button');
+
+  let formService: BescheidFormService;
+
+  beforeEach(() => {
+    formService = new BescheidFormService(new FormBuilder(), null);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardBescheidVersendenFormComponent,
+        MockComponent(RadioButtonCardComponent),
+        MockComponent(SendIconComponent),
+        MockComponent(SaveIconComponent),
+        HasLinkPipe,
+        ReactiveFormsModule,
+      ],
+      providers: [{ provide: BescheidFormService, useValue: formService }],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardBescheidVersendenFormComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    describe('changeSendBy', () => {
+      it('should emit', () => {
+        component.sendBy.emit = jest.fn();
+
+        component.changeSendBy(BescheidSendBy.NACHRICHT);
+
+        expect(component.sendBy.emit).toHaveBeenCalledWith(BescheidSendBy.NACHRICHT);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('als neue nachricht radio button', () => {
+      it('should exists', () => {
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN]);
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, sendBescheidMessageTestId);
+      });
+
+      it('should NOT exists', () => {
+        component.bescheidResource = createBescheidResource();
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, sendBescheidMessageTestId);
+      });
+
+      it('should have inputs', () => {
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN]);
+
+        fixture.detectChanges();
+        const radioButton: RadioButtonCardComponent = getElementComponentFromFixtureByCss<RadioButtonCardComponent>(
+          fixture,
+          sendBescheidMessageTestId,
+        );
+
+        expect(radioButton.value).toEqual(BescheidSendBy.NACHRICHT);
+        expect(radioButton.name).toEqual(BescheidFormService.FIELD_SEND_BY);
+        expect(radioButton.fullWidthText).toEqual(true);
+      });
+
+      describe('output', () => {
+        describe('change', () => {
+          it('should call handler', () => {
+            component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN]);
+            component.changeSendBy = jest.fn();
+            fixture.detectChanges();
+
+            triggerEvent({ fixture, elementSelector: sendBescheidMessageTestId, name: 'change', data: BescheidSendBy.NACHRICHT });
+
+            expect(component.changeSendBy).toHaveBeenCalledWith(BescheidSendBy.NACHRICHT);
+          });
+        });
+      });
+    });
+
+    describe('nur speichern radio button', () => {
+      it('should exists', () => {
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN, BescheidLinkRel.BESCHEIDEN]);
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, saveBeschedTestId);
+      });
+
+      it('should NOT exists if on missing bescheiden und send link', () => {
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN]);
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, saveBeschedTestId);
+      });
+
+      it('should NOT exists if on missing bescheiden link', () => {
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN]);
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, saveBeschedTestId);
+      });
+
+      it('should NOT exists if on missinglinks', () => {
+        component.bescheidResource = createBescheidResource();
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, saveBeschedTestId);
+      });
+
+      it('should have inputs', () => {
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN, BescheidLinkRel.BESCHEIDEN]);
+
+        fixture.detectChanges();
+        const radioButton: RadioButtonCardComponent = getElementComponentFromFixtureByCss<RadioButtonCardComponent>(
+          fixture,
+          saveBeschedTestId,
+        );
+
+        expect(radioButton.value).toEqual(BescheidSendBy.MANUAL);
+        expect(radioButton.name).toEqual(BescheidFormService.FIELD_SEND_BY);
+        expect(radioButton.fullWidthText).toEqual(true);
+      });
+
+      describe('output', () => {
+        describe('change', () => {
+          it('should call handler', () => {
+            component.bescheidResource = createBescheidResource([
+              BescheidLinkRel.BESCHEIDEN_UND_SENDEN,
+              BescheidLinkRel.BESCHEIDEN,
+            ]);
+            component.changeSendBy = jest.fn();
+            fixture.detectChanges();
+
+            triggerEvent({ fixture, elementSelector: saveBeschedTestId, name: 'change', data: BescheidSendBy.MANUAL });
+
+            expect(component.changeSendBy).toHaveBeenCalledWith(BescheidSendBy.MANUAL);
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/form/bescheid-wizard-bescheid-versenden-form.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/form/bescheid-wizard-bescheid-versenden-form.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..de149b55c7e9e215a9d3284fe4a441a5bbf19c30
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/form/bescheid-wizard-bescheid-versenden-form.component.ts
@@ -0,0 +1,23 @@
+import { BescheidLinkRel, BescheidResource, BescheidSendBy } from '@alfa-client/bescheid-shared';
+import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
+import { BescheidFormService } from '../../../bescheid.formservice';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-bescheid-versenden-form',
+  templateUrl: './bescheid-wizard-bescheid-versenden-form.component.html',
+})
+export class BescheidWizardBescheidVersendenFormComponent {
+  @Input() bescheidResource: BescheidResource;
+
+  @Output() sendBy: EventEmitter<BescheidSendBy> = new EventEmitter<BescheidSendBy>();
+
+  public readonly formService: BescheidFormService = inject(BescheidFormService);
+
+  public readonly bescheidLinkRel = BescheidLinkRel;
+  public readonly formServiceClass = BescheidFormService;
+  public readonly bescheidSendBy = BescheidSendBy;
+
+  public changeSendBy(sendBy: BescheidSendBy): void {
+    this.sendBy.emit(sendBy);
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/bescheid-wizard-bescheid-versenden-summary.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/bescheid-wizard-bescheid-versenden-summary.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..be23ec4fce623714a97ce620605b74fd7b09a9ae
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/bescheid-wizard-bescheid-versenden-summary.component.html
@@ -0,0 +1,15 @@
+<section tabindex="0" class="h-full">
+  @if (wizard.sendBy === bescheidSendBy.MANUAL) {
+    <alfa-bescheid-wizard-bescheid-versenden-speichern
+      [bescheidResource]="bescheidResource"
+      data-test-id="bescheid-versenden-speichern"
+    ></alfa-bescheid-wizard-bescheid-versenden-speichern>
+  }
+  @if (wizard.sendBy === bescheidSendBy.NACHRICHT) {
+    <alfa-bescheid-wizard-bescheid-versenden-senden
+      [bescheidResource]="bescheidResource"
+      [wizard]="wizard"
+      data-test-id="bescheid-versenden-senden"
+    ></alfa-bescheid-wizard-bescheid-versenden-senden>
+  }
+</section>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/bescheid-wizard-bescheid-versenden-summary.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/bescheid-wizard-bescheid-versenden-summary.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..83b9df452df3cde3a70ef32cc1cc032123f43cd5
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/bescheid-wizard-bescheid-versenden-summary.component.spec.ts
@@ -0,0 +1,105 @@
+import { BescheidResource, BescheidSendBy } from '@alfa-client/bescheid-shared';
+import { existsAsHtmlElement, getElementComponentFromFixtureByCss, notExistsAsHtmlElement } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+import { createBescheidResource, createWizard } from '../../../../../../../bescheid-shared/src/test/bescheid';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { BescheidWizardBescheidVersendenSummaryComponent } from './bescheid-wizard-bescheid-versenden-summary.component';
+import { BescheidWizardBescheidVersendenSendenComponent } from './senden/bescheid-wizard-bescheid-versenden-senden.component';
+import { BescheidWizardBescheidVersendenSpeichernComponent } from './speichern/bescheid-wizard-bescheid-versenden-speichern.component';
+
+describe('BescheidWizardBescheidVersendenSummaryComponent', () => {
+  let component: BescheidWizardBescheidVersendenSummaryComponent;
+  let fixture: ComponentFixture<BescheidWizardBescheidVersendenSummaryComponent>;
+
+  const bescheidVersendenSpeichernTestId: string = getDataTestIdOf('bescheid-versenden-speichern');
+  const bescheidVersendenSendenTestId: string = getDataTestIdOf('bescheid-versenden-senden');
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardBescheidVersendenSummaryComponent,
+        MockComponent(BescheidWizardBescheidVersendenSpeichernComponent),
+        MockComponent(BescheidWizardBescheidVersendenSendenComponent),
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardBescheidVersendenSummaryComponent);
+    component = fixture.componentInstance;
+    component.wizard = createWizard();
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('template', () => {
+    const bescheidResource: BescheidResource = createBescheidResource();
+
+    describe('bescheid versenden speichern', () => {
+      it('should exists', () => {
+        component.wizard = { ...createWizard(), sendBy: BescheidSendBy.MANUAL };
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, bescheidVersendenSpeichernTestId);
+      });
+
+      it('should NOT exists', () => {
+        component.wizard = { ...createWizard(), sendBy: BescheidSendBy.NACHRICHT };
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, bescheidVersendenSpeichernTestId);
+      });
+
+      it('should have inputs', () => {
+        component.wizard = { ...createWizard(), sendBy: BescheidSendBy.MANUAL };
+        component.bescheidResource = bescheidResource;
+
+        fixture.detectChanges();
+        const speichernComponent: BescheidWizardBescheidVersendenSpeichernComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardBescheidVersendenSpeichernComponent>(
+            fixture,
+            bescheidVersendenSpeichernTestId,
+          );
+
+        expect(speichernComponent.bescheidResource).toEqual(bescheidResource);
+      });
+    });
+
+    describe('bescheid versenden senden', () => {
+      it('should exists', () => {
+        component.wizard = { ...createWizard(), sendBy: BescheidSendBy.NACHRICHT };
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, bescheidVersendenSendenTestId);
+      });
+
+      it('should NOT exists', () => {
+        component.wizard = { ...createWizard(), sendBy: BescheidSendBy.MANUAL };
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, bescheidVersendenSendenTestId);
+      });
+
+      it('should have inputs', () => {
+        component.wizard = { ...createWizard(), sendBy: BescheidSendBy.NACHRICHT };
+        component.bescheidResource = bescheidResource;
+
+        fixture.detectChanges();
+        const sendenComponent: BescheidWizardBescheidVersendenSendenComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardBescheidVersendenSendenComponent>(
+            fixture,
+            bescheidVersendenSendenTestId,
+          );
+
+        expect(sendenComponent.bescheidResource).toEqual(bescheidResource);
+        expect(sendenComponent.wizard).toEqual(component.wizard);
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/bescheid-wizard-bescheid-versenden-summary.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/bescheid-wizard-bescheid-versenden-summary.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..da53ce4b8adedd2adeb59a8829653b85d983c3fa
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/bescheid-wizard-bescheid-versenden-summary.component.ts
@@ -0,0 +1,14 @@
+import { BescheidLinkRel, BescheidResource, BescheidSendBy, Wizard } from '@alfa-client/bescheid-shared';
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-bescheid-versenden-summary',
+  templateUrl: './bescheid-wizard-bescheid-versenden-summary.component.html',
+})
+export class BescheidWizardBescheidVersendenSummaryComponent {
+  @Input() bescheidResource: BescheidResource;
+  @Input() wizard: Wizard;
+
+  public readonly bescheidLinkRel = BescheidLinkRel;
+  public readonly bescheidSendBy = BescheidSendBy;
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/senden/bescheid-wizard-bescheid-versenden-senden.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/senden/bescheid-wizard-bescheid-versenden-senden.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..0631bc2d3607a669dc82fd6185fce16cc3593113
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/senden/bescheid-wizard-bescheid-versenden-senden.component.html
@@ -0,0 +1,45 @@
+<div class="flex h-full flex-col justify-between">
+  <div>
+    <div data-test-id="bescheid-nachricht-an-antragsteller">
+      <h3 class="mb-3 font-medium text-primary">Neue Nachricht</h3>
+      @if (wizard?.empfaenger) {
+        <p data-test-id="bescheid-nachricht-empfaenger" class="mb-2 text-sm font-medium">An: {{ wizard.empfaenger }}</p>
+      }
+    </div>
+    <div [formGroup]="formService.form">
+      <ods-text-editor
+        [formControlName]="formServiceClass.FIELD_NACHRICHT_SUBJECT"
+        label="Betreff"
+        placeholder="Betreff hier eingeben"
+        [focus]="focusBetreff"
+        [isRequired]="true"
+      >
+      </ods-text-editor>
+
+      <ods-textarea-editor
+        [formControlName]="formServiceClass.FIELD_NACHRICHT_TEXT"
+        label="Text"
+        placeholder="Nachrichtentext hier eingeben"
+        [focus]="focusNachricht"
+        [isRequired]="true"
+      >
+      </ods-textarea-editor>
+    </div>
+
+    <alfa-bescheid-wizard-dokumente-hochladen-summary
+      [isBescheidDocumentMissing]="false"
+      data-test-id="bescheid-versenden-dokumente"
+    ></alfa-bescheid-wizard-dokumente-hochladen-summary>
+  </div>
+  @if (
+    (bescheidResource | hasLink: bescheidLinkRel.UPDATE) || (bescheidResource | hasLink: bescheidLinkRel.BESCHEIDEN_UND_SENDEN)
+  ) {
+    <ods-button-with-spinner
+      class="self-end"
+      [stateResource]="submitStateResource$ | async"
+      text="Bescheid senden"
+      (clickEmitter)="submit()"
+      data-test-id="send-button"
+    ></ods-button-with-spinner>
+  }
+</div>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/senden/bescheid-wizard-bescheid-versenden-senden.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/senden/bescheid-wizard-bescheid-versenden-senden.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9f90d5f49aead888a0b1eff751476d748859fe07
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/senden/bescheid-wizard-bescheid-versenden-senden.component.spec.ts
@@ -0,0 +1,314 @@
+import { BescheidLinkRel, BescheidWizardDialogResult } from '@alfa-client/bescheid-shared';
+import { CommandResource } from '@alfa-client/command-shared';
+import {
+  createEmptyStateResource,
+  createErrorStateResource,
+  createLoadingStateResource,
+  HasLinkPipe,
+  StateResource,
+} from '@alfa-client/tech-shared';
+import {
+  existsAsHtmlElement,
+  getElementComponentFromFixtureByCss,
+  mock,
+  Mock,
+  notExistsAsHtmlElement,
+  triggerEvent,
+  useFromMock,
+} from '@alfa-client/test-utils';
+import { DialogRef } from '@angular/cdk/dialog';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
+import { expect } from '@jest/globals';
+import { ButtonWithSpinnerComponent, TextareaEditorComponent, TextEditorComponent } from '@ods/component';
+import { MockComponent } from 'ng-mocks';
+import { EMPTY, of } from 'rxjs';
+import { BescheidService2 } from '../../../../../../../../bescheid-shared/src/lib/bescheid2.service';
+import { createBescheidResource, createWizard } from '../../../../../../../../bescheid-shared/src/test/bescheid';
+import { createSuccessfullyDoneCommandStateResource } from '../../../../../../../../command-shared/test/command';
+import { getDataTestIdOf } from '../../../../../../../../tech-shared/test/data-test';
+import { createProblemDetail } from '../../../../../../../../tech-shared/test/error';
+import { singleColdCompleted } from '../../../../../../../../tech-shared/test/marbles';
+import { BescheidFormService } from '../../../../bescheid.formservice';
+import { BescheidWizardDokumenteHochladenSummaryComponent } from '../../../dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component';
+import { BescheidWizardBescheidVersendenSendenComponent } from './bescheid-wizard-bescheid-versenden-senden.component';
+
+describe('BescheidWizardBescheidVersendenSendenComponent', () => {
+  let component: BescheidWizardBescheidVersendenSendenComponent;
+  let fixture: ComponentFixture<BescheidWizardBescheidVersendenSendenComponent>;
+
+  const dokumenteTestsId: string = getDataTestIdOf('bescheid-versenden-dokumente');
+  const submitButtonTestId: string = getDataTestIdOf('send-button');
+  const empfaengerTestId: string = getDataTestIdOf('bescheid-nachricht-empfaenger');
+
+  let bescheidService: Mock<BescheidService2>;
+  let formService: BescheidFormService;
+  let dialogRef: Mock<DialogRef<BescheidWizardDialogResult>>;
+
+  beforeEach(() => {
+    bescheidService = mock(BescheidService2);
+    formService = new BescheidFormService(new FormBuilder(), useFromMock(bescheidService));
+    formService.submit = jest.fn();
+    dialogRef = mock(DialogRef<BescheidWizardDialogResult>);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardBescheidVersendenSendenComponent,
+        MockComponent(BescheidWizardDokumenteHochladenSummaryComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(TextareaEditorComponent),
+        MockComponent(TextEditorComponent),
+        HasLinkPipe,
+        ReactiveFormsModule,
+      ],
+      providers: [
+        { provide: BescheidFormService, useValue: formService },
+        { provide: DialogRef<BescheidWizardDialogResult>, useValue: dialogRef },
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardBescheidVersendenSendenComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      expect(component.submitStateResource$).toBeObservable(singleColdCompleted(createEmptyStateResource()));
+    });
+
+    describe('submit', () => {
+      beforeEach(() => {
+        formService.submit = jest.fn().mockReturnValue(EMPTY);
+        component._resetFocus = jest.fn();
+      });
+
+      it('should reset focus', () => {
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(component._resetFocus).toHaveBeenCalled();
+      });
+
+      it('should call form service', () => {
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(formService.submit).toHaveBeenCalled();
+      });
+
+      it('should close dialog', () => {
+        formService.submit = jest.fn().mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(dialogRef.close).toHaveBeenCalledWith({ reloadVorgang: true } as BescheidWizardDialogResult);
+      });
+
+      it('should NOT close dialog on pending send', () => {
+        formService.submit = jest.fn().mockReturnValue(of(createLoadingStateResource()));
+
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(dialogRef.close).not.toHaveBeenCalled();
+      });
+
+      it('should NOT close dialog on failed send', () => {
+        formService.submit = jest.fn().mockReturnValue(of(createErrorStateResource(createProblemDetail())));
+
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(dialogRef.close).not.toHaveBeenCalled();
+      });
+
+      it('should focus to first invalid control', () => {
+        component._focusToFirstInvalidControl = jest.fn();
+        formService.submit = jest.fn().mockReturnValue(of(createErrorStateResource(createProblemDetail())));
+
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(component._focusToFirstInvalidControl).toHaveBeenCalled();
+      });
+
+      it('should NOT focus to first invalid control on pending submit', () => {
+        component._focusToFirstInvalidControl = jest.fn();
+        formService.submit = jest.fn().mockReturnValue(of(createLoadingStateResource()));
+
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(component._focusToFirstInvalidControl).not.toHaveBeenCalled();
+      });
+
+      it('should NOT focus to first invalid control on successful submit', () => {
+        component._focusToFirstInvalidControl = jest.fn();
+        formService.submit = jest.fn().mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(component._focusToFirstInvalidControl).not.toHaveBeenCalled();
+      });
+    });
+
+    describe('_focusToFirstInvalidControl', () => {
+      beforeEach(() => {
+        component._resetFocus = jest.fn();
+
+        formService.isBetreffInvalid = jest.fn();
+        formService.isNachrichtInvalid = jest.fn();
+      });
+
+      it('should check betreff', () => {
+        component._focusToFirstInvalidControl();
+
+        expect(formService.isBetreffInvalid).toHaveBeenCalled();
+      });
+
+      it('should check nachricht', () => {
+        formService.isBetreffInvalid = jest.fn().mockReturnValue(false);
+
+        component._focusToFirstInvalidControl();
+
+        expect(formService.isNachrichtInvalid).toHaveBeenCalled();
+      });
+
+      it('should NOT check nachricht', () => {
+        formService.isBetreffInvalid = jest.fn().mockReturnValue(true);
+
+        component._focusToFirstInvalidControl();
+
+        expect(formService.isNachrichtInvalid).not.toHaveBeenCalled();
+      });
+
+      it('should focus betreff', () => {
+        formService.isBetreffInvalid = jest.fn().mockReturnValue(true);
+
+        component._focusToFirstInvalidControl();
+
+        expect(component.focusBetreff).toBe(true);
+      });
+
+      it('should NOT focus betreff', () => {
+        formService.isBetreffInvalid = jest.fn().mockReturnValue(false);
+
+        component._focusToFirstInvalidControl();
+
+        expect(component.focusBetreff).toBe(false);
+      });
+
+      it('should focus nachricht', () => {
+        formService.isBetreffInvalid = jest.fn().mockReturnValue(false);
+        formService.isNachrichtInvalid = jest.fn().mockReturnValue(true);
+
+        component._focusToFirstInvalidControl();
+
+        expect(component.focusNachricht).toBe(true);
+      });
+
+      it('should NOT focus nachricht', () => {
+        formService.isBetreffInvalid = jest.fn().mockReturnValue(true);
+        formService.isNachrichtInvalid = jest.fn().mockReturnValue(false);
+
+        component._focusToFirstInvalidControl();
+
+        expect(component.focusNachricht).toBe(false);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('empfaenger', () => {
+      it('should exists', () => {
+        component.wizard = createWizard();
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, empfaengerTestId);
+      });
+
+      it('should NOT exits', () => {
+        component.wizard = { ...createWizard(), empfaenger: null };
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, empfaengerTestId);
+      });
+    });
+
+    describe('dokumente hochladen summary', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, dokumenteTestsId);
+      });
+
+      it('should have inputs', () => {
+        const dokumentComponent: BescheidWizardDokumenteHochladenSummaryComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardDokumenteHochladenSummaryComponent>(fixture, dokumenteTestsId);
+
+        expect(dokumentComponent.isBescheidDocumentMissing).toBe(false);
+      });
+
+      describe('submit button', () => {
+        it('should exists with update link', () => {
+          component.bescheidResource = createBescheidResource([BescheidLinkRel.UPDATE]);
+
+          fixture.detectChanges();
+
+          existsAsHtmlElement(fixture, dokumenteTestsId);
+        });
+
+        it('should exists with bescheiden link', () => {
+          component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN]);
+
+          fixture.detectChanges();
+
+          existsAsHtmlElement(fixture, dokumenteTestsId);
+        });
+
+        it('should NOT exists on missing links', () => {
+          component.bescheidResource = createBescheidResource();
+
+          fixture.detectChanges();
+
+          notExistsAsHtmlElement(fixture, submitButtonTestId);
+        });
+
+        it('should have inputs', () => {
+          component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN]);
+          const submitCommandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+          component.submitStateResource$ = of(submitCommandStateResource);
+
+          fixture.detectChanges();
+          const submitButtonComponent: ButtonWithSpinnerComponent =
+            getElementComponentFromFixtureByCss<ButtonWithSpinnerComponent>(fixture, submitButtonTestId);
+
+          expect(submitButtonComponent.stateResource).toEqual(submitCommandStateResource);
+        });
+
+        describe('output', () => {
+          describe('clickEmitter', () => {
+            it('should call handler', () => {
+              component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN]);
+              component.submit = jest.fn();
+              fixture.detectChanges();
+
+              triggerEvent({ fixture, elementSelector: submitButtonTestId, name: 'clickEmitter' });
+
+              expect(component.submit).toHaveBeenCalled();
+            });
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/senden/bescheid-wizard-bescheid-versenden-senden.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/senden/bescheid-wizard-bescheid-versenden-senden.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5d03f994ed85918c979d7101e8d6b4ec14a59ee3
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/senden/bescheid-wizard-bescheid-versenden-senden.component.ts
@@ -0,0 +1,48 @@
+import { BescheidLinkRel, BescheidResource, BescheidWizardDialogResult, Wizard } from '@alfa-client/bescheid-shared';
+import { CommandResource, tapOnCommandSuccessfullyDone, tapOnFailedCommand } from '@alfa-client/command-shared';
+import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
+import { DialogRef } from '@angular/cdk/dialog';
+import { Component, inject, Input } from '@angular/core';
+import { Observable, of } from 'rxjs';
+import { BescheidFormService } from '../../../../bescheid.formservice';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-bescheid-versenden-senden',
+  templateUrl: './bescheid-wizard-bescheid-versenden-senden.component.html',
+})
+export class BescheidWizardBescheidVersendenSendenComponent {
+  @Input() bescheidResource: BescheidResource;
+  @Input() wizard: Wizard;
+
+  public readonly formService: BescheidFormService = inject(BescheidFormService);
+  private readonly dialogRef = inject(DialogRef<BescheidWizardDialogResult>);
+
+  public submitStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
+
+  public focusBetreff: boolean = false;
+  public focusNachricht: boolean = false;
+
+  public readonly bescheidLinkRel = BescheidLinkRel;
+  public readonly formServiceClass = BescheidFormService;
+
+  public submit(): void {
+    this._resetFocus();
+    this.submitStateResource$ = this.formService.submit().pipe(
+      tapOnFailedCommand(() => this._focusToFirstInvalidControl()),
+      tapOnCommandSuccessfullyDone(() => this.dialogRef.close({ reloadVorgang: true })),
+    );
+  }
+
+  _focusToFirstInvalidControl(): void {
+    if (this.formService.isBetreffInvalid()) {
+      this.focusBetreff = true;
+    } else if (this.formService.isNachrichtInvalid()) {
+      this.focusNachricht = true;
+    }
+  }
+
+  _resetFocus(): void {
+    this.focusBetreff = false;
+    this.focusNachricht = false;
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/speichern/bescheid-wizard-bescheid-versenden-speichern.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/speichern/bescheid-wizard-bescheid-versenden-speichern.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..a19c2b53db33741056c2cc6844e7b83536512f5d
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/speichern/bescheid-wizard-bescheid-versenden-speichern.component.html
@@ -0,0 +1,20 @@
+<div class="flex h-full flex-col justify-between">
+  <div>
+    <alfa-bescheid-wizard-antrag-bescheiden-summary></alfa-bescheid-wizard-antrag-bescheiden-summary>
+    <alfa-bescheid-wizard-dokumente-hochladen-summary
+      [isBescheidDocumentMissing]="false"
+      data-test-id="bescheid-versenden-dokumente"
+    ></alfa-bescheid-wizard-dokumente-hochladen-summary>
+    <p class="mb-8 text-base font-normal text-text">Der Bescheid muss manuell versendet werden.</p>
+  </div>
+
+  @if ((bescheidResource | hasLink: bescheidLinkRel.UPDATE) || (bescheidResource | hasLink: bescheidLinkRel.BESCHEIDEN)) {
+    <ods-button-with-spinner
+      class="self-end"
+      [stateResource]="submitStateResource$ | async"
+      text="Antrag bescheiden und speichern"
+      (clickEmitter)="submit()"
+      data-test-id="confirm-and-save-button"
+    ></ods-button-with-spinner>
+  }
+</div>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/speichern/bescheid-wizard-bescheid-versenden-speichern.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/speichern/bescheid-wizard-bescheid-versenden-speichern.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4382985e2f96fcff9aee1b1604a7622641202420
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/speichern/bescheid-wizard-bescheid-versenden-speichern.component.spec.ts
@@ -0,0 +1,186 @@
+import { BescheidLinkRel, BescheidWizardDialogResult } from '@alfa-client/bescheid-shared';
+import { CommandResource } from '@alfa-client/command-shared';
+import {
+  createEmptyStateResource,
+  createErrorStateResource,
+  createLoadingStateResource,
+  HasLinkPipe,
+  StateResource,
+} from '@alfa-client/tech-shared';
+import {
+  existsAsHtmlElement,
+  getElementComponentFromFixtureByCss,
+  Mock,
+  mock,
+  notExistsAsHtmlElement,
+  triggerEvent,
+} from '@alfa-client/test-utils';
+import { DialogRef } from '@angular/cdk/dialog';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { expect } from '@jest/globals';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { MockComponent } from 'ng-mocks';
+import { EMPTY, of } from 'rxjs';
+import { createBescheidResource } from '../../../../../../../../bescheid-shared/src/test/bescheid';
+import { createSuccessfullyDoneCommandStateResource } from '../../../../../../../../command-shared/test/command';
+import { getDataTestIdOf } from '../../../../../../../../tech-shared/test/data-test';
+import { createProblemDetail } from '../../../../../../../../tech-shared/test/error';
+import { singleColdCompleted } from '../../../../../../../../tech-shared/test/marbles';
+import { BescheidFormService } from '../../../../bescheid.formservice';
+import { BescheidWizardAntragBescheidenSummaryComponent } from '../../../antrag-bescheiden/summary/bescheid-wizard-antrag-bescheiden-summary.component';
+import { BescheidWizardDokumenteHochladenSummaryComponent } from '../../../dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component';
+import { BescheidWizardBescheidVersendenSpeichernComponent } from './bescheid-wizard-bescheid-versenden-speichern.component';
+
+describe('BescheidWizardBescheidVersendenSpeichernComponent', () => {
+  let component: BescheidWizardBescheidVersendenSpeichernComponent;
+  let fixture: ComponentFixture<BescheidWizardBescheidVersendenSpeichernComponent>;
+
+  const dokumenteTestsId: string = getDataTestIdOf('bescheid-versenden-dokumente');
+  const submitButtonTestId: string = getDataTestIdOf('confirm-and-save-button');
+
+  let formService: Mock<BescheidFormService>;
+  let dialogRef: Mock<DialogRef<BescheidWizardDialogResult>>;
+
+  beforeEach(() => {
+    formService = mock(BescheidFormService);
+    formService.submit = jest.fn();
+    dialogRef = mock(DialogRef<BescheidWizardDialogResult>);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardBescheidVersendenSpeichernComponent,
+        MockComponent(BescheidWizardAntragBescheidenSummaryComponent),
+        MockComponent(BescheidWizardDokumenteHochladenSummaryComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        HasLinkPipe,
+      ],
+      providers: [
+        { provide: BescheidFormService, useValue: formService },
+        { provide: DialogRef<BescheidWizardDialogResult>, useValue: dialogRef },
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardBescheidVersendenSpeichernComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      expect(component.submitStateResource$).toBeObservable(singleColdCompleted(createEmptyStateResource()));
+    });
+
+    describe('submit', () => {
+      beforeEach(() => {
+        formService.submit.mockReturnValue(EMPTY);
+      });
+
+      it('should call form service', () => {
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(formService.submit).toHaveBeenCalled();
+      });
+
+      it('should close dialog', () => {
+        formService.submit.mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(dialogRef.close).toHaveBeenCalled();
+      });
+
+      it('should NOT close dialog on pending send', () => {
+        formService.submit.mockReturnValue(of(createLoadingStateResource()));
+
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(dialogRef.close).not.toHaveBeenCalled();
+      });
+
+      it('should NOT close dialog on failed send', () => {
+        formService.submit.mockReturnValue(of(createErrorStateResource(createProblemDetail())));
+
+        component.submit();
+        component.submitStateResource$.subscribe();
+
+        expect(dialogRef.close).not.toHaveBeenCalled();
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('dokumente hochladen summary', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, dokumenteTestsId);
+      });
+
+      it('should have inputs', () => {
+        const dokumentComponent: BescheidWizardDokumenteHochladenSummaryComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardDokumenteHochladenSummaryComponent>(fixture, dokumenteTestsId);
+
+        expect(dokumentComponent.isBescheidDocumentMissing).toBe(false);
+      });
+
+      describe('submit button', () => {
+        it('should exists with update link', () => {
+          component.bescheidResource = createBescheidResource([BescheidLinkRel.UPDATE]);
+
+          fixture.detectChanges();
+
+          existsAsHtmlElement(fixture, dokumenteTestsId);
+        });
+
+        it('should exists with bescheiden link', () => {
+          component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN]);
+
+          fixture.detectChanges();
+
+          existsAsHtmlElement(fixture, dokumenteTestsId);
+        });
+
+        it('should NOT exists on missing links', () => {
+          component.bescheidResource = createBescheidResource();
+
+          fixture.detectChanges();
+
+          notExistsAsHtmlElement(fixture, submitButtonTestId);
+        });
+
+        it('should have inputs', () => {
+          component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN]);
+          const submitCommandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+          component.submitStateResource$ = of(submitCommandStateResource);
+
+          fixture.detectChanges();
+          const submitButtonComponent: ButtonWithSpinnerComponent =
+            getElementComponentFromFixtureByCss<ButtonWithSpinnerComponent>(fixture, submitButtonTestId);
+
+          expect(submitButtonComponent.stateResource).toEqual(submitCommandStateResource);
+        });
+
+        describe('output', () => {
+          describe('clickEmitter', () => {
+            it('should call handler', () => {
+              component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN]);
+              component.submit = jest.fn();
+              fixture.detectChanges();
+
+              triggerEvent({ fixture, elementSelector: submitButtonTestId, name: 'clickEmitter' });
+
+              expect(component.submit).toHaveBeenCalled();
+            });
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/speichern/bescheid-wizard-bescheid-versenden-speichern.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/speichern/bescheid-wizard-bescheid-versenden-speichern.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f7ee9b36506b3b783c70df4e5238eb690a7bb0c2
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/speichern/bescheid-wizard-bescheid-versenden-speichern.component.ts
@@ -0,0 +1,28 @@
+import { BescheidLinkRel, BescheidResource, BescheidWizardDialogResult } from '@alfa-client/bescheid-shared';
+import { CommandResource, tapOnCommandSuccessfullyDone } from '@alfa-client/command-shared';
+import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
+import { DialogRef } from '@angular/cdk/dialog';
+import { Component, inject, Input } from '@angular/core';
+import { Observable, of } from 'rxjs';
+import { BescheidFormService } from '../../../../bescheid.formservice';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-bescheid-versenden-speichern',
+  templateUrl: './bescheid-wizard-bescheid-versenden-speichern.component.html',
+})
+export class BescheidWizardBescheidVersendenSpeichernComponent {
+  @Input() bescheidResource: BescheidResource;
+
+  private readonly formService: BescheidFormService = inject(BescheidFormService);
+  private readonly dialogRef = inject(DialogRef<BescheidWizardDialogResult>);
+
+  public submitStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
+
+  public readonly bescheidLinkRel = BescheidLinkRel;
+
+  public submit(): void {
+    this.submitStateResource$ = this.formService
+      .submit()
+      .pipe(tapOnCommandSuccessfullyDone(() => this.dialogRef.close({ reloadVorgang: true })));
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.html
index c7041e1f2afb7f84f09f5f6591815279ae82a87f..178a0f574555303c350994f4696c6e9e42f1fc52 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.html
@@ -32,18 +32,27 @@
 
 <form [formGroup]="formService.form" class="h-full">
   <div class="grid h-full">
-    <alfa-bescheid-wizard-antrag-bescheiden
-      *ngIf="activeStep === bescheidWizardStep.AntragBescheiden"
-      [vorgangWithEingangResource]="vorgangWithEingangResource"
-      [bescheidResource]="bescheidStateResource.resource"
-      [submitStateResource]="submitStateResource"
-      (weiterClickEmitter)="weiterClickEmitter.emit($event)"
-      (vorgangAbgeschlossen)="vorgangAbgeschlossen.emit()"
-      data-test-id="antrag-bescheiden-step"
-    ></alfa-bescheid-wizard-antrag-bescheiden>
-    <alfa-bescheid-wizard-dokumente-hochladen
-      *ngIf="activeStep === bescheidWizardStep.DokumenteHochladen"
-      data-test-id="dokumente-hochladen-step"
-    ></alfa-bescheid-wizard-dokumente-hochladen>
+    @switch (activeStep) {
+      @case (bescheidWizardStep.AntragBescheiden) {
+        <alfa-bescheid-wizard-antrag-bescheiden-container
+          [vorgangWithEingangResource]="vorgangWithEingangResource"
+          [bescheidResource]="bescheidResource"
+          (vorgangAbgeschlossen)="vorgangAbgeschlossen.emit()"
+          data-test-id="antrag-bescheiden-step"
+        ></alfa-bescheid-wizard-antrag-bescheiden-container>
+      }
+      @case (bescheidWizardStep.DokumenteHochladen) {
+        <alfa-bescheid-wizard-dokumente-hochladen-container
+          [bescheidResource]="bescheidResource"
+          data-test-id="dokumente-hochladen-step"
+        ></alfa-bescheid-wizard-dokumente-hochladen-container>
+      }
+      @case (bescheidWizardStep.BescheidVersenden) {
+        <alfa-bescheid-wizard-bescheid-versenden-container
+          [bescheidResource]="bescheidResource"
+          data-test-id="bescheid-versenden-step"
+        ></alfa-bescheid-wizard-bescheid-versenden-container>
+      }
+    }
   </div>
 </form>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.spec.ts
index 0f84df6c0fb722b9b4c8cded349b71edf8b039a9..c818a3613876e7b6533d508d5714fbbfa5881330 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.spec.ts
@@ -21,12 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { BescheidResource, BescheidService, BescheidWizardStep } from '@alfa-client/bescheid-shared';
-import { HasLinkPipe, StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
+import { BescheidResource, BescheidWizardStep } from '@alfa-client/bescheid-shared';
+import {
+  createEmptyStateResource,
+  createErrorStateResource,
+  createLoadingStateResource,
+  HasLinkPipe,
+  StateResource,
+} from '@alfa-client/tech-shared';
 import {
-  Mock,
   existsAsHtmlElement,
-  getElementFromFixtureByType,
+  getElementComponentFromFixtureByCss,
+  Mock,
   mock,
   notExistsAsHtmlElement,
   triggerEvent,
@@ -37,15 +43,18 @@ import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
 import { EventEmitter } from '@angular/core';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
+import { expect } from '@jest/globals';
 import { MockComponent } from 'ng-mocks';
-import { createBescheidStateResource } from '../../../../../bescheid-shared/src/test/bescheid';
-import { createSuccessfullyDoneCommandStateResource } from '../../../../../command-shared/test/command';
+import { BescheidService2 } from '../../../../../bescheid-shared/src/lib/bescheid2.service';
+import { createBescheidResource, createBescheidStateResource } from '../../../../../bescheid-shared/src/test/bescheid';
 import { getDataTestIdOf } from '../../../../../tech-shared/test/data-test';
+import { createProblemDetail } from '../../../../../tech-shared/test/error';
 import { createVorgangWithEingangResource } from '../../../../../vorgang-shared/test/vorgang';
 import { BescheidFormService } from '../bescheid.formservice';
-import { BescheidWizardAntragBescheidenComponent } from './antrag-bescheiden/bescheid-wizard-antrag-bescheiden.component';
+import { BescheidWizardAntragBescheidenContainerComponent } from './antrag-bescheiden/bescheid-wizard-antrag-bescheiden-container.component';
+import { BescheidWizardBescheidVersendenContainerComponent } from './bescheid-versenden/bescheid-wizard-bescheid-versenden-container.component';
 import { BescheidWizardComponent } from './bescheid-wizard.component';
-import { BescheidWizardDokumenteHochladenComponent } from './dokumente-hochladen/bescheid-wizard-dokumente-hochladen.component';
+import { BescheidWizardDokumenteHochladenContainerComponent } from './dokumente-hochladen-container/bescheid-wizard-dokumente-hochladen-container.component';
 import { BescheidWizardStepperComponent } from './stepper/bescheid-wizard-stepper.component';
 
 describe('BescheidWizardComponent', () => {
@@ -55,12 +64,13 @@ describe('BescheidWizardComponent', () => {
   const bescheidLoadingSpinner: string = getDataTestIdOf('bescheid-loading-spinner');
   const antragBescheidenStep: string = getDataTestIdOf('antrag-bescheiden-step');
   const dokumenteHochladenStep: string = getDataTestIdOf('dokumente-hochladen-step');
+  const bescheidVersendenStepTestId: string = getDataTestIdOf('bescheid-versenden-step');
 
-  let bescheidService: Mock<BescheidService>;
+  let bescheidService: Mock<BescheidService2>;
   let formService: BescheidFormService;
 
   beforeEach(() => {
-    bescheidService = mock(BescheidService);
+    bescheidService = mock(BescheidService2);
     formService = new BescheidFormService(new UntypedFormBuilder(), useFromMock(bescheidService));
   });
 
@@ -69,8 +79,9 @@ describe('BescheidWizardComponent', () => {
       declarations: [
         BescheidWizardComponent,
         MockComponent(BescheidWizardStepperComponent),
-        MockComponent(BescheidWizardAntragBescheidenComponent),
-        MockComponent(BescheidWizardDokumenteHochladenComponent),
+        MockComponent(BescheidWizardAntragBescheidenContainerComponent),
+        MockComponent(BescheidWizardDokumenteHochladenContainerComponent),
+        MockComponent(BescheidWizardBescheidVersendenContainerComponent),
         MockComponent(SpinnerComponent),
         HasLinkPipe,
       ],
@@ -85,7 +96,6 @@ describe('BescheidWizardComponent', () => {
 
     fixture = TestBed.createComponent(BescheidWizardComponent);
     component = fixture.componentInstance;
-    component.weiterClickEmitter = useFromMock(mock(EventEmitter<BescheidWizardStep>));
     component.vorgangAbgeschlossen = useFromMock(mock(EventEmitter<void>));
     fixture.detectChanges();
   });
@@ -117,6 +127,30 @@ describe('BescheidWizardComponent', () => {
 
         expect(component.bescheidStateResource).toEqual(component.bescheidStateResource);
       });
+
+      it('should set bescheid resource if loaded', () => {
+        component.bescheidStateResource = createBescheidStateResource();
+
+        expect(component.bescheidResource).toEqual(component.bescheidStateResource.resource);
+      });
+
+      it('should NOT set bescheid resource on pending load', () => {
+        const bescheidResource: BescheidResource = createBescheidResource();
+        component.bescheidResource = bescheidResource;
+
+        component.bescheidStateResource = createLoadingStateResource();
+
+        expect(component.bescheidResource).toEqual(bescheidResource);
+      });
+
+      it('should NOT set bescheid resource on failed load', () => {
+        const bescheidResource: BescheidResource = createBescheidResource();
+        component.bescheidResource = bescheidResource;
+
+        component.bescheidStateResource = createErrorStateResource(createProblemDetail());
+
+        expect(component.bescheidResource).toEqual(bescheidResource);
+      });
     });
   });
 
@@ -125,7 +159,7 @@ describe('BescheidWizardComponent', () => {
       component.bescheidStateResource = createBescheidStateResource();
     });
 
-    describe('ozgcloud-spinner', () => {
+    describe('spinner', () => {
       it('should exists', () => {
         component.vorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEID_DRAFT]);
         component.bescheidStateResource = createEmptyStateResource();
@@ -153,110 +187,126 @@ describe('BescheidWizardComponent', () => {
         notExistsAsHtmlElement(fixture, bescheidLoadingSpinner);
       });
 
-      describe('input', () => {
-        it('should set stateResource', () => {
-          component.vorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEID_DRAFT]);
-          component.bescheidStateResource = createEmptyStateResource();
+      it('should have been called with inputs', () => {
+        component.vorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEID_DRAFT]);
+        component.bescheidStateResource = createEmptyStateResource();
 
-          fixture.detectChanges();
+        fixture.detectChanges();
+        const spinnerComponent: SpinnerComponent = getElementComponentFromFixtureByCss<SpinnerComponent>(
+          fixture,
+          bescheidLoadingSpinner,
+        );
 
-          expect(getElementFromFixtureByType(fixture, SpinnerComponent).stateResource).toEqual(component.bescheidStateResource);
-        });
+        expect(spinnerComponent.stateResource).toEqual(component.bescheidStateResource);
       });
     });
 
-    describe('alfa-bescheid-wizard-antrag-bescheiden', () => {
-      function getElementComponent(): BescheidWizardAntragBescheidenComponent {
-        return getElementFromFixtureByType(fixture, BescheidWizardAntragBescheidenComponent);
-      }
-
-      it('should show', () => {
-        givenActiveStep(1);
-        givenLoadedBescheidStateResrouce();
+    describe('antrag bescheiden', () => {
+      it('should exists', () => {
+        givenActiveStep(BescheidWizardStep.AntragBescheiden);
 
         existsAsHtmlElement(fixture, antragBescheidenStep);
       });
 
-      it.each([2, 3])('should NOT show in step %d', (step: number) => {
+      it.each([2, 3])('should NOT exists in step %d', (step: number) => {
         givenActiveStep(step);
-        givenLoadedBescheidStateResrouce();
 
         notExistsAsHtmlElement(fixture, antragBescheidenStep);
       });
 
-      describe('input', () => {
-        it('should set vorgangWithEingangResource', () => {
-          givenActiveStep(1);
-          givenLoadedBescheidStateResrouce();
-          component.vorgangWithEingangResource = createVorgangWithEingangResource();
-
-          fixture.detectChanges();
+      it('should have been called with inputs', () => {
+        givenActiveStep(BescheidWizardStep.AntragBescheiden);
+        givenLoadedBescheidStateResource();
+        givenLoadedBescheidStateResource();
+        component.vorgangWithEingangResource = createVorgangWithEingangResource();
 
-          expect(getElementComponent().vorgangWithEingangResource).toBe(component.vorgangWithEingangResource);
-        });
+        fixture.detectChanges();
 
-        it('should set bescheidResource', () => {
-          givenActiveStep(1);
-          givenLoadedBescheidStateResrouce();
+        const antragBescheidenComponent: BescheidWizardAntragBescheidenContainerComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardAntragBescheidenContainerComponent>(fixture, antragBescheidenStep);
 
-          fixture.detectChanges();
+        expect(antragBescheidenComponent.vorgangWithEingangResource).toBe(component.vorgangWithEingangResource);
+        expect(antragBescheidenComponent.bescheidResource).toEqual(component.bescheidResource);
+      });
 
-          expect(getElementComponent().bescheidResource).toEqual(component.bescheidStateResource.resource);
+      describe('output', () => {
+        beforeEach(() => {
+          givenActiveStep(BescheidWizardStep.AntragBescheiden);
+          givenLoadedBescheidStateResource();
         });
 
-        it('should set submitStateResource', () => {
-          givenActiveStep(1);
-          givenLoadedBescheidStateResrouce();
-          component.submitStateResource = createSuccessfullyDoneCommandStateResource();
+        describe('vorgangAbgeschlossen', () => {
+          it('should emit', () => {
+            triggerEvent({
+              fixture,
+              name: 'vorgangAbgeschlossen',
+              elementSelector: antragBescheidenStep,
+            });
 
-          fixture.detectChanges();
-
-          expect(getElementComponent().submitStateResource).toEqual(component.submitStateResource);
+            expect(component.vorgangAbgeschlossen.emit).toHaveBeenCalled();
+          });
         });
       });
+    });
 
-      describe('output', () => {
-        beforeEach(() => {
-          givenActiveStep(1);
-          givenLoadedBescheidStateResrouce();
-        });
+    describe('dokumente hochladen', () => {
+      beforeEach(() => {
+        givenActiveStep(BescheidWizardStep.DokumenteHochladen);
+        fixture.detectChanges();
+      });
 
-        it('should emit weiterClickEmitter', () => {
-          triggerEvent({
-            fixture,
-            name: 'weiterClickEmitter',
-            elementSelector: antragBescheidenStep,
-            data: BescheidWizardStep.DokumenteHochladen,
-          });
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, dokumenteHochladenStep);
+      });
 
-          expect(component.weiterClickEmitter.emit).toHaveBeenCalledWith(BescheidWizardStep.DokumenteHochladen);
-        });
+      it.each([1, 3])('should NOT exists in step %d', (step: number) => {
+        givenActiveStep(step);
+
+        notExistsAsHtmlElement(fixture, dokumenteHochladenStep);
+      });
 
-        it('should emit vorgangAbgeschlossen', () => {
-          triggerEvent({
+      it('should have been called with inputs', () => {
+        givenActiveStep(BescheidWizardStep.DokumenteHochladen);
+
+        fixture.detectChanges();
+
+        const dokumenteHochladenComponent: BescheidWizardDokumenteHochladenContainerComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardDokumenteHochladenContainerComponent>(
             fixture,
-            name: 'vorgangAbgeschlossen',
-            elementSelector: antragBescheidenStep,
-          });
+            dokumenteHochladenStep,
+          );
 
-          expect(component.vorgangAbgeschlossen.emit).toHaveBeenCalled();
-        });
+        expect(dokumenteHochladenComponent.bescheidResource).toEqual(component.bescheidResource);
       });
     });
 
-    describe('alfa-bescheid-wizard-dokumente-hochladen', () => {
-      it('should show', () => {
-        givenActiveStep(2);
-        givenLoadedBescheidStateResrouce();
+    describe('bescheid versenden', () => {
+      beforeEach(() => {
+        component.activeStep = BescheidWizardStep.BescheidVersenden;
+        fixture.detectChanges();
+      });
 
-        existsAsHtmlElement(fixture, dokumenteHochladenStep);
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, bescheidVersendenStepTestId);
       });
 
-      it.each([1, 3])('should NOT show in step %d', (step: number) => {
+      it.each([1, 2])('should NOT exists in step %d', (step: number) => {
         givenActiveStep(step);
-        givenLoadedBescheidStateResrouce();
 
-        notExistsAsHtmlElement(fixture, dokumenteHochladenStep);
+        notExistsAsHtmlElement(fixture, bescheidVersendenStepTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        component.bescheidStateResource = createBescheidStateResource();
+
+        fixture.detectChanges();
+        const bescheidVersendenComponent: BescheidWizardBescheidVersendenContainerComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardBescheidVersendenContainerComponent>(
+            fixture,
+            bescheidVersendenStepTestId,
+          );
+
+        expect(bescheidVersendenComponent.bescheidResource).toEqual(component.bescheidResource);
       });
     });
   });
@@ -266,10 +316,11 @@ describe('BescheidWizardComponent', () => {
     fixture.detectChanges();
   }
 
-  function givenLoadedBescheidStateResrouce(): StateResource<BescheidResource> {
-    const resource: StateResource<BescheidResource> = createBescheidStateResource();
-    component.bescheidStateResource = resource;
+  function givenLoadedBescheidStateResource(): StateResource<BescheidResource> {
+    const stateResource: StateResource<BescheidResource> = createBescheidStateResource();
+    component.bescheidStateResource = stateResource;
+    component.bescheidResource = stateResource.resource;
     fixture.detectChanges();
-    return resource;
+    return stateResource;
   }
 });
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.ts
index bbeb757952ace3785c2fafbd24e0e80f862b9959..d601c79c77cbfe839e4563419004d503810b012e 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component.ts
@@ -22,10 +22,9 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { BescheidResource, BescheidWizardStep } from '@alfa-client/bescheid-shared';
-import { StateResource, isLoaded } from '@alfa-client/tech-shared';
+import { isLoaded, StateResource } from '@alfa-client/tech-shared';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { Component, EventEmitter, Input, Output } from '@angular/core';
-import { Resource } from '@ngxp/rest';
 import { BescheidFormService } from '../bescheid.formservice';
 
 @Component({
@@ -38,6 +37,7 @@ export class BescheidWizardComponent {
   @Input() set bescheidStateResource(value: StateResource<BescheidResource>) {
     if (isLoaded(value)) {
       this.formService.patchValues(value.resource);
+      this.bescheidResource = value.resource;
     }
     this._bescheidStateResource = value;
   }
@@ -46,12 +46,11 @@ export class BescheidWizardComponent {
     return this._bescheidStateResource;
   }
 
-  @Input() activeStep: number;
-  @Input() submitStateResource: StateResource<Resource>;
+  @Input() activeStep: BescheidWizardStep;
 
-  @Output() weiterClickEmitter: EventEmitter<BescheidWizardStep> = new EventEmitter<BescheidWizardStep>();
   @Output() vorgangAbgeschlossen: EventEmitter<void> = new EventEmitter<void>();
 
+  public bescheidResource: BescheidResource;
   private _bescheidStateResource: StateResource<BescheidResource>;
 
   public readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel;
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/cancel-dialog-container/bescheid-wizard-cancel-dialog-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/cancel-dialog-container/bescheid-wizard-cancel-dialog-container.component.spec.ts
index 2e4c13bcb369d85dba5df9be85adff92e41bb760..5dfde26e4da2a928be6046e7c14d50b60790900a 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/cancel-dialog-container/bescheid-wizard-cancel-dialog-container.component.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/cancel-dialog-container/bescheid-wizard-cancel-dialog-container.component.spec.ts
@@ -21,36 +21,23 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { BescheidService } from '@alfa-client/bescheid-shared';
 import { CommandResource } from '@alfa-client/command-shared';
-import { StateResource, createErrorStateResource } from '@alfa-client/tech-shared';
-import {
-  DialogRefMock,
-  Mock,
-  createDialogRefMock,
-  existsAsHtmlElement,
-  getElementComponentFromFixtureByCss,
-  mock,
-  triggerEvent,
-} from '@alfa-client/test-utils';
+import { createErrorStateResource, StateResource } from '@alfa-client/tech-shared';
+import { createDialogRefMock, DialogRefMock, existsAsHtmlElement, getElementComponentFromFixtureByCss, Mock, mock, triggerEvent, } from '@alfa-client/test-utils';
 import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { expect } from '@jest/globals';
 import { MockComponent } from 'ng-mocks';
 import { EMPTY, of } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
 import { createBescheidResource } from '../../../../../../bescheid-shared/src/test/bescheid';
-import {
-  createCommandStateResource,
-  createSuccessfullyDoneCommandStateResource,
-} from '../../../../../../command-shared/test/command';
+import { createCommandStateResource, createSuccessfullyDoneCommandStateResource, } from '../../../../../../command-shared/test/command';
 import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
 import { createApiError } from '../../../../../../tech-shared/test/error';
 import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
 import { BescheidFormService } from '../../bescheid.formservice';
-import {
-  BescheidWizardCancelDialogContainerComponent,
-  CancelWizardDialogData,
-} from './bescheid-wizard-cancel-dialog-container.component';
+import { BescheidWizardCancelDialogContainerComponent, CancelWizardDialogData, } from './bescheid-wizard-cancel-dialog-container.component';
 
 describe('BescheidWizardCancelDialogContainerComponent', () => {
   let component: BescheidWizardCancelDialogContainerComponent;
@@ -64,21 +51,23 @@ describe('BescheidWizardCancelDialogContainerComponent', () => {
   };
 
   let formService: Mock<BescheidFormService>;
-  let bescheidService: Mock<BescheidService>;
+  let bescheidService: Mock<BescheidService2>;
   let dialogRef: DialogRefMock;
 
   beforeEach(() => {
-    formService = { ...mock(BescheidFormService), submit: jest.fn().mockReturnValue(EMPTY) };
-    bescheidService = { ...mock(BescheidService), bescheidVerwerfen: jest.fn().mockReturnValue(EMPTY) };
+    formService = mock(BescheidFormService);
+    formService.submit = jest.fn().mockReturnValue(EMPTY);
+    bescheidService = mock(BescheidService2);
+    bescheidService.deleteBescheid.mockReturnValue(EMPTY);
     dialogRef = createDialogRefMock();
   });
 
-  beforeEach(async () => {
+  async function configureTestingModule(dialogData: CancelWizardDialogData) {
     await TestBed.configureTestingModule({
       declarations: [BescheidWizardCancelDialogContainerComponent, MockComponent(OzgcloudStrokedButtonWithSpinnerComponent)],
       providers: [
         {
-          provide: BescheidService,
+          provide: BescheidService2,
           useValue: bescheidService,
         },
         {
@@ -99,13 +88,33 @@ describe('BescheidWizardCancelDialogContainerComponent', () => {
     fixture = TestBed.createComponent(BescheidWizardCancelDialogContainerComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
-  });
+  }
 
-  it('should create', () => {
-    expect(component).toBeTruthy();
+  beforeEach(async () => {
+    await configureTestingModule(dialogData);
   });
 
   describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    describe('ngOnInit', () => {
+      it('should lock bescheid sending', () => {
+        component.ngOnInit();
+
+        expect(bescheidService.lockBescheidSending).toHaveBeenCalled();
+      });
+    });
+
+    describe('ngOnDestroy', () => {
+      it('should unlock bescheid sending', () => {
+        component.ngOnDestroy();
+
+        expect(bescheidService.unlockBescheidSending).toHaveBeenCalled();
+      });
+    });
+
     describe('save', () => {
       beforeEach(() => {
         component.closeDialogWithWizard = jest.fn();
@@ -117,7 +126,7 @@ describe('BescheidWizardCancelDialogContainerComponent', () => {
         expect(formService.submit).toHaveBeenCalled();
       });
 
-      it('should emit save command state resource', () => {
+      it('should set save state resource', () => {
         const commandStateResource: StateResource<CommandResource> = createCommandStateResource();
         formService.submit = jest.fn().mockReturnValue(of(commandStateResource));
 
@@ -126,7 +135,7 @@ describe('BescheidWizardCancelDialogContainerComponent', () => {
         expect(component.saveStateResource$).toBeObservable(singleColdCompleted(commandStateResource));
       });
 
-      it('should handle successfully saved bescheid', () => {
+      it('should close dialog with wizard', () => {
         const commandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
         formService.submit = jest.fn().mockReturnValue(of(commandStateResource));
 
@@ -136,7 +145,7 @@ describe('BescheidWizardCancelDialogContainerComponent', () => {
         expect(component.closeDialogWithWizard).toHaveBeenCalled();
       });
 
-      it('should NOT handle successfully saved bescheid', () => {
+      it('should NOT close dialog with wizard', () => {
         const commandStateResource: StateResource<CommandResource> = createErrorStateResource(createApiError());
         formService.submit = jest.fn().mockReturnValue(of(commandStateResource));
 
@@ -155,20 +164,20 @@ describe('BescheidWizardCancelDialogContainerComponent', () => {
       it('should delete bescheid', () => {
         component.cancel();
 
-        expect(bescheidService.bescheidVerwerfen).toHaveBeenCalled();
+        expect(bescheidService.deleteBescheid).toHaveBeenCalled();
       });
 
-      it('should NOT delete bescheid', () => {
-        component.bescheidResource = null;
+      it('should NOT delete bescheid', async () => {
+        await configureTestingModule({} as CancelWizardDialogData);
 
         component.cancel();
 
-        expect(bescheidService.bescheidVerwerfen).not.toHaveBeenCalled();
+        expect(bescheidService.deleteBescheid).not.toHaveBeenCalled();
       });
 
-      it('should emit delete command state resource', () => {
+      it('should set delete command state resource', () => {
         const commandStateResource: StateResource<CommandResource> = createCommandStateResource();
-        bescheidService.bescheidVerwerfen = jest.fn().mockReturnValue(of(commandStateResource));
+        bescheidService.deleteBescheid = jest.fn().mockReturnValue(of(commandStateResource));
 
         component.cancel();
 
@@ -177,7 +186,7 @@ describe('BescheidWizardCancelDialogContainerComponent', () => {
 
       it('should close dialog on success', () => {
         const commandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
-        bescheidService.bescheidVerwerfen = jest.fn().mockReturnValue(of(commandStateResource));
+        bescheidService.deleteBescheid = jest.fn().mockReturnValue(of(commandStateResource));
 
         component.cancel();
         component.deleteStateResource$.subscribe();
@@ -187,7 +196,7 @@ describe('BescheidWizardCancelDialogContainerComponent', () => {
 
       it('should NOT close dialog on error', () => {
         const commandStateResource: StateResource<CommandResource> = createErrorStateResource(createApiError());
-        bescheidService.bescheidVerwerfen = jest.fn().mockReturnValue(of(commandStateResource));
+        bescheidService.deleteBescheid = jest.fn().mockReturnValue(of(commandStateResource));
 
         component.cancel();
         component.deleteStateResource$.subscribe();
@@ -195,8 +204,9 @@ describe('BescheidWizardCancelDialogContainerComponent', () => {
         expect(component.closeDialogWithWizard).not.toHaveBeenCalled();
       });
 
-      it('should close dialog with cancel result on non existing bescheid', () => {
-        component.bescheidResource = null;
+      it('should close dialog with cancel result on non existing bescheid', async () => {
+        await configureTestingModule({} as CancelWizardDialogData);
+        component.closeDialogWithWizard = jest.fn();
 
         component.cancel();
 
@@ -214,25 +224,23 @@ describe('BescheidWizardCancelDialogContainerComponent', () => {
   });
 
   describe('template', () => {
-    describe('ozgcloud-stroked-button-with-spinner Entwurf speichern', () => {
-      it('should show', () => {
+    describe('save button', () => {
+      it('should exists', () => {
         existsAsHtmlElement(fixture, speichernButton);
       });
 
-      describe('input', () => {
-        it('should set stateResource', () => {
-          const commandStateResource: StateResource<CommandResource> = createCommandStateResource();
-          component.saveStateResource$ = of(commandStateResource);
+      it('should have been called with inputs', () => {
+        const commandStateResource: StateResource<CommandResource> = createCommandStateResource();
+        component.saveStateResource$ = of(commandStateResource);
 
-          const elementComponent: OzgcloudStrokedButtonWithSpinnerComponent = getElementComponentFromFixtureByCss(
-            fixture,
-            speichernButton,
-          );
+        const elementComponent: OzgcloudStrokedButtonWithSpinnerComponent = getElementComponentFromFixtureByCss(
+          fixture,
+          speichernButton,
+        );
 
-          fixture.detectChanges();
+        fixture.detectChanges();
 
-          expect(elementComponent.stateResource).toBe(commandStateResource);
-        });
+        expect(elementComponent.stateResource).toBe(commandStateResource);
       });
 
       describe('output', () => {
@@ -246,25 +254,23 @@ describe('BescheidWizardCancelDialogContainerComponent', () => {
       });
     });
 
-    describe('ozgcloud-stroked-button-with-spinner Verwerfen', () => {
-      it('should show', () => {
+    describe('delete button', () => {
+      it('should exists', () => {
         existsAsHtmlElement(fixture, verwerfenButton);
       });
 
-      describe('input', () => {
-        it('should set stateResource', () => {
-          const commandStateResource: StateResource<CommandResource> = createCommandStateResource();
-          component.deleteStateResource$ = of(commandStateResource);
+      it('should have been called with inputs', () => {
+        const commandStateResource: StateResource<CommandResource> = createCommandStateResource();
+        component.deleteStateResource$ = of(commandStateResource);
 
-          const elementComponent: OzgcloudStrokedButtonWithSpinnerComponent = getElementComponentFromFixtureByCss(
-            fixture,
-            verwerfenButton,
-          );
+        const elementComponent: OzgcloudStrokedButtonWithSpinnerComponent = getElementComponentFromFixtureByCss(
+          fixture,
+          verwerfenButton,
+        );
 
-          fixture.detectChanges();
+        fixture.detectChanges();
 
-          expect(elementComponent.stateResource).toBe(commandStateResource);
-        });
+        expect(elementComponent.stateResource).toBe(commandStateResource);
       });
 
       describe('output', () => {
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/cancel-dialog-container/bescheid-wizard-cancel-dialog-container.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/cancel-dialog-container/bescheid-wizard-cancel-dialog-container.component.ts
index ae452113e7c35d55c6341ba1c79aa0fadb2005d3..2b2ee2327c607f41cc889b00a62c84ff3b9560b2 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/cancel-dialog-container/bescheid-wizard-cancel-dialog-container.component.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/cancel-dialog-container/bescheid-wizard-cancel-dialog-container.component.ts
@@ -21,13 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { BescheidResource, BescheidService } from '@alfa-client/bescheid-shared';
+import { BescheidResource } from '@alfa-client/bescheid-shared';
 import { tapOnCommandSuccessfullyDone } from '@alfa-client/command-shared';
-import { StateResource, isNotNil } from '@alfa-client/tech-shared';
+import { isNotNil, StateResource } from '@alfa-client/tech-shared';
 import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';
-import { Component, Inject } from '@angular/core';
+import { Component, inject, OnDestroy, OnInit } from '@angular/core';
 import { Resource } from '@ngxp/rest';
 import { Observable } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
 import { BescheidFormService } from '../../bescheid.formservice';
 
 export interface CancelWizardDialogData {
@@ -41,19 +42,23 @@ export interface CancelWizardDialogResult {
 @Component({
   templateUrl: './bescheid-wizard-cancel-dialog-container.component.html',
 })
-export class BescheidWizardCancelDialogContainerComponent {
+export class BescheidWizardCancelDialogContainerComponent implements OnInit, OnDestroy {
+  private readonly dialogData: CancelWizardDialogData = inject(DIALOG_DATA);
+  private readonly dialogRef = inject(DialogRef);
+  private readonly bescheidService = inject(BescheidService2);
+  private readonly formService = inject(BescheidFormService);
+
   public saveStateResource$: Observable<StateResource<Resource>>;
   public deleteStateResource$: Observable<StateResource<Resource>>;
 
-  bescheidResource: BescheidResource;
+  private readonly bescheidResource: BescheidResource = this.dialogData.bescheidResource;
+
+  ngOnInit(): void {
+    this.bescheidService.lockBescheidSending();
+  }
 
-  constructor(
-    @Inject(DIALOG_DATA) readonly dialogData: CancelWizardDialogData,
-    public dialogRef: DialogRef<CancelWizardDialogResult>,
-    private readonly bescheidService: BescheidService,
-    private readonly formService: BescheidFormService,
-  ) {
-    this.bescheidResource = dialogData.bescheidResource;
+  ngOnDestroy(): void {
+    this.bescheidService.unlockBescheidSending();
   }
 
   public save(): void {
@@ -63,7 +68,7 @@ export class BescheidWizardCancelDialogContainerComponent {
   public cancel(): void {
     if (isNotNil(this.bescheidResource)) {
       this.deleteStateResource$ = this.bescheidService
-        .bescheidVerwerfen()
+        .deleteBescheid()
         .pipe(tapOnCommandSuccessfullyDone(() => this.closeDialogWithWizard()));
     } else {
       this.closeDialogWithWizard();
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/bescheid-wizard-create-document-button-container.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/bescheid-wizard-create-document-button-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..e1c9cb9a825ec71879a005c00d792e406280dfc3
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/bescheid-wizard-create-document-button-container.component.html
@@ -0,0 +1,6 @@
+<alfa-bescheid-wizard-create-document-button
+  [bescheidResource]="bescheidResource"
+  [bescheidDocument]="bescheidDocument$ | async"
+  (clickEmitter)="createBescheidDocument()"
+  data-test-id="bescheid-wizard-create-button"
+></alfa-bescheid-wizard-create-document-button>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/bescheid-wizard-create-document-button-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/bescheid-wizard-create-document-button-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..578b614b16d24e6b9d40ed36e1a0608b04781e24
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/bescheid-wizard-create-document-button-container.component.spec.ts
@@ -0,0 +1,100 @@
+import { BescheidDocument, BescheidResource } from '@alfa-client/bescheid-shared';
+import { existsAsHtmlElement, getElementComponentFromFixtureByCss, mock, Mock, triggerEvent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+import { createBescheidDocument, createBescheidResource } from '../../../../../../bescheid-shared/src/test/bescheid';
+import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
+import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
+import { BescheidWizardCreateDocumentButtonContainerComponent } from './bescheid-wizard-create-document-button-container.component';
+import { BescheidWizardCreateDocumentButtonComponent } from './create-document-button/bescheid-wizard-create-document-button.component';
+
+describe('BescheidWizardCreateDocumentButtonContainerComponent', () => {
+  let component: BescheidWizardCreateDocumentButtonContainerComponent;
+  let fixture: ComponentFixture<BescheidWizardCreateDocumentButtonContainerComponent>;
+
+  const buttonTestId: string = getDataTestIdOf('bescheid-wizard-create-button');
+
+  const bescheidDocument: BescheidDocument = createBescheidDocument();
+  const bescheidResource: BescheidResource = createBescheidResource();
+
+  let bescheidService: Mock<BescheidService2>;
+
+  beforeEach(() => {
+    bescheidService = mock(BescheidService2);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardCreateDocumentButtonContainerComponent,
+        MockComponent(BescheidWizardCreateDocumentButtonComponent),
+      ],
+      providers: [{ provide: BescheidService2, useValue: bescheidService }],
+    }).compileComponents();
+
+    createComponent();
+  });
+
+  function createComponent() {
+    fixture = TestBed.createComponent(BescheidWizardCreateDocumentButtonContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      bescheidService.getBescheidDocument.mockReturnValue(of(bescheidDocument));
+      createComponent();
+
+      expect(component.bescheidDocument$).toBeObservable(singleColdCompleted(bescheidDocument));
+    });
+
+    describe('createBescheidDocument', () => {
+      it('should call service', () => {
+        component.createBescheidDocument();
+
+        expect(bescheidService.createBescheidDocument).toHaveBeenCalledWith(component.bescheidResource);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('create button', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, buttonTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        bescheidService.getBescheidDocument.mockReturnValue(of(bescheidDocument));
+        createComponent();
+        component.bescheidResource = bescheidResource;
+
+        fixture.detectChanges();
+
+        const buttonComponent: BescheidWizardCreateDocumentButtonComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardCreateDocumentButtonComponent>(fixture, buttonTestId);
+
+        expect(buttonComponent.bescheidResource).toEqual(bescheidResource);
+        expect(buttonComponent.bescheidDocument).toEqual(bescheidDocument);
+      });
+
+      describe('output', () => {
+        describe('clickEmitter', () => {
+          it('should call handler', () => {
+            component.createBescheidDocument = jest.fn();
+
+            triggerEvent({ fixture, elementSelector: buttonTestId, name: 'clickEmitter' });
+
+            expect(component.createBescheidDocument).toHaveBeenCalled();
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/bescheid-wizard-create-document-button-container.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/bescheid-wizard-create-document-button-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..63c525d76932091bdf971c5789c843568afd8112
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/bescheid-wizard-create-document-button-container.component.ts
@@ -0,0 +1,20 @@
+import { BescheidDocument, BescheidResource } from '@alfa-client/bescheid-shared';
+import { Component, inject, Input } from '@angular/core';
+import { Observable } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-create-document-button-container',
+  templateUrl: './bescheid-wizard-create-document-button-container.component.html',
+})
+export class BescheidWizardCreateDocumentButtonContainerComponent {
+  @Input() bescheidResource: BescheidResource;
+
+  private readonly bescheidService = inject(BescheidService2);
+
+  public readonly bescheidDocument$: Observable<BescheidDocument> = this.bescheidService.getBescheidDocument();
+
+  public createBescheidDocument(): void {
+    this.bescheidService.createBescheidDocument(this.bescheidResource);
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/create-document-button/bescheid-wizard-create-document-button.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/create-document-button/bescheid-wizard-create-document-button.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..db9307187ec8c100d91ff2c2ffc7b99dd22fc5e2
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/create-document-button/bescheid-wizard-create-document-button.component.html
@@ -0,0 +1,12 @@
+@if (bescheidResource | hasLink: BescheidLinkRel.CREATE_DOCUMENT) {
+  <ods-button-card
+    class="w-full max-w-72"
+    [isLoading]="bescheidDocument.create.loading"
+    (click)="clickEmitter.emit()"
+    text="Bescheiddokument"
+    subText="automatisch erstellen"
+    data-test-id="create-bescheid-document-button"
+  >
+    <ods-bescheid-generate-icon icon />
+  </ods-button-card>
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/create-document-button/bescheid-wizard-create-document-button.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/create-document-button/bescheid-wizard-create-document-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0870d4c34bd3f5dab6ae510dfe171877bc700590
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/create-document-button/bescheid-wizard-create-document-button.component.spec.ts
@@ -0,0 +1,119 @@
+import { BescheidDocument, BescheidLinkRel, createEmptyBescheidDocument } from '@alfa-client/bescheid-shared';
+import { HasLinkPipe } from '@alfa-client/tech-shared';
+import {
+  existsAsHtmlElement,
+  getElementComponentFromFixtureByCss,
+  mock,
+  Mock,
+  notExistsAsHtmlElement,
+  triggerEvent,
+} from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { BescheidGenerateIconComponent, ButtonCardComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+import { createBescheidDocument, createBescheidResource } from '../../../../../../../bescheid-shared/src/test/bescheid';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { BescheidFormService } from '../../../bescheid.formservice';
+import { BescheidWizardCreateDocumentButtonComponent } from './bescheid-wizard-create-document-button.component';
+
+describe('BescheidWizardAutomatischErstellenButtonComponent', () => {
+  let component: BescheidWizardCreateDocumentButtonComponent;
+  let fixture: ComponentFixture<BescheidWizardCreateDocumentButtonComponent>;
+
+  const createButtonTestId: string = getDataTestIdOf('create-bescheid-document-button');
+
+  let formService: Mock<BescheidFormService>;
+
+  const bescheidDocument: BescheidDocument = createBescheidDocument();
+
+  beforeEach(() => {
+    formService = mock(BescheidFormService);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardCreateDocumentButtonComponent,
+        MockComponent(ButtonCardComponent),
+        MockComponent(BescheidGenerateIconComponent),
+        HasLinkPipe,
+      ],
+      providers: [{ provide: BescheidFormService, useValue: formService }],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardCreateDocumentButtonComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      expect(component.bescheidDocument).toEqual(createEmptyBescheidDocument());
+    });
+
+    describe('set bescheid document', () => {
+      it('should set value', () => {
+        component.bescheidDocument = bescheidDocument;
+
+        expect(component.bescheidDocument).toEqual(bescheidDocument);
+      });
+
+      it('should call form service', () => {
+        component.bescheidDocument = bescheidDocument;
+
+        expect(formService.updateBescheidDocumentFile).toHaveBeenCalledWith(bescheidDocument.documentUri);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('create button', () => {
+      it('should exists', () => {
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.CREATE_DOCUMENT]);
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, createButtonTestId);
+      });
+
+      it('should NOT exists', () => {
+        component.bescheidResource = createBescheidResource();
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, createButtonTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.CREATE_DOCUMENT]);
+        component.bescheidDocument = bescheidDocument;
+
+        fixture.detectChanges();
+        const buttonComponent: ButtonCardComponent = getElementComponentFromFixtureByCss<ButtonCardComponent>(
+          fixture,
+          createButtonTestId,
+        );
+
+        expect(buttonComponent.isLoading).toEqual(bescheidDocument.create.loading);
+      });
+
+      describe('output', () => {
+        describe('clickEmitter', () => {
+          it('should emit', () => {
+            component.clickEmitter.emit = jest.fn();
+            component.bescheidResource = createBescheidResource([BescheidLinkRel.CREATE_DOCUMENT]);
+            fixture.detectChanges();
+
+            triggerEvent({ fixture, elementSelector: createButtonTestId, name: 'click' });
+
+            expect(component.clickEmitter.emit).toHaveBeenCalled();
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/create-document-button/bescheid-wizard-create-document-button.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/create-document-button/bescheid-wizard-create-document-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..083aec95ac2ddd1d4b030e8ab57a3baf6b55f72e
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/create-document-button-container/create-document-button/bescheid-wizard-create-document-button.component.ts
@@ -0,0 +1,28 @@
+import { BescheidDocument, BescheidLinkRel, BescheidResource, createEmptyBescheidDocument } from '@alfa-client/bescheid-shared';
+import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
+import { BescheidFormService } from '../../../bescheid.formservice';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-create-document-button',
+  templateUrl: './bescheid-wizard-create-document-button.component.html',
+})
+export class BescheidWizardCreateDocumentButtonComponent {
+  @Input() bescheidResource: BescheidResource;
+
+  @Input() set bescheidDocument(value: BescheidDocument) {
+    this._bescheidDocument = value;
+    this.formService.updateBescheidDocumentFile(value.documentUri);
+  }
+
+  get bescheidDocument(): BescheidDocument {
+    return this._bescheidDocument;
+  }
+
+  @Output() clickEmitter: EventEmitter<void> = new EventEmitter<void>();
+
+  private readonly formService = inject(BescheidFormService);
+
+  private _bescheidDocument: BescheidDocument = createEmptyBescheidDocument();
+
+  public readonly BescheidLinkRel = BescheidLinkRel;
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/bescheid-wizard-document-file-container.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/bescheid-wizard-document-file-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..dcf2a2ac6fc332f13bd56c900007dd25d16a2375
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/bescheid-wizard-document-file-container.component.html
@@ -0,0 +1,7 @@
+<alfa-bescheid-wizard-document-file
+  [bescheidDocument]="bescheidDocument$ | async"
+  [deletable]="(activeStep$ | async) === bescheidWizardStep.DokumenteHochladen"
+  (deleteFile)="deleteBescheidDocument()"
+  data-test-id="bescheid-document"
+>
+</alfa-bescheid-wizard-document-file>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/bescheid-wizard-document-file-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/bescheid-wizard-document-file-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9171b0143e8af45416b48d4a779d6e277ad0a5ef
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/bescheid-wizard-document-file-container.component.spec.ts
@@ -0,0 +1,123 @@
+import { BescheidDocument, BescheidWizardStep } from '@alfa-client/bescheid-shared';
+import { existsAsHtmlElement, getElementComponentFromFixtureByCss, Mock, mock, triggerEvent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+import { createBescheidDocument } from '../../../../../../bescheid-shared/src/test/bescheid';
+import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
+import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
+import { BescheidFormService } from '../../bescheid.formservice';
+import { BescheidWizardDocumentFileContainerComponent } from './bescheid-wizard-document-file-container.component';
+import { BescheidWizardDocumentFileComponent } from './document-file/bescheid-wizard-document-file.component';
+
+describe('BescheidWizardDocumentFileContainerComponent', () => {
+  let component: BescheidWizardDocumentFileContainerComponent;
+  let fixture: ComponentFixture<BescheidWizardDocumentFileContainerComponent>;
+
+  const documentFileTestId: string = getDataTestIdOf('bescheid-document');
+
+  const bescheidDocument: BescheidDocument = createBescheidDocument();
+
+  let bescheidService: Mock<BescheidService2>;
+  let formService: Mock<BescheidFormService>;
+
+  beforeEach(() => {
+    bescheidService = mock(BescheidService2);
+    formService = mock(BescheidFormService);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [BescheidWizardDocumentFileContainerComponent, MockComponent(BescheidWizardDocumentFileComponent)],
+      providers: [
+        { provide: BescheidService2, useValue: bescheidService },
+        { provide: BescheidFormService, useValue: formService },
+      ],
+    }).compileComponents();
+
+    createComponent();
+  });
+
+  function createComponent() {
+    fixture = TestBed.createComponent(BescheidWizardDocumentFileContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      bescheidService.getBescheidDocument.mockReturnValue(of(bescheidDocument));
+      bescheidService.getActiveStep.mockReturnValue(of(BescheidWizardStep.BescheidVersenden));
+
+      createComponent();
+
+      expect(component.bescheidDocument$).toBeObservable(singleColdCompleted(bescheidDocument));
+      expect(component.activeStep$).toBeObservable(singleColdCompleted(BescheidWizardStep.BescheidVersenden));
+    });
+
+    describe('deleteBescheidDocument', () => {
+      it('should call form service', () => {
+        component.deleteBescheidDocument();
+
+        expect(formService.clearBescheidDocumentFile).toHaveBeenCalled();
+        expect(bescheidService.deleteBescheidDocument).toHaveBeenCalled();
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('document file', () => {
+      function getComponent(): BescheidWizardDocumentFileComponent {
+        return getElementComponentFromFixtureByCss<BescheidWizardDocumentFileComponent>(fixture, documentFileTestId);
+      }
+
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, documentFileTestId);
+      });
+
+      it('should have been called with bescheid document', () => {
+        bescheidService.getBescheidDocument.mockReturnValue(of(bescheidDocument));
+
+        createComponent();
+        fixture.detectChanges();
+
+        expect(getComponent().bescheidDocument).toEqual(bescheidDocument);
+      });
+
+      it('should have been called with deletable true', () => {
+        bescheidService.getActiveStep.mockReturnValue(of(BescheidWizardStep.DokumenteHochladen));
+
+        createComponent();
+        fixture.detectChanges();
+
+        expect(getComponent().deletable).toEqual(true);
+      });
+
+      it('should have been called with deletable false', () => {
+        bescheidService.getActiveStep.mockReturnValue(of(BescheidWizardStep.BescheidVersenden));
+
+        createComponent();
+        fixture.detectChanges();
+
+        expect(getComponent().deletable).toEqual(false);
+      });
+
+      describe('output', () => {
+        describe('deleteFile', () => {
+          it('should call handler', () => {
+            component.deleteBescheidDocument = jest.fn();
+
+            triggerEvent({ fixture, elementSelector: documentFileTestId, name: 'deleteFile' });
+
+            expect(component.deleteBescheidDocument).toHaveBeenCalled();
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/bescheid-wizard-document-file-container.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/bescheid-wizard-document-file-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f50758a6f2914eacb0f1f0a3711e6d0eec3f5d13
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/bescheid-wizard-document-file-container.component.ts
@@ -0,0 +1,24 @@
+import { BescheidDocument, BescheidWizardStep } from '@alfa-client/bescheid-shared';
+import { Component, inject } from '@angular/core';
+import { Observable } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+import { BescheidFormService } from '../../bescheid.formservice';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-document-file-container',
+  templateUrl: './bescheid-wizard-document-file-container.component.html',
+})
+export class BescheidWizardDocumentFileContainerComponent {
+  private readonly bescheidService = inject(BescheidService2);
+  private readonly formService = inject(BescheidFormService);
+
+  public readonly bescheidDocument$: Observable<BescheidDocument> = this.bescheidService.getBescheidDocument();
+  public readonly activeStep$: Observable<BescheidWizardStep> = this.bescheidService.getActiveStep();
+
+  public readonly bescheidWizardStep = BescheidWizardStep;
+
+  public deleteBescheidDocument(): void {
+    this.formService.clearBescheidDocumentFile();
+    this.bescheidService.deleteBescheidDocument();
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/document-file/bescheid-wizard-document-file.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/document-file/bescheid-wizard-document-file.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..c77ff1d88a92fcc3b6141fb911ac50580ffa9b95
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/document-file/bescheid-wizard-document-file.component.html
@@ -0,0 +1,28 @@
+<ods-attachment-wrapper>
+  @if (showAutomaticCreation) {
+    <ods-attachment
+      errorCaption="Fehler beim automatischen Erstellen"
+      loadingCaption="Bescheiddokument"
+      description="Bescheiddokument wird erstellt"
+      [isLoading]="bescheidDocument.create.loading"
+      [errorMessages]="createDocumentErrorMessages"
+      data-test-id="create-bescheid-document-attachment"
+    ></ods-attachment>
+  }
+
+  @if (showUpload) {
+    <ods-attachment
+      errorCaption="Fehler beim Hochladen"
+      [loadingCaption]="bescheidDocument.upload.fileName"
+      [attr.data-test-id]="'upload-bescheid-document'"
+      [isLoading]="bescheidDocument.upload.loading"
+      [errorMessages]="bescheidDocument.upload.error | convertProblemDetailToErrorMessages"
+      description="Bescheiddokument wird hochgeladen"
+    ></ods-attachment>
+  }
+
+  @if (showDocument) {
+    <alfa-binary-file2-container [file]="bescheidDocument.resource" [deletable]="deletable" (startDelete)="deleteFile.emit()" data-test-id="bescheid-document-binary-file">
+    </alfa-binary-file2-container>
+  }
+</ods-attachment-wrapper>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/document-file/bescheid-wizard-document-file.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/document-file/bescheid-wizard-document-file.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..412b4eb3ff92220473ee167ef709f8fbf3baf77d
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/document-file/bescheid-wizard-document-file.component.spec.ts
@@ -0,0 +1,301 @@
+import { BescheidDocument, createEmptyBescheidDocument, createEmptyUploadInProgress } from '@alfa-client/bescheid-shared';
+import { BinaryFile2ContainerComponent } from '@alfa-client/binary-file';
+import {
+  ConvertProblemDetailToErrorMessagesPipe,
+  createEmptyStateResource,
+  createErrorStateResource,
+  createLoadingStateResource,
+  ProblemDetail,
+} from '@alfa-client/tech-shared';
+import {
+  existsAsHtmlElement,
+  getElementComponentFromFixtureByCss,
+  notExistsAsHtmlElement,
+  triggerEvent,
+} from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { AttachmentComponent, AttachmentWrapperComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+import {
+  createBescheidDocument,
+  createErrorUpload,
+  createPendingUpload,
+  createSuccessfulUpload,
+} from '../../../../../../../bescheid-shared/src/test/bescheid';
+import { createSuccessfullyDoneCommandStateResource } from '../../../../../../../command-shared/test/command';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { createProblemDetail } from '../../../../../../../tech-shared/test/error';
+import { BescheidWizardDocumentFileComponent } from './bescheid-wizard-document-file.component';
+
+describe('BescheidWizardDocumentFileComponent', () => {
+  let component: BescheidWizardDocumentFileComponent;
+  let fixture: ComponentFixture<BescheidWizardDocumentFileComponent>;
+
+  const convertProblemDetailsToErrorMessages: ConvertProblemDetailToErrorMessagesPipe =
+    new ConvertProblemDetailToErrorMessagesPipe();
+
+  const createBescheidTestId: string = getDataTestIdOf('create-bescheid-document-attachment');
+  const uploadBescheidTestId: string = getDataTestIdOf('upload-bescheid-document');
+  const bescheidDocumentTestId: string = getDataTestIdOf('bescheid-document-binary-file');
+
+  const bescheidDocument: BescheidDocument = createBescheidDocument();
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardDocumentFileComponent,
+        MockComponent(AttachmentWrapperComponent),
+        MockComponent(AttachmentComponent),
+        MockComponent(BinaryFile2ContainerComponent),
+        ConvertProblemDetailToErrorMessagesPipe,
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardDocumentFileComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      expect(component.showAutomaticCreation).toEqual(false);
+      expect(component.showUpload).toEqual(false);
+      expect(component.showDocument).toEqual(false);
+      expect(component.createDocumentErrorMessages).toEqual([]);
+      expect(component.bescheidDocument).toEqual(createEmptyBescheidDocument());
+    });
+
+    describe('set bescheid document', () => {
+      it('should update component state', () => {
+        component.update = jest.fn();
+
+        component.bescheidDocument = bescheidDocument;
+
+        expect(component.update).toHaveBeenCalled();
+      });
+    });
+
+    describe('update', () => {
+      it('should set bescheid document', () => {
+        component.update(bescheidDocument);
+
+        expect(component.bescheidDocument).toEqual(bescheidDocument);
+      });
+
+      it('should show automatic creation on loading', () => {
+        component.update({ ...bescheidDocument, create: createLoadingStateResource() });
+
+        expect(component.showAutomaticCreation).toEqual(true);
+      });
+
+      it('should show automatic creation on error', () => {
+        component.update({
+          ...bescheidDocument,
+          create: createErrorStateResource(createProblemDetail()),
+        });
+
+        expect(component.showAutomaticCreation).toEqual(true);
+      });
+
+      it('should show upload on loading', () => {
+        component.update({ ...bescheidDocument, upload: createPendingUpload() });
+
+        expect(component.showUpload).toEqual(true);
+      });
+
+      it('should show upload on error', () => {
+        component.update({
+          ...bescheidDocument,
+          upload: createErrorUpload(),
+        });
+
+        expect(component.showUpload).toEqual(true);
+      });
+
+      it('should show created document', () => {
+        component.update({
+          ...bescheidDocument,
+          create: createSuccessfullyDoneCommandStateResource(),
+          upload: createEmptyUploadInProgress(),
+        });
+
+        expect(component.showDocument).toEqual(true);
+      });
+
+      it('should show uploaded document', () => {
+        component.update({
+          ...bescheidDocument,
+          create: createEmptyStateResource(),
+          upload: createSuccessfulUpload(),
+        });
+
+        expect(component.showDocument).toEqual(true);
+      });
+
+      it('should NOT show document on pending creation', () => {
+        component.update({
+          ...bescheidDocument,
+          create: createLoadingStateResource(),
+          upload: createEmptyUploadInProgress(),
+        });
+
+        expect(component.showDocument).toEqual(false);
+      });
+
+      it('should NOT show document on pending upload', () => {
+        component.update({
+          ...bescheidDocument,
+          create: createEmptyStateResource(),
+          upload: createPendingUpload(),
+        });
+
+        expect(component.showDocument).toEqual(false);
+      });
+
+      it('should NOT show document if not exists', () => {
+        component.update({
+          ...bescheidDocument,
+          resource: null,
+          create: createEmptyStateResource(),
+          upload: createPendingUpload(),
+        });
+
+        expect(component.showDocument).toEqual(false);
+      });
+
+      it('should have error messages', () => {
+        component.update({
+          ...bescheidDocument,
+          create: createErrorStateResource(createProblemDetail()),
+          upload: createEmptyUploadInProgress(),
+        });
+
+        expect(component.createDocumentErrorMessages).toEqual([BescheidWizardDocumentFileComponent.CREATE_ERROR_MESSAGE]);
+      });
+
+      it('should NOT have error messages', () => {
+        component.update({
+          ...bescheidDocument,
+          create: createSuccessfullyDoneCommandStateResource(),
+          upload: createEmptyUploadInProgress(),
+        });
+
+        expect(component.createDocumentErrorMessages).toEqual([]);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('automatic creation attachment', () => {
+      it('should exists', () => {
+        component.showAutomaticCreation = true;
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, createBescheidTestId);
+      });
+
+      it('should NOT exists', () => {
+        component.showAutomaticCreation = false;
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, createBescheidTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        component.showAutomaticCreation = true;
+
+        fixture.detectChanges();
+        const attachmentComponent: AttachmentComponent = getElementComponentFromFixtureByCss<AttachmentComponent>(
+          fixture,
+          createBescheidTestId,
+        );
+
+        expect(attachmentComponent.isLoading).toEqual(component.bescheidDocument.create.loading);
+        expect(attachmentComponent.errorMessages).toEqual(component.createDocumentErrorMessages);
+      });
+    });
+
+    describe('upload file', () => {
+      it('should exists', () => {
+        component.showUpload = true;
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, uploadBescheidTestId);
+      });
+
+      it('should NOT exists', () => {
+        component.showUpload = false;
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, uploadBescheidTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        component.showUpload = true;
+
+        fixture.detectChanges();
+        const attachmentComponent: AttachmentComponent = getElementComponentFromFixtureByCss<AttachmentComponent>(
+          fixture,
+          uploadBescheidTestId,
+        );
+
+        expect(attachmentComponent.loadingCaption).toEqual(component.bescheidDocument.upload.fileName);
+        expect(attachmentComponent.isLoading).toEqual(component.bescheidDocument.upload.loading);
+        expect(attachmentComponent.errorMessages).toEqual(
+          convertProblemDetailsToErrorMessages.transform(component.bescheidDocument.upload.error as ProblemDetail),
+        );
+      });
+    });
+
+    describe('document binary file', () => {
+      it('should exists', () => {
+        component.showDocument = true;
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, bescheidDocumentTestId);
+      });
+
+      it('should NOT exists', () => {
+        component.showDocument = false;
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, bescheidDocumentTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        component.showDocument = true;
+
+        fixture.detectChanges();
+        const attachmentComponent: BinaryFile2ContainerComponent =
+          getElementComponentFromFixtureByCss<BinaryFile2ContainerComponent>(fixture, bescheidDocumentTestId);
+
+        expect(attachmentComponent.file).toEqual(component.bescheidDocument.resource);
+        expect(attachmentComponent.deletable).toEqual(component.deletable);
+      });
+
+      describe('output', () => {
+        describe('startDelete', () => {
+          it('should emit', () => {
+            component.showDocument = true;
+            fixture.detectChanges();
+            component.deleteFile.emit = jest.fn();
+
+            triggerEvent({ fixture, elementSelector: bescheidDocumentTestId, name: 'startDelete' });
+
+            expect(component.deleteFile.emit).toHaveBeenCalled();
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/document-file/bescheid-wizard-document-file.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/document-file/bescheid-wizard-document-file.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..231c486fde2bcae1b49a21eca2319751b76865c4
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/document-file-container/document-file/bescheid-wizard-document-file.component.ts
@@ -0,0 +1,39 @@
+import { BescheidDocument, createEmptyBescheidDocument } from '@alfa-client/bescheid-shared';
+import { hasStateResourceError, isNotNil } from '@alfa-client/tech-shared';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-document-file',
+  templateUrl: './bescheid-wizard-document-file.component.html',
+})
+export class BescheidWizardDocumentFileComponent {
+  static readonly CREATE_ERROR_MESSAGE = 'Bescheiddokument konnte nicht erzeugt werden.';
+
+  @Input() set bescheidDocument(value: BescheidDocument) {
+    this.update(value);
+  }
+
+  get bescheidDocument(): BescheidDocument {
+    return this._bescheidDocument;
+  }
+
+  @Input() public deletable: boolean;
+
+  @Output() deleteFile: EventEmitter<void> = new EventEmitter<void>();
+
+  public showAutomaticCreation: boolean = false;
+  public showUpload: boolean = false;
+  public showDocument: boolean = false;
+  public createDocumentErrorMessages: string[] = [];
+
+  private _bescheidDocument: BescheidDocument = createEmptyBescheidDocument();
+
+  update(value: BescheidDocument) {
+    this._bescheidDocument = value;
+    this.showAutomaticCreation = value.create.loading || hasStateResourceError(value.create);
+    this.showUpload = value.upload.loading || isNotNil(value.upload.error);
+    this.showDocument = isNotNil(value.resource) && !value.upload.loading && !value.create.loading;
+    this.createDocumentErrorMessages =
+      hasStateResourceError(value.create) ? [BescheidWizardDocumentFileComponent.CREATE_ERROR_MESSAGE] : [];
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/bescheid-wizard-dokumente-hochladen-container.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/bescheid-wizard-dokumente-hochladen-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..c039d147b1d8c2f8be9d3fe0f63ef42ccd1a0972
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/bescheid-wizard-dokumente-hochladen-container.component.html
@@ -0,0 +1,53 @@
+<!--
+
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<alfa-step-content-layout
+  [activeStep]="BescheidWizardStep.DokumenteHochladen"
+  (stepChange)="onStepChange($event)"
+  data-test-id="step-content-layout"
+>
+  <ng-container stepPanel>
+    <alfa-bescheid-wizard-step-title
+      label="Antrag bescheiden"
+      [inactiveStep]="true"
+      data-test-id="antrag-bescheiden-step-title"
+    />
+    <alfa-bescheid-wizard-step-title label="Dokumente hinzufügen" />
+    <alfa-bescheid-wizard-dokumente-hochladen-form
+      [bescheidResource]="bescheidResource"
+      [bescheidDocument]="bescheidDocument$ | async"
+      (weiterClickEmitter)="onWeiterClick()"
+      (bescheidDocumentMissing)="onBescheidDocumentMissing($event)"
+      data-test-id="bescheid-wizard-dokumente-hochladen-form"
+    />
+  </ng-container>
+  <ng-container summary>
+    <alfa-bescheid-wizard-antrag-bescheiden-summary />
+    <alfa-bescheid-wizard-dokumente-hochladen-summary
+      [isBescheidDocumentMissing]="isBescheidDocumentMissing"
+      data-test-id="bescheid-wizard-dokumente-hochladen-summary"
+    />
+  </ng-container>
+</alfa-step-content-layout>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/bescheid-wizard-dokumente-hochladen-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/bescheid-wizard-dokumente-hochladen-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..749ab02b1417d171af7d7549c1c2994d4116fc04
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/bescheid-wizard-dokumente-hochladen-container.component.spec.ts
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { BescheidDocument, BescheidResource, BescheidWizardStep } from '@alfa-client/bescheid-shared';
+import { getElementComponentFromFixtureByCss, Mock, mock, triggerEvent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { expect } from '@jest/globals';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+import { createBescheidDocument, createBescheidResource } from '../../../../../../bescheid-shared/src/test/bescheid';
+import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
+import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
+import { BescheidWizardAntragBescheidenSummaryComponent } from '../antrag-bescheiden/summary/bescheid-wizard-antrag-bescheiden-summary.component';
+import { StepContentLayoutComponent } from '../step-content-layout/step-content-layout.component';
+import { BescheidWizardStepTitleComponent } from '../step-title/bescheid-wizard-step-title.component';
+import { BescheidWizardStepperComponent } from '../stepper/bescheid-wizard-stepper.component';
+import { BescheidWizardSummaryComponent } from '../summary/bescheid-wizard-summary.component';
+import { BescheidWizardDokumenteHochladenContainerComponent } from './bescheid-wizard-dokumente-hochladen-container.component';
+import { BescheidWizardDokumenteHochladenFormComponent } from './form/bescheid-wizard-dokumente-hochladen-form.component';
+import { BescheidWizardDokumenteHochladenSummaryComponent } from './summary/bescheid-wizard-dokumente-hochladen-summary.component';
+
+describe('BescheidWizardDokumenteHochladenComponent', () => {
+  let component: BescheidWizardDokumenteHochladenContainerComponent;
+  let fixture: ComponentFixture<BescheidWizardDokumenteHochladenContainerComponent>;
+
+  const stepContentLayout: string = getDataTestIdOf('step-content-layout');
+  const antragBescheidenStepTitleTestId: string = getDataTestIdOf('antrag-bescheiden-step-title');
+  const dokumenteHochladenFormTestId: string = getDataTestIdOf('bescheid-wizard-dokumente-hochladen-form');
+  const dokumenteHochladenSummaryTestId: string = getDataTestIdOf('bescheid-wizard-dokumente-hochladen-summary');
+
+  const bescheidResource: BescheidResource = createBescheidResource();
+  const bescheidDocument: BescheidDocument = createBescheidDocument();
+
+  let bescheidService: Mock<BescheidService2>;
+
+  beforeEach(() => {
+    bescheidService = mock(BescheidService2);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardDokumenteHochladenContainerComponent,
+        MockComponent(StepContentLayoutComponent),
+        MockComponent(BescheidWizardSummaryComponent),
+        MockComponent(BescheidWizardAntragBescheidenSummaryComponent),
+        MockComponent(BescheidWizardDokumenteHochladenSummaryComponent),
+        MockComponent(BescheidWizardStepTitleComponent),
+        MockComponent(BescheidWizardDokumenteHochladenFormComponent),
+        MockComponent(BescheidWizardStepperComponent),
+      ],
+      providers: [{ provide: BescheidService2, useValue: bescheidService }],
+    }).compileComponents();
+
+    createComponent();
+  });
+
+  function createComponent() {
+    fixture = TestBed.createComponent(BescheidWizardDokumenteHochladenContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      bescheidService.getBescheidDocument.mockReturnValue(of(bescheidDocument));
+
+      createComponent();
+
+      expect(component.bescheidDocument$).toBeObservable(singleColdCompleted(bescheidDocument));
+    });
+
+    describe('ngOnInit', () => {
+      it('should load files', () => {
+        component.ngOnInit();
+
+        expect(bescheidService.loadFiles).toHaveBeenCalled();
+      });
+    });
+
+    describe('set bescheid resource', () => {
+      it('should set value', () => {
+        component.bescheidResource = bescheidResource;
+
+        expect(component.bescheidResource).toEqual(bescheidResource);
+      });
+    });
+
+    describe('onWeiterClick', () => {
+      it('should finish adding attachments', () => {
+        component.onWeiterClick();
+
+        expect(bescheidService.finishAddingAttachments).toHaveBeenCalled();
+      });
+
+      it('should finish adding bescheid document', () => {
+        component.onWeiterClick();
+
+        expect(bescheidService.finishAddingBescheidDocument).toHaveBeenCalled();
+      });
+
+      it('should change active step', () => {
+        component.onWeiterClick();
+
+        expect(bescheidService.setActiveStep).toHaveBeenCalledWith(BescheidWizardStep.BescheidVersenden);
+      });
+    });
+
+    describe('onBescheidDocumentMissing', () => {
+      it('should set value', () => {
+        component.isBescheidDocumentMissing = false;
+
+        component.onBescheidDocumentMissing(true);
+
+        expect(component.isBescheidDocumentMissing).toEqual(true);
+      });
+    });
+
+    describe('onStepChange', () => {
+      it('should change step', () => {
+        component.onStepChange(BescheidWizardStep.AntragBescheiden);
+
+        expect(bescheidService.setActiveStep).toHaveBeenCalledWith(BescheidWizardStep.AntragBescheiden);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('step content layout', () => {
+      describe('output', () => {
+        it('should call handler', () => {
+          component.onStepChange = jest.fn();
+
+          triggerEvent({
+            fixture,
+            name: 'stepChange',
+            elementSelector: stepContentLayout,
+            data: BescheidWizardStep.AntragBescheiden,
+          });
+
+          expect(component.onStepChange).toHaveBeenCalledWith(BescheidWizardStep.AntragBescheiden);
+        });
+      });
+    });
+
+    describe('antrag bescheiden step title', () => {
+      it('should have been called with inputs', () => {
+        const stepTitle: BescheidWizardStepTitleComponent = getElementComponentFromFixtureByCss<BescheidWizardStepTitleComponent>(
+          fixture,
+          antragBescheidenStepTitleTestId,
+        );
+
+        expect(stepTitle.inactiveStep).toBeTruthy();
+      });
+    });
+
+    describe('hochladen form', () => {
+      it('should have been called with inputs', () => {
+        bescheidService.getBescheidDocument.mockReturnValue(of(bescheidDocument));
+        createComponent();
+        component.bescheidResource = bescheidResource;
+
+        fixture.detectChanges();
+        const hochladenForm: BescheidWizardDokumenteHochladenFormComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardDokumenteHochladenFormComponent>(
+            fixture,
+            dokumenteHochladenFormTestId,
+          );
+
+        expect(hochladenForm.bescheidResource).toEqual(bescheidResource);
+        expect(hochladenForm.bescheidDocument).toEqual(bescheidDocument);
+      });
+
+      describe('output', () => {
+        describe('weiterClickEmitter', () => {
+          it('should call handler', () => {
+            component.onWeiterClick = jest.fn();
+
+            triggerEvent({ fixture, elementSelector: dokumenteHochladenFormTestId, name: 'weiterClickEmitter' });
+
+            expect(component.onWeiterClick).toHaveBeenCalled();
+          });
+        });
+
+        describe('bescheidDocumentMissing', () => {
+          it('should call handler', () => {
+            component.onBescheidDocumentMissing = jest.fn();
+
+            triggerEvent({ fixture, elementSelector: dokumenteHochladenFormTestId, name: 'bescheidDocumentMissing' });
+
+            expect(component.onBescheidDocumentMissing).toHaveBeenCalled();
+          });
+        });
+      });
+    });
+
+    describe('hochladen summary', () => {
+      it('should have been called with inputs', () => {
+        component.isBescheidDocumentMissing = true;
+
+        fixture.detectChanges();
+        const hochladenSummary: BescheidWizardDokumenteHochladenSummaryComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardDokumenteHochladenSummaryComponent>(
+            fixture,
+            dokumenteHochladenSummaryTestId,
+          );
+
+        expect(hochladenSummary).toBeTruthy();
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/bescheid-wizard-dokumente-hochladen-container.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/bescheid-wizard-dokumente-hochladen-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eb90a6109b54253184476b5b3542bd31f0851d94
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/bescheid-wizard-dokumente-hochladen-container.component.ts
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { BescheidDocument, BescheidResource, BescheidWizardStep } from '@alfa-client/bescheid-shared';
+import { Component, inject, Input, OnInit } from '@angular/core';
+import { Observable } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-dokumente-hochladen-container',
+  templateUrl: './bescheid-wizard-dokumente-hochladen-container.component.html',
+})
+export class BescheidWizardDokumenteHochladenContainerComponent implements OnInit {
+  @Input() bescheidResource: BescheidResource;
+
+  private readonly bescheidService = inject(BescheidService2);
+
+  public readonly bescheidDocument$: Observable<BescheidDocument> = this.bescheidService.getBescheidDocument();
+  public isBescheidDocumentMissing: boolean = false;
+
+  public readonly BescheidWizardStep = BescheidWizardStep;
+
+  ngOnInit(): void {
+    this.bescheidService.loadFiles(this.bescheidResource);
+  }
+
+  public onWeiterClick(): void {
+    this.bescheidService.finishAddingAttachments();
+    this.bescheidService.finishAddingBescheidDocument();
+    this.bescheidService.setActiveStep(BescheidWizardStep.BescheidVersenden);
+  }
+
+  public onBescheidDocumentMissing(value: boolean): void {
+    this.isBescheidDocumentMissing = value;
+  }
+
+  public onStepChange(step: BescheidWizardStep): void {
+    this.bescheidService.setActiveStep(step);
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/bescheid-wizard-dokumente-hochladen.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.html
similarity index 51%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/bescheid-wizard-dokumente-hochladen.component.html
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.html
index 95c0c3895cacf7701e2b189c74964fa72072056f..fd2a2ab6c43b6e00ba06a0347278e2ab53b0c5aa 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/bescheid-wizard-dokumente-hochladen.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.html
@@ -23,15 +23,24 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<div class="mt-2 grid h-full grid-cols-[min-content_1fr_1fr] gap-7">
-  <alfa-bescheid-wizard-stepper [activeStep]="bescheidWizardStep.DokumenteHochladen"></alfa-bescheid-wizard-stepper>
-  <div>
-    <alfa-bescheid-wizard-step-title label="Antrag bescheiden" [inactiveStep]="true"></alfa-bescheid-wizard-step-title>
-    <alfa-bescheid-wizard-step-title label="Dokumente hochladen"></alfa-bescheid-wizard-step-title>
-    <alfa-bescheid-wizard-dokumente-hochladen-form></alfa-bescheid-wizard-dokumente-hochladen-form>
-  </div>
-  <alfa-bescheid-wizard-summary>
-    <alfa-bescheid-wizard-antrag-bescheiden-summary></alfa-bescheid-wizard-antrag-bescheiden-summary>
-    <alfa-bescheid-wizard-dokumente-hochladen-summary></alfa-bescheid-wizard-dokumente-hochladen-summary>
-  </alfa-bescheid-wizard-summary>
+<div class="mt-4 flex flex-col gap-4">
+  <alfa-bescheid-wizard-create-document-button-container
+    [bescheidResource]="bescheidResource"
+    data-test-id="create-document-button"
+  ></alfa-bescheid-wizard-create-document-button-container>
+  <alfa-bescheid-wizard-upload-document-button-container
+    [bescheidResource]="bescheidResource"
+    data-test-id="upload-document-button"
+  ></alfa-bescheid-wizard-upload-document-button-container>
+  <alfa-bescheid-wizard-upload-attachment-button-container
+    [bescheidResource]="bescheidResource"
+    data-test-id="upload-attachment-button"
+  ></alfa-bescheid-wizard-upload-attachment-button-container>
+  @if (bescheidResource | hasLink: bescheidLinkRel.UPDATE) {
+    <alfa-bescheid-wizard-weiter-button
+      [submitStateResource]="submitStateResource$ | async"
+      (clickEmitter)="gotoNextStep()"
+      data-test-id="weiter-button"
+    ></alfa-bescheid-wizard-weiter-button>
+  }
 </div>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..02452fe302b69a044cef2cf621ea5a1e5734d6c2
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.spec.ts
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierun
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { BescheidDocument, BescheidLinkRel, createEmptyBescheidDocument } from '@alfa-client/bescheid-shared';
+import { CommandResource } from '@alfa-client/command-shared';
+import { HasLinkPipe, StateResource } from '@alfa-client/tech-shared';
+import { existsAsHtmlElement, getElementComponentFromFixtureByCss, mock, Mock, notExistsAsHtmlElement, triggerEvent, } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+import { EMPTY, of } from 'rxjs';
+import { createBescheidDocument, createBescheidResource } from '../../../../../../../bescheid-shared/src/test/bescheid';
+import { createSuccessfullyDoneCommandStateResource } from '../../../../../../../command-shared/test/command';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { BescheidFormService } from '../../../bescheid.formservice';
+import { BescheidWizardCreateDocumentButtonContainerComponent } from '../../create-document-button-container/bescheid-wizard-create-document-button-container.component';
+import { BescheidWizardUploadAttachmentButtonContainerComponent } from '../../upload-attachment-button-container/bescheid-wizard-upload-attachment-button-container.component';
+import { BescheidWizardUploadDocumentButtonContainerComponent } from '../../upload-document-button-container/bescheid-wizard-upload-document-button-container.component';
+import { BescheidWizardWeiterButtonComponent } from '../../weiter-button/bescheid-wizard-weiter-button.component';
+import { BescheidWizardDokumenteHochladenFormComponent } from './bescheid-wizard-dokumente-hochladen-form.component';
+
+describe('BescheidWizardDokumenteHochladenFormComponent', () => {
+  let component: BescheidWizardDokumenteHochladenFormComponent;
+  let fixture: ComponentFixture<BescheidWizardDokumenteHochladenFormComponent>;
+
+  const createDocumentButtonTestId: string = getDataTestIdOf('create-document-button');
+  const uploadDocumentButtonTestId: string = getDataTestIdOf('upload-document-button');
+  const uploadAttachmentButtonTestId: string = getDataTestIdOf('upload-attachment-button');
+  const weiterButtonTestId: string = getDataTestIdOf('weiter-button');
+
+  const bescheidDocument: BescheidDocument = createBescheidDocument();
+
+  let formService: Mock<BescheidFormService>;
+
+  beforeEach(() => {
+    formService = mock(BescheidFormService);
+    formService.submit = jest.fn().mockReturnValue(EMPTY);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardDokumenteHochladenFormComponent,
+        MockComponent(BescheidWizardCreateDocumentButtonContainerComponent),
+        MockComponent(BescheidWizardUploadDocumentButtonContainerComponent),
+        MockComponent(BescheidWizardUploadAttachmentButtonContainerComponent),
+        MockComponent(BescheidWizardWeiterButtonComponent),
+        HasLinkPipe,
+      ],
+      providers: [{ provide: BescheidFormService, useValue: formService }],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardDokumenteHochladenFormComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    describe('set bescheid document', () => {
+      it('should emit missing bescheid document false', () => {
+        component.bescheidDocumentMissing.emit = jest.fn();
+        component.bescheidDocument = bescheidDocument;
+
+        expect(component.bescheidDocumentMissing.emit).toHaveBeenCalledWith(false);
+      });
+
+      it('should NOT emit missing bescheid document', () => {
+        component.bescheidDocumentMissing.emit = jest.fn();
+        component.bescheidDocument = createEmptyBescheidDocument();
+
+        expect(component.bescheidDocumentMissing.emit).not.toHaveBeenCalled();
+      });
+    });
+
+    describe('gotoNextStep', () => {
+      it('should emit missing bescheid document true', () => {
+        component.bescheidDocumentMissing.emit = jest.fn();
+        component.bescheidDocument = createEmptyBescheidDocument();
+
+        component.gotoNextStep();
+
+        expect(component.bescheidDocumentMissing.emit).toHaveBeenCalledWith(true);
+      });
+
+      it('should submit form', () => {
+        component.bescheidDocumentMissing.emit = jest.fn();
+        component.bescheidDocument = bescheidDocument;
+
+        component.gotoNextStep();
+
+        expect(formService.submit).toHaveBeenCalled();
+      });
+
+      it('should emit weiter click', () => {
+        component.weiterClickEmitter.emit = jest.fn();
+        component.bescheidDocument = bescheidDocument;
+        formService.submit = jest.fn().mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+
+        component.gotoNextStep();
+        component.submitStateResource$.subscribe();
+
+        expect(component.weiterClickEmitter.emit).toHaveBeenCalled();
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('create document button', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, createDocumentButtonTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        component.bescheidResource = createBescheidResource();
+
+        fixture.detectChanges();
+        const createDocumentButton: BescheidWizardCreateDocumentButtonContainerComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardCreateDocumentButtonContainerComponent>(
+            fixture,
+            createDocumentButtonTestId,
+          );
+
+        expect(createDocumentButton.bescheidResource).toEqual(component.bescheidResource);
+      });
+    });
+
+    describe('upload document button', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, uploadDocumentButtonTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        component.bescheidResource = createBescheidResource();
+
+        fixture.detectChanges();
+        const uploadDocumentButton: BescheidWizardUploadDocumentButtonContainerComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardUploadDocumentButtonContainerComponent>(
+            fixture,
+            uploadDocumentButtonTestId,
+          );
+
+        expect(uploadDocumentButton.bescheidResource).toEqual(component.bescheidResource);
+      });
+    });
+
+    describe('upload attachment button', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, uploadAttachmentButtonTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        component.bescheidResource = createBescheidResource();
+
+        fixture.detectChanges();
+        const uploadAttachmentButton: BescheidWizardUploadAttachmentButtonContainerComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardUploadAttachmentButtonContainerComponent>(
+            fixture,
+            uploadDocumentButtonTestId,
+          );
+
+        expect(uploadAttachmentButton.bescheidResource).toEqual(component.bescheidResource);
+      });
+    });
+
+    describe('weiter button', () => {
+      it('should exists', () => {
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.UPDATE]);
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, weiterButtonTestId);
+      });
+
+      it('should NOT exists', () => {
+        component.bescheidResource = createBescheidResource();
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, weiterButtonTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        const commandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+        component.submitStateResource$ = of(commandStateResource);
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.UPDATE]);
+
+        fixture.detectChanges();
+        const weiterButton: BescheidWizardWeiterButtonComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardWeiterButtonComponent>(fixture, weiterButtonTestId);
+        component.submitStateResource$.subscribe();
+
+        expect(weiterButton.submitStateResource).toEqual(commandStateResource);
+      });
+
+      describe('output', () => {
+        describe('clickEmitter', () => {
+          it('should call handler', () => {
+            component.gotoNextStep = jest.fn();
+            component.bescheidResource = createBescheidResource([BescheidLinkRel.UPDATE]);
+            fixture.detectChanges();
+
+            triggerEvent({ fixture, elementSelector: weiterButtonTestId, name: 'clickEmitter' });
+
+            expect(component.gotoNextStep).toHaveBeenCalled();
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d09a24bce3dfd8a65dac3470147f42fff00aeda9
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.ts
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { BescheidDocument, BescheidLinkRel, BescheidResource } from '@alfa-client/bescheid-shared';
+import { tapOnCommandSuccessfullyDone } from '@alfa-client/command-shared';
+import { isNotNil, StateResource } from '@alfa-client/tech-shared';
+import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
+import { Resource } from '@ngxp/rest';
+import { isNil } from 'lodash-es';
+import { Observable } from 'rxjs';
+import { BescheidFormService } from '../../../bescheid.formservice';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-dokumente-hochladen-form',
+  templateUrl: './bescheid-wizard-dokumente-hochladen-form.component.html',
+})
+export class BescheidWizardDokumenteHochladenFormComponent {
+  @Input() set bescheidDocument(value: BescheidDocument) {
+    this._bescheidDocument = value;
+    if (isNotNil(value.resource)) {
+      this.bescheidDocumentMissing.emit(false);
+    }
+  }
+
+  @Input() bescheidResource: BescheidResource;
+
+  @Output() weiterClickEmitter: EventEmitter<void> = new EventEmitter<void>();
+  @Output() bescheidDocumentMissing: EventEmitter<boolean> = new EventEmitter<boolean>();
+
+  private readonly formService = inject(BescheidFormService);
+
+  public submitStateResource$: Observable<StateResource<Resource>>;
+
+  private _bescheidDocument: BescheidDocument;
+
+  protected readonly bescheidLinkRel = BescheidLinkRel;
+
+  public gotoNextStep(): void {
+    if (isNil(this._bescheidDocument.resource)) {
+      this.bescheidDocumentMissing.emit(true);
+    } else {
+      this.submitStateResource$ = this.formService
+        .submit()
+        .pipe(tapOnCommandSuccessfullyDone(() => this.weiterClickEmitter.emit()));
+    }
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/summary/bescheid-wizard-dokumente-hochladen-summary.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component.html
similarity index 65%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/summary/bescheid-wizard-dokumente-hochladen-summary.component.html
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component.html
index 1ce18413c69e7b7399288ffa987dfdeb0b2d4ee5..b8c80fafbcec28185f7ff568c8b5357c197b1503 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/summary/bescheid-wizard-dokumente-hochladen-summary.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component.html
@@ -23,4 +23,17 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<p>bescheid-wizard-dokumente-hochladen-summary works!</p>
+
+@if (isBescheidDocumentMissing) {
+  <p data-test-id="missing-bescheid-document-error-message" class="my-4 text-base text-error">
+    Bitte fügen Sie ein Bescheiddokument hinzu.
+  </p>
+}
+<div class="my-4">
+  <alfa-bescheid-wizard-document-file-container data-test-id="bescheid-document-file">
+  </alfa-bescheid-wizard-document-file-container>
+</div>
+<div class="my-4">
+  <alfa-bescheid-wizard-attachment-files-container data-test-id="bescheid-attachment-files">
+  </alfa-bescheid-wizard-attachment-files-container>
+</div>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5ed6c9e5d11f1e5ebbe9fda0b395d70bc856c323
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component.spec.ts
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { BescheidWizardAttachmentFilesContainerComponent } from '../../attachment-files-container/bescheid-wizard-attachment-files-container.component';
+import { BescheidWizardDocumentFileContainerComponent } from '../../document-file-container/bescheid-wizard-document-file-container.component';
+import { BescheidWizardDokumenteHochladenSummaryComponent } from './bescheid-wizard-dokumente-hochladen-summary.component';
+
+describe('BescheidWizardDokumenteHochladenSummaryComponent', () => {
+  let component: BescheidWizardDokumenteHochladenSummaryComponent;
+  let fixture: ComponentFixture<BescheidWizardDokumenteHochladenSummaryComponent>;
+
+  const missingBescheidErrorMessageTestId: string = getDataTestIdOf('missing-bescheid-document-error-message');
+  const documentFileTestId: string = getDataTestIdOf('bescheid-document-file');
+  const attachmentFilesTestId: string = getDataTestIdOf('bescheid-attachment-files');
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardDokumenteHochladenSummaryComponent,
+        MockComponent(BescheidWizardDocumentFileContainerComponent),
+        MockComponent(BescheidWizardAttachmentFilesContainerComponent),
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardDokumenteHochladenSummaryComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('template', () => {
+    describe('missing bescheid error message', () => {
+      it('should exists', () => {
+        component.isBescheidDocumentMissing = true;
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, missingBescheidErrorMessageTestId);
+      });
+
+      it('should NOT exists', () => {
+        component.isBescheidDocumentMissing = false;
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, missingBescheidErrorMessageTestId);
+      });
+    });
+
+    describe('document file', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, documentFileTestId);
+      });
+    });
+
+    describe('attachment files', () => {
+      it('should exists', () => {
+        existsAsHtmlElement(fixture, attachmentFilesTestId);
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/summary/bescheid-wizard-dokumente-hochladen-summary.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component.ts
similarity index 87%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/summary/bescheid-wizard-dokumente-hochladen-summary.component.ts
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component.ts
index 9ef966f315ee77c10a08a177d0eddc0ce2d86c61..6bf136b2492c45205aa1fe115c3a033d92c1d174 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/summary/bescheid-wizard-dokumente-hochladen-summary.component.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component.ts
@@ -21,10 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component } from '@angular/core';
+import { Component, Input } from '@angular/core';
 
 @Component({
   selector: 'alfa-bescheid-wizard-dokumente-hochladen-summary',
   templateUrl: './bescheid-wizard-dokumente-hochladen-summary.component.html',
 })
-export class BescheidWizardDokumenteHochladenSummaryComponent {}
+export class BescheidWizardDokumenteHochladenSummaryComponent {
+  @Input() isBescheidDocumentMissing: boolean;
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/bescheid-wizard-dokumente-hochladen.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/bescheid-wizard-dokumente-hochladen.component.spec.ts
deleted file mode 100644
index 3776924bd38321a3ae2e369805d408f7e0961582..0000000000000000000000000000000000000000
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/bescheid-wizard-dokumente-hochladen.component.spec.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { BescheidWizardStep } from '@alfa-client/bescheid-shared';
-import { getElementFromFixtureByType } from '@alfa-client/test-utils';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MockComponent } from 'ng-mocks';
-import { BescheidWizardAntragBescheidenSummaryComponent } from '../antrag-bescheiden/summary/bescheid-wizard-antrag-bescheiden-summary.component';
-import { BescheidWizardStepTitleComponent } from '../step-title/bescheid-wizard-step-title.component';
-import { BescheidWizardStepperComponent } from '../stepper/bescheid-wizard-stepper.component';
-import { BescheidWizardSummaryComponent } from '../summary/bescheid-wizard-summary.component';
-import { BescheidWizardDokumenteHochladenComponent } from './bescheid-wizard-dokumente-hochladen.component';
-import { BescheidWizardDokumenteHochladenFormComponent } from './form/bescheid-wizard-dokumente-hochladen-form.component';
-import { BescheidWizardDokumenteHochladenSummaryComponent } from './summary/bescheid-wizard-dokumente-hochladen-summary.component';
-
-describe('BescheidWizardDokumenteHochladenComponent', () => {
-  let component: BescheidWizardDokumenteHochladenComponent;
-  let fixture: ComponentFixture<BescheidWizardDokumenteHochladenComponent>;
-
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      declarations: [
-        BescheidWizardDokumenteHochladenComponent,
-        MockComponent(BescheidWizardSummaryComponent),
-        MockComponent(BescheidWizardAntragBescheidenSummaryComponent),
-        MockComponent(BescheidWizardDokumenteHochladenSummaryComponent),
-        MockComponent(BescheidWizardStepTitleComponent),
-        MockComponent(BescheidWizardDokumenteHochladenFormComponent),
-        MockComponent(BescheidWizardStepperComponent),
-      ],
-    }).compileComponents();
-
-    fixture = TestBed.createComponent(BescheidWizardDokumenteHochladenComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-
-  describe('template', () => {
-    describe('alfa-bescheid-wizard-stepper', () => {
-      function getElementComponent(): BescheidWizardStepperComponent {
-        return getElementFromFixtureByType(fixture, BescheidWizardStepperComponent);
-      }
-
-      describe('input', () => {
-        it('should set activeStep', () => {
-          fixture.detectChanges();
-
-          expect(getElementComponent().activeStep).toBe(BescheidWizardStep.DokumenteHochladen);
-        });
-      });
-    });
-
-    describe('alfa-bescheid-wizard-step-title', () => {
-      function getElementComponent(): BescheidWizardStepTitleComponent {
-        return getElementFromFixtureByType(fixture, BescheidWizardStepTitleComponent);
-      }
-
-      describe('input', () => {
-        it('should set inactiveStep', () => {
-          fixture.detectChanges();
-
-          expect(getElementComponent().inactiveStep).toBeTruthy();
-        });
-      });
-    });
-  });
-});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/form/bescheid-wizard-dokumente-hochladen-form.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/form/bescheid-wizard-dokumente-hochladen-form.component.spec.ts
deleted file mode 100644
index bcf7a846b3cca932af5613b3af7baec9a57d43d6..0000000000000000000000000000000000000000
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/form/bescheid-wizard-dokumente-hochladen-form.component.spec.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { BescheidWizardDokumenteHochladenFormComponent } from './bescheid-wizard-dokumente-hochladen-form.component';
-
-describe('BescheidWizardDokumenteHochladenFormComponent', () => {
-  let component: BescheidWizardDokumenteHochladenFormComponent;
-  let fixture: ComponentFixture<BescheidWizardDokumenteHochladenFormComponent>;
-
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      declarations: [BescheidWizardDokumenteHochladenFormComponent],
-    }).compileComponents();
-
-    fixture = TestBed.createComponent(BescheidWizardDokumenteHochladenFormComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/form/bescheid-wizard-dokumente-hochladen-form.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/form/bescheid-wizard-dokumente-hochladen-form.component.ts
deleted file mode 100644
index 3f4923a9b4a0b40edc3b6392aae2d52f2b3b4d8d..0000000000000000000000000000000000000000
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/form/bescheid-wizard-dokumente-hochladen-form.component.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { Component } from '@angular/core';
-
-@Component({
-  selector: 'alfa-bescheid-wizard-dokumente-hochladen-form',
-  templateUrl: './bescheid-wizard-dokumente-hochladen-form.component.html',
-})
-export class BescheidWizardDokumenteHochladenFormComponent {}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/summary/bescheid-wizard-dokumente-hochladen-summary.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/summary/bescheid-wizard-dokumente-hochladen-summary.component.spec.ts
deleted file mode 100644
index 0b30871de20941b223787ab12b0e40d233dd8f9f..0000000000000000000000000000000000000000
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/summary/bescheid-wizard-dokumente-hochladen-summary.component.spec.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { BescheidWizardDokumenteHochladenSummaryComponent } from './bescheid-wizard-dokumente-hochladen-summary.component';
-
-describe('BescheidWizardDokumenteHochladenSummaryComponent', () => {
-  let component: BescheidWizardDokumenteHochladenSummaryComponent;
-  let fixture: ComponentFixture<BescheidWizardDokumenteHochladenSummaryComponent>;
-
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      declarations: [BescheidWizardDokumenteHochladenSummaryComponent],
-    }).compileComponents();
-
-    fixture = TestBed.createComponent(BescheidWizardDokumenteHochladenSummaryComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/form/bescheid-wizard-dokumente-hochladen-form.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/step-content-layout/step-content-layout.component.html
similarity index 60%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/form/bescheid-wizard-dokumente-hochladen-form.component.html
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/step-content-layout/step-content-layout.component.html
index d147a2c6bdf7308ae737b78a7814e447702120fa..43b8946ab2d59886a58ed927028c68158785dedc 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/form/bescheid-wizard-dokumente-hochladen-form.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/step-content-layout/step-content-layout.component.html
@@ -1,6 +1,6 @@
 <!--
 
-    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
     Ministerpräsidenten des Landes Schleswig-Holstein
     Staatskanzlei
     Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,4 +23,20 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<p>bescheid-wizard-dokumente-hochladen-form works!</p>
+<div class="flex h-full gap-11">
+  <div class="flex w-1/2 flex-row gap-7">
+    <alfa-bescheid-wizard-stepper
+      [activeStep]="activeStep"
+      (stepChange)="stepChange.emit($event)"
+      data-test-id="wizard-stepper"
+    />
+    <div class="mt-2 flex flex-1 flex-col">
+      <ng-content select="[stepPanel]" />
+    </div>
+  </div>
+  <div class="flex w-1/2">
+    <alfa-bescheid-wizard-summary headline="Bescheid" data-test-id="wizard-summary">
+      <ng-content select="[summary]" />
+    </alfa-bescheid-wizard-summary>
+  </div>
+</div>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/step-content-layout/step-content-layout.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/step-content-layout/step-content-layout.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9a3c8cc809e97eb6b89cf7b3dc7ed15b6f6d81f9
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/step-content-layout/step-content-layout.component.spec.ts
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { BescheidWizardStep } from '@alfa-client/bescheid-shared';
+import { triggerEvent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { MockComponent } from 'ng-mocks';
+import { BescheidWizardStepperComponent } from '../stepper/bescheid-wizard-stepper.component';
+import { BescheidWizardSummaryComponent } from '../summary/bescheid-wizard-summary.component';
+import { StepContentLayoutComponent } from './step-content-layout.component';
+
+describe('StepContentLayoutComponent', () => {
+  let component: StepContentLayoutComponent;
+  let fixture: ComponentFixture<StepContentLayoutComponent>;
+
+  const wizardStepper: string = getDataTestIdOf('wizard-stepper');
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        StepContentLayoutComponent,
+        MockComponent(BescheidWizardStepperComponent),
+        MockComponent(BescheidWizardSummaryComponent),
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(StepContentLayoutComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('on stepper step change', () => {
+    it('should emit', () => {
+      component.stepChange.emit = jest.fn();
+
+      triggerEvent({
+        fixture,
+        name: 'stepChange',
+        elementSelector: wizardStepper,
+        data: BescheidWizardStep.AntragBescheiden,
+      });
+
+      expect(component.stepChange.emit).toHaveBeenCalledWith(BescheidWizardStep.AntragBescheiden);
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/bescheid-wizard-dokumente-hochladen.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/step-content-layout/step-content-layout.component.ts
similarity index 70%
rename from alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/bescheid-wizard-dokumente-hochladen.component.ts
rename to alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/step-content-layout/step-content-layout.component.ts
index c145f7b4995e9ac1193ce9dd148dc78a50e682da..8fd8d880d084fdcb16f9f121becfdbd1dc850e41 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/bescheid-wizard-dokumente-hochladen.component.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/step-content-layout/step-content-layout.component.ts
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -22,12 +22,14 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { BescheidWizardStep } from '@alfa-client/bescheid-shared';
-import { Component } from '@angular/core';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
 
 @Component({
-  selector: 'alfa-bescheid-wizard-dokumente-hochladen',
-  templateUrl: './bescheid-wizard-dokumente-hochladen.component.html',
+  selector: 'alfa-step-content-layout',
+  templateUrl: './step-content-layout.component.html',
 })
-export class BescheidWizardDokumenteHochladenComponent {
-  public readonly bescheidWizardStep = BescheidWizardStep;
+export class StepContentLayoutComponent {
+  @Input() public activeStep: BescheidWizardStep;
+
+  @Output() public stepChange: EventEmitter<BescheidWizardStep> = new EventEmitter();
 }
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/summary/bescheid-wizard-summary.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/summary/bescheid-wizard-summary.component.html
index b8fa88049ce906de0d08d137018d21d725c3ded3..cda7188f9d38f435d1c3f582ed9980061bb98c08 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/summary/bescheid-wizard-summary.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/summary/bescheid-wizard-summary.component.html
@@ -23,7 +23,9 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<section class="flex h-full w-full flex-col overflow-auto rounded-xl bg-background-100 px-4 py-5">
-  <h3 class="mb-4 text-base font-bold text-primary-600">Bescheid</h3>
-  <ng-content></ng-content>
+<section class="absolute flex size-full flex-col gap-4 overflow-auto rounded-xl bg-background-100 px-4 py-5">
+  <h3 class="text-base font-bold text-primary">{{ headline }}</h3>
+  <div class="flex-1">
+    <ng-content />
+  </div>
 </section>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/summary/bescheid-wizard-summary.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/summary/bescheid-wizard-summary.component.ts
index f6ca78a11b86260c57e235229ec2333e80ff6d85..2a6b34b223a8dd367abc352356c67799274d1323 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/summary/bescheid-wizard-summary.component.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/summary/bescheid-wizard-summary.component.ts
@@ -21,10 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component } from '@angular/core';
+import { Component, Input } from '@angular/core';
 
 @Component({
   selector: 'alfa-bescheid-wizard-summary',
   templateUrl: './bescheid-wizard-summary.component.html',
+  styles: [':host {@apply relative w-full}'],
 })
-export class BescheidWizardSummaryComponent {}
+export class BescheidWizardSummaryComponent {
+  @Input() public headline: string;
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/bescheid-wizard-upload-attachment-button-container.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/bescheid-wizard-upload-attachment-button-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..0442de58d2afd83f13f0adb7f928829302ffcea2
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/bescheid-wizard-upload-attachment-button-container.component.html
@@ -0,0 +1,5 @@
+<alfa-bescheid-wizard-upload-attachment-button
+  [attachments]="attachments$ | async"
+  (uploadFile)="uploadFile($event)"
+  data-test-id="upload-attachment-button"
+></alfa-bescheid-wizard-upload-attachment-button>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/bescheid-wizard-upload-attachment-button-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/bescheid-wizard-upload-attachment-button-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6035095eb818710798ad643934245f0ad1cf503f
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/bescheid-wizard-upload-attachment-button-container.component.spec.ts
@@ -0,0 +1,101 @@
+import { BescheidAttachments, BescheidResource } from '@alfa-client/bescheid-shared';
+import { getElementComponentFromFixtureByCss, Mock, mock, triggerEvent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+import { createBescheidAttachments, createBescheidResource } from '../../../../../../bescheid-shared/src/test/bescheid';
+import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
+import { createFile } from '../../../../../../tech-shared/test/file';
+import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
+import { BescheidWizardUploadAttachmentButtonContainerComponent } from './bescheid-wizard-upload-attachment-button-container.component';
+import { BescheidWizardUploadAttachmentButtonComponent } from './upload-attachment-button/bescheid-wizard-upload-attachment-button.component';
+
+describe('BescheidWizardUploadAttachmentButtonContainerComponent', () => {
+  let component: BescheidWizardUploadAttachmentButtonContainerComponent;
+  let fixture: ComponentFixture<BescheidWizardUploadAttachmentButtonContainerComponent>;
+
+  const uploadAttachmentButtonTestId: string = getDataTestIdOf('upload-attachment-button');
+
+  const bescheidAttachments: BescheidAttachments = createBescheidAttachments();
+
+  let bescheidService: Mock<BescheidService2>;
+
+  beforeEach(() => {
+    bescheidService = mock(BescheidService2);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardUploadAttachmentButtonContainerComponent,
+        MockComponent(BescheidWizardUploadAttachmentButtonComponent),
+      ],
+      providers: [{ provide: BescheidService2, useValue: bescheidService }],
+    }).compileComponents();
+
+    createComponent();
+  });
+
+  function createComponent() {
+    fixture = TestBed.createComponent(BescheidWizardUploadAttachmentButtonContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      bescheidService.getAttachments.mockReturnValue(of(bescheidAttachments));
+
+      createComponent();
+
+      expect(component.attachments$).toBeObservable(singleColdCompleted(bescheidAttachments));
+    });
+
+    describe('uploadFile', () => {
+      it('should call bescheid service', () => {
+        const bescheidResource: BescheidResource = createBescheidResource();
+        const file: File = createFile();
+        component.bescheidResource = bescheidResource;
+
+        component.uploadFile(file);
+
+        expect(bescheidService.uploadAttachment).toHaveBeenCalledWith(file, bescheidResource);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('upload attachment button', () => {
+      it('should have been called with inputs', () => {
+        bescheidService.getAttachments.mockReturnValue(of(bescheidAttachments));
+        createComponent();
+
+        const uploadAttachmentButtonComponent: BescheidWizardUploadAttachmentButtonComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardUploadAttachmentButtonComponent>(
+            fixture,
+            uploadAttachmentButtonTestId,
+          );
+
+        expect(uploadAttachmentButtonComponent.attachments).toEqual(bescheidAttachments);
+      });
+
+      describe('output', () => {
+        describe('uploadFile', () => {
+          it('should call handler', () => {
+            component.uploadFile = jest.fn();
+            const file: File = createFile();
+
+            triggerEvent({ fixture, elementSelector: uploadAttachmentButtonTestId, name: 'uploadFile', data: file });
+
+            expect(component.uploadFile).toHaveBeenCalledWith(file);
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/bescheid-wizard-upload-attachment-button-container.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/bescheid-wizard-upload-attachment-button-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..620adb8db26f04e7dc6b810c37c6acdef0c12d4e
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/bescheid-wizard-upload-attachment-button-container.component.ts
@@ -0,0 +1,20 @@
+import { BescheidAttachments, BescheidResource } from '@alfa-client/bescheid-shared';
+import { Component, inject, Input } from '@angular/core';
+import { Observable } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-upload-attachment-button-container',
+  templateUrl: './bescheid-wizard-upload-attachment-button-container.component.html',
+})
+export class BescheidWizardUploadAttachmentButtonContainerComponent {
+  @Input() bescheidResource: BescheidResource;
+
+  private readonly bescheidService = inject(BescheidService2);
+
+  public readonly attachments$: Observable<BescheidAttachments> = this.bescheidService.getAttachments();
+
+  public uploadFile(file: File): void {
+    this.bescheidService.uploadAttachment(file, this.bescheidResource);
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/upload-attachment-button/bescheid-wizard-upload-attachment-button.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/upload-attachment-button/bescheid-wizard-upload-attachment-button.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..daa2be54c067aee56f12918fc97895d4a9cfd87f
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/upload-attachment-button/bescheid-wizard-upload-attachment-button.component.html
@@ -0,0 +1,11 @@
+<div [formGroup]="formService.form">
+  <ods-file-upload-editor
+    [parentFormArrayName]="formServiceClass.FIELD_ATTACHMENTS"
+    [uploadInProgress]="upload"
+    [fileLinkList]="fileUrls"
+    (newFile)="uploadFile.emit($event)"
+    label="Anhang hochladen"
+    data-test-id="bescheid-wizard-upload-editor"
+  >
+  </ods-file-upload-editor>
+</div>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/upload-attachment-button/bescheid-wizard-upload-attachment-button.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/upload-attachment-button/bescheid-wizard-upload-attachment-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7aff85b5a346f756fae78c33398f875236e24390
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/upload-attachment-button/bescheid-wizard-upload-attachment-button.component.spec.ts
@@ -0,0 +1,84 @@
+import { BescheidAttachments } from '@alfa-client/bescheid-shared';
+import { createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared';
+import { getElementComponentFromFixtureByCss, triggerEvent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
+import { faker } from '@faker-js/faker';
+import { FileUploadEditorComponent } from '@ods/component';
+import { MockComponent } from 'ng-mocks';
+import { createBescheidAttachments } from '../../../../../../../bescheid-shared/src/test/bescheid';
+import { createBinaryFileResource } from '../../../../../../../binary-file-shared/test/binary-file';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { createFile } from '../../../../../../../tech-shared/test/file';
+import { BescheidFormService } from '../../../bescheid.formservice';
+import { BescheidWizardUploadAttachmentButtonComponent } from './bescheid-wizard-upload-attachment-button.component';
+
+describe('BescheidWizardUploadAttachmentButtonComponent', () => {
+  let component: BescheidWizardUploadAttachmentButtonComponent;
+  let fixture: ComponentFixture<BescheidWizardUploadAttachmentButtonComponent>;
+
+  const uploadEditorTestId: string = getDataTestIdOf('bescheid-wizard-upload-editor');
+
+  const bescheidAttachments: BescheidAttachments = createBescheidAttachments();
+
+  let formService: BescheidFormService;
+
+  beforeEach(() => {
+    formService = new BescheidFormService(new FormBuilder(), null);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [BescheidWizardUploadAttachmentButtonComponent, MockComponent(FileUploadEditorComponent)],
+      providers: [{ provide: BescheidFormService, useValue: formService }],
+      imports: [ReactiveFormsModule],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardUploadAttachmentButtonComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      expect(component.upload).toEqual(createEmptyStateResource());
+      expect(component.fileUrls).toEqual([]);
+    });
+  });
+
+  describe('template', () => {
+    describe('upload editor', () => {
+      it('should have been called with inputs', () => {
+        component.upload = createStateResource(createBinaryFileResource());
+        component.fileUrls = [faker.internet.url()];
+
+        fixture.detectChanges();
+        const uploadEditorComponent: FileUploadEditorComponent = getElementComponentFromFixtureByCss<FileUploadEditorComponent>(
+          fixture,
+          uploadEditorTestId,
+        );
+
+        expect(uploadEditorComponent.parentFormArrayName).toEqual(BescheidFormService.FIELD_ATTACHMENTS);
+        expect(uploadEditorComponent.uploadInProgress).toEqual(component.upload);
+        expect(uploadEditorComponent.fileLinkList).toEqual(component.fileUrls);
+      });
+
+      describe('output', () => {
+        describe('newFile', () => {
+          it('should emit', () => {
+            component.uploadFile.emit = jest.fn();
+            const file: File = createFile();
+
+            triggerEvent({ fixture, elementSelector: uploadEditorTestId, name: 'newFile', data: file });
+
+            expect(component.uploadFile.emit).toHaveBeenCalledWith(file);
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/upload-attachment-button/bescheid-wizard-upload-attachment-button.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/upload-attachment-button/bescheid-wizard-upload-attachment-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0ec17648a4f94e19a0b6184e4a2cbb68f1b6edcd
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/upload-attachment-button/bescheid-wizard-upload-attachment-button.component.ts
@@ -0,0 +1,32 @@
+import { BescheidAttachments, createEmptyBescheidAttachments } from '@alfa-client/bescheid-shared';
+import { BinaryFileResource } from '@alfa-client/binary-file-shared';
+import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
+import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
+import { getUrl } from '@ngxp/rest';
+import { BescheidFormService } from '../../../bescheid.formservice';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-upload-attachment-button',
+  templateUrl: './bescheid-wizard-upload-attachment-button.component.html',
+})
+export class BescheidWizardUploadAttachmentButtonComponent {
+  @Input() set attachments(value: BescheidAttachments) {
+    this.updateAttachments(value);
+  }
+
+  @Output() uploadFile: EventEmitter<File> = new EventEmitter<File>();
+
+  public readonly formService: BescheidFormService = inject(BescheidFormService);
+
+  public fileUrls: string[] = [];
+  public upload: StateResource<BinaryFileResource> = createEmptyStateResource();
+  private _attachments: BescheidAttachments = createEmptyBescheidAttachments();
+
+  public readonly formServiceClass = BescheidFormService;
+
+  updateAttachments(value: BescheidAttachments) {
+    this._attachments = value;
+    this.upload = value.uploadStateResource;
+    this.fileUrls = this._attachments.items.map((binaryFileResource: BinaryFileResource) => getUrl(binaryFileResource));
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/bescheid-wizard-upload-document-button-container.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/bescheid-wizard-upload-document-button-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..99efc09710ff3289b34e59461294c0a3e39596a7
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/bescheid-wizard-upload-document-button-container.component.html
@@ -0,0 +1,6 @@
+<alfa-bescheid-wizard-upload-document-button
+  [bescheidResource]="bescheidResource"
+  [bescheidDocument]="bescheidDocument$ | async"
+  (file)="uploadBescheidDocumentFile($event)"
+  data-test-id="bescheid-wizard-upload-document-button"
+></alfa-bescheid-wizard-upload-document-button>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/bescheid-wizard-upload-document-button-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/bescheid-wizard-upload-document-button-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..aad7d40ccedf3a798acadb6be1b76e9560b43912
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/bescheid-wizard-upload-document-button-container.component.spec.ts
@@ -0,0 +1,102 @@
+import { BescheidDocument, BescheidResource } from '@alfa-client/bescheid-shared';
+import { getElementComponentFromFixtureByCss, mock, Mock, triggerEvent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+import { createBescheidDocument, createBescheidResource } from '../../../../../../bescheid-shared/src/test/bescheid';
+import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
+import { createFile } from '../../../../../../tech-shared/test/file';
+import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
+import { BescheidWizardUploadDocumentButtonContainerComponent } from './bescheid-wizard-upload-document-button-container.component';
+import { BescheidWizardUploadDocumentButtonComponent } from './upload-document-button/bescheid-wizard-upload-document-button.component';
+
+describe('BescheidWizardDokumentHochladenContainerButtonComponent', () => {
+  let component: BescheidWizardUploadDocumentButtonContainerComponent;
+  let fixture: ComponentFixture<BescheidWizardUploadDocumentButtonContainerComponent>;
+
+  const uploadDocumentButtonTestId: string = getDataTestIdOf('bescheid-wizard-upload-document-button');
+
+  const bescheidDocument: BescheidDocument = createBescheidDocument();
+
+  let bescheidService: Mock<BescheidService2>;
+
+  beforeEach(() => {
+    bescheidService = mock(BescheidService2);
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardUploadDocumentButtonContainerComponent,
+        MockComponent(BescheidWizardUploadDocumentButtonComponent),
+      ],
+      providers: [{ provide: BescheidService2, useValue: bescheidService }],
+    }).compileComponents();
+
+    createComponent();
+  });
+
+  function createComponent() {
+    fixture = TestBed.createComponent(BescheidWizardUploadDocumentButtonContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      bescheidService.getBescheidDocument.mockReturnValue(of(bescheidDocument));
+
+      createComponent();
+
+      expect(component.bescheidDocument$).toBeObservable(singleColdCompleted(bescheidDocument));
+    });
+
+    describe('uploadBescheidDocumentFile', () => {
+      it('should call bescheid service', () => {
+        const file: File = createFile();
+        const bescheidResource: BescheidResource = createBescheidResource();
+        component.bescheidResource = bescheidResource;
+
+        component.uploadBescheidDocumentFile(file);
+
+        expect(bescheidService.uploadBescheidDocument).toHaveBeenCalledWith(file, bescheidResource);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('upload document button', () => {
+      it('should have been called with inputs', () => {
+        const bescheidResource: BescheidResource = createBescheidResource();
+        bescheidService.getBescheidDocument.mockReturnValue(of(bescheidDocument));
+        createComponent();
+        component.bescheidResource = bescheidResource;
+
+        fixture.detectChanges();
+        const uploadDocumentButtonComponent: BescheidWizardUploadDocumentButtonComponent =
+          getElementComponentFromFixtureByCss<BescheidWizardUploadDocumentButtonComponent>(fixture, uploadDocumentButtonTestId);
+
+        expect(uploadDocumentButtonComponent.bescheidResource).toEqual(bescheidResource);
+        expect(uploadDocumentButtonComponent.bescheidDocument).toEqual(bescheidDocument);
+      });
+
+      describe('output', () => {
+        describe('file', () => {
+          it('should call handler', () => {
+            component.uploadBescheidDocumentFile = jest.fn();
+            const file: File = createFile();
+
+            triggerEvent({ fixture, elementSelector: uploadDocumentButtonTestId, name: 'file', data: file });
+
+            expect(component.uploadBescheidDocumentFile).toHaveBeenCalledWith(file);
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/bescheid-wizard-upload-document-button-container.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/bescheid-wizard-upload-document-button-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a874617f496f42ccb8492a8fd116ae29d2384d36
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/bescheid-wizard-upload-document-button-container.component.ts
@@ -0,0 +1,20 @@
+import { BescheidDocument, BescheidResource } from '@alfa-client/bescheid-shared';
+import { Component, inject, Input } from '@angular/core';
+import { Observable } from 'rxjs';
+import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-upload-document-button-container',
+  templateUrl: './bescheid-wizard-upload-document-button-container.component.html',
+})
+export class BescheidWizardUploadDocumentButtonContainerComponent {
+  @Input() bescheidResource: BescheidResource;
+
+  private readonly bescheidService = inject(BescheidService2);
+
+  public readonly bescheidDocument$: Observable<BescheidDocument> = this.bescheidService.getBescheidDocument();
+
+  public uploadBescheidDocumentFile(file: File): void {
+    this.bescheidService.uploadBescheidDocument(file, this.bescheidResource);
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/upload-document-button/bescheid-wizard-upload-document-button.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/upload-document-button/bescheid-wizard-upload-document-button.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..0b04ceb6fc50d6d98b70f95f7f252c6a62a11252
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/upload-document-button/bescheid-wizard-upload-document-button.component.html
@@ -0,0 +1,14 @@
+<div [formGroup]="formService.form" class="w-full">
+  <ods-single-file-upload-editor
+    *ngIf="bescheidResource | hasLink: bescheidLinkRel.UPLOAD_BESCHEID_FILE"
+    [uploadInProgress]="upload.loading"
+    [formControlName]="formServiceClass.FIELD_BESCHEID_DOCUMENT"
+    (newFile)="uploadFile($event)"
+    class="w-72"
+    data-test-id="bescheid-wizard-upload-document-upload-editor"
+  >
+    <ods-bescheid-upload-icon icon></ods-bescheid-upload-icon>
+    <ods-spinner-icon spinner size="extra-large"></ods-spinner-icon>
+    <div text class="text-center">Bescheiddokument hochladen</div>
+  </ods-single-file-upload-editor>
+</div>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/upload-document-button/bescheid-wizard-upload-document-button.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/upload-document-button/bescheid-wizard-upload-document-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d6616d37317a467e6a8c1976cfb1f2f5fc937ffc
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/upload-document-button/bescheid-wizard-upload-document-button.component.spec.ts
@@ -0,0 +1,148 @@
+import { BescheidDocument, BescheidLinkRel, createEmptyUploadInProgress } from '@alfa-client/bescheid-shared';
+import { HasLinkPipe } from '@alfa-client/tech-shared';
+import {
+  existsAsHtmlElement,
+  getElementComponentFromFixtureByCss,
+  mock,
+  notExistsAsHtmlElement,
+  triggerEvent,
+  useFromMock,
+} from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
+import { SingleFileUploadEditorComponent } from '@ods/component';
+import { BescheidUploadIconComponent, SpinnerIconComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+import { BescheidService2 } from '../../../../../../../bescheid-shared/src/lib/bescheid2.service';
+import {
+  createBescheidDocument,
+  createBescheidResource,
+  createPendingUpload,
+} from '../../../../../../../bescheid-shared/src/test/bescheid';
+import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
+import { createFile } from '../../../../../../../tech-shared/test/file';
+import { BescheidFormService } from '../../../bescheid.formservice';
+import { BescheidWizardUploadDocumentButtonComponent } from './bescheid-wizard-upload-document-button.component';
+
+describe('BescheidWizardDokumentHochladenButtonComponent', () => {
+  let component: BescheidWizardUploadDocumentButtonComponent;
+  let fixture: ComponentFixture<BescheidWizardUploadDocumentButtonComponent>;
+
+  const fileUploadEditorTestId: string = getDataTestIdOf('bescheid-wizard-upload-document-upload-editor');
+
+  const bescheidDocument: BescheidDocument = createBescheidDocument();
+
+  let formService: BescheidFormService;
+
+  beforeEach(() => {
+    formService = new BescheidFormService(new UntypedFormBuilder(), useFromMock(mock(BescheidService2)));
+  });
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [
+        BescheidWizardUploadDocumentButtonComponent,
+        MockComponent(SingleFileUploadEditorComponent),
+        MockComponent(BescheidUploadIconComponent),
+        MockComponent(SpinnerIconComponent),
+        HasLinkPipe,
+      ],
+      providers: [
+        {
+          provide: BescheidFormService,
+          useValue: formService,
+        },
+      ],
+      imports: [ReactiveFormsModule],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWizardUploadDocumentButtonComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  describe('component', () => {
+    it('should create', () => {
+      expect(component).toBeTruthy();
+    });
+
+    it('should set initial values', () => {
+      expect(component.upload).toEqual(createEmptyUploadInProgress());
+    });
+
+    describe('set bescheid document', () => {
+      it('should call form service', () => {
+        formService.updateBescheidDocumentFile = jest.fn();
+
+        component.bescheidDocument = bescheidDocument;
+
+        expect(formService.updateBescheidDocumentFile).toHaveBeenCalledWith(bescheidDocument.documentUri);
+      });
+
+      it('should set upload', () => {
+        formService.updateBescheidDocumentFile = jest.fn();
+
+        component.bescheidDocument = bescheidDocument;
+
+        expect(component.upload).toEqual(bescheidDocument.upload);
+      });
+    });
+
+    describe('uploadFile', () => {
+      it('should emit', () => {
+        component.file.emit = jest.fn();
+        const file: File = createFile();
+
+        component.uploadFile(file);
+
+        expect(component.file.emit).toHaveBeenCalledWith(file);
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('file upload editor', () => {
+      it('should exists', () => {
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.UPLOAD_BESCHEID_FILE]);
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, fileUploadEditorTestId);
+      });
+
+      it('should NOT exists', () => {
+        component.bescheidResource = createBescheidResource();
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, fileUploadEditorTestId);
+      });
+
+      it('should have been called with inputs', () => {
+        component.bescheidResource = createBescheidResource([BescheidLinkRel.UPLOAD_BESCHEID_FILE]);
+        component.upload = createPendingUpload();
+
+        fixture.detectChanges();
+        const fileUploadEditorComponent: SingleFileUploadEditorComponent =
+          getElementComponentFromFixtureByCss<SingleFileUploadEditorComponent>(fixture, fileUploadEditorTestId);
+
+        expect(fileUploadEditorComponent.uploadInProgress).toEqual(component.upload.loading);
+      });
+
+      describe('output', () => {
+        describe('newFile', () => {
+          it('should call handler', () => {
+            component.bescheidResource = createBescheidResource([BescheidLinkRel.UPLOAD_BESCHEID_FILE]);
+            const file: File = createFile();
+            component.uploadFile = jest.fn();
+            fixture.detectChanges();
+
+            triggerEvent({ fixture, elementSelector: fileUploadEditorTestId, name: 'newFile', data: file });
+
+            expect(component.uploadFile).toHaveBeenCalledWith(file);
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/upload-document-button/bescheid-wizard-upload-document-button.component.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/upload-document-button/bescheid-wizard-upload-document-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d48f7dbde8774df3bf2599415e84da79a123d49d
--- /dev/null
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/upload-document-button-container/upload-document-button/bescheid-wizard-upload-document-button.component.ts
@@ -0,0 +1,36 @@
+import {
+  BescheidDocument,
+  BescheidLinkRel,
+  BescheidResource,
+  createEmptyUploadInProgress,
+  UploadFileInProgress,
+} from '@alfa-client/bescheid-shared';
+import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
+import { BescheidFormService } from '../../../bescheid.formservice';
+
+@Component({
+  selector: 'alfa-bescheid-wizard-upload-document-button',
+  templateUrl: './bescheid-wizard-upload-document-button.component.html',
+  styles: [':host {@apply flex grow}'],
+})
+export class BescheidWizardUploadDocumentButtonComponent {
+  @Input() bescheidResource: BescheidResource;
+
+  @Input() set bescheidDocument(value: BescheidDocument) {
+    this.formService.updateBescheidDocumentFile(value.documentUri);
+    this.upload = value.upload;
+  }
+
+  @Output() file: EventEmitter<File> = new EventEmitter<File>();
+
+  public readonly formService = inject(BescheidFormService);
+
+  public upload: UploadFileInProgress = createEmptyUploadInProgress();
+
+  public readonly formServiceClass = BescheidFormService;
+  public readonly bescheidLinkRel = BescheidLinkRel;
+
+  public uploadFile(file: File): void {
+    this.file.emit(file);
+  }
+}
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/weiter-button/bescheid-wizard-weiter-button.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/weiter-button/bescheid-wizard-weiter-button.component.html
index e02e0583599c0f9efd985994734571c1e19de055..491749c3c65e2134761b1588f930f5a29bde5561 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/weiter-button/bescheid-wizard-weiter-button.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/weiter-button/bescheid-wizard-weiter-button.component.html
@@ -28,8 +28,8 @@
   (clickEmitter)="clickEmitter.emit()"
   variant="primary"
   size="medium"
-  class="mt-8 flex"
-  data-test-id="bescheid-weiter-button"
+  class="mt-4 flex"
   text="Weiter"
+  dataTestId="bescheid-weiter-button"
 >
 </ods-button-with-spinner>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/weiter-button/bescheid-wizard-weiter-button.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/weiter-button/bescheid-wizard-weiter-button.component.spec.ts
index 5f970240cbfc56e5c7bb123b1c93060e1360b195..d5f5cded5a3a08e16a482c4674febf9a5c66fd21 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/weiter-button/bescheid-wizard-weiter-button.component.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/weiter-button/bescheid-wizard-weiter-button.component.spec.ts
@@ -29,14 +29,14 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ButtonWithSpinnerComponent } from '@ods/component';
 import { MockComponent } from 'ng-mocks';
 import { createCommandResource } from '../../../../../../command-shared/test/command';
-import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
+import { getDataTestIdAttributeOf } from '../../../../../../tech-shared/test/data-test';
 import { BescheidWizardWeiterButtonComponent } from './bescheid-wizard-weiter-button.component';
 
 describe('BescheidWizardWeiterButtonComponent', () => {
   let component: BescheidWizardWeiterButtonComponent;
   let fixture: ComponentFixture<BescheidWizardWeiterButtonComponent>;
 
-  const button: string = getDataTestIdOf('bescheid-weiter-button');
+  const button: string = getDataTestIdAttributeOf('bescheid-weiter-button');
 
   let clickEmitter: Mock<EventEmitter<MouseEvent>>;
 
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.spec.ts
index 68c46faa40d9354dfcb976a2726e533f76b96cb3..2125d0b8e171796f264901d4b22e40c269d0cc7d 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.spec.ts
@@ -21,18 +21,23 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Bescheid, BescheidLinkRel, BescheidResource, BescheidSendBy, BescheidService } from '@alfa-client/bescheid-shared';
-import { formatForDatabase } from '@alfa-client/tech-shared';
+import { Bescheid, BescheidLinkRel, BescheidResource, BescheidSendBy, BescheidWizardStep, Wizard, } from '@alfa-client/bescheid-shared';
+import { CommandResource } from '@alfa-client/command-shared';
+import { createErrorStateResource, createLoadingStateResource, formatForDatabase, StateResource } from '@alfa-client/tech-shared';
 import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { registerLocaleData } from '@angular/common';
 import localeDe from '@angular/common/locales/de';
 import { UntypedFormBuilder } from '@angular/forms';
 import { faker } from '@faker-js/faker';
+import { expect } from '@jest/globals';
 import { ResourceUri } from '@ngxp/rest';
 import { EMPTY, Observable, of } from 'rxjs';
-import { createBescheid, createBescheidResource } from '../../../../bescheid-shared/src/test/bescheid';
-import { singleCold } from '../../../../tech-shared/test/marbles';
+import { BescheidService2 } from '../../../../bescheid-shared/src/lib/bescheid2.service';
+import { createBescheid, createBescheidResource, createWizard } from '../../../../bescheid-shared/src/test/bescheid';
+import { createSuccessfullyDoneCommandStateResource } from '../../../../command-shared/test/command';
+import { createProblemDetail } from '../../../../tech-shared/test/error';
+import { singleCold, singleColdCompleted } from '../../../../tech-shared/test/marbles';
 import { createVorgangWithEingangResource } from '../../../../vorgang-shared/test/vorgang';
 import { BescheidFormService } from './bescheid.formservice';
 
@@ -40,27 +45,373 @@ registerLocaleData(localeDe);
 
 describe('BescheidFormService', () => {
   let service: BescheidFormService;
-  let bescheidService: Mock<BescheidService>;
+  let bescheidService: Mock<BescheidService2>;
   const now: Date = new Date();
   Date.now = jest.fn().mockReturnValue(now);
   const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource();
 
   beforeEach(() => {
-    bescheidService = mock(BescheidService);
-    bescheidService.createBescheid.mockReturnValue(of(EMPTY));
+    bescheidService = mock(BescheidService2);
     service = new BescheidFormService(new UntypedFormBuilder(), useFromMock(bescheidService));
     service.setVorgangWithEingangResource(vorgangWithEingangResource);
   });
 
   describe('doSubmit', () => {
+    const wizard: Wizard = createWizard();
+
+    beforeEach(() => {
+      service._submitBescheid = jest.fn().mockReturnValue(EMPTY);
+      bescheidService.getWizard.mockReturnValue(of(wizard));
+    });
+
+    it('should get wizard', () => {
+      service.submit().subscribe();
+
+      expect(bescheidService.getWizard).toHaveBeenCalled();
+    });
+
+    it('should submit bescheid', () => {
+      service.submit().subscribe();
+
+      expect(service._submitBescheid).toHaveBeenCalledWith(wizard);
+    });
+
+    it('should return command', () => {
+      const command: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+      service._submitBescheid = jest.fn().mockReturnValue(of(command));
+
+      const submit$: Observable<StateResource<CommandResource>> = service.submit();
+
+      expect(submit$).toBeObservable(singleColdCompleted(command));
+    });
+  });
+
+  describe('_submitBescheid', () => {
+    const command: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+
+    beforeEach(() => {
+      service._updateAndSendBescheid = jest.fn().mockReturnValue(EMPTY);
+      service._createBescheid = jest.fn().mockReturnValue(EMPTY);
+      service._updateBescheid = jest.fn().mockReturnValue(EMPTY);
+      service.isPatch = jest.fn();
+    });
+
+    describe('create', () => {
+      beforeEach(() => {
+        service.isPatch = jest.fn().mockReturnValue(false);
+      });
+
+      it('should create', () => {
+        service._submitBescheid(createWizard()).subscribe();
+
+        expect(service._createBescheid).toHaveBeenCalled();
+      });
+
+      it('should return command', () => {
+        service._createBescheid = jest.fn().mockReturnValue(of(command));
+
+        const submit$: Observable<StateResource<CommandResource>> = service._submitBescheid(createWizard());
+
+        expect(submit$).toBeObservable(singleColdCompleted(command));
+      });
+    });
+
+    describe('update', () => {
+      beforeEach(() => {
+        service._canSendBescheid = jest.fn().mockReturnValue(false);
+      });
+
+      it('should update on change bescheid', () => {
+        service.isPatch = jest.fn().mockReturnValue(true);
+
+        service._submitBescheid(createWizard()).subscribe();
+
+        expect(service._updateBescheid).toHaveBeenCalled();
+      });
+
+      it('should update on existing bescheid', () => {
+        service.isPatch = jest.fn().mockReturnValue(false);
+        service.patchValues(createBescheidResource());
+
+        service._submitBescheid(createWizard()).subscribe();
+
+        expect(service._updateBescheid).toHaveBeenCalled();
+      });
+
+      it('should return command', () => {
+        service.isPatch = jest.fn().mockReturnValue(true);
+        service._updateBescheid = jest.fn().mockReturnValue(of(command));
+
+        const submit$: Observable<StateResource<CommandResource>> = service._submitBescheid(createWizard());
+
+        expect(submit$).toBeObservable(singleColdCompleted(command));
+      });
+    });
+
+    describe('update and send', () => {
+      const wizard: Wizard = createWizard();
+
+      beforeEach(() => {
+        service.isPatch = jest.fn().mockReturnValue(true);
+      });
+
+      it('should update and send', () => {
+        service._canSendBescheid = jest.fn().mockReturnValue(true);
+
+        service._submitBescheid(wizard).subscribe();
+
+        expect(service._updateAndSendBescheid).toHaveBeenCalledWith(wizard.sendBy);
+      });
+
+      it('should NOT update and send', () => {
+        service._canSendBescheid = jest.fn().mockReturnValue(false);
+
+        service._submitBescheid(wizard).subscribe();
+
+        expect(service._updateAndSendBescheid).not.toHaveBeenCalled();
+      });
+
+      it('should return command', () => {
+        service._updateAndSendBescheid = jest.fn().mockReturnValue(of(command));
+
+        const submit$: Observable<StateResource<CommandResource>> = service._submitBescheid(wizard);
+
+        expect(submit$).toBeObservable(singleColdCompleted(command));
+      });
+    });
+  });
+
+  describe('_canSendBescheid', () => {
+    it('should return true', () => {
+      const canSendBescheid: boolean = service._canSendBescheid({
+        ...createWizard(),
+        activeStep: BescheidWizardStep.BescheidVersenden,
+        canBeSend: true,
+      });
+
+      expect(canSendBescheid).toBeTruthy();
+    });
+
+    it.each([BescheidWizardStep.AntragBescheiden, BescheidWizardStep.DokumenteHochladen])(
+      'should return false on step %s',
+      (step: BescheidWizardStep) => {
+        const canSendBescheid: boolean = service._canSendBescheid({
+          ...createWizard(),
+          activeStep: step,
+          canBeSend: true,
+        });
+
+        expect(canSendBescheid).toBeFalsy();
+      },
+    );
+
+    it('should return false if bescheid sending locked', () => {
+      const canSendBescheid: boolean = service._canSendBescheid({
+        ...createWizard(),
+        activeStep: BescheidWizardStep.BescheidVersenden,
+        canBeSend: false,
+      });
+
+      expect(canSendBescheid).toBeFalsy();
+    });
+  });
+
+  describe('_createBescheid', () => {
+    beforeEach(() => {
+      bescheidService.createBescheid.mockReturnValue(of(EMPTY));
+    });
+
     it('should create bescheid', () => {
       const formValue: Bescheid = createBescheid();
       service.getBescheidFormValue = jest.fn().mockReturnValue(formValue);
 
-      service.submit();
+      service._createBescheid();
 
       expect(bescheidService.createBescheid).toHaveBeenCalledWith(vorgangWithEingangResource, formValue);
     });
+
+    it('should return create command', () => {
+      const formValue: Bescheid = createBescheid();
+      service.getBescheidFormValue = jest.fn().mockReturnValue(formValue);
+      const createCommand: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+      bescheidService.createBescheid.mockReturnValue(of(createCommand));
+
+      const command$: Observable<StateResource<CommandResource>> = service._createBescheid();
+
+      expect(command$).toBeObservable(singleColdCompleted(createCommand));
+    });
+  });
+
+  describe('_updateBescheid', () => {
+    beforeEach(() => {
+      bescheidService.updateBescheid.mockReturnValue(of(EMPTY));
+    });
+
+    it('should update bescheid', () => {
+      const formValue: Bescheid = createBescheid();
+      service.getBescheidFormValue = jest.fn().mockReturnValue(formValue);
+      const bescheidResource: BescheidResource = createBescheidResource();
+      service.patchValues(bescheidResource);
+
+      service._updateBescheid();
+
+      expect(bescheidService.updateBescheid).toHaveBeenCalledWith(bescheidResource, formValue);
+    });
+
+    it('should return create command', () => {
+      const formValue: Bescheid = createBescheid();
+      service.getBescheidFormValue = jest.fn().mockReturnValue(formValue);
+      const bescheidResource: BescheidResource = createBescheidResource();
+      service.patchValues(bescheidResource);
+      const createCommand: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+      bescheidService.updateBescheid.mockReturnValue(of(createCommand));
+
+      const command$: Observable<StateResource<CommandResource>> = service._updateBescheid();
+
+      expect(command$).toBeObservable(singleColdCompleted(createCommand));
+    });
+  });
+
+  describe('_updateAndSendBescheid', () => {
+    beforeEach(() => {
+      service._updateBescheid = jest.fn().mockReturnValue(EMPTY);
+    });
+
+    describe('send manually', () => {
+      it('should update bescheid', () => {
+        service._updateAndSendBescheid(BescheidSendBy.MANUAL).subscribe();
+
+        expect(service._updateBescheid).toHaveBeenCalled();
+      });
+
+      it('should send bescheid manually', () => {
+        service._updateBescheid = jest.fn().mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+
+        service._updateAndSendBescheid(BescheidSendBy.MANUAL).subscribe();
+
+        expect(bescheidService.sendBescheidManually).toHaveBeenCalled();
+      });
+
+      it('should not send on pending update', () => {
+        service._updateBescheid = jest.fn().mockReturnValue(of(createLoadingStateResource()));
+
+        service._updateAndSendBescheid(BescheidSendBy.MANUAL).subscribe();
+
+        expect(bescheidService.sendBescheidManually).not.toHaveBeenCalled();
+      });
+
+      it('should not send on failed update', () => {
+        service._updateBescheid = jest.fn().mockReturnValue(of(createErrorStateResource(createProblemDetail())));
+
+        service._updateAndSendBescheid(BescheidSendBy.MANUAL).subscribe();
+
+        expect(bescheidService.sendBescheidManually).not.toHaveBeenCalled();
+      });
+
+      it('should return update command on pending update', () => {
+        const command: StateResource<CommandResource> = createLoadingStateResource();
+        service._updateBescheid = jest.fn().mockReturnValue(of(command));
+
+        const command$: Observable<StateResource<CommandResource>> = service._updateAndSendBescheid(BescheidSendBy.MANUAL);
+
+        expect(command$).toBeObservable(singleColdCompleted(command));
+      });
+
+      it('should return update command on failed update', () => {
+        const command: StateResource<CommandResource> = createErrorStateResource(createProblemDetail());
+        service._updateBescheid = jest.fn().mockReturnValue(of(command));
+
+        const command$: Observable<StateResource<CommandResource>> = service._updateAndSendBescheid(BescheidSendBy.MANUAL);
+
+        expect(command$).toBeObservable(singleColdCompleted(command));
+      });
+
+      it('should return send bescheid command on successful update', () => {
+        const command: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+        service._updateBescheid = jest.fn().mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+        bescheidService.sendBescheidManually.mockReturnValue(of(command));
+
+        const command$: Observable<StateResource<CommandResource>> = service._updateAndSendBescheid(BescheidSendBy.MANUAL);
+
+        expect(command$).toBeObservable(singleColdCompleted(command));
+      });
+
+      it('should not send message', () => {
+        service._updateBescheid = jest.fn().mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+
+        service._updateAndSendBescheid(BescheidSendBy.MANUAL).subscribe();
+
+        expect(bescheidService.sendBescheidMessage).not.toHaveBeenCalled();
+      });
+    });
+
+    describe('send by nachricht', () => {
+      it('should update bescheid', () => {
+        service._updateAndSendBescheid(BescheidSendBy.NACHRICHT);
+
+        expect(service._updateBescheid).toHaveBeenCalled();
+      });
+
+      it('should send bescheid message', () => {
+        service._updateBescheid = jest.fn().mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+
+        service._updateAndSendBescheid(BescheidSendBy.NACHRICHT).subscribe();
+
+        expect(bescheidService.sendBescheidMessage).toHaveBeenCalled();
+      });
+
+      it('should not send on pending update', () => {
+        service._updateBescheid = jest.fn().mockReturnValue(of(createLoadingStateResource()));
+
+        service._updateAndSendBescheid(BescheidSendBy.NACHRICHT).subscribe();
+
+        expect(bescheidService.sendBescheidMessage).not.toHaveBeenCalled();
+      });
+
+      it('should not send on failed update', () => {
+        service._updateBescheid = jest.fn().mockReturnValue(of(createErrorStateResource(createProblemDetail())));
+
+        service._updateAndSendBescheid(BescheidSendBy.NACHRICHT).subscribe();
+
+        expect(bescheidService.sendBescheidMessage).not.toHaveBeenCalled();
+      });
+
+      it('should return update command on pending update', () => {
+        const command: StateResource<CommandResource> = createLoadingStateResource();
+        service._updateBescheid = jest.fn().mockReturnValue(of(command));
+
+        const command$: Observable<StateResource<CommandResource>> = service._updateAndSendBescheid(BescheidSendBy.NACHRICHT);
+
+        expect(command$).toBeObservable(singleColdCompleted(command));
+      });
+
+      it('should return update command on failed update', () => {
+        const command: StateResource<CommandResource> = createErrorStateResource(createProblemDetail());
+        service._updateBescheid = jest.fn().mockReturnValue(of(command));
+
+        const command$: Observable<StateResource<CommandResource>> = service._updateAndSendBescheid(BescheidSendBy.NACHRICHT);
+
+        expect(command$).toBeObservable(singleColdCompleted(command));
+      });
+
+      it('should return send bescheid command on successful update', () => {
+        const command: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
+        service._updateBescheid = jest.fn().mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+        bescheidService.sendBescheidMessage.mockReturnValue(of(command));
+
+        const command$: Observable<StateResource<CommandResource>> = service._updateAndSendBescheid(BescheidSendBy.NACHRICHT);
+
+        expect(command$).toBeObservable(singleColdCompleted(command));
+      });
+
+      it('should not send manually', () => {
+        service._updateBescheid = jest.fn().mockReturnValue(of(createSuccessfullyDoneCommandStateResource()));
+
+        service._updateAndSendBescheid(BescheidSendBy.NACHRICHT).subscribe();
+
+        expect(bescheidService.sendBescheidManually).not.toHaveBeenCalled();
+      });
+    });
   });
 
   describe('patchValues', () => {
@@ -162,4 +513,30 @@ describe('BescheidFormService', () => {
       } as Bescheid);
     });
   });
+
+  describe('clearBescheidDocumentFile', () => {
+    it('should update bescheid document file', () => {
+      service.updateBescheidDocumentFile = jest.fn();
+
+      service.clearBescheidDocumentFile();
+
+      expect(service.updateBescheidDocumentFile).toHaveBeenCalledWith(null);
+    });
+  });
+
+  describe('updateBescheidDocumentFile', () => {
+    it('should patch form control value to null', () => {
+      service.updateBescheidDocumentFile();
+
+      expect(service.getBescheidFormValue().bescheidDocument).toBeNull();
+    });
+
+    it('should patch form control value', () => {
+      const bescheidResource: BescheidResource = createBescheidResource();
+
+      service.updateBescheidDocumentFile(bescheidResource.bescheidDocument);
+
+      expect(service.getBescheidFormValue().bescheidDocument).toEqual(bescheidResource.bescheidDocument);
+    });
+  });
 });
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.ts
index 4f9036dadf2779eff368da4ceeef7709f53df4e7..4e650ff9f6660e2e987ee53979858474096cafe2 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.ts
@@ -21,15 +21,23 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Bescheid, BescheidLinkRel, BescheidResource, BescheidSendBy, BescheidService } from '@alfa-client/bescheid-shared';
-import { CommandResource } from '@alfa-client/command-shared';
-import { AbstractFormService, StateResource, convertToBoolean, formatForDatabase } from '@alfa-client/tech-shared';
+import {
+  Bescheid,
+  BescheidLinkRel,
+  BescheidResource,
+  BescheidSendBy,
+  BescheidWizardStep,
+  Wizard,
+} from '@alfa-client/bescheid-shared';
+import { CommandResource, switchMapCommandSuccessfullyDone } from '@alfa-client/command-shared';
+import { AbstractFormService, convertToBoolean, formatForDatabase, isNotNil, StateResource } from '@alfa-client/tech-shared';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { Injectable } from '@angular/core';
-import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
-import { ResourceUri, getUrl, hasLink } from '@ngxp/rest';
-import { isUndefined } from 'lodash-es';
-import { Observable, startWith } from 'rxjs';
+import { FormControl, UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
+import { getUrl, hasLink, ResourceUri } from '@ngxp/rest';
+import { isNil, isUndefined } from 'lodash-es';
+import { first, Observable, startWith, switchMap } from 'rxjs';
+import { BescheidService2 } from '../../../../bescheid-shared/src/lib/bescheid2.service';
 
 @Injectable()
 export class BescheidFormService extends AbstractFormService<CommandResource> {
@@ -44,10 +52,11 @@ export class BescheidFormService extends AbstractFormService<CommandResource> {
   static readonly FIELD_PATH_PREFIX = 'command.body';
 
   private vorgangWithEingangResource: VorgangWithEingangResource;
+  private bescheidResource: BescheidResource;
 
   constructor(
     formBuilder: UntypedFormBuilder,
-    private readonly bescheidService: BescheidService,
+    private readonly bescheidService: BescheidService2,
   ) {
     super(formBuilder);
   }
@@ -65,25 +74,61 @@ export class BescheidFormService extends AbstractFormService<CommandResource> {
   }
 
   protected doSubmit(): Observable<StateResource<CommandResource>> {
+    return this.bescheidService.getWizard().pipe(
+      first(),
+      switchMap((wizard: Wizard) => this._submitBescheid(wizard)),
+    );
+  }
+
+  _submitBescheid(wizard: Wizard): Observable<StateResource<CommandResource>> {
+    if (this.isPatch() || isNotNil(this.bescheidResource)) {
+      if (this._canSendBescheid(wizard)) {
+        return this._updateAndSendBescheid(wizard.sendBy);
+      }
+      return this._updateBescheid();
+    }
+    return this._createBescheid();
+  }
+
+  _canSendBescheid(wizard: Wizard): boolean {
+    return wizard.activeStep === BescheidWizardStep.BescheidVersenden && wizard.canBeSend;
+  }
+
+  _createBescheid(): Observable<StateResource<CommandResource>> {
     return this.bescheidService.createBescheid(this.vorgangWithEingangResource, this.getBescheidFormValue());
   }
 
+  _updateBescheid(): Observable<StateResource<CommandResource>> {
+    return this.bescheidService.updateBescheid(this.bescheidResource, this.getBescheidFormValue());
+  }
+
+  _updateAndSendBescheid(sendBy: BescheidSendBy): Observable<StateResource<CommandResource>> {
+    if (sendBy === BescheidSendBy.MANUAL) {
+      return this._updateBescheid().pipe(switchMapCommandSuccessfullyDone(() => this.bescheidService.sendBescheidManually()));
+    }
+    if (sendBy === BescheidSendBy.NACHRICHT) {
+      return this._updateBescheid().pipe(switchMapCommandSuccessfullyDone(() => this.bescheidService.sendBescheidMessage()));
+    }
+  }
+
   protected getPathPrefix(): string {
     return BescheidFormService.FIELD_PATH_PREFIX;
   }
 
-  public patchValues(bescheid: BescheidResource): void {
-    const bescheidDocumentUri: ResourceUri = this.getBescheidDocumentUri(bescheid);
-    this.bescheidService.setDocumentUri(bescheidDocumentUri);
+  public patchValues(bescheidResource: BescheidResource): void {
+    this.bescheidResource = bescheidResource;
+    const bescheidDocumentUri: ResourceUri = this.getBescheidDocumentUri(bescheidResource);
     this.patch({
-      [BescheidFormService.FIELD_BESCHIEDEN_AM]: bescheid.beschiedenAm,
-      [BescheidFormService.FIELD_BEWILLIGT]: String(bescheid.bewilligt),
+      [BescheidFormService.FIELD_BESCHIEDEN_AM]: bescheidResource.beschiedenAm,
+      [BescheidFormService.FIELD_BEWILLIGT]: String(bescheidResource.bewilligt),
       [BescheidFormService.FIELD_BESCHEID_DOCUMENT]: bescheidDocumentUri,
-      [BescheidFormService.FIELD_SEND_BY]: isUndefined(bescheid.sendBy) ? BescheidSendBy.NACHRICHT : bescheid.sendBy,
-      [BescheidFormService.FIELD_NACHRICHT_SUBJECT]: bescheid.nachrichtSubject,
-      [BescheidFormService.FIELD_NACHRICHT_TEXT]: bescheid.nachrichtText,
+      [BescheidFormService.FIELD_SEND_BY]:
+        isUndefined(bescheidResource.sendBy) ? BescheidSendBy.NACHRICHT : bescheidResource.sendBy,
+      [BescheidFormService.FIELD_NACHRICHT_SUBJECT]: bescheidResource.nachrichtSubject,
+      [BescheidFormService.FIELD_NACHRICHT_TEXT]: bescheidResource.nachrichtText,
     });
-    bescheid.attachments.forEach((attachmentLink) =>
+    (this.form.controls[BescheidFormService.FIELD_ATTACHMENTS] as UntypedFormArray).clear();
+    bescheidResource.attachments.forEach((attachmentLink) =>
       (this.form.controls[BescheidFormService.FIELD_ATTACHMENTS] as UntypedFormArray).push(
         new UntypedFormControl(attachmentLink),
       ),
@@ -114,4 +159,28 @@ export class BescheidFormService extends AbstractFormService<CommandResource> {
   public setVorgangWithEingangResource(vorgangWithEingangResource: VorgangWithEingangResource): void {
     this.vorgangWithEingangResource = vorgangWithEingangResource;
   }
+
+  public clearBescheidDocumentFile(): void {
+    this.updateBescheidDocumentFile(null);
+  }
+
+  public updateBescheidDocumentFile(uri?: ResourceUri): void {
+    if (isNil(uri)) {
+      this.getBescheidDocumentControl().patchValue(null);
+    } else {
+      this.getBescheidDocumentControl().patchValue(uri);
+    }
+  }
+
+  private getBescheidDocumentControl(): FormControl {
+    return <FormControl>this.form.controls[BescheidFormService.FIELD_BESCHEID_DOCUMENT];
+  }
+
+  public isBetreffInvalid(): boolean {
+    return this.form.controls[BescheidFormService.FIELD_NACHRICHT_SUBJECT].invalid;
+  }
+
+  public isNachrichtInvalid(): boolean {
+    return this.form.controls[BescheidFormService.FIELD_NACHRICHT_TEXT].invalid;
+  }
 }
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid.module.ts b/alfa-client/libs/bescheid/src/lib/bescheid.module.ts
index 1771b5fc23ff9ce35d049fe26904470bd8e6ffd4..b8f0eb5dafcd5b84ec2d13457ae195d2f4589ef9 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid.module.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid.module.ts
@@ -24,10 +24,22 @@
 import { BescheidSharedModule } from '@alfa-client/bescheid-shared';
 import { BinaryFileModule } from '@alfa-client/binary-file';
 import { CommandSharedModule } from '@alfa-client/command-shared';
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import {
+  ConvertForDataTestPipe,
+  ConvertProblemDetailToErrorMessagesPipe,
+  GetUrlPipe,
+  HasLinkPipe,
+  ToEmbeddedResourcesPipe,
+} from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
+import {
+  ButtonWithSpinnerComponent,
+  FileUploadEditorComponent,
+  SingleFileUploadEditorComponent,
+  TextareaEditorComponent,
+  TextEditorComponent,
+} from '@ods/component';
 import { BescheidInVorgangContainerComponent } from './bescheid-in-vorgang-container/bescheid-in-vorgang-container.component';
 import { BescheidInVorgangComponent } from './bescheid-in-vorgang-container/bescheid-in-vorgang/bescheid-in-vorgang.component';
 import { BescheidListInVorgangContainerComponent } from './bescheid-list-in-vorgang-container/bescheid-list-in-vorgang-container.component';
@@ -36,30 +48,62 @@ import { DocumentInBescheidContainerComponent } from './bescheid-list-in-vorgang
 import { BeschiedenDateContainerComponent } from './beschieden-date-in-vorgang-container/beschieden-date-container/beschieden-date-container.component';
 import { BeschiedenDateInVorgangContainerComponent } from './beschieden-date-in-vorgang-container/beschieden-date-in-vorgang-container.component';
 
-import { ButtonWithSpinnerComponent } from '@ods/component';
 import {
+  DateEditorComponent,
+  ExpansionPanelComponent,
+  OzgcloudStrokedButtonWithSpinnerComponent,
+  SpinnerComponent,
+} from '@alfa-client/ui';
+import { ReactiveFormsModule } from '@angular/forms';
+import { MatIcon } from '@angular/material/icon';
+import {
+  AttachmentComponent,
+  AttachmentWrapperComponent,
+  BescheidGenerateIconComponent,
   BescheidStatusTextComponent,
+  BescheidUploadIconComponent,
   BescheidWrapperComponent,
+  ButtonCardComponent,
   ButtonComponent,
   CloseIconComponent,
   RadioButtonCardComponent,
+  SaveIconComponent,
+  SendIconComponent,
+  SpinnerIconComponent,
   StampIconComponent,
 } from '@ods/system';
+import { FormatFullDatePipe } from '../../../tech-shared/src/lib/pipe/format-full-date.pipe';
 import { BescheidWizardContainerComponent } from './bescheid-wizard-container/bescheid-wizard-container.component';
-import { BescheidWizardAbschliessenButtonComponent } from './bescheid-wizard-container/bescheid-wizard/abschliessen-button/bescheid-wizard-abschliessen-button.component';
-import { BescheidWizardAbschliessenDialogContainerComponent } from './bescheid-wizard-container/bescheid-wizard/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component';
-import { BescheidWizardAntragBescheidenComponent } from './bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden.component';
+import { BescheidWizardAbschliessenButtonComponent } from './bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-button/bescheid-wizard-abschliessen-button.component';
+import { BescheidWizardAbschliessenDialogContainerComponent } from './bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/abschliessen-dialog-container/bescheid-wizard-abschliessen-dialog-container.component';
+import { BescheidWizardAntragBescheidenContainerComponent } from './bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/bescheid-wizard-antrag-bescheiden-container.component';
 import { BescheidWizardAntragBescheidenFormComponent } from './bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/form/bescheid-wizard-antrag-bescheiden-form.component';
 import { BescheidWizardAntragBescheidenSummaryComponent } from './bescheid-wizard-container/bescheid-wizard/antrag-bescheiden/summary/bescheid-wizard-antrag-bescheiden-summary.component';
+import { BescheidWizardAttachmentFilesComponent } from './bescheid-wizard-container/bescheid-wizard/attachment-files-container/attachment-files/bescheid-wizard-attachment-files.component';
+import { BescheidWizardAttachmentFilesContainerComponent } from './bescheid-wizard-container/bescheid-wizard/attachment-files-container/bescheid-wizard-attachment-files-container.component';
+import { BescheidWizardBescheidVersendenContainerComponent } from './bescheid-wizard-container/bescheid-wizard/bescheid-versenden/bescheid-wizard-bescheid-versenden-container.component';
+import { BescheidWizardBescheidVersendenFormComponent } from './bescheid-wizard-container/bescheid-wizard/bescheid-versenden/form/bescheid-wizard-bescheid-versenden-form.component';
+import { BescheidWizardBescheidVersendenSummaryComponent } from './bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/bescheid-wizard-bescheid-versenden-summary.component';
+import { BescheidWizardBescheidVersendenSendenComponent } from './bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/senden/bescheid-wizard-bescheid-versenden-senden.component';
+import { BescheidWizardBescheidVersendenSpeichernComponent } from './bescheid-wizard-container/bescheid-wizard/bescheid-versenden/summary/speichern/bescheid-wizard-bescheid-versenden-speichern.component';
 import { BescheidWizardComponent } from './bescheid-wizard-container/bescheid-wizard/bescheid-wizard.component';
 import { BescheidWizardCancelDialogContainerComponent } from './bescheid-wizard-container/bescheid-wizard/cancel-dialog-container/bescheid-wizard-cancel-dialog-container.component';
-import { BescheidWizardDokumenteHochladenComponent } from './bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/bescheid-wizard-dokumente-hochladen.component';
-import { BescheidWizardDokumenteHochladenFormComponent } from './bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/form/bescheid-wizard-dokumente-hochladen-form.component';
-import { BescheidWizardDokumenteHochladenSummaryComponent } from './bescheid-wizard-container/bescheid-wizard/dokumente-hochladen/summary/bescheid-wizard-dokumente-hochladen-summary.component';
+import { BescheidWizardCreateDocumentButtonContainerComponent } from './bescheid-wizard-container/bescheid-wizard/create-document-button-container/bescheid-wizard-create-document-button-container.component';
+import { BescheidWizardCreateDocumentButtonComponent } from './bescheid-wizard-container/bescheid-wizard/create-document-button-container/create-document-button/bescheid-wizard-create-document-button.component';
+import { BescheidWizardDocumentFileContainerComponent } from './bescheid-wizard-container/bescheid-wizard/document-file-container/bescheid-wizard-document-file-container.component';
+import { BescheidWizardDocumentFileComponent } from './bescheid-wizard-container/bescheid-wizard/document-file-container/document-file/bescheid-wizard-document-file.component';
+import { BescheidWizardDokumenteHochladenContainerComponent } from './bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/bescheid-wizard-dokumente-hochladen-container.component';
+import { BescheidWizardDokumenteHochladenFormComponent } from './bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component';
+import { BescheidWizardDokumenteHochladenSummaryComponent } from './bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component';
+import { StepContentLayoutComponent } from './bescheid-wizard-container/bescheid-wizard/step-content-layout/step-content-layout.component';
 import { BescheidWizardStepTitleComponent } from './bescheid-wizard-container/bescheid-wizard/step-title/bescheid-wizard-step-title.component';
 import { BescheidWizardStepperComponent } from './bescheid-wizard-container/bescheid-wizard/stepper/bescheid-wizard-stepper.component';
 import { BescheidWizardStepComponent } from './bescheid-wizard-container/bescheid-wizard/stepper/step/bescheid-wizard-step.component';
 import { BescheidWizardSummaryComponent } from './bescheid-wizard-container/bescheid-wizard/summary/bescheid-wizard-summary.component';
+import { BescheidWizardUploadAttachmentButtonContainerComponent } from './bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/bescheid-wizard-upload-attachment-button-container.component';
+import { BescheidWizardUploadAttachmentButtonComponent } from './bescheid-wizard-container/bescheid-wizard/upload-attachment-button-container/upload-attachment-button/bescheid-wizard-upload-attachment-button.component';
+import { BescheidWizardUploadDocumentButtonContainerComponent } from './bescheid-wizard-container/bescheid-wizard/upload-document-button-container/bescheid-wizard-upload-document-button-container.component';
+import { BescheidWizardUploadDocumentButtonComponent } from './bescheid-wizard-container/bescheid-wizard/upload-document-button-container/upload-document-button/bescheid-wizard-upload-document-button.component';
 import { BescheidWizardWeiterButtonComponent } from './bescheid-wizard-container/bescheid-wizard/weiter-button/bescheid-wizard-weiter-button.component';
 
 @NgModule({
@@ -67,8 +111,6 @@ import { BescheidWizardWeiterButtonComponent } from './bescheid-wizard-container
     CommonModule,
     BescheidSharedModule,
     BinaryFileModule,
-    TechSharedModule,
-    UiModule,
     CommandSharedModule,
     BescheidStatusTextComponent,
     BescheidWrapperComponent,
@@ -77,6 +119,31 @@ import { BescheidWizardWeiterButtonComponent } from './bescheid-wizard-container
     ButtonWithSpinnerComponent,
     RadioButtonCardComponent,
     ButtonComponent,
+    FormatFullDatePipe,
+    HasLinkPipe,
+    GetUrlPipe,
+    ToEmbeddedResourcesPipe,
+    SpinnerComponent,
+    ExpansionPanelComponent,
+    AttachmentWrapperComponent,
+    MatIcon,
+    DateEditorComponent,
+    OzgcloudStrokedButtonWithSpinnerComponent,
+    ReactiveFormsModule,
+    ButtonCardComponent,
+    BescheidGenerateIconComponent,
+    SingleFileUploadEditorComponent,
+    BescheidUploadIconComponent,
+    SpinnerIconComponent,
+    AttachmentComponent,
+    AttachmentWrapperComponent,
+    FileUploadEditorComponent,
+    SendIconComponent,
+    SaveIconComponent,
+    TextEditorComponent,
+    TextareaEditorComponent,
+    ConvertForDataTestPipe,
+    ConvertProblemDetailToErrorMessagesPipe,
   ],
   declarations: [
     BescheidInVorgangContainerComponent,
@@ -94,14 +161,31 @@ import { BescheidWizardWeiterButtonComponent } from './bescheid-wizard-container
     BescheidWizardSummaryComponent,
     BescheidWizardWeiterButtonComponent,
     BescheidWizardCancelDialogContainerComponent,
-    BescheidWizardAntragBescheidenComponent,
+    BescheidWizardAntragBescheidenContainerComponent,
     BescheidWizardAntragBescheidenFormComponent,
     BescheidWizardAntragBescheidenSummaryComponent,
-    BescheidWizardDokumenteHochladenComponent,
+    BescheidWizardDokumenteHochladenContainerComponent,
     BescheidWizardDokumenteHochladenFormComponent,
     BescheidWizardDokumenteHochladenSummaryComponent,
     BescheidWizardAbschliessenButtonComponent,
     BescheidWizardAbschliessenDialogContainerComponent,
+    BescheidWizardCreateDocumentButtonContainerComponent,
+    BescheidWizardCreateDocumentButtonComponent,
+    BescheidWizardUploadDocumentButtonComponent,
+    BescheidWizardUploadDocumentButtonContainerComponent,
+    BescheidWizardDocumentFileComponent,
+    BescheidWizardDocumentFileContainerComponent,
+    BescheidWizardDocumentFileComponent,
+    BescheidWizardUploadAttachmentButtonContainerComponent,
+    BescheidWizardUploadAttachmentButtonComponent,
+    BescheidWizardAttachmentFilesContainerComponent,
+    BescheidWizardAttachmentFilesComponent,
+    BescheidWizardBescheidVersendenContainerComponent,
+    BescheidWizardBescheidVersendenFormComponent,
+    BescheidWizardBescheidVersendenSummaryComponent,
+    BescheidWizardBescheidVersendenSendenComponent,
+    BescheidWizardBescheidVersendenSpeichernComponent,
+    StepContentLayoutComponent,
   ],
   exports: [
     BescheidInVorgangContainerComponent,
diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts
index 98650f90ed0824bf3764373e3e07e9e8951b0599..27377b3854e4b1e87900b83f4d957a7751641b1b 100644
--- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts
+++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts
@@ -28,26 +28,22 @@ import {
   HttpErrorHandler,
   HttpHeader,
   ListResource,
-  TechSharedModule,
 } from '@alfa-client/tech-shared';
 import { mock, mockClass, useFromMock } from '@alfa-client/test-utils';
 import { HttpClient, HttpHeaders } from '@angular/common/http';
 import { faker } from '@faker-js/faker';
 import { Resource, ResourceFactory, ResourceUri, getUrl } from '@ngxp/rest';
 import { cold, hot } from 'jest-marbles';
+import { InjectorService } from 'libs/tech-shared/src/lib/injector/injector.service';
 import { DummyLinkRel } from 'libs/tech-shared/test/dummy';
 import { createDummyListResource, createDummyResource } from 'libs/tech-shared/test/resource';
 import { Observable, of } from 'rxjs';
-import {
-  createBinaryFileResource,
-  createBlob,
-  createGetRequestOptions,
-} from '../../test/binary-file';
+import { createBinaryFileResource, createBlob, createGetRequestOptions } from '../../test/binary-file';
 import { BinaryFileLinkRel } from './binary-file.linkrel';
 import { BinaryFileResource } from './binary-file.model';
 import { BinaryFileRepository } from './binary-file.repository';
 
-import * as HttpUtil from '../../../tech-shared/src/lib/http.util';
+import * as HttpUtil from 'libs/tech-shared/src/lib/http.util';
 
 describe('BinaryFileRepository', () => {
   let repository: BinaryFileRepository;
@@ -66,7 +62,7 @@ describe('BinaryFileRepository', () => {
   });
 
   function mockInterceptor(): void {
-    mockClass(TechSharedModule).injector = <any>{ get: () => useFromMock(mock(HttpErrorHandler)) };
+    mockClass(InjectorService).injector = <any>{ get: () => useFromMock(mock(HttpErrorHandler)) };
   }
 
   it('should be created', () => {
@@ -102,9 +98,7 @@ describe('BinaryFileRepository', () => {
 
   describe('download', () => {
     const blob = {};
-    const binaryFileResource: BinaryFileResource = createBinaryFileResource([
-      BinaryFileLinkRel.DOWNLOAD,
-    ]);
+    const binaryFileResource: BinaryFileResource = createBinaryFileResource([BinaryFileLinkRel.DOWNLOAD]);
 
     beforeEach(() => {
       httpClient.get.mockReturnValue(hot('a', { a: blob }));
@@ -117,10 +111,7 @@ describe('BinaryFileRepository', () => {
 
       repository.download(binaryFileResource);
 
-      expect(httpClient.get).toHaveBeenCalledWith(
-        getUrl(binaryFileResource, BinaryFileLinkRel.DOWNLOAD),
-        requestOptions,
-      );
+      expect(httpClient.get).toHaveBeenCalledWith(getUrl(binaryFileResource, BinaryFileLinkRel.DOWNLOAD), requestOptions);
     });
 
     it('should return value', () => {
@@ -189,10 +180,7 @@ describe('BinaryFileRepository', () => {
     });
 
     function getExpectedRequestOptions(): HttpHeaders {
-      return new HttpHeaders().set(HttpHeader.ACCEPT, [
-        ContentType.APPLICATION_PDF,
-        ContentType.APPLICATION_JSON,
-      ]);
+      return new HttpHeaders().set(HttpHeader.ACCEPT, [ContentType.APPLICATION_PDF, ContentType.APPLICATION_JSON]);
     }
   });
 
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file.module.ts b/alfa-client/libs/binary-file/src/lib/binary-file.module.ts
index ee4cacdb5f276222620c9a4297808dc6e836c007..9327cbb0be7ef4527eff2aaf36b8f4ffac6e0cb3 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file.module.ts
+++ b/alfa-client/libs/binary-file/src/lib/binary-file.module.ts
@@ -21,10 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import { ConvertForDataTestPipe, FileSizePipe, HasLinkPipe, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared';
+import { IconButtonWithSpinnerComponent, SpinnerComponent } from '@alfa-client/ui';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
+import { MatIcon } from '@angular/material/icon';
+import { MatTooltip } from '@angular/material/tooltip';
 import { DownloadButtonComponent } from '@ods/component';
 import {
   AttachmentComponent,
@@ -34,6 +36,8 @@ import {
   SpinnerIconComponent,
   TooltipDirective,
 } from '@ods/system';
+import { FileSizePlainPipe } from '../../../tech-shared/src/lib/pipe/file-size-plain.pipe';
+import { FileUploadEditorComponent } from '../../../ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component';
 import { BinaryFileAttachmentContainerComponent } from './binary-file-attachment-container/binary-file-attachment-container.component';
 import { BinaryFileContainerComponent } from './binary-file-container/binary-file-container.component';
 import { BinaryFileComponent } from './binary-file-container/binary-file/binary-file.component';
@@ -49,14 +53,22 @@ import { VerticalBinaryFileListComponent } from './vertical-binary-file-list/ver
 @NgModule({
   imports: [
     CommonModule,
-    UiModule,
-    TechSharedModule,
     AttachmentComponent,
     AttachmentHeaderComponent,
     AttachmentWrapperComponent,
     SpinnerIconComponent,
     CloseIconComponent,
     DownloadButtonComponent,
+    FileUploadEditorComponent,
+    HasLinkPipe,
+    MatTooltip,
+    MatIcon,
+    SpinnerComponent,
+    IconButtonWithSpinnerComponent,
+    FileSizePipe,
+    ConvertForDataTestPipe,
+    ToEmbeddedResourcesPipe,
+    FileSizePlainPipe,
     TooltipDirective,
   ],
   declarations: [
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.html b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.html
index 83e0a83f944e796fb61fda44e53b40d6637dda78..96927c6b043705cd333e9783282e98ceeca9bc79 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.html
+++ b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.html
@@ -37,7 +37,7 @@
     <button
       *ngIf="deletable"
       class="flex size-10 items-center justify-center rounded-md hover:border hover:border-grayborder hover:bg-background-50"
-      (click)="deleteFile()"
+      (click)="deleteFile($event)"
       title="Anhang löschen"
       aria-label="Anhang löschen Button"
     >
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.spec.ts
index 148cf03abfaa5832df7eed67cdb819b925793c33..7f114ea64baf234b8c76d4a549464d87c21b3801 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.spec.ts
+++ b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.spec.ts
@@ -89,10 +89,11 @@ describe('BinaryFile2Component', () => {
 
   describe('click on delete button', () => {
     it('should emit delete', () => {
+      const clickEvent = new Event('');
       jest.spyOn(component.startDelete, 'emit');
       component.file = createBinaryFileResource();
 
-      component.deleteFile();
+      component.deleteFile(clickEvent);
 
       expect(component.startDelete.emit).toHaveBeenCalledWith(component.file);
     });
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.ts b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.ts
index bcf41375a0ef242662a7261d1f7d6cea78bfddb6..6b0e9946b551196a9968ec0d3f590a876e5c1fb5 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.ts
+++ b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.ts
@@ -22,11 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { ApiDownloadToken } from '@alfa-client/api-root-shared';
-import {
-  BinaryFileIcon,
-  BinaryFileLinkRel,
-  BinaryFileResource,
-} from '@alfa-client/binary-file-shared';
+import { BinaryFileIcon, BinaryFileLinkRel, BinaryFileResource } from '@alfa-client/binary-file-shared';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
 import { HttpParams } from '@angular/common/http';
 import { Component, EventEmitter, Input, Output } from '@angular/core';
@@ -45,10 +41,8 @@ export class BinaryFile2Component {
 
   readonly fileLinkRel = BinaryFileLinkRel;
 
-  @Output() public startDownload: EventEmitter<BinaryFileResource> =
-    new EventEmitter<BinaryFileResource>();
-  @Output() public startDelete: EventEmitter<BinaryFileResource> =
-    new EventEmitter<BinaryFileResource>();
+  @Output() public startDownload: EventEmitter<BinaryFileResource> = new EventEmitter<BinaryFileResource>();
+  @Output() public startDelete: EventEmitter<BinaryFileResource> = new EventEmitter<BinaryFileResource>();
   @Output() public getDownloadToken: EventEmitter<void> = new EventEmitter<void>();
 
   get isDisabled(): boolean {
@@ -71,7 +65,8 @@ export class BinaryFile2Component {
     this.startDownload.emit(this.file);
   }
 
-  deleteFile(): void {
+  deleteFile(e: Event): void {
+    e.stopPropagation();
     this.startDelete.emit(this.file);
   }
 
diff --git a/alfa-client/libs/collaboration/src/lib/collaboration-in-vorgang-container/collaboration-request-form/collaboration.request.formservice.spec.ts b/alfa-client/libs/collaboration/src/lib/collaboration-in-vorgang-container/collaboration-request-form/collaboration.request.formservice.spec.ts
index 9af26540fdf4031d434bcb3d4000e2a3f56d3c96..d5726c77529ec251188d2323565ad95742986a58 100644
--- a/alfa-client/libs/collaboration/src/lib/collaboration-in-vorgang-container/collaboration-request-form/collaboration.request.formservice.spec.ts
+++ b/alfa-client/libs/collaboration/src/lib/collaboration-in-vorgang-container/collaboration-request-form/collaboration.request.formservice.spec.ts
@@ -22,11 +22,11 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { CollaborationListResource } from '@alfa-client/collaboration-shared';
-import { SnackBarService } from '@alfa-client/ui';
-import { TestBed } from '@angular/core/testing';
 import { CommandLinkRel, CommandResource } from '@alfa-client/command-shared';
 import { StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared';
-import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
+import { Mock, mock } from '@alfa-client/test-utils';
+import { SnackBarService } from '@alfa-client/ui';
+import { TestBed } from '@angular/core/testing';
 import { UntypedFormBuilder } from '@angular/forms';
 import { CollaborationService } from 'libs/collaboration-shared/src/lib/collaboration.service';
 import { createCollaborationListResource } from 'libs/collaboration-shared/test/collaboration';
@@ -57,7 +57,6 @@ describe('CollaborationRequestFormService', () => {
     });
 
     formService = TestBed.inject(CollaborationRequestFormService);
-    TestBed.inject(CollaborationRequestFormService);
   });
 
   it('should create', () => {
diff --git a/alfa-client/libs/collaboration/src/lib/collaboration.module.ts b/alfa-client/libs/collaboration/src/lib/collaboration.module.ts
index a99b23f737e31e8e6024ac8aa471ea53024d61b2..62308b9704c1157391003ae56408374b6ca23cb7 100644
--- a/alfa-client/libs/collaboration/src/lib/collaboration.module.ts
+++ b/alfa-client/libs/collaboration/src/lib/collaboration.module.ts
@@ -22,8 +22,8 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { CollaborationSharedModule } from '@alfa-client/collaboration-shared';
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import { HasLinkPipe } from '@alfa-client/tech-shared';
+import { SpinnerComponent } from '@alfa-client/ui';
 import { ZustaendigeStelleModule } from '@alfa-client/zustaendige-stelle';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
@@ -63,7 +63,6 @@ import { CollaborationRequestFormComponent } from './collaboration-in-vorgang-co
     TextareaEditorComponent,
     FormsModule,
     ReactiveFormsModule,
-    TechSharedModule,
     ButtonWithSpinnerComponent,
     ZustaendigeStelleModule,
     OfficeIconComponent,
@@ -71,7 +70,8 @@ import { CollaborationRequestFormComponent } from './collaboration-in-vorgang-co
     PublicAdministrationIconComponent,
     OrganisationsEinheitListItemContainerComponent,
     ExterneFachstelleListItemContainerComponent,
-    UiModule,
+    HasLinkPipe,
+    SpinnerComponent,
   ],
   declarations: [
     CollaborationInVorgangContainerComponent,
diff --git a/alfa-client/libs/command-shared/src/lib/command-resource.service.spec.ts b/alfa-client/libs/command-shared/src/lib/command-resource.service.spec.ts
index 200b8572a2ed3faccb5d14a2346e085ca8262024..c7640cb221008d78f73dd470ae9d3f10287d4bcb 100644
--- a/alfa-client/libs/command-shared/src/lib/command-resource.service.spec.ts
+++ b/alfa-client/libs/command-shared/src/lib/command-resource.service.spec.ts
@@ -74,13 +74,13 @@ describe('CommandResourceService', () => {
 
   describe('doSave', () => {
     it('should throw error', () => {
-      expect(() => service.doSave(configResource, {})).toThrowError('Method not implemented.');
+      expect(() => service.doSave(configResource, {})).toThrow('Method not implemented.');
     });
   });
 
   describe('doPatch', () => {
     it('should throw error', () => {
-      expect(() => service.doPatch(configResource, {})).toThrowError('Method not implemented.');
+      expect(() => service.doPatch(configResource, {})).toThrow('Method not implemented.');
     });
   });
 
diff --git a/alfa-client/libs/command-shared/src/lib/command.rxjs.operator.spec.ts b/alfa-client/libs/command-shared/src/lib/command.rxjs.operator.spec.ts
index 33396fafe3df1fc0f053eb653f7884bf0e5d8788..f4ae75529acf2ebe89875ff3a99f1cc73bc6046e 100644
--- a/alfa-client/libs/command-shared/src/lib/command.rxjs.operator.spec.ts
+++ b/alfa-client/libs/command-shared/src/lib/command.rxjs.operator.spec.ts
@@ -21,12 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { StateResource, createStateResource } from '@alfa-client/tech-shared';
-import { createCommandResource } from 'libs/command-shared/test/command';
+import { createErrorStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared';
+import { createCommandResource, createSuccessfullyDoneCommandStateResource } from 'libs/command-shared/test/command';
 import { Observable, of } from 'rxjs';
 import { CommandResource } from './command.model';
-import { tapOnCommandSuccessfullyDone } from './command.rxjs.operator';
+import { tapOnCommandSuccessfullyDone, tapOnFailedCommand } from './command.rxjs.operator';
 
+import { createProblemDetail } from '../../../tech-shared/test/error';
 import * as CommandUtil from './command.util';
 
 describe('Command rxjs operator', () => {
@@ -54,4 +55,28 @@ describe('Command rxjs operator', () => {
       });
     });
   });
+
+  describe('tapOnFailedCommand', () => {
+    it('should call the execute the runnable if command has failed', (done) => {
+      const command = createErrorStateResource(createProblemDetail());
+      const commandStateResource$: Observable<StateResource<CommandResource>> = of(command);
+      const runnable = jest.fn();
+
+      commandStateResource$.pipe(tapOnFailedCommand(runnable)).subscribe(() => {
+        expect(runnable).toHaveBeenCalledWith(command);
+        done();
+      });
+    });
+
+    it('should NOT execute the runnable if command was successful', (done) => {
+      const command = createSuccessfullyDoneCommandStateResource();
+      const commandStateResource$: Observable<StateResource<CommandResource>> = of(command);
+      const runnable = jest.fn();
+
+      commandStateResource$.pipe(tapOnFailedCommand(runnable)).subscribe(() => {
+        expect(runnable).not.toHaveBeenCalled();
+        done();
+      });
+    });
+  });
 });
diff --git a/alfa-client/libs/command-shared/src/lib/command.rxjs.operator.ts b/alfa-client/libs/command-shared/src/lib/command.rxjs.operator.ts
index 3acbebff9699ea2dbc5695212070f63e9b07a96b..9e0fddd601cc937185b27a525fab2d710bebe16f 100644
--- a/alfa-client/libs/command-shared/src/lib/command.rxjs.operator.ts
+++ b/alfa-client/libs/command-shared/src/lib/command.rxjs.operator.ts
@@ -21,19 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { StateResource } from '@alfa-client/tech-shared';
+import { hasStateResourceError, StateResource } from '@alfa-client/tech-shared';
 import { Observable, of, switchMap, tap } from 'rxjs';
 import { CommandResource } from './command.model';
 import { isSuccessfulDone } from './command.util';
 
 export function tapOnCommandSuccessfullyDone(
   runnable: (commandStateResource: StateResource<CommandResource>) => void,
-): (
-  source: Observable<StateResource<CommandResource>>,
-) => Observable<StateResource<CommandResource>> {
-  return (
-    source: Observable<StateResource<CommandResource>>,
-  ): Observable<StateResource<CommandResource>> => {
+): (source: Observable<StateResource<CommandResource>>) => Observable<StateResource<CommandResource>> {
+  return (source: Observable<StateResource<CommandResource>>): Observable<StateResource<CommandResource>> => {
     return source.pipe(
       tap((commandStateResource: StateResource<CommandResource>) => {
         if (isSuccessfulDone(commandStateResource.resource)) runnable(commandStateResource);
@@ -42,14 +38,22 @@ export function tapOnCommandSuccessfullyDone(
   };
 }
 
+export function tapOnFailedCommand(
+  runnable: (commandStateResource: StateResource<CommandResource>) => void,
+): (source: Observable<StateResource<CommandResource>>) => Observable<StateResource<CommandResource>> {
+  return (source: Observable<StateResource<CommandResource>>): Observable<StateResource<CommandResource>> => {
+    return source.pipe(
+      tap((commandStateResource: StateResource<CommandResource>) => {
+        if (hasStateResourceError(commandStateResource)) runnable(commandStateResource);
+      }),
+    );
+  };
+}
+
 export function switchMapCommandSuccessfullyDone(
   runnable: (command: StateResource<CommandResource>) => Observable<StateResource<CommandResource>>,
-): (
-  source: Observable<StateResource<CommandResource>>,
-) => Observable<StateResource<CommandResource>> {
-  return (
-    source: Observable<StateResource<CommandResource>>,
-  ): Observable<StateResource<CommandResource>> => {
+): (source: Observable<StateResource<CommandResource>>) => Observable<StateResource<CommandResource>> {
+  return (source: Observable<StateResource<CommandResource>>): Observable<StateResource<CommandResource>> => {
     return source.pipe(
       switchMap((commandStateResource: StateResource<CommandResource>) => {
         if (isSuccessfulDone(commandStateResource.resource)) {
diff --git a/alfa-client/libs/common/src/lib/build-info/build-info.component.spec.ts b/alfa-client/libs/common/src/lib/build-info/build-info.component.spec.ts
index 0f8d5ff01398c359e4eefc7c4b635e454e1ec694..a47f70b4bf63016ac31f407352ff3973d64bca1a 100644
--- a/alfa-client/libs/common/src/lib/build-info/build-info.component.spec.ts
+++ b/alfa-client/libs/common/src/lib/build-info/build-info.component.spec.ts
@@ -47,8 +47,7 @@ describe('BuildInfoComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [BuildInfoComponent],
-      declarations: [FormatDateWithTimePipe],
+      imports: [BuildInfoComponent, FormatDateWithTimePipe],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.spec.ts b/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.spec.ts
index de1242c608e560f453c76ee160ddaf89dc3b9b0c..7643fbc6e08d29e0aadf7792f87d1f40348b709b 100644
--- a/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.spec.ts
+++ b/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.spec.ts
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { createStateResource, StateResource } from '@alfa-client/tech-shared';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { createCommandErrorStateResource, createCommandResource } from 'libs/command-shared/test/command';
+import { createCommandErrorStateResource } from 'libs/command-shared/test/command';
 import { createApiError } from 'libs/tech-shared/test/error';
+import { createDummyResource } from '../../../../tech-shared/test/resource';
 import { ButtonWithSpinnerComponent } from './button-with-spinner.component';
 
-import * as ResourceUtils from 'libs/tech-shared/src/lib/resource/resource.util';
-
 describe('ButtonWithSpinnerComponent', () => {
   let component: ButtonWithSpinnerComponent;
   let fixture: ComponentFixture<ButtonWithSpinnerComponent>;
@@ -46,39 +46,25 @@ describe('ButtonWithSpinnerComponent', () => {
     expect(component).toBeTruthy();
   });
 
-  describe('onInit', () => {
-    it('should call getStateResource', () => {
-      component.getStateResource = jest.fn();
+  describe('set stateResource', () => {
+    it('should set stateResource', () => {
+      const stateResource: StateResource<unknown> = createStateResource(createDummyResource());
 
-      component.ngOnInit();
+      component.stateResource = stateResource;
 
-      expect(component.getStateResource).toHaveBeenCalled();
+      expect(component._stateResource).toBe(stateResource);
     });
-  });
-
-  describe('getStateResource', () => {
-    it('should return stateResource', () => {
-      component.stateResource = ResourceUtils.createStateResource(createCommandResource());
-
-      component.getStateResource();
 
-      const valid: boolean = ResourceUtils.isValidStateResource(component.stateResource);
-      expect(valid).toBeTruthy();
-    });
-
-    it('should return empty stateResource', () => {
-      const spy = jest.spyOn(ResourceUtils, 'createEmptyStateResource');
+    it('should not set stateResource', () => {
       component.stateResource = null;
 
-      component.getStateResource();
-
-      expect(spy).toHaveBeenCalled();
+      expect(component._stateResource).not.toBe(null);
     });
   });
 
   describe('isLoading', () => {
     it('should return false', () => {
-      component.stateResource.loading = component.stateResource.reload = false;
+      component._stateResource.loading = component._stateResource.reload = false;
 
       const isLoading: boolean = component.isLoading;
 
@@ -86,8 +72,8 @@ describe('ButtonWithSpinnerComponent', () => {
     });
 
     it('should return true if stateResource is loading', () => {
-      component.stateResource.loading = true;
-      component.stateResource.reload = false;
+      component._stateResource.loading = true;
+      component._stateResource.reload = false;
 
       const isLoading: boolean = component.isLoading;
 
@@ -95,8 +81,8 @@ describe('ButtonWithSpinnerComponent', () => {
     });
 
     it('should return true if stateResource is reloading', () => {
-      component.stateResource.loading = false;
-      component.stateResource.reload = true;
+      component._stateResource.loading = false;
+      component._stateResource.reload = true;
 
       const isLoading: boolean = component.isLoading;
 
@@ -106,7 +92,7 @@ describe('ButtonWithSpinnerComponent', () => {
 
   describe('isError', () => {
     it('should return false if error is not set', () => {
-      component.stateResource.error = null;
+      component._stateResource.error = null;
 
       const isError: boolean = component.isError;
 
@@ -114,7 +100,7 @@ describe('ButtonWithSpinnerComponent', () => {
     });
 
     it('should return false if error is set and error is ApiError', () => {
-      component.stateResource.error = createApiError();
+      component._stateResource.error = createApiError();
 
       const isError: boolean = component.isError;
 
@@ -122,7 +108,7 @@ describe('ButtonWithSpinnerComponent', () => {
     });
 
     it('should return true if error is set and error is not ApiError', () => {
-      component.stateResource = createCommandErrorStateResource();
+      component._stateResource = createCommandErrorStateResource();
 
       const isError: boolean = component.isError;
 
diff --git a/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.ts b/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.ts
index f76f1f907cecaa625c3e1c6dc950458e3f4aa640..a12b0a8ad74b49d34ec172ae36682d7d0ce01104 100644
--- a/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.ts
+++ b/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.ts
@@ -24,7 +24,7 @@
 import { CommandResource, hasCommandError } from '@alfa-client/command-shared';
 import { StateResource, createEmptyStateResource, isLoaded } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
 import { ButtonComponent, ErrorMessageComponent, buttonVariants } from '@ods/system';
 import { VariantProps } from 'class-variance-authority';
 import { isNil } from 'lodash-es';
@@ -49,28 +49,24 @@ type ButtonVariants = VariantProps<typeof buttonVariants>;
       <ng-content icon select="[icon]" />
     </ods-button>`,
 })
-export class ButtonWithSpinnerComponent implements OnInit {
+export class ButtonWithSpinnerComponent {
+  @Input() set stateResource(value: StateResource<unknown>) {
+    if (!isNil(value)) this._stateResource = value;
+  }
   @Input() text: string = '';
   @Input() dataTestId: string = '';
-  @Input() stateResource: StateResource<unknown>;
   @Input() variant: ButtonVariants['variant'] = 'primary';
   @Input() size: ButtonVariants['size'] = 'medium';
 
   @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
 
-  ngOnInit(): void {
-    this.stateResource = this.getStateResource();
-  }
-
-  getStateResource(): StateResource<unknown> {
-    return isNil(this.stateResource) ? createEmptyStateResource() : this.stateResource;
-  }
+  _stateResource: StateResource<unknown> = createEmptyStateResource();
 
   get isLoading(): boolean {
-    return this.stateResource.loading || this.stateResource.reload;
+    return this._stateResource.loading || this._stateResource.reload;
   }
 
   get isError(): boolean {
-    return isLoaded(this.stateResource) && hasCommandError(<CommandResource>this.stateResource.resource);
+    return isLoaded(this._stateResource) && hasCommandError(<CommandResource>this._stateResource.resource);
   }
 }
diff --git a/alfa-client/libs/design-component/src/lib/form/checkbox-editor/checkbox-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/checkbox-editor/checkbox-editor.component.ts
index 121f52bb8d5778c67a38097c5766632adbdb3199..dfab859671455c3354bd14297d069ffde5474cde 100644
--- a/alfa-client/libs/design-component/src/lib/form/checkbox-editor/checkbox-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/checkbox-editor/checkbox-editor.component.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { Component, Input } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
 import { CheckboxComponent } from '@ods/system';
@@ -31,7 +31,7 @@ import { ValidationErrorComponent } from '../validation-error/validation-error.c
 @Component({
   selector: 'ods-checkbox-editor',
   standalone: true,
-  imports: [CheckboxComponent, ValidationErrorComponent, TechSharedModule, ReactiveFormsModule],
+  imports: [CheckboxComponent, ValidationErrorComponent, ReactiveFormsModule, ConvertForDataTestPipe],
   templateUrl: './checkbox-editor.component.html',
 })
 export class CheckboxEditorComponent extends FormControlEditorAbstractComponent {
diff --git a/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.html b/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.html
index 4a9fe0c97298f30da5307f19c7ca79cbeca42f73..ff08ce18e4ad8cc6037b84833bd941f375a6da0f 100644
--- a/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.html
+++ b/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.html
@@ -34,7 +34,7 @@
   [accept]="accept"
   [attr.data-test-id]="(label | convertForDataTest) + '-file-upload-button'"
   [isLoading]="uploadInProgress.loading"
-  class="relative w-72"
+  class="relative w-full max-w-72"
 >
   <ods-spinner-icon spinner size="medium" />
   <ods-attachment-icon icon size="medium" />
diff --git a/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.spec.ts b/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.spec.ts
index e23d68f4fd3158c668a388aad404022810f1202f..9bb05063e492ff44967a3e62cd4d23bfad2a835e 100644
--- a/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.spec.ts
+++ b/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.spec.ts
@@ -21,15 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule, createEmptyStateResource } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe, createEmptyStateResource } from '@alfa-client/tech-shared';
 import { getElementFromFixture } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import {
-  AbstractControl,
-  FormGroupDirective,
-  ReactiveFormsModule,
-  UntypedFormBuilder,
-} from '@angular/forms';
+import { AbstractControl, FormGroupDirective, ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
 import { FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
@@ -48,12 +43,8 @@ describe('FileUploadEditorComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [
-        FileUploadEditorComponent,
-        MockComponent(SpinnerIconComponent),
-        MockComponent(FileUploadButtonComponent),
-      ],
-      imports: [ReactiveFormsModule, TechSharedModule],
+      declarations: [FileUploadEditorComponent, MockComponent(SpinnerIconComponent), MockComponent(FileUploadButtonComponent)],
+      imports: [ReactiveFormsModule, ConvertForDataTestPipe],
       providers: [
         {
           provide: FormGroupDirective,
diff --git a/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.ts
index 0a9f5a53efe396aa9345b39f56d1b2f6ca1e1b63..2a412d827f7501dc914cf05bad19dbe00b85ebfe 100644
--- a/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.ts
@@ -21,22 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { StateResource, TechSharedModule } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe, StateResource } from '@alfa-client/tech-shared';
 import { NgForOf } from '@angular/common';
 import { Component, EventEmitter, HostListener, Input, OnInit, Output } from '@angular/core';
-import {
-  ControlContainer,
-  FormGroupDirective,
-  ReactiveFormsModule,
-  UntypedFormArray,
-  UntypedFormControl,
-} from '@angular/forms';
+import { ControlContainer, FormGroupDirective, ReactiveFormsModule, UntypedFormArray, UntypedFormControl } from '@angular/forms';
 import { Resource } from '@ngxp/rest';
-import {
-  AttachmentIconComponent,
-  FileUploadButtonComponent,
-  SpinnerIconComponent,
-} from '@ods/system';
+import { AttachmentIconComponent, FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system';
 import { uniqueId } from 'lodash-es';
 import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
 
@@ -51,13 +41,10 @@ import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstra
     SpinnerIconComponent,
     ReactiveFormsModule,
     NgForOf,
-    TechSharedModule,
+    ConvertForDataTestPipe,
   ],
 })
-export class FileUploadEditorComponent
-  extends FormControlEditorAbstractComponent
-  implements OnInit
-{
+export class FileUploadEditorComponent extends FormControlEditorAbstractComponent implements OnInit {
   @Input() label: string = '';
   @Input() parentFormArrayName: string;
   @Input() accept: string = '*/*';
@@ -88,9 +75,7 @@ export class FileUploadEditorComponent
 
   buildFormArray(fileLinkList: string[]): void {
     this.fileLinkControls.clear();
-    fileLinkList.forEach((link: string) =>
-      this.fileLinkControls.push(new UntypedFormControl(link)),
-    );
+    fileLinkList.forEach((link: string) => this.fileLinkControls.push(new UntypedFormControl(link)));
   }
 
   upload(file: File): void {
diff --git a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.html b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.html
index ab4172edc10957129320faf3a6533cfe9d1c77ce..837b069ad149e2e7e2eb08305e54e8ab74df16f5 100644
--- a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.html
+++ b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.html
@@ -24,7 +24,7 @@
 
 -->
 <ods-file-upload-button
-  class="w-72"
+  class="w-full max-w-72"
   [id]="uploadFileId"
   [isLoading]="uploadInProgress"
   [accept]="accept"
diff --git a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts
index 4ae84174d1a25498142f7c5f0b8584172b5aff40..a62e384fb3c9ff9c15b453cc9927438d1e1790c4 100644
--- a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule, isNotNil } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe, isNotNil } from '@alfa-client/tech-shared';
 import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
 import { FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system';
@@ -32,7 +32,7 @@ import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstra
   selector: 'ods-single-file-upload-editor',
   templateUrl: './single-file-upload-editor.component.html',
   standalone: true,
-  imports: [FileUploadButtonComponent, SpinnerIconComponent, ReactiveFormsModule, TechSharedModule],
+  imports: [FileUploadButtonComponent, SpinnerIconComponent, ReactiveFormsModule, ConvertForDataTestPipe],
 })
 export class SingleFileUploadEditorComponent extends FormControlEditorAbstractComponent {
   @Input() label: string = '';
diff --git a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts
index 88059147b43c73716251cd6999184bba085a3479..cfdd66512de073b74f0dbfd2bbed633573f9651f 100644
--- a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
@@ -32,13 +32,7 @@ import { ValidationErrorComponent } from '../validation-error/validation-error.c
 @Component({
   selector: 'ods-text-editor',
   standalone: true,
-  imports: [
-    CommonModule,
-    ReactiveFormsModule,
-    TechSharedModule,
-    TextInputComponent,
-    ValidationErrorComponent,
-  ],
+  imports: [CommonModule, ReactiveFormsModule, TextInputComponent, ValidationErrorComponent, ConvertForDataTestPipe],
   templateUrl: './text-editor.component.html',
 })
 export class TextEditorComponent extends FormControlEditorAbstractComponent {
diff --git a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts
index be0fc9b4f33d4ca6ddceb6912c8dc82c769e3ac5..c7032ef03b58627369f4857d0b2bda4546d092b5 100644
--- a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
@@ -32,13 +32,7 @@ import { ValidationErrorComponent } from '../validation-error/validation-error.c
 @Component({
   selector: 'ods-textarea-editor',
   standalone: true,
-  imports: [
-    CommonModule,
-    ReactiveFormsModule,
-    TechSharedModule,
-    TextareaComponent,
-    ValidationErrorComponent,
-  ],
+  imports: [CommonModule, ReactiveFormsModule, TextareaComponent, ValidationErrorComponent, ConvertForDataTestPipe],
   templateUrl: './textarea-editor.component.html',
 })
 export class TextareaEditorComponent extends FormControlEditorAbstractComponent {
diff --git a/alfa-client/libs/design-component/src/lib/routing-button/routing-button.component.ts b/alfa-client/libs/design-component/src/lib/routing-button/routing-button.component.ts
index 2a25cd22e5df3e74e404a3fd986d737b29ab5a2c..98346f3903e1cff4b363c5f4f4dc49243ce84c7d 100644
--- a/alfa-client/libs/design-component/src/lib/routing-button/routing-button.component.ts
+++ b/alfa-client/libs/design-component/src/lib/routing-button/routing-button.component.ts
@@ -1,22 +1,26 @@
 import { CommonModule } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { RouterLink } from '@angular/router';
+import { ButtonVariants, buttonVariants } from '@ods/system';
 
 @Component({
   selector: 'ods-routing-button',
   standalone: true,
   imports: [CommonModule, RouterLink],
   host: { class: 'block' },
-  template: `<a
-    [routerLink]="'/' + linkPath"
-    [attr.data-test-id]="dataTestId"
-    class="block min-h-9 w-fit min-w-32 rounded bg-primary px-4 py-2 text-sm font-medium text-white shadow-sm outline-focus hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2"
-  >
-    {{ text }}
+  template: `<a [routerLink]="'/' + linkPath" [attr.data-test-id]="dataTestId" [ngClass]="buttonVariants({ size, variant })">
+    <ng-content select="[icon]" />
+    @if (text) {
+      <p class="flex-grow">{{ text }}</p>
+    }
   </a>`,
 })
 export class RoutingButtonComponent {
   @Input() linkPath: string;
   @Input() text: string;
   @Input() dataTestId: string;
+  @Input() variant: ButtonVariants['variant'];
+  @Input() size: ButtonVariants['size'];
+
+  readonly buttonVariants = buttonVariants;
 }
diff --git a/alfa-client/libs/design-system/run_helm_test.sh b/alfa-client/libs/design-system/run_helm_test.sh
old mode 100755
new mode 100644
diff --git a/alfa-client/libs/design-system/src/index.ts b/alfa-client/libs/design-system/src/index.ts
index 467032047c06e4ae9c4a6e3948cc13a704b8761d..e7ae662925633f6c656ce0c64ba919debf94b774 100644
--- a/alfa-client/libs/design-system/src/index.ts
+++ b/alfa-client/libs/design-system/src/index.ts
@@ -52,6 +52,7 @@ export * from './lib/icons/bescheid-upload-icon/bescheid-upload-icon.component';
 export * from './lib/icons/check-circle-icon/check-circle-icon.component';
 export * from './lib/icons/check-icon/check-icon.component';
 export * from './lib/icons/close-icon/close-icon.component';
+export * from './lib/icons/delete-icon/delete-icon.component';
 export * from './lib/icons/delete-vorgang-finally-icon/delete-vorgang-finally-icon.component';
 export * from './lib/icons/discard-vorgang-icon/discard-vorgang-icon.component';
 export * from './lib/icons/edit-icon/edit-icon.component';
diff --git a/alfa-client/libs/design-system/src/lib/button/button.component.ts b/alfa-client/libs/design-system/src/lib/button/button.component.ts
index 46b0308c205dff5a889142e76693dd27cffc30bb..15a9b7efdc261b462f3dade0f93b2a6902e36507 100644
--- a/alfa-client/libs/design-system/src/lib/button/button.component.ts
+++ b/alfa-client/libs/design-system/src/lib/button/button.component.ts
@@ -64,22 +64,24 @@ export const buttonVariants = cva(
       {
         variant: 'primary',
         destructive: true,
-        class: '[&]:hover:enabled:bg-destructive-primary-hover [&]:bg-destructive [&]:outline-destructive',
+        class:
+          '[&]:hover:enabled:bg-destructive-primary-hover [&]:bg-destructive [&]:outline-destructive [&]:focus-visible:bg-destructive-primary-hover',
       },
       {
         variant: 'outline',
         destructive: true,
-        class: '[&]:border-destructive [&]:text-destructive [&]:hover:enabled:bg-destructive-hover',
+        class:
+          '[&]:border-destructive [&]:text-destructive [&]:hover:enabled:bg-destructive-hover [&]:focus-visible:bg-destructive-hover',
       },
       {
         variant: 'ghost',
         destructive: true,
-        class: '[&]:text-destructive [&]:hover:enabled:bg-destructive-hover',
+        class: '[&]:text-destructive [&]:hover:enabled:bg-destructive-hover [&]:focus-visible:bg-destructive-hover',
       },
     ],
   },
 );
-type ButtonVariants = VariantProps<typeof buttonVariants>;
+export type ButtonVariants = VariantProps<typeof buttonVariants>;
 
 @Component({
   selector: 'ods-button',
diff --git a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.ts b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.ts
index 52b3e46d6ac1e69ce02472bec600580c6e7663af..045191b56a76618a85600a82757607f267b4c8e4 100644
--- a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.ts
+++ b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.ts
@@ -5,7 +5,7 @@ import { LinkComponent } from '../../link/link.component';
 @Component({
   selector: 'ods-dropdown-menu-link-item',
   standalone: true,
-  imports: [LinkComponent, OpenLinkIconComponent],
+  imports: [OpenLinkIconComponent, LinkComponent],
   styles: [':host {@apply first:mt-2}'],
   template: ` <ods-link [url]="url" class="bg-whitetext" [openInNewTab]="true">
     <div class="flex items-center gap-2 px-4 py-3">
diff --git a/alfa-client/libs/design-system/src/lib/form/checkbox/checkbox.component.ts b/alfa-client/libs/design-system/src/lib/form/checkbox/checkbox.component.ts
index 120fa956bb755ed800f6742dfe7ddfe69d5acd38..ffadf796c9031418fda5463896a1452351f2e109 100644
--- a/alfa-client/libs/design-system/src/lib/form/checkbox/checkbox.component.ts
+++ b/alfa-client/libs/design-system/src/lib/form/checkbox/checkbox.component.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { FormControl, ReactiveFormsModule } from '@angular/forms';
@@ -29,7 +29,7 @@ import { FormControl, ReactiveFormsModule } from '@angular/forms';
 @Component({
   selector: 'ods-checkbox',
   standalone: true,
-  imports: [CommonModule, ReactiveFormsModule, TechSharedModule],
+  imports: [CommonModule, ReactiveFormsModule, ConvertForDataTestPipe],
   template: `
     <div>
       <div class="relative flex items-start gap-3 text-start">
diff --git a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.spec.ts b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.spec.ts
index 0972a93d2bce07621c9426953b0374f4e3167d6f..fee4fa492f168106fce4c7f8c97dc6b31a956ddd 100644
--- a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.spec.ts
+++ b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.spec.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { getElementFromFixture } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { faker } from '@faker-js/faker';
@@ -37,7 +37,7 @@ describe('FileUploadButtonComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [FileUploadButtonComponent, TechSharedModule],
+      imports: [FileUploadButtonComponent, ConvertForDataTestPipe],
     }).compileComponents();
 
     fixture = TestBed.createComponent(FileUploadButtonComponent);
diff --git a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts
index 8a1f968b27776f44ab77b0931867fc39487e13d5..3e111b19ad208b4b4505a67bb8ef343ae6de0d2e 100644
--- a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts
+++ b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts
@@ -21,14 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, ElementRef, Input, ViewChild } from '@angular/core';
 
 @Component({
   selector: 'ods-file-upload-button',
   standalone: true,
-  imports: [CommonModule, TechSharedModule],
+  imports: [CommonModule, ConvertForDataTestPipe],
   styles: [':host {@apply inline-flex}'],
   templateUrl: './file-upload-button.component.html',
 })
diff --git a/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.spec.ts b/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.spec.ts
index 6d1f5b7eb8b1fab21996dd2991b2b09780edf82e..974db9b7c5c5dc93f83768157da9d570cfb0a2d3 100644
--- a/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.spec.ts
+++ b/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.spec.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { convertForDataTest } from '@alfa-client/tech-shared';
+import { convertForDataTest, ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { getElementFromFixture } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { FormControl, ReactiveFormsModule } from '@angular/forms';
@@ -37,7 +37,7 @@ describe('TextInputComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [ReactiveFormsModule, TextInputComponent],
+      imports: [ReactiveFormsModule, TextInputComponent, ConvertForDataTestPipe],
     }).compileComponents();
 
     fixture = TestBed.createComponent(TextInputComponent);
diff --git a/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts b/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts
index 1b038667fb82ad7c9832ded8ed18185eb1cd8780..ca6a007c19e49ebb481ff0655b407cc3076a9c08 100644
--- a/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts
+++ b/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts
@@ -21,11 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { convertForDataTest, EMPTY_STRING, TechSharedModule } from '@alfa-client/tech-shared';
+import { convertForDataTest, ConvertForDataTestPipe, EMPTY_STRING } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
 import { FormControl, ReactiveFormsModule } from '@angular/forms';
 import { cva, VariantProps } from 'class-variance-authority';
+import { uniqueId } from 'lodash-es';
 
 const textInputVariants = cva(
   [
@@ -50,7 +51,7 @@ type TextInputVariants = VariantProps<typeof textInputVariants>;
 @Component({
   selector: 'ods-text-input',
   standalone: true,
-  imports: [CommonModule, ReactiveFormsModule, TechSharedModule],
+  imports: [CommonModule, ReactiveFormsModule, ConvertForDataTestPipe],
   template: `
     <div class="relative">
       <label *ngIf="showLabel" [for]="id" class="text-md mb-2 block font-medium text-text">
@@ -86,7 +87,7 @@ export class TextInputComponent {
 
   @Input({ required: true }) set label(label: string) {
     this.inputLabel = label;
-    this.id = convertForDataTest(label);
+    this.id = `${convertForDataTest(label)}-${uniqueId()}`;
   }
   @Input() placeholder: string = '';
   @Input() autocomplete: string = 'off';
diff --git a/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.spec.ts b/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.spec.ts
index 872bec5354754d00e3f7d64eb724b20ed447e56c..580f9cab71a29070581554c29320b4ca86cd83fe 100644
--- a/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.spec.ts
+++ b/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.spec.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { convertForDataTest } from '@alfa-client/tech-shared';
+import { convertForDataTest, ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { getElementFromFixture } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { FormControl, ReactiveFormsModule } from '@angular/forms';
@@ -37,7 +37,7 @@ describe('TextareaComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [ReactiveFormsModule, TextareaComponent],
+      imports: [ReactiveFormsModule, TextareaComponent, ConvertForDataTestPipe],
     }).compileComponents();
 
     fixture = TestBed.createComponent(TextareaComponent);
diff --git a/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts b/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts
index ddc4a66781c0334c956a0d0b1b283b74110d2d38..f3eb84af9d638567a3bcbdc644b400abf344643e 100644
--- a/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts
+++ b/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { EMPTY_STRING, TechSharedModule, convertForDataTest } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe, EMPTY_STRING, convertForDataTest } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, ElementRef, Input, ViewChild } from '@angular/core';
 import { FormControl, ReactiveFormsModule } from '@angular/forms';
@@ -37,8 +37,7 @@ const textareaVariants = cva(
       variant: {
         default:
           'border-primary-600/50 focus-visible:outline-focus focus-visible:border-background-200 hover:border-primary-hover',
-        error:
-          'border-error/50 hover:border-error focus-visible:outline-error focus-visible:border-background-200',
+        error: 'border-error/50 hover:border-error focus-visible:outline-error focus-visible:border-background-200',
       },
     },
     defaultVariants: {
@@ -51,7 +50,7 @@ type TextareaVariants = VariantProps<typeof textareaVariants>;
 @Component({
   selector: 'ods-textarea',
   standalone: true,
-  imports: [CommonModule, ReactiveFormsModule, TechSharedModule],
+  imports: [CommonModule, ReactiveFormsModule, ConvertForDataTestPipe],
   template: `
     <div class="mt-2">
       <label *ngIf="showLabel" [for]="id" class="text-md mb-2 block font-medium text-text">
@@ -61,7 +60,7 @@ type TextareaVariants = VariantProps<typeof textareaVariants>;
         [id]="id"
         [formControl]="fieldControl"
         [rows]="rows"
-        [ngClass]="[textareaVariants({ variant }), isResizable ? 'resize' : 'resize-none']"
+        [ngClass]="[textareaVariants({ variant }), isResizable ? 'resize-y' : 'resize-none']"
         [placeholder]="placeholder"
         [autocomplete]="autocomplete"
         [attr.aria-required]="required"
diff --git a/alfa-client/libs/design-system/src/lib/icons/delete-icon/delete-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/delete-icon/delete-icon.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..354449bdfb0652606ec23dee7b970a5d793fd292
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/delete-icon/delete-icon.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { DeleteIconComponent } from './delete-icon.component';
+
+describe('DeleteIconComponent', () => {
+  let component: DeleteIconComponent;
+  let fixture: ComponentFixture<DeleteIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [DeleteIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(DeleteIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/delete-icon/delete-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/delete-icon/delete-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fc06f683c6790f219c7c08fb258764b35cdf2b6c
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/delete-icon/delete-icon.component.ts
@@ -0,0 +1,27 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { IconVariants, iconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-delete-icon',
+  standalone: true,
+  imports: [CommonModule],
+  template: `<svg
+    viewBox="0 0 24 24"
+    xmlns="http://www.w3.org/2000/svg"
+    [ngClass]="[twMerge(iconVariants({ size }), 'fill-error', class)]"
+    aria-hidden="true"
+  >
+    <path
+      d="M7 21C6.45 21 5.97917 20.8042 5.5875 20.4125C5.19583 20.0208 5 19.55 5 19V6H4V4H9V3H15V4H20V6H19V19C19 19.55 18.8042 20.0208 18.4125 20.4125C18.0208 20.8042 17.55 21 17 21H7ZM17 6H7V19H17V6ZM9 17H11V8H9V17ZM13 17H15V8H13V17Z"
+    />
+  </svg> `,
+})
+export class DeleteIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = '';
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/design-system/src/lib/icons/delete-icon/delete-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/delete-icon/delete-icon.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4602289bc57c1be551e4bf2ba29003ab4bd7de31
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/delete-icon/delete-icon.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/angular';
+
+import { DeleteIconComponent } from './delete-icon.component';
+
+const meta: Meta<DeleteIconComponent> = {
+  title: 'Icons/Delete icon',
+  component: DeleteIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<DeleteIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'large' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/navbar/nav-item/nav-item.component.spec.ts b/alfa-client/libs/design-system/src/lib/navbar/nav-item/nav-item.component.spec.ts
index 81485f802c48588260d6b38b383de316984fa55d..f4fd0fc39d030ec83824c3c8c0a7daefe3764de6 100644
--- a/alfa-client/libs/design-system/src/lib/navbar/nav-item/nav-item.component.spec.ts
+++ b/alfa-client/libs/design-system/src/lib/navbar/nav-item/nav-item.component.spec.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { convertForDataTest, TechSharedModule } from '@alfa-client/tech-shared';
+import { convertForDataTest, ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { getElementFromFixture, Mock, mock } from '@alfa-client/test-utils';
 import { importProvidersFrom } from '@angular/core';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
@@ -37,7 +37,7 @@ describe('NavItemComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [NavItemComponent, TechSharedModule],
+      imports: [NavItemComponent, ConvertForDataTestPipe],
       providers: [
         {
           provide: Router,
diff --git a/alfa-client/libs/design-system/src/lib/navbar/nav-item/nav-item.component.ts b/alfa-client/libs/design-system/src/lib/navbar/nav-item/nav-item.component.ts
index ac28440c045dd78e514f7f898d0f241b8e88921c..a3bd688e8120d42fba03efcde48d23510fdc66e7 100644
--- a/alfa-client/libs/design-system/src/lib/navbar/nav-item/nav-item.component.ts
+++ b/alfa-client/libs/design-system/src/lib/navbar/nav-item/nav-item.component.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, HostBinding, Input } from '@angular/core';
 import { RouterLink, RouterLinkActive } from '@angular/router';
@@ -29,13 +29,11 @@ import { RouterLink, RouterLinkActive } from '@angular/router';
 @Component({
   selector: 'ods-nav-item',
   standalone: true,
-  imports: [CommonModule, RouterLink, RouterLinkActive, TechSharedModule],
+  imports: [CommonModule, RouterLink, RouterLinkActive, ConvertForDataTestPipe],
   template: `<a
     [routerLink]="path"
     routerLinkActive="bg-selected-light border-selected"
-    class="flex min-h-8 items-center gap-2 rounded-2xl border border-transparent
-    px-4 py-2 outline-2 outline-offset-2 outline-focus hover:border-primary
-    focus-visible:border-background-200 focus-visible:outline"
+    class="flex min-h-8 items-center gap-2 rounded-2xl border border-transparent px-4 py-2 outline-2 outline-offset-2 outline-focus hover:border-primary focus-visible:border-background-200 focus-visible:outline"
     [attr.data-test-id]="'link-path-' + path | convertForDataTest"
   >
     <ng-content select="[icon]" />
diff --git a/alfa-client/libs/externe-fachstelle/src/lib/externe-fachstelle-list-item-container/externe-fachstelle-list-item/externe-fachstelle-list-item.component.ts b/alfa-client/libs/externe-fachstelle/src/lib/externe-fachstelle-list-item-container/externe-fachstelle-list-item/externe-fachstelle-list-item.component.ts
index 51d26eecb5813638527dc472c75d3ea22b744233..274c1b9090b1b6e299db74c41b9a1e08cb1dd62c 100644
--- a/alfa-client/libs/externe-fachstelle/src/lib/externe-fachstelle-list-item-container/externe-fachstelle-list-item/externe-fachstelle-list-item.component.ts
+++ b/alfa-client/libs/externe-fachstelle/src/lib/externe-fachstelle-list-item-container/externe-fachstelle-list-item/externe-fachstelle-list-item.component.ts
@@ -22,7 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { StateResource } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import { SpinnerComponent } from '@alfa-client/ui';
 import { ExterneFachstelleResource } from '@alfa-client/zustaendige-stelle-shared';
 import { Component, Input } from '@angular/core';
 import { ExternalUnitIconComponent, PublicAdministrationIconComponent } from '@ods/system';
@@ -30,7 +30,7 @@ import { ExternalUnitIconComponent, PublicAdministrationIconComponent } from '@o
 @Component({
   selector: 'alfa-externe-fachstelle-list-item',
   standalone: true,
-  imports: [PublicAdministrationIconComponent, ExternalUnitIconComponent, UiModule],
+  imports: [PublicAdministrationIconComponent, ExternalUnitIconComponent, SpinnerComponent],
   templateUrl: './externe-fachstelle-list-item.component.html',
 })
 export class ExterneFachstelleListItemComponent {
diff --git a/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.spec.ts b/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.spec.ts
index 0bdb21fd38ad815027918f1b3e13b7a1818f57d4..8aab319a28e6ed8a3cd49270fdd27a42e2ed09f3 100644
--- a/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.spec.ts
+++ b/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.spec.ts
@@ -1,3 +1,4 @@
+import { HasLinkPipe } from '@alfa-client/tech-shared';
 import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
 import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
@@ -17,7 +18,7 @@ describe('ForwardByOzgcloudButtonContainerComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [ForwardByOzgcloudButtonContainerComponent],
+      imports: [ForwardByOzgcloudButtonContainerComponent, HasLinkPipe],
       declarations: [
         MockComponent(ButtonWithSpinnerComponent),
         MockComponent(ForwardVorgangIconComponent),
diff --git a/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.ts b/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.ts
index b00da7ddb3c481ac14502f9091ec29c4b9af2748..f5fbad7ed1280171822f6746847c08887dbaff75 100644
--- a/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.ts
+++ b/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.ts
@@ -1,4 +1,4 @@
-import { TechSharedModule } from '@alfa-client/tech-shared';
+import { HasLinkPipe } from '@alfa-client/tech-shared';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { CommonModule } from '@angular/common';
 import { Component, Input } from '@angular/core';
@@ -8,7 +8,7 @@ import { ForwardVorgangIconComponent, TooltipDirective } from '@ods/system';
 @Component({
   selector: 'alfa-forward-by-ozgcloud-button-container',
   standalone: true,
-  imports: [CommonModule, TechSharedModule, ButtonWithSpinnerComponent, ForwardVorgangIconComponent, TooltipDirective],
+  imports: [CommonModule, ButtonWithSpinnerComponent, ForwardVorgangIconComponent, TooltipDirective, HasLinkPipe],
   templateUrl: './forward-by-ozgcloud-button-container.component.html',
   styles: [':host {@apply empty:hidden}'],
 })
diff --git a/alfa-client/libs/forwarding/src/lib/forwarding.module.ts b/alfa-client/libs/forwarding/src/lib/forwarding.module.ts
index 56ba3f3ad8c2a79a91c9cbe1dd619140d63a9427..973cf7b7a1603273e98ca30ee0bd511c57bb9cc1 100644
--- a/alfa-client/libs/forwarding/src/lib/forwarding.module.ts
+++ b/alfa-client/libs/forwarding/src/lib/forwarding.module.ts
@@ -21,12 +21,19 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
 import { CommandSharedModule } from '@alfa-client/command-shared';
 import { ForwardingSharedModule } from '@alfa-client/forwarding-shared';
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import { FormatDateWithTimePipe, HasLinkPipe, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared';
+import {
+  ExpansionPanelComponent,
+  OzgcloudStrokedButtonWithSpinnerComponent,
+  OzgcloudTextEditorComponent,
+  SpinnerComponent,
+} from '@alfa-client/ui';
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { MatIcon } from '@angular/material/icon';
 import { VorgangForwardFormComponent } from './vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component';
 import { VorgangForwardFormularComponent } from './vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component';
 import { VorgangForwardingContainerComponent } from './vorgang-forwarding-container/vorgang-forwarding-container.component';
@@ -35,7 +42,20 @@ import { VorgangForwardingInfoComponent } from './vorgang-forwarding-container/v
 import { VorgangForwardZustellenContainerComponent } from './vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component';
 
 @NgModule({
-  imports: [CommonModule, TechSharedModule, ForwardingSharedModule, CommandSharedModule, UiModule],
+  imports: [
+    CommonModule,
+    ForwardingSharedModule,
+    CommandSharedModule,
+    OzgcloudTextEditorComponent,
+    OzgcloudStrokedButtonWithSpinnerComponent,
+    SpinnerComponent,
+    FormatDateWithTimePipe,
+    MatIcon,
+    HasLinkPipe,
+    ToEmbeddedResourcesPipe,
+    ExpansionPanelComponent,
+    ReactiveFormsModule,
+  ],
   declarations: [
     VorgangForwardZustellenContainerComponent,
     VorgangForwardingContainerComponent,
diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.spec.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.spec.ts
index 19d141bc8d2ff6553331a408380f77d29ee028cd..d4de767de8c460d74794b21ec61a5152ee38d2c6 100644
--- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.spec.ts
+++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.spec.ts
@@ -21,15 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { mock } from '@alfa-client/test-utils';
+import { OzgcloudStrokedButtonWithSpinnerComponent, OzgcloudTextEditorComponent } from '@alfa-client/ui';
+import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ReactiveFormsModule, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
 import { MatFormFieldModule } from '@angular/material/form-field';
 import { MatIcon } from '@angular/material/icon';
 import { MatInputModule } from '@angular/material/input';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { mock } from '@alfa-client/test-utils';
-import { OzgcloudStrokedButtonWithSpinnerComponent, TextEditorComponent } from '@alfa-client/ui';
-import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { VorgangForwardFormComponent } from './vorgang-forward-form.component';
@@ -54,7 +54,7 @@ describe('VorgangForwardFormComponent', () => {
         VorgangForwardFormComponent,
         MatIcon,
         MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(TextEditorComponent),
+        MockComponent(OzgcloudTextEditorComponent),
       ],
       imports: [MatFormFieldModule, MatInputModule, ReactiveFormsModule, BrowserAnimationsModule],
       providers: [
@@ -112,10 +112,7 @@ describe('VorgangForwardFormComponent', () => {
 
       component.patchEmail();
 
-      expect(formService.patchField).toHaveBeenCalledWith(
-        'email',
-        vorgangWithEingang.eingang.zustaendigeStelle.email,
-      );
+      expect(formService.patchField).toHaveBeenCalledWith('email', vorgangWithEingang.eingang.zustaendigeStelle.email);
     });
   });
 });
diff --git a/alfa-client/libs/hint-shared/src/lib/hint-shared.module.ts b/alfa-client/libs/hint-shared/src/lib/hint-shared.module.ts
index e0304dd1d6259a58a58fa0f66405cb22c7c64ba8..482c311a15767e88f3c95d8db8d7f8c2523611c9 100644
--- a/alfa-client/libs/hint-shared/src/lib/hint-shared.module.ts
+++ b/alfa-client/libs/hint-shared/src/lib/hint-shared.module.ts
@@ -21,10 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ApiRootModule } from '@alfa-client/api-root-shared';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
-import { ApiRootModule } from '@alfa-client/api-root-shared';
-import { TechSharedModule } from '@alfa-client/tech-shared';
 import { EffectsModule } from '@ngrx/effects';
 import { StoreModule } from '@ngrx/store';
 import { HintEffects } from './+state/hint.effects';
@@ -38,7 +37,6 @@ import { HintService } from './hint.service';
     CommonModule,
     StoreModule.forFeature(HINT_FEATURE_KEY, reducer),
     EffectsModule.forFeature([HintEffects]),
-    TechSharedModule,
     ApiRootModule,
   ],
   providers: [HintService, HintFacade, HintRepository],
diff --git a/alfa-client/libs/hint/src/lib/hint.module.ts b/alfa-client/libs/hint/src/lib/hint.module.ts
index 37fa3fb082fb9ee488c5ee44648ac4cda32f3d93..d72695756dffe723cb6532ff1a558ce17477e2ef 100644
--- a/alfa-client/libs/hint/src/lib/hint.module.ts
+++ b/alfa-client/libs/hint/src/lib/hint.module.ts
@@ -21,16 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
 import { ApiRootModule } from '@alfa-client/api-root-shared';
 import { HintSharedModule } from '@alfa-client/hint-shared';
-import { TechSharedModule } from '@alfa-client/tech-shared';
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
 import { HintContainerComponent } from './hint-container/hint-container.component';
 import { UserNoOrganisationsEinheitIdHintComponent } from './hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component';
 
 @NgModule({
-  imports: [CommonModule, TechSharedModule, ApiRootModule, HintSharedModule],
+  imports: [CommonModule, ApiRootModule, HintSharedModule],
   declarations: [UserNoOrganisationsEinheitIdHintComponent, HintContainerComponent],
   exports: [HintContainerComponent],
 })
diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-bescheid/historie-item-bescheid-status/historie-item-bescheid-status.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-bescheid/historie-item-bescheid-status/historie-item-bescheid-status.component.spec.ts
index a47331f8708e9ef6f86be744fe00a40eb307d539..cea37b23a9a580a7daf7f10cadda775444d6cebe 100644
--- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-bescheid/historie-item-bescheid-status/historie-item-bescheid-status.component.spec.ts
+++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-bescheid/historie-item-bescheid-status/historie-item-bescheid-status.component.spec.ts
@@ -42,7 +42,8 @@ describe('HistorieItemBescheidStatusComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [HistorieItemBescheidStatusComponent, ConvertToBooleanPipe, FormatFullDatePipe],
+      imports: [ConvertToBooleanPipe, FormatFullDatePipe],
+      declarations: [HistorieItemBescheidStatusComponent],
     }).compileComponents();
 
     fixture = TestBed.createComponent(HistorieItemBescheidStatusComponent);
diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.spec.ts
index 97a69102871a05a4114818db1c0b44bdfb113c79..1fb501bf07dfb0fbf0c966f35582ac9894178582 100644
--- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.spec.ts
+++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.spec.ts
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { registerLocaleData } from '@angular/common';
-import localeDe from '@angular/common/locales/de';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { FormatDateWithTimePipe } from '@alfa-client/tech-shared';
 import { getElementFromFixture } from '@alfa-client/test-utils';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { registerLocaleData } from '@angular/common';
+import localeDe from '@angular/common/locales/de';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { HistorieItemVorgangCreatedComponent } from './historie-item-vorgang-created.component';
@@ -43,7 +43,8 @@ describe('HistorieItemVorgangCreatedComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [FormatDateWithTimePipe, HistorieItemVorgangCreatedComponent],
+      imports: [FormatDateWithTimePipe],
+      declarations: [HistorieItemVorgangCreatedComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/historie/src/lib/historie.module.ts b/alfa-client/libs/historie/src/lib/historie.module.ts
index 7c064391c2e621a96da017383c07edb67ec65f7e..c9675a36427c958658176eac4776cbc1fdf23c9d 100644
--- a/alfa-client/libs/historie/src/lib/historie.module.ts
+++ b/alfa-client/libs/historie/src/lib/historie.module.ts
@@ -23,11 +23,20 @@
  */
 import { CommandSharedModule } from '@alfa-client/command-shared';
 import { HistorieSharedModule } from '@alfa-client/historie-shared';
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import {
+  ConvertToBooleanPipe,
+  FormatDateWithTimePipe,
+  FormatToPrettyDatePipe,
+  HasLinkPipe,
+  ToEmbeddedResourcesPipe,
+} from '@alfa-client/tech-shared';
+import { AccordionComponent, AppIconComponent, SpinnerComponent } from '@alfa-client/ui';
 import { UserProfileModule } from '@alfa-client/user-profile';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
+import { MatExpansionPanel, MatExpansionPanelTitle } from '@angular/material/expansion';
+import { MatIcon } from '@angular/material/icon';
+import { FormatFullDatePipe } from '../../../tech-shared/src/lib/pipe/format-full-date.pipe';
 import { HistorieContainerComponent } from './historie-container/historie-container.component';
 import { ExpansionPanelWithUserComponent } from './historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component';
 import { HistorieItemAktenzeichenComponent } from './historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component';
@@ -52,11 +61,21 @@ import { HistorieListComponent } from './historie-container/historie-list/histor
 @NgModule({
   imports: [
     CommonModule,
-    TechSharedModule,
     HistorieSharedModule,
     UserProfileModule,
-    UiModule,
     CommandSharedModule,
+    MatExpansionPanel,
+    MatExpansionPanelTitle,
+    MatIcon,
+    ConvertToBooleanPipe,
+    FormatFullDatePipe,
+    HasLinkPipe,
+    AppIconComponent,
+    FormatDateWithTimePipe,
+    FormatToPrettyDatePipe,
+    SpinnerComponent,
+    AccordionComponent,
+    ToEmbeddedResourcesPipe,
   ],
   declarations: [
     HistorieContainerComponent,
diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.ts
index f87a70b3cbc9d588e2f2ea0b002d0590724279ef..de0954a3f8febb42069459356746526f8a9bc977 100644
--- a/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.ts
+++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.ts
@@ -21,12 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { VorgangSharedModule } from '@alfa-client/vorgang-shared';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { VorgangSharedModule } from '@alfa-client/vorgang-shared';
 
 @NgModule({
-  imports: [CommonModule, TechSharedModule, VorgangSharedModule],
+  imports: [CommonModule, VorgangSharedModule],
 })
 export class KommentarSharedModule {}
diff --git a/alfa-client/libs/kommentar/src/lib/kommentar.module.ts b/alfa-client/libs/kommentar/src/lib/kommentar.module.ts
index 978a2bf16d4cdd9e1c53149ffc1aefefab5e8cdb..4c9da054bee43f9411bd2e93ce3c4242246bf3aa 100644
--- a/alfa-client/libs/kommentar/src/lib/kommentar.module.ts
+++ b/alfa-client/libs/kommentar/src/lib/kommentar.module.ts
@@ -21,14 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
 import { BinaryFileModule } from '@alfa-client/binary-file';
 import { KommentarSharedModule } from '@alfa-client/kommentar-shared';
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import { ConvertForDataTestPipe, FormatDateWithTimePipe, HasLinkPipe } from '@alfa-client/tech-shared';
+import { ExpansionPanelComponent, OzgcloudStrokedButtonWithSpinnerComponent, TextAreaEditorComponent } from '@alfa-client/ui';
 import { UserProfileModule } from '@alfa-client/user-profile';
 import { VorgangSharedModule } from '@alfa-client/vorgang-shared';
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
 import { KommentarFormComponent } from './kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component';
 import { KommentarListInVorgangContainerComponent } from './kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component';
 import { KommentarListInVorgangComponent } from './kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component';
@@ -38,11 +39,16 @@ import { KommentarListItemInVorgangComponent } from './kommentar-list-in-vorgang
   imports: [
     CommonModule,
     VorgangSharedModule,
-    UiModule,
     KommentarSharedModule,
-    TechSharedModule,
     UserProfileModule,
     BinaryFileModule,
+    ReactiveFormsModule,
+    TextAreaEditorComponent,
+    OzgcloudStrokedButtonWithSpinnerComponent,
+    ConvertForDataTestPipe,
+    HasLinkPipe,
+    FormatDateWithTimePipe,
+    ExpansionPanelComponent,
   ],
   declarations: [
     KommentarListInVorgangContainerComponent,
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts
index 4841c7b2b27decf170b93076d58369f9aa9d4a58..ff527cfc478f145690f5a846abb7fbfb1bff33ec 100644
--- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts
+++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts
@@ -22,8 +22,8 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { LoeschAnforderungSharedModule } from '@alfa-client/loesch-anforderung-shared';
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import { HasLinkPipe } from '@alfa-client/tech-shared';
+import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { VorgangSharedModule } from '@alfa-client/vorgang-shared';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
@@ -45,9 +45,10 @@ import { LoeschenAnfordernButtonComponent } from './loeschen-anfordern-button-co
   imports: [
     CommonModule,
     LoeschAnforderungSharedModule,
-    TechSharedModule,
-    UiModule,
     VorgangSharedModule,
+    OzgcloudStrokedButtonWithSpinnerComponent,
+    IconButtonWithSpinnerComponent,
+    HasLinkPipe,
     RequestVorgangDeletionIconComponent,
     ButtonWithSpinnerComponent,
     DeleteVorgangFinallyIconComponent,
diff --git a/alfa-client/libs/navigation-shared/src/lib/navigation-shared.module.ts b/alfa-client/libs/navigation-shared/src/lib/navigation-shared.module.ts
index b596ca2b99d19f47cd1e08dfdffbf0c9307b2130..16fde28370c70d812f2e55f778b474ac5afc834e 100644
--- a/alfa-client/libs/navigation-shared/src/lib/navigation-shared.module.ts
+++ b/alfa-client/libs/navigation-shared/src/lib/navigation-shared.module.ts
@@ -23,7 +23,6 @@
  */
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
-import { TechSharedModule } from '@alfa-client/tech-shared';
 import { EffectsModule } from '@ngrx/effects';
 import { StoreModule } from '@ngrx/store';
 import { NavigationEffects } from './+state/navigation.effects';
@@ -36,7 +35,6 @@ import { NavigationService } from './navigation.service';
     CommonModule,
     StoreModule.forFeature(fromNavigation.NAVIGATION_FEATURE_KEY, fromNavigation.reducer),
     EffectsModule.forFeature([NavigationEffects]),
-    TechSharedModule,
   ],
   providers: [NavigationFacade, NavigationService],
 })
diff --git a/alfa-client/libs/navigation/src/lib/header-container/header/header.component.spec.ts b/alfa-client/libs/navigation/src/lib/header-container/header/header.component.spec.ts
index 34bfb94cc20aad98d03a09e66c82578fb694ea97..3566cb04a61f9fac5fbfb37af6fa8e8faefc19bf 100644
--- a/alfa-client/libs/navigation/src/lib/header-container/header/header.component.spec.ts
+++ b/alfa-client/libs/navigation/src/lib/header-container/header/header.component.spec.ts
@@ -22,7 +22,6 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { AccessibilityButtonComponent } from '@alfa-client/common';
-import { UiModule } from '@alfa-client/ui';
 import { HelpMenuComponent } from '@alfa-client/user-assistance';
 import { UserProfileInHeaderContainerComponent } from '@alfa-client/user-profile';
 import { UserSettingsContainerComponent } from '@alfa-client/user-settings';
@@ -38,7 +37,6 @@ describe('HeaderComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [UiModule],
       declarations: [
         HeaderComponent,
         MockComponent(HeaderLogoComponent),
diff --git a/alfa-client/libs/navigation/src/lib/navigation.module.spec.ts b/alfa-client/libs/navigation/src/lib/navigation.module.spec.ts
index 8cb65e6da40705f8e87e00a461202ff56ce23fb7..a4f111d64e4aef9ee2f22a302917397ce923cbd5 100644
--- a/alfa-client/libs/navigation/src/lib/navigation.module.spec.ts
+++ b/alfa-client/libs/navigation/src/lib/navigation.module.spec.ts
@@ -24,7 +24,7 @@
 import { TestBed } from '@angular/core/testing';
 import { NavigationModule } from './navigation.module';
 
-describe('UiModule', () => {
+describe('NavigationModule', () => {
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       imports: [NavigationModule],
diff --git a/alfa-client/libs/navigation/src/lib/navigation.module.ts b/alfa-client/libs/navigation/src/lib/navigation.module.ts
index 67cd2f216c40a0e850204b31089771c3912fffda..37ee7178625f6fbd7ffb92228dfb25f04cffacd7 100644
--- a/alfa-client/libs/navigation/src/lib/navigation.module.ts
+++ b/alfa-client/libs/navigation/src/lib/navigation.module.ts
@@ -22,7 +22,6 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { AccessibilityButtonComponent } from '@alfa-client/common';
-import { UiModule } from '@alfa-client/ui';
 import { UserAssistanceModule } from '@alfa-client/user-assistance';
 import { UserProfileModule } from '@alfa-client/user-profile';
 import { UserSettingsModule } from '@alfa-client/user-settings';
@@ -38,7 +37,6 @@ import { HeaderComponent } from './header-container/header/header.component';
   declarations: [HeaderComponent, HeaderContainerComponent, HeaderLogoComponent],
   imports: [
     CommonModule,
-    UiModule,
     RouterModule,
     VorgangSharedUiModule,
     UserProfileModule,
diff --git a/alfa-client/libs/organisations-einheit/src/lib/organisations-einheit-list-item-container/organisations-einheit-list-item/organisations-einheit-list-item.component.ts b/alfa-client/libs/organisations-einheit/src/lib/organisations-einheit-list-item-container/organisations-einheit-list-item/organisations-einheit-list-item.component.ts
index f4fc21b66bd7915eeb58bcc6537f4c644a78a509..05558ae4b77e69cb7b278d5862fa0662c4823a93 100644
--- a/alfa-client/libs/organisations-einheit/src/lib/organisations-einheit-list-item-container/organisations-einheit-list-item/organisations-einheit-list-item.component.ts
+++ b/alfa-client/libs/organisations-einheit/src/lib/organisations-einheit-list-item-container/organisations-einheit-list-item/organisations-einheit-list-item.component.ts
@@ -22,7 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { StateResource } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import { SpinnerComponent } from '@alfa-client/ui';
 import { OrganisationsEinheitResource } from '@alfa-client/zustaendige-stelle-shared';
 import { Component, Input } from '@angular/core';
 import { ExternalUnitIconComponent, PublicAdministrationIconComponent } from '@ods/system';
@@ -30,7 +30,7 @@ import { ExternalUnitIconComponent, PublicAdministrationIconComponent } from '@o
 @Component({
   selector: 'alfa-organisations-einheit-list-item',
   standalone: true,
-  imports: [ExternalUnitIconComponent, PublicAdministrationIconComponent, UiModule],
+  imports: [ExternalUnitIconComponent, PublicAdministrationIconComponent, SpinnerComponent],
   templateUrl: './organisations-einheit-list-item.component.html',
 })
 export class OrganisationsEinheitListItemComponent {
diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.spec.ts
index c3fd2f97ae173d6ef591e90cc8c3eedc2194bf8f..5b5beec8bf365ee4a043970eb471f592faeb4ed7 100644
--- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.spec.ts
+++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.spec.ts
@@ -29,9 +29,9 @@ import {
   FileUploadComponent,
   IconButtonWithSpinnerComponent,
   OzgcloudStrokedButtonWithSpinnerComponent,
+  OzgcloudTextEditorComponent,
   SpinnerComponent,
   TextAreaEditorComponent,
-  TextEditorComponent,
 } from '@alfa-client/ui';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
@@ -58,10 +58,7 @@ describe('PostfachMailFormComponent', () => {
     ...mock(PostfachService),
     getSettings: jest.fn().mockReturnValue(of(createPostfachSettings())),
   };
-  const formService: PostfachMailFormservice = new PostfachMailFormservice(
-    new FormBuilder(),
-    useFromMock(postfachService),
-  );
+  const formService: PostfachMailFormservice = new PostfachMailFormservice(new FormBuilder(), useFromMock(postfachService));
   const dialogService: Mock<DialogService> = mock(DialogService);
 
   beforeEach(async () => {
@@ -69,7 +66,7 @@ describe('PostfachMailFormComponent', () => {
       declarations: [
         PostfachMailFormComponent,
         MockComponent(TextAreaEditorComponent),
-        MockComponent(TextEditorComponent),
+        MockComponent(OzgcloudTextEditorComponent),
         MockComponent(IconButtonWithSpinnerComponent),
         MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
         MockComponent(PostfachNachrichtReplyEditorContainerComponent),
diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.spec.ts
index 5a488822426b781de116fa4204e9133a6c3d3565..ca8fd42b29448ed3b4e56f55c00eca3f50d758a5 100644
--- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.spec.ts
+++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.spec.ts
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { registerLocaleData } from '@angular/common';
-import localeDe from '@angular/common/locales/de';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { Direction } from '@alfa-client/postfach-shared';
 import { FormatDateWithTimePipe, HasLinkPipe } from '@alfa-client/tech-shared';
 import { getElementFromFixture } from '@alfa-client/test-utils';
+import { registerLocaleData } from '@angular/common';
+import localeDe from '@angular/common/locales/de';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { createPostfachMailResource } from 'libs/postfach-shared/test/postfach';
 import { PostfachMailDateComponent } from './postfach-mail-date.component';
 
@@ -41,7 +41,8 @@ describe('PostfachMailDateComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [PostfachMailDateComponent, HasLinkPipe, FormatDateWithTimePipe],
+      imports: [HasLinkPipe, FormatDateWithTimePipe],
+      declarations: [PostfachMailDateComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/postfach/src/lib/postfach.module.ts b/alfa-client/libs/postfach/src/lib/postfach.module.ts
index e206c35d6c8efaad6336bf8f3740e1f075f5ada7..2a6fe82af2922461a8ed345f322b54e754f2ccec 100644
--- a/alfa-client/libs/postfach/src/lib/postfach.module.ts
+++ b/alfa-client/libs/postfach/src/lib/postfach.module.ts
@@ -23,11 +23,24 @@
  */
 import { BinaryFileModule } from '@alfa-client/binary-file';
 import { ON_PAGE, PostfachSharedModule } from '@alfa-client/postfach-shared';
-import { UiModule } from '@alfa-client/ui';
+import { ConvertForDataTestPipe, FormatDateWithTimePipe, HasLinkPipe, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared';
+import {
+  BackButtonComponent,
+  CheckboxEnumEditorComponent,
+  IconButtonWithSpinnerComponent,
+  OzgcloudIconComponent,
+  OzgcloudStrokedButtonWithSpinnerComponent,
+  OzgcloudTextEditorComponent,
+  SpinnerComponent,
+  SubnavigationComponent,
+  TextAreaEditorComponent,
+} from '@alfa-client/ui';
 import { UserProfileModule } from '@alfa-client/user-profile';
 import { VorgangSharedUiModule } from '@alfa-client/vorgang-shared-ui';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { MatIcon } from '@angular/material/icon';
 import { RouterModule, Routes } from '@angular/router';
 import { ButtonComponent, MailboxIconComponent, PlusIconComponent, TooltipDirective } from '@ods/system';
 import { PostfachMailButtonContainerComponent } from './postfach-mail-button-container/postfach-mail-button-container.component';
@@ -63,11 +76,25 @@ const routes: Routes = [
   imports: [
     CommonModule,
     RouterModule.forChild(routes),
-    UiModule,
     PostfachSharedModule,
     UserProfileModule,
     VorgangSharedUiModule,
     BinaryFileModule,
+    OzgcloudStrokedButtonWithSpinnerComponent,
+    HasLinkPipe,
+    CheckboxEnumEditorComponent,
+    ReactiveFormsModule,
+    OzgcloudTextEditorComponent,
+    TextAreaEditorComponent,
+    MatIcon,
+    OzgcloudIconComponent,
+    FormatDateWithTimePipe,
+    SpinnerComponent,
+    ToEmbeddedResourcesPipe,
+    ConvertForDataTestPipe,
+    SubnavigationComponent,
+    BackButtonComponent,
+    IconButtonWithSpinnerComponent,
     ButtonComponent,
     PlusIconComponent,
     MailboxIconComponent,
diff --git a/alfa-client/libs/resource-redirect-shared/src/lib/resource-redirect-shared.module.ts b/alfa-client/libs/resource-redirect-shared/src/lib/resource-redirect-shared.module.ts
index c595c6eed1d99ffe27153f717583e2f99b8f4248..33ef83703dab9eb294a07b39e499349780932399 100644
--- a/alfa-client/libs/resource-redirect-shared/src/lib/resource-redirect-shared.module.ts
+++ b/alfa-client/libs/resource-redirect-shared/src/lib/resource-redirect-shared.module.ts
@@ -21,10 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
 import { NgModule } from '@angular/core';
 
-@NgModule({
-  imports: [TechSharedModule],
-})
+@NgModule({})
 export class ResourceRedirectSharedModule {}
diff --git a/alfa-client/libs/tech-shared/src/index.ts b/alfa-client/libs/tech-shared/src/index.ts
index f2c01ec546c183620b05b39ad37f6af73368cddd..6fbc4e5294b1490dd9924a225715b0007c0ba80f 100644
--- a/alfa-client/libs/tech-shared/src/index.ts
+++ b/alfa-client/libs/tech-shared/src/index.ts
@@ -29,6 +29,7 @@ export * from './lib/error/error.handler';
 export * from './lib/error/error.util';
 export * from './lib/form.util';
 export * from './lib/http.util';
+export * from './lib/injector/injector.service';
 export * from './lib/keyboard.util';
 export * from './lib/message-code';
 export * from './lib/ngrx/actions';
@@ -57,7 +58,6 @@ export * from './lib/resource/resource.rxjs.operator';
 export * from './lib/resource/resource.service';
 export * from './lib/resource/resource.util';
 export * from './lib/service/formservice.abstract';
-export * from './lib/tech-shared.module';
 export * from './lib/tech.model';
 export * from './lib/tech.util';
 export * from './lib/validation/tech.validation.util';
diff --git a/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.ts b/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.ts
index 669b6872398a4d9a3539741ec84fad461375f445..f02936d4fbd11d5a37b30d5e1864323bc0fa9cb1 100644
--- a/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.ts
+++ b/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.ts
@@ -22,10 +22,10 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { HttpErrorHandler } from '../error/error.handler';
-import { TechSharedModule } from '../tech-shared.module';
+import { InjectorService } from '../injector/injector.service';
 
 export function injectHttpErrorHandler(): HttpErrorHandler {
-  return TechSharedModule.injector.get(HttpErrorHandler);
+  return InjectorService.getInjector().get(HttpErrorHandler);
 }
 
 export function enableInterceptorDefaultHandling(httpErrorHandler: HttpErrorHandler): void {
diff --git a/alfa-client/libs/tech-shared/src/lib/injector/injector.service.spec.ts b/alfa-client/libs/tech-shared/src/lib/injector/injector.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1833f3fd12e12fa277a131186d3a27623a3c2251
--- /dev/null
+++ b/alfa-client/libs/tech-shared/src/lib/injector/injector.service.spec.ts
@@ -0,0 +1,30 @@
+import { Injector } from '@angular/core';
+import { TestBed } from '@angular/core/testing';
+import { InjectorService } from './injector.service';
+
+describe('InjectorService', () => {
+  let injector: Injector;
+  let injectorService: InjectorService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      providers: [InjectorService, { provide: Injector, useValue: {} }],
+    });
+    injector = TestBed.inject(Injector);
+    injectorService = TestBed.inject(InjectorService);
+  });
+
+  it('should be created', () => {
+    expect(injectorService).toBeTruthy();
+  });
+
+  it('should set and get the injector', () => {
+    expect(InjectorService.getInjector()).toBe(injector);
+  });
+
+  describe('getInjector', () => {
+    it('should return the injector', () => {
+      expect(InjectorService.getInjector()).toBe(injector);
+    });
+  });
+});
diff --git a/alfa-client/libs/tech-shared/src/lib/injector/injector.service.ts b/alfa-client/libs/tech-shared/src/lib/injector/injector.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eb2ad9d101376adff380bc8930f5e0274503ddbb
--- /dev/null
+++ b/alfa-client/libs/tech-shared/src/lib/injector/injector.service.ts
@@ -0,0 +1,16 @@
+import { Injectable, Injector } from '@angular/core';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class InjectorService {
+  private static injector: Injector;
+
+  constructor(injector: Injector) {
+    InjectorService.injector = injector;
+  }
+
+  public static getInjector(): Injector {
+    return InjectorService.injector;
+  }
+}
diff --git a/alfa-client/libs/tech-shared/src/lib/keyboard.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/keyboard.util.spec.ts
index 10b46493b6c1d89755bddaefb378a4691ac82cae..92ba5f3e69a27a05a50ee8fbdf1ec33f70b776cf 100644
--- a/alfa-client/libs/tech-shared/src/lib/keyboard.util.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/keyboard.util.spec.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { createKeydownKeyboardEvent } from '../../../test-utils/src/lib/keyboard';
+import { createKeydownKeyboardEvent } from 'libs/test-utils/src/lib/keyboard';
 import {
   ARROW_DOWN_KEY,
   ARROW_UP_KEY,
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/convert-api-error-to-error-messages.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/convert-api-error-to-error-messages.pipe.ts
index 20392c34d74bdcd980c5f3ba961f6f4be8484dae..e57e531260cb15aa718a6193fd624b5fc277c917 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/convert-api-error-to-error-messages.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/convert-api-error-to-error-messages.pipe.ts
@@ -25,7 +25,10 @@ import { ApiError, EMPTY_STRING, getMessageForIssue, Issue } from '@alfa-client/
 import { Pipe, PipeTransform } from '@angular/core';
 import { isNil } from 'lodash-es';
 
-@Pipe({ name: 'convertApiErrorToErrorMessages' })
+@Pipe({
+  name: 'convertApiErrorToErrorMessages',
+  standalone: true,
+})
 export class ConvertApiErrorToErrorMessagesPipe implements PipeTransform {
   transform(value: ApiError) {
     if (isNil(value)) {
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.ts
index b1873901646b2c270a3e353158821aed99a19059..dd6bb93c51596fd3d4e6f40973e1050c94f83330 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.ts
@@ -25,7 +25,10 @@ import { Pipe, PipeTransform } from '@angular/core';
 import { isNil } from 'lodash-es';
 import { convertForDataTest } from '../tech.util';
 
-@Pipe({ name: 'convertForDataTest' })
+@Pipe({
+  name: 'convertForDataTest',
+  standalone: true,
+})
 export class ConvertForDataTestPipe implements PipeTransform {
   transform(value: string): string {
     return isNil(value) ? null : convertForDataTest(value);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/convert-problem-detail-to-error-messages.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/convert-problem-detail-to-error-messages.pipe.ts
index 24f50446e27078791793cb671bee05d3cef19868..7ce05836fe5a7e410c9467cc4a676c7fa13c9338 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/convert-problem-detail-to-error-messages.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/convert-problem-detail-to-error-messages.pipe.ts
@@ -27,14 +27,15 @@ import { InvalidParam, ProblemDetail } from '../tech.model';
 import { EMPTY_STRING } from '../tech.util';
 import { getMessageForInvalidParam } from '../validation/tech.validation.util';
 
-@Pipe({ name: 'convertProblemDetailToErrorMessages' })
+@Pipe({
+  name: 'convertProblemDetailToErrorMessages',
+  standalone: true,
+})
 export class ConvertProblemDetailToErrorMessagesPipe implements PipeTransform {
   transform(value: ProblemDetail) {
     if (isNil(value)) {
       return [];
     }
-    return value.invalidParams.map((invalidParam: InvalidParam) =>
-      getMessageForInvalidParam(EMPTY_STRING, invalidParam),
-    );
+    return value.invalidParams.map((invalidParam: InvalidParam) => getMessageForInvalidParam(EMPTY_STRING, invalidParam));
   }
 }
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/convert-to-boolean.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/convert-to-boolean.pipe.ts
index daac6384c220168403ffc3fdb50395bbee2dc4e1..ad5da3e0789786d617ee3e61d7ac56c075c43cae 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/convert-to-boolean.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/convert-to-boolean.pipe.ts
@@ -24,7 +24,10 @@
 import { Pipe, PipeTransform } from '@angular/core';
 import { convertToBoolean } from '../tech.util';
 
-@Pipe({ name: 'convertToBoolean' })
+@Pipe({
+  name: 'convertToBoolean',
+  standalone: true,
+})
 export class ConvertToBooleanPipe implements PipeTransform {
   public transform(booleanStr: string): boolean {
     return convertToBoolean(booleanStr);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.ts
index 194e92483d10610441c53b3924f84e0d550cf307..38033a71822e29d42e25b491e28b5dd956d062e8 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.ts
@@ -24,7 +24,10 @@
 import { Pipe, PipeTransform } from '@angular/core';
 import { isNil } from 'lodash-es';
 
-@Pipe({ name: 'enumToLabel' })
+@Pipe({
+  name: 'enumToLabel',
+  standalone: true,
+})
 export class EnumToLabelPipe implements PipeTransform {
   transform(enumValue: any, enumLabel: any) {
     return isNil(enumValue) || isNil(enumLabel) ? null : enumLabel[enumValue];
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/file-size-plain.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/file-size-plain.pipe.ts
index 186326278800e742fb80e860f070d0d7c308afc9..d18d294fa363a63a4e54686a8e8370d042195304 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/file-size-plain.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/file-size-plain.pipe.ts
@@ -23,7 +23,10 @@
  */
 import { Pipe, PipeTransform } from '@angular/core';
 
-@Pipe({ name: 'fileSizePlain' })
+@Pipe({
+  name: 'fileSizePlain',
+  standalone: true,
+})
 export class FileSizePlainPipe implements PipeTransform {
   readonly kB = 1024;
   readonly MB = Math.pow(this.kB, 2);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.ts
index 327058ea9ccd0dc223546898463addb963061d7f..db4f54706322fda80474fca4e0a6876876e84d50 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.ts
@@ -23,7 +23,10 @@
  */
 import { Pipe, PipeTransform } from '@angular/core';
 
-@Pipe({ name: 'fileSize' })
+@Pipe({
+  name: 'fileSize',
+  standalone: true,
+})
 export class FileSizePipe implements PipeTransform {
   readonly kB = 1024;
   readonly MB = Math.pow(this.kB, 2);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.ts
index fc33dcc8a3fa493b49c8b944a23231aed86e2e21..7d95383257bd84540653acef2140d74ecac8d267 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.ts
@@ -24,11 +24,12 @@
 import { Pipe, PipeTransform } from '@angular/core';
 import { formatFullDateWithTimeAndDay, formatFullDateWithTimeWithoutSeconds } from '../date.util';
 
-@Pipe({ name: 'formatDateWithTimePipe' })
+@Pipe({
+  name: 'formatDateWithTimePipe',
+  standalone: true,
+})
 export class FormatDateWithTimePipe implements PipeTransform {
   transform(date: Date, withSeconds: boolean = true): string {
-    return withSeconds ?
-        formatFullDateWithTimeAndDay(date)
-      : formatFullDateWithTimeWithoutSeconds(date);
+    return withSeconds ? formatFullDateWithTimeAndDay(date) : formatFullDateWithTimeWithoutSeconds(date);
   }
 }
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.ts
index 42694b05a7c55be2d0069129125e25d85ad2c107..f2835bd7e653ec1d7e0ebab6388e7cd1bf086c44 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.ts
@@ -24,7 +24,10 @@
 import { Pipe, PipeTransform } from '@angular/core';
 import { formatDateWithoutYearWithTime } from '../date.util';
 
-@Pipe({ name: 'formatDateWithoutYearWithTime' })
+@Pipe({
+  name: 'formatDateWithoutYearWithTime',
+  standalone: true,
+})
 export class FormatDateWithoutYearWithTimePipe implements PipeTransform {
   transform(date: Date): string {
     return formatDateWithoutYearWithTime(date);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/format-full-date.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/format-full-date.pipe.ts
index 250167b0bcf28a441ee744360e5f687676778da5..c9bec878f1e56d9fdb740cbcb1bc971d4cb4501a 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/format-full-date.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/format-full-date.pipe.ts
@@ -25,7 +25,10 @@ import { Pipe, PipeTransform } from '@angular/core';
 import { isString } from 'lodash-es';
 import { formatFullDate } from '../date.util';
 
-@Pipe({ name: 'formatFullDatePipe' })
+@Pipe({
+  name: 'formatFullDatePipe',
+  standalone: true,
+})
 export class FormatFullDatePipe implements PipeTransform {
   transform(date: Date | string): string {
     date = isString(date) ? new Date(date) : date;
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.ts
index 054f4f8b9c6226fd82eacc6b4b368a8955bfdef9..0d16ccd7a7dd6cd3c9c1404070de177f621e86b9 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.ts
@@ -24,7 +24,10 @@
 import { Pipe, PipeTransform } from '@angular/core';
 import { formatToPrettyDate } from '../date.util';
 
-@Pipe({ name: 'formatToPrettyDate' })
+@Pipe({
+  name: 'formatToPrettyDate',
+  standalone: true,
+})
 export class FormatToPrettyDatePipe implements PipeTransform {
   transform(date: Date): string {
     return formatToPrettyDate(date);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.ts
index c41e3024cd91c233094847e8ba43771d50c965a7..d936124c617e2ad94b4c901be87a9987714fc76c 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.ts
@@ -24,7 +24,10 @@
 import { Pipe, PipeTransform } from '@angular/core';
 import { Resource, ResourceUri, getUrl } from '@ngxp/rest';
 
-@Pipe({ name: 'getUrl' })
+@Pipe({
+  name: 'getUrl',
+  standalone: true,
+})
 export class GetUrlPipe implements PipeTransform {
   transform(resource: Resource, link: string): ResourceUri {
     return getUrl(resource, link);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts
index 1bf5a803a8af9e39cce2211b854db6871ed8907d..ec9083014c9e2527df574f2367d2bfd8b4e7d6dc 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts
@@ -26,7 +26,10 @@ import { Resource } from '@ngxp/rest';
 import { LinkRelationName } from '../resource/resource.model';
 import { hasAnyLink } from '../tech.util';
 
-@Pipe({ name: 'hasAnyLink' })
+@Pipe({
+  name: 'hasAnyLink',
+  standalone: true,
+})
 export class HasAnyLinkPipe implements PipeTransform {
   transform(resource: Resource, ...links: LinkRelationName[]): boolean {
     return hasAnyLink(resource, ...links);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.ts
index d2d15cb1eaa008c7ec87667924c230c1d9546365..34abe1a2f2d071b4419c93e64cd8950d9f96a6a4 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.ts
@@ -24,7 +24,10 @@
 import { Pipe, PipeTransform } from '@angular/core';
 import { Resource, hasLink } from '@ngxp/rest';
 
-@Pipe({ name: 'hasLink' })
+@Pipe({
+  name: 'hasLink',
+  standalone: true,
+})
 export class HasLinkPipe implements PipeTransform {
   transform(resource: Resource, link: string): boolean {
     return hasLink(resource, link);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/not-has-any-link.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-any-link.pipe.ts
index 19d64e5599d3b377cb9e4bac93782ce5e1cb988b..b04c9a7b613a2e6b03f1fec4f0115f902aa2629e 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/not-has-any-link.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-any-link.pipe.ts
@@ -26,7 +26,10 @@ import { Resource } from '@ngxp/rest';
 import { LinkRelationName } from '../resource/resource.model';
 import { notHasAnyLink } from '../tech.util';
 
-@Pipe({ name: 'notHasAnyLink' })
+@Pipe({
+  name: 'notHasAnyLink',
+  standalone: true,
+})
 export class NotHasAnyLinkPipe implements PipeTransform {
   transform(resource: Resource, ...links: LinkRelationName[]): boolean {
     return notHasAnyLink(resource, ...links);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.ts
index 8c8f879b0388c490b209dfdbf1a9abe126a721bc..018d49e877e90b56dd0ad0438c86b09b186af2f8 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.ts
@@ -24,7 +24,10 @@
 import { Pipe, PipeTransform } from '@angular/core';
 import { Resource, hasLink } from '@ngxp/rest';
 
-@Pipe({ name: 'notHasLink' })
+@Pipe({
+  name: 'notHasLink',
+  standalone: true,
+})
 export class NotHasLinkPipe implements PipeTransform {
   transform(resource: Resource, link: string): boolean {
     return !hasLink(resource, link);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.ts
index 537bd91348a6722854d153bc7c7ceec53aff17a8..dbb7025753327feff619bd1a0559951bf8b6ebe0 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.ts
@@ -28,7 +28,10 @@ import { LinkRelationName } from '../resource/resource.model';
 import { ListResource } from '../resource/resource.util';
 import { EMPTY_ARRAY } from '../tech.util';
 
-@Pipe({ name: 'toEmbeddedResources' })
+@Pipe({
+  name: 'toEmbeddedResources',
+  standalone: true,
+})
 export class ToEmbeddedResourcesPipe implements PipeTransform {
   transform(listResource: ListResource, linkRel: LinkRelationName): Resource[] {
     if (isNil(listResource) || isNil(linkRel)) return EMPTY_ARRAY;
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.ts
index d102cc20129903fa363c4c5b7708ee4c7cb70e6b..9ac1e3aaa42f8121843ce0effb45caa1c020edeb 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.ts
@@ -26,7 +26,10 @@ import { Resource, ResourceUri } from '@ngxp/rest';
 import { isNil } from 'lodash-es';
 import { toResourceUri } from '../resource/resource.util';
 
-@Pipe({ name: 'toResourceUri' })
+@Pipe({
+  name: 'toResourceUri',
+  standalone: true,
+})
 export class ToResourceUriPipe implements PipeTransform {
   transform(resource: Resource, linkRel?: string): ResourceUri {
     if (isNil(resource)) {
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.ts
index f0e66e4fd889a11a9908cb32a760c95eb6e454e3..ab1c286a7c1e5a1a593a4c4d58f41593be42ef21 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.ts
@@ -24,7 +24,10 @@
 import { Pipe, PipeTransform } from '@angular/core';
 import { isPast, isToday, isValid, parseISO } from 'date-fns';
 
-@Pipe({ name: 'toTrafficLightTooltip' })
+@Pipe({
+  name: 'toTrafficLightTooltip',
+  standalone: true,
+})
 export class ToTrafficLightTooltipPipe implements PipeTransform {
   transform(date: Date): string {
     date = isValid(date) ? date : parseISO(date as unknown as string);
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.ts
index 83f4e421d1ec0453adeb716aec47eb06689407dc..1763a26143e09e51458b019dab3a402e78ea0e3d 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.ts
@@ -24,7 +24,10 @@
 import { Pipe, PipeTransform } from '@angular/core';
 import { isPast, isToday, isValid, parseISO } from 'date-fns';
 
-@Pipe({ name: 'toTrafficLight' })
+@Pipe({
+  name: 'toTrafficLight',
+  standalone: true,
+})
 export class ToTrafficLightPipe implements PipeTransform {
   transform(date: Date): string {
     date = isValid(date) ? date : parseISO(date as unknown as string);
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts
index 76fac14c0bfe11b7f9b97a634e922aad14a417ca..60c4640d92c10a70d0bec7d763d80a8f9618ff33 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.spec.ts
@@ -29,7 +29,7 @@ import { cold } from 'jest-marbles';
 import { DummyLinkRel, DummyListLinkRel } from 'libs/tech-shared/test/dummy';
 import { createDummyListResource, createDummyResource, createFilledDummyListResource } from 'libs/tech-shared/test/resource';
 import { BehaviorSubject, Observable, of } from 'rxjs';
-import { singleCold, singleHot } from '../../../test/marbles';
+import { multipleCold, singleCold, singleHot } from '../../../test/marbles';
 import { EMPTY_ARRAY } from '../tech.util';
 import { ResourceListService } from './list-resource.service';
 import { CreateResourceData, LinkRelationName, ListItemResource, ListResourceServiceConfig } from './resource.model';
@@ -84,16 +84,22 @@ describe('ListResourceService', () => {
       isInvalidResourceCombinationSpy = jest.spyOn(ResourceUtil, 'isInvalidResourceCombination').mockReturnValue(true);
     });
 
+    it('should have debounce', () => {
+      service.getList().subscribe();
+
+      expect(service.handleChanges).not.toHaveBeenCalled();
+    });
+
     it('should handle config resource changed', fakeAsync(() => {
       service.getList().subscribe();
-      tick();
+      tick(50);
 
       expect(service.handleChanges).toHaveBeenCalledWith(listStateResource, baseResource);
     }));
 
     it('should call isInvalidResourceCombinationSpy', fakeAsync(() => {
       service.getList().subscribe();
-      tick();
+      tick(50);
 
       expect(isInvalidResourceCombinationSpy).toHaveBeenCalled();
     }));
@@ -305,25 +311,27 @@ describe('ListResourceService', () => {
 
   describe('create', () => {
     const toCreate: unknown = {};
+    const returnResource: Resource = createDummyResource();
 
     beforeEach(() => {
       service.listResource.value.resource = listResource;
+      resourceRepository.createResource.mockReturnValue(of(returnResource));
     });
 
     it('should throw error if link is not present', () => {
       service.listResource.next(createStateResource(createDummyListResource()));
 
-      expect(() => service.create(toCreate)).toThrowError('No creation link exists.');
+      expect(() => service.create(toCreate)).toThrow('No creation link exists.');
     });
 
     it('should throw error if list resource is empty', () => {
       service.listResource.next(createEmptyStateResource());
 
-      expect(() => service.create(toCreate)).toThrowError('No list resource available.');
+      expect(() => service.create(toCreate)).toThrow('No list resource available.');
     });
 
     it('should trigger resourceLoader', () => {
-      service.create(toCreate);
+      service.create(toCreate).subscribe();
 
       const createResourceData: CreateResourceData<ListResource> = {
         resource: listResource,
@@ -335,11 +343,11 @@ describe('ListResourceService', () => {
 
     it('should return value', () => {
       const returnResource: Resource = createDummyResource();
-      resourceRepository.createResource.mockReturnValue(singleHot(returnResource));
+      resourceRepository.createResource.mockReturnValue(singleCold(returnResource, '-a'));
 
-      const createdResource: Observable<Resource> = service.create(toCreate);
+      const createdResource: Observable<StateResource<Resource>> = service.create(toCreate);
 
-      expect(createdResource).toBeObservable(singleCold(returnResource));
+      expect(createdResource).toBeObservable(multipleCold(createEmptyStateResource(true), createStateResource(returnResource)));
     });
   });
 
@@ -437,7 +445,7 @@ describe('ListResourceService', () => {
     it('should throw error if prev link is not present', () => {
       service.listResource.next(createStateResource(listResource));
 
-      expect(() => service.prev()).toThrowError('There is no previous page.');
+      expect(() => service.prev()).toThrow('There is no previous page.');
     });
 
     it('should call resourceLoader with prev link', () => {
@@ -465,7 +473,7 @@ describe('ListResourceService', () => {
     it('should throw error if next link is not present', () => {
       service.listResource.next(createStateResource(listResource));
 
-      expect(() => service.next()).toThrowError('There is no next page.');
+      expect(() => service.next()).toThrow('There is no next page.');
     });
 
     it('should call resourceLoader with next link', () => {
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts
index 50cee3aa72fb828211d7a70dadc5cdca3d5f55c2..852a8299c56d256d93bf778e9600ab0717edc00f 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/list-resource.service.ts
@@ -23,7 +23,7 @@
  */
 import { Resource, ResourceUri, getUrl, hasLink } from '@ngxp/rest';
 import { isEqual, isNil, isNull } from 'lodash-es';
-import { BehaviorSubject, Observable, combineLatest, filter, first, map, startWith, tap } from 'rxjs';
+import { BehaviorSubject, Observable, combineLatest, debounceTime, filter, first, map, startWith, tap } from 'rxjs';
 import { isNotNull, isNotUndefined } from '../tech.util';
 import { CreateResourceData, ListItemResource, ListResourceServiceConfig } from './resource.model';
 import { ResourceRepository } from './resource.repository';
@@ -58,11 +58,12 @@ export class ResourceListService<B extends Resource, T extends ListResource, I e
 
   constructor(
     private config: ListResourceServiceConfig<B>,
-    private repository: ResourceRepository,
+    private repository: ResourceRepository<I>,
   ) {}
 
   public getList(): Observable<StateResource<T>> {
     return combineLatest([this.listResource.asObservable(), this.getConfigResource()]).pipe(
+      debounceTime(50),
       tap(([stateResource, configResource]) => {
         this.handleChanges(stateResource, configResource);
       }),
@@ -105,9 +106,12 @@ export class ResourceListService<B extends Resource, T extends ListResource, I e
     this.listResource.next(createEmptyStateResource());
   }
 
-  public create(toCreate: unknown): Observable<Resource> {
+  public create(toCreate: unknown): Observable<StateResource<I>> {
     this.verifyBeforeCreation();
-    return this.repository.createResource(this.buildCreateResourceData(toCreate, this.config.createLinkRel));
+    return this.repository.createResource(this.buildCreateResourceData(toCreate, this.config.createLinkRel)).pipe(
+      map((listItemResource: I) => createStateResource(listItemResource)),
+      startWith(createEmptyStateResource<I>(true)),
+    );
   }
 
   private verifyBeforeCreation(): void {
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.repository.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.repository.spec.ts
index bbd264a3587623c8af04f1f293fb0c5e3c6a639c..cade44ce12d85185a6b00d1804d6bc22ba4f27e3 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/resource.repository.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.repository.spec.ts
@@ -22,6 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { mock, useFromMock } from '@alfa-client/test-utils';
+import { TestBed } from '@angular/core/testing';
 import { faker } from '@faker-js/faker';
 import { Resource, ResourceFactory, ResourceUri, getUrl } from '@ngxp/rest';
 import { DummyLinkRel, DummyListLinkRel } from 'libs/tech-shared/test/dummy';
@@ -42,7 +43,11 @@ describe('ResourceRepository', () => {
     resourceFactory.from.mockReturnValue(resourceWrapper);
     resourceFactory.fromId.mockReturnValue(resourceWrapper);
 
-    repository = new ResourceRepository(useFromMock(resourceFactory));
+    TestBed.configureTestingModule({
+      providers: [{ provide: ResourceFactory, useValue: useFromMock(resourceFactory) }],
+    });
+
+    repository = TestBed.inject(ResourceRepository);
   });
 
   it('should be created', () => {
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.repository.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.repository.ts
index d8f90a78eb269f096a4f159237d07926ad130881..33d37b87af453f7fb777dd2ca69d8cf7a8f394c4 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/resource.repository.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.repository.ts
@@ -21,17 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Injectable } from '@angular/core';
-import { Resource, ResourceFactory, ResourceUri, getUrl } from '@ngxp/rest';
+import { inject, Injectable } from '@angular/core';
+import { getUrl, Resource, ResourceFactory, ResourceUri } from '@ngxp/rest';
 import { Observable } from 'rxjs';
 import { CreateResourceData, LinkRelationName, SaveResourceData } from './resource.model';
 import { ListResource } from './resource.util';
 
 @Injectable({ providedIn: 'root' })
-export class ResourceRepository {
-  static SEARCH_PARAM: string = 'searchBy';
+export class ResourceRepository<T extends Resource = Resource> {
+  private resourceFactory = inject(ResourceFactory);
 
-  constructor(private resourceFactory: ResourceFactory) {}
+  static SEARCH_PARAM: string = 'searchBy';
 
   public getListResource(resource: Resource, linkRel: string): Observable<ListResource> {
     const uriWithoutParameter: string = this.getUrlWithoutParameter(getUrl(resource, linkRel));
@@ -45,7 +45,7 @@ export class ResourceRepository {
     return uri;
   }
 
-  public createResource(createResourceData: CreateResourceData<Resource>): Observable<Resource> {
+  public createResource(createResourceData: CreateResourceData<Resource>): Observable<T> {
     return this.resourceFactory.from(createResourceData.resource).post(createResourceData.linkRel, createResourceData.toCreate);
   }
 
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts
index 7a045fa7514ae98cf24c58209a709551fb0def98..87869c5c4e0aa1dff4a3050b95ed26abd476c0d6 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts
@@ -82,16 +82,22 @@ describe('ResourceService', () => {
       isInvalidResourceCombinationSpy = jest.spyOn(ResourceUtil, 'isInvalidResourceCombination').mockReturnValue(true);
     });
 
+    it('should have debounce', () => {
+      service.get().subscribe();
+
+      expect(service.handleResourceChanges).not.toHaveBeenCalled();
+    });
+
     it('should handle config resource changed', fakeAsync(() => {
       service.get().subscribe();
-      tick();
+      tick(50);
 
       expect(service.handleResourceChanges).toHaveBeenCalledWith(stateResource, configResource);
     }));
 
     it('should call isInvalidResourceCombinationSpy', fakeAsync(() => {
       service.get().subscribe();
-      tick();
+      tick(50);
 
       expect(isInvalidResourceCombinationSpy).toHaveBeenCalled();
     }));
@@ -497,7 +503,7 @@ describe('ResourceService', () => {
       const thrownError$: Observable<StateResource<unknown>> = service.handleError(error);
 
       expect.assertions(1);
-      expect(lastValueFrom(thrownError$)).rejects.toThrowError('Internal Server Error');
+      expect(lastValueFrom(thrownError$)).rejects.toThrow('Internal Server Error');
     });
   });
 
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts
index 990005991995cce82ed108fe0c6f7cd64a1ac1c0..1953e85ff4691dec3b95771a73f1bc1c7283efd1 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts
@@ -24,7 +24,20 @@
 import { HttpErrorResponse } from '@angular/common/http';
 import { getUrl, hasLink, Resource, ResourceUri } from '@ngxp/rest';
 import { isEqual, isNull } from 'lodash-es';
-import { BehaviorSubject, catchError, combineLatest, filter, first, map, Observable, of, startWith, tap, throwError } from 'rxjs';
+import {
+  BehaviorSubject,
+  catchError,
+  combineLatest,
+  debounceTime,
+  filter,
+  first,
+  map,
+  Observable,
+  of,
+  startWith,
+  tap,
+  throwError,
+} from 'rxjs';
 import { isUnprocessableEntity } from '../http.util';
 import { HttpError } from '../tech.model';
 import { isNotNull } from '../tech.util';
@@ -57,6 +70,7 @@ export abstract class ResourceService<B extends Resource, T extends Resource> {
 
   public get(): Observable<StateResource<T>> {
     return combineLatest([this.stateResource.asObservable(), this.getConfigResource()]).pipe(
+      debounceTime(50),
       tap(([stateResource, configResource]) => this.handleResourceChanges(stateResource, configResource)),
       filter(([stateResource]) => !isInvalidResourceCombination(stateResource, this.configResource)),
       mapToFirst<T, B>(),
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts
index 068bdad4584c8956198ed8aa008b2b9a5516cc96..3bfc293f96169bd19c2db03eb6c3030a15d8a8f1 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts
@@ -22,7 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Resource } from '@ngxp/rest';
-import { createCommandStateResource } from '../../../../command-shared/test/command';
+import { createCommandStateResource } from 'libs/command-shared/test/command';
 import { DummyListLinkRel } from '../../../test/dummy';
 import { createApiError } from '../../../test/error';
 import { createDummyListResource, createDummyResource, toResource } from '../../../test/resource';
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.util.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.util.ts
index e90e4a2702d5185cde6f244b5075bfc237952026..201e8100c1682cafdeb57d86521d0b60b99a7b36 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/resource.util.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.util.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Resource, ResourceUri, getEmbeddedResource, getUrl, hasLink } from '@ngxp/rest';
+import { getEmbeddedResource, getUrl, hasLink, Resource, ResourceUri } from '@ngxp/rest';
 import { isEqual, isNil, isNull } from 'lodash-es';
 import { HttpError } from '../tech.model';
 import { encodeUrlForEmbedding, isNotNull } from '../tech.util';
@@ -42,6 +42,10 @@ export function createEmptyStateResource<T>(loading: boolean = false): StateReso
   return createStateResource(null, loading);
 }
 
+export function createLoadingStateResource<T>(): StateResource<T> {
+  return createEmptyStateResource(true);
+}
+
 export function createStateResource<T>(resource: T, loading: boolean = false): StateResource<T> {
   return { loading, loaded: !isNil(resource), reload: false, resource };
 }
@@ -50,10 +54,7 @@ export function createErrorStateResource<T>(error: HttpError): StateResource<any
   return { ...createEmptyStateResource<T>(), error, loaded: true };
 }
 
-export function doIfLoadingRequired(
-  stateResource: StateResource<any>,
-  runable: () => void,
-): boolean {
+export function doIfLoadingRequired(stateResource: StateResource<any>, runable: () => void): boolean {
   if (isLoadingRequired(stateResource)) {
     runable();
     return true;
@@ -82,10 +83,7 @@ export function toResourceUri(resource: Resource, linkRel?: string): string {
   return encodeUrlForEmbedding(url);
 }
 
-export function doOnValidStateResource(
-  stateResource: StateResource<Resource>,
-  actionOnValid: () => void,
-): void {
+export function doOnValidStateResource(stateResource: StateResource<Resource>, actionOnValid: () => void): void {
   if (isValidStateResource(stateResource)) actionOnValid();
 }
 
@@ -93,10 +91,7 @@ export function isValidStateResource(stateResource: StateResource<unknown>): boo
   return stateResource.loaded && isNotNull(stateResource.resource);
 }
 
-export function getEmbeddedResources<T>(
-  stateResource: StateResource<Resource>,
-  linkRel: string,
-): T[] {
+export function getEmbeddedResources<T>(stateResource: StateResource<Resource>, linkRel: string): T[] {
   if (isNil(stateResource) || isNil(stateResource.resource)) {
     return [];
   }
@@ -115,12 +110,8 @@ export function containsLoading(stateResources: StateResource<Resource>[]): bool
   return stateResources.findIndex((stateResources) => stateResources.loading) > -1;
 }
 
-export function getSuccessfullyLoaded<T extends Resource>(
-  stateResources: StateResource<T>[],
-): StateResource<T>[] {
-  return stateResources.filter(
-    (stateResource) => isLoaded(stateResource) && !hasStateResourceError(stateResource),
-  );
+export function getSuccessfullyLoaded<T extends Resource>(stateResources: StateResource<T>[]): StateResource<T>[] {
+  return stateResources.filter((stateResource) => isLoaded(stateResource) && !hasStateResourceError(stateResource));
 }
 
 export function isEmptyStateResource<T extends Resource>(stateResource: StateResource<T>): boolean {
@@ -135,8 +126,7 @@ export function isInvalidResourceCombination<T extends Resource, B extends Resou
   return (
     stateResource.reload ||
     (!stateResource.loading &&
-      ((!stateResource.loaded && isNotNull(baseResource)) ||
-        (stateResource.loaded && isNull(baseResource))))
+      ((!stateResource.loaded && isNotNull(baseResource)) || (stateResource.loaded && isNull(baseResource))))
   );
 }
 
diff --git a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts
index 47119c7a1b2aba5e369af100593d58569dee002a..05e53e161df3758106375d53082cbf77dcd697e2 100644
--- a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts
@@ -25,9 +25,9 @@ import { CommandResource } from '@alfa-client/command-shared';
 import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
 import { Resource } from '@ngxp/rest';
 import { cold } from 'jest-marbles';
+import { createCommandResource } from 'libs/command-shared/test/command';
 import { createInvalidParam, createProblemDetail } from 'libs/tech-shared/test/error';
 import { Observable, of } from 'rxjs';
-import { createCommandResource } from '../../../../command-shared/test/command';
 import {
   StateResource,
   createEmptyStateResource,
diff --git a/alfa-client/libs/tech-shared/src/lib/tech-shared.module.spec.ts b/alfa-client/libs/tech-shared/src/lib/tech-shared.module.spec.ts
deleted file mode 100644
index 740aaee232ce8c6bcebc45bf4b5f585cd504e530..0000000000000000000000000000000000000000
--- a/alfa-client/libs/tech-shared/src/lib/tech-shared.module.spec.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { TechSharedModule } from './tech-shared.module';
-import { TestBed } from '@angular/core/testing';
-
-describe('TechSharedModule', () => {
-  beforeEach(() => {
-    TestBed.configureTestingModule({
-      imports: [TechSharedModule],
-    }).compileComponents();
-  });
-
-  it('should create', () => {
-    expect(TechSharedModule).toBeDefined();
-  });
-});
diff --git a/alfa-client/libs/tech-shared/src/lib/tech-shared.module.ts b/alfa-client/libs/tech-shared/src/lib/tech-shared.module.ts
deleted file mode 100644
index be795a66c9f36138e235125f6bd2995ce64da5da..0000000000000000000000000000000000000000
--- a/alfa-client/libs/tech-shared/src/lib/tech-shared.module.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { CommonModule } from '@angular/common';
-import { HTTP_INTERCEPTORS } from '@angular/common/http';
-import { Injector, NgModule } from '@angular/core';
-import { HttpBinaryFileInterceptor } from './interceptor/http-binary-file.interceptor';
-import { HttpXsrfInterceptor } from './interceptor/http-xsrf.interceptor';
-import { XhrInterceptor } from './interceptor/xhr.interceptor';
-import { ConvertApiErrorToErrorMessagesPipe } from './pipe/convert-api-error-to-error-messages.pipe';
-import { ConvertForDataTestPipe } from './pipe/convert-for-data-test.pipe';
-import { ConvertProblemDetailToErrorMessagesPipe } from './pipe/convert-problem-detail-to-error-messages.pipe';
-import { ConvertToBooleanPipe } from './pipe/convert-to-boolean.pipe';
-import { EnumToLabelPipe } from './pipe/enum-to-label.pipe';
-import { FileSizePlainPipe } from './pipe/file-size-plain.pipe';
-import { FileSizePipe } from './pipe/file-size.pipe';
-import { FormatDateWithTimePipe } from './pipe/format-date-with-time.pipe';
-import { FormatDateWithoutYearWithTimePipe } from './pipe/format-date-without-year-with-time.pipe';
-import { FormatFullDatePipe } from './pipe/format-full-date.pipe';
-import { FormatToPrettyDatePipe } from './pipe/format-to-pretty-date.pipe';
-import { GetUrlPipe } from './pipe/get-url.pipe';
-import { HasAnyLinkPipe } from './pipe/has-any-link.pipe';
-import { HasLinkPipe } from './pipe/has-link.pipe';
-import { NotHasAnyLinkPipe } from './pipe/not-has-any-link.pipe';
-import { NotHasLinkPipe } from './pipe/not-has-link.pipe';
-import { ToEmbeddedResourcesPipe } from './pipe/to-embedded-resource.pipe';
-import { ToResourceUriPipe } from './pipe/to-resource-uri.pipe';
-import { ToTrafficLightTooltipPipe } from './pipe/to-traffic-light-tooltip.pipe';
-import { ToTrafficLightPipe } from './pipe/to-traffic-light.pipe';
-
-@NgModule({
-  imports: [CommonModule],
-  declarations: [
-    FormatToPrettyDatePipe,
-    FormatFullDatePipe,
-    EnumToLabelPipe,
-    FormatDateWithTimePipe,
-    FormatDateWithoutYearWithTimePipe,
-    HasLinkPipe,
-    HasAnyLinkPipe,
-    NotHasLinkPipe,
-    NotHasAnyLinkPipe,
-    ToResourceUriPipe,
-    ToTrafficLightPipe,
-    ToTrafficLightTooltipPipe,
-    ToEmbeddedResourcesPipe,
-    ConvertForDataTestPipe,
-    FileSizePipe,
-    FileSizePlainPipe,
-    GetUrlPipe,
-    ConvertToBooleanPipe,
-    ConvertApiErrorToErrorMessagesPipe,
-    ConvertProblemDetailToErrorMessagesPipe,
-  ],
-  exports: [
-    FormatToPrettyDatePipe,
-    FormatFullDatePipe,
-    EnumToLabelPipe,
-    FormatDateWithTimePipe,
-    FormatDateWithoutYearWithTimePipe,
-    HasLinkPipe,
-    HasAnyLinkPipe,
-    NotHasLinkPipe,
-    NotHasAnyLinkPipe,
-    ToResourceUriPipe,
-    ToTrafficLightPipe,
-    ToTrafficLightTooltipPipe,
-    ToEmbeddedResourcesPipe,
-    ConvertForDataTestPipe,
-    FileSizePipe,
-    FileSizePlainPipe,
-    GetUrlPipe,
-    ConvertToBooleanPipe,
-    ConvertApiErrorToErrorMessagesPipe,
-    ConvertProblemDetailToErrorMessagesPipe,
-  ],
-  providers: [
-    {
-      provide: HTTP_INTERCEPTORS,
-      useClass: XhrInterceptor,
-      multi: true,
-    },
-    {
-      provide: HTTP_INTERCEPTORS,
-      useClass: HttpXsrfInterceptor,
-      multi: true,
-    },
-    {
-      provide: HTTP_INTERCEPTORS,
-      useClass: HttpBinaryFileInterceptor,
-      multi: true,
-    },
-  ],
-})
-export class TechSharedModule {
-  public static injector: Injector;
-
-  constructor(private injector: Injector) {
-    TechSharedModule.injector = this.injector;
-  }
-}
diff --git a/alfa-client/libs/tech-shared/test/data-test.ts b/alfa-client/libs/tech-shared/test/data-test.ts
index 98db6b1f6fb58fa31cc9353c8440c442bbfb4112..795b2dee30c083f71da5842c2cc64738c3dd9da4 100644
--- a/alfa-client/libs/tech-shared/test/data-test.ts
+++ b/alfa-client/libs/tech-shared/test/data-test.ts
@@ -38,3 +38,7 @@ export function getDataTestIdOf(value: string): string {
 export function getDataTestIdAttributeOf(value: string): string {
   return `[dataTestId="${value}"]`;
 }
+
+export function getDynamicDataTestIdAttributOf(value: string): string {
+  return `[ng-reflect-data-test-id="${value}"]`;
+}
diff --git a/alfa-client/libs/tech-shared/test/marbles.ts b/alfa-client/libs/tech-shared/test/marbles.ts
index ea8e04237504cc8104ddb569ce574dd66c6ad362..fecda8769f38a80dd34c693c9ca39bf175a69eef 100644
--- a/alfa-client/libs/tech-shared/test/marbles.ts
+++ b/alfa-client/libs/tech-shared/test/marbles.ts
@@ -34,3 +34,7 @@ export function singleCold(object: any, frame: string = 'a'): ObservableWithSubs
 export function singleColdCompleted(object: any, frame: string = 'a'): ObservableWithSubscriptions {
   return cold(`(${frame}|)`, { a: object });
 }
+
+export function multipleCold(first: any, second: any): ObservableWithSubscriptions {
+  return cold('ab', { a: first, b: second });
+}
diff --git a/alfa-client/libs/test-utils/src/lib/mocking.ts b/alfa-client/libs/test-utils/src/lib/mocking.ts
index a5e3137a17d3fed7c81cd72e350599195cd079f7..0fb616db60420994880e9acfddec1d0d37e10486 100644
--- a/alfa-client/libs/test-utils/src/lib/mocking.ts
+++ b/alfa-client/libs/test-utils/src/lib/mocking.ts
@@ -47,3 +47,9 @@ export function mockClass(clazz: any): Mock<any> {
 export function createSpy(clazz: any, functionName: string) {
   return jest.spyOn(clazz.prototype, functionName);
 }
+
+export function mockGetValue(object: any, name: string, returnValue: any): void {
+  Object.defineProperty(object, name, {
+    get: jest.fn(() => returnValue),
+  });
+}
diff --git a/alfa-client/libs/test-utils/src/lib/model.ts b/alfa-client/libs/test-utils/src/lib/model.ts
index d89ed415513a8528908c72641e609bc43c86c7c7..1094ac96376b5a8d2d81cf5a7ebf13c69aa2a550 100644
--- a/alfa-client/libs/test-utils/src/lib/model.ts
+++ b/alfa-client/libs/test-utils/src/lib/model.ts
@@ -29,3 +29,7 @@ export interface EventData<T> {
   name: string;
   data?: unknown;
 }
+
+export const MockEvent = {
+  CLICK: 'clickEmitter',
+};
diff --git a/alfa-client/libs/ui/src/index.ts b/alfa-client/libs/ui/src/index.ts
index 8571055878c35b394402ba51f45953717cc14090..2db371a18e23b0b2d01eb93bcf1738bd8ef43f61 100644
--- a/alfa-client/libs/ui/src/index.ts
+++ b/alfa-client/libs/ui/src/index.ts
@@ -35,7 +35,7 @@ export * from './lib/ui/editor/autocomplete-editor/autocomplete-editor.component
 export * from './lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component';
 export * from './lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.model';
 export * from './lib/ui/editor/date-editor/date-editor.component';
-export * from './lib/ui/editor/text-editor/text-editor.component';
+export * from './lib/ui/editor/text-editor/ozgcloud-text-editor.component';
 export * from './lib/ui/editor/textarea-editor/textarea-editor.component';
 export * from './lib/ui/expansion-panel/expansion-panel.component';
 export * from './lib/ui/file-upload/file-upload.component';
@@ -50,10 +50,11 @@ export * from './lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozg
 export * from './lib/ui/ozgcloud-dialog/ozgcloud-dialog.result';
 export * from './lib/ui/ozgcloud-dialog/ozgcloud-dialog.service';
 export * from './lib/ui/ozgcloud-icon/ozgcloud-icon.component';
+export * from './lib/ui/ozgcloud-menu/ozgcloud-menu.component';
 export * from './lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component';
 export * from './lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component';
 export * from './lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component';
+export * from './lib/ui/slide-toggle/slide-toggle.component';
 export * from './lib/ui/spinner-transparency/spinner-transparency.component';
 export * from './lib/ui/spinner/spinner.component';
 export * from './lib/ui/subnavigation/subnavigation.component';
-export * from './lib/ui/ui.module';
diff --git a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.spec.ts b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.spec.ts
index b39b315dbd6786a3a84db361281b369d5936319f..c773235e923ae95da36cb21391770c50c7abff31 100644
--- a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.spec.ts
@@ -32,8 +32,7 @@ describe('AppIconComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [AppIconComponent],
-      imports: [MatIcon, MatIconTestingModule],
+      imports: [MatIcon, MatIconTestingModule, AppIconComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.ts b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.ts
index 0b93d2c2448eebae700b8a64cefa5972962c63d2..a09417be79e311588262813e850535ef718acc62 100644
--- a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.ts
+++ b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.ts
@@ -22,10 +22,13 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component } from '@angular/core';
+import { MatIcon } from '@angular/material/icon';
 
 @Component({
   selector: 'ozgcloud-app-icon',
   templateUrl: './app-icon.component.html',
   styleUrls: ['./app-icon.component.scss'],
+  standalone: true,
+  imports: [MatIcon],
 })
 export class AppIconComponent {}
diff --git a/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.spec.ts b/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.spec.ts
index 7d0696427c9216a9e49c27678c1f5f4a4705fc39..a5ce3c8c702872b119526e7d95378a83519890a4 100644
--- a/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.spec.ts
@@ -37,8 +37,7 @@ describe('PostfachIconComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [PostfachIconComponent],
-      imports: [MatIconTestingModule, MatBadgeModule, MatBadge, MatIcon],
+      imports: [MatIconTestingModule, MatBadgeModule, MatBadge, MatIcon, PostfachIconComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.ts b/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.ts
index 3ad4d01502824949af23604158bf16a87a285663..684c8781ea0697ab90cba9389672c905ca6eac66 100644
--- a/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.ts
+++ b/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.ts
@@ -22,11 +22,15 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, Input } from '@angular/core';
+import { MatBadge } from '@angular/material/badge';
+import { MatIcon } from '@angular/material/icon';
 
 @Component({
   selector: 'ozgcloud-postfach-icon',
   templateUrl: './postfach-icon.component.html',
   styleUrls: ['./postfach-icon.component.scss'],
+  standalone: true,
+  imports: [MatIcon, MatBadge],
 })
 export class PostfachIconComponent {
   @Input() showBadge: boolean = false;
diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.spec.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.spec.ts
index a591c897b1738a689568c6a03ced8812f7dcf382..51f5f1b134195d3ac4b0805afe63784571e084ae 100644
--- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.spec.ts
@@ -36,8 +36,7 @@ describe('SnackbarCloseButtonComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [SnackbarCloseButtonComponent],
-      imports: [MatIcon],
+      imports: [MatIcon, SnackbarCloseButtonComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.ts
index 53d5bc40186fedcf833b1c0fff3d36043b9e94a5..6a4ea9b58c108f02f1d77900517f673d8d6abc85 100644
--- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.ts
+++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.ts
@@ -22,11 +22,15 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, EventEmitter, Output } from '@angular/core';
+import { MatIconButton } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
 
 @Component({
   selector: 'ozgcloud-snackbar-close-button',
   templateUrl: './snackbar-close-button.component.html',
   styleUrls: ['./snackbar-close-button.component.scss'],
+  standalone: true,
+  imports: [MatIconButton, MatIcon],
 })
 export class SnackbarCloseButtonComponent {
   @Output() close: EventEmitter<void> = new EventEmitter();
diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts
index 1421a91855149895f44da33bfd0ca59bde2562b3..c18e96c89e4b583be68444c10eb324c6a6def687 100644
--- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { mock } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatIconModule } from '@angular/material/icon';
 import { MAT_SNACK_BAR_DATA, MatSnackBarRef } from '@angular/material/snack-bar';
-import { mock } from '@alfa-client/test-utils';
 import { MockComponent } from 'ng-mocks';
 import { SnackbarCloseButtonComponent } from '../snackbar-close-button/snackbar-close-button.component';
 import { SnackBarData } from '../snackbar.model';
@@ -39,8 +39,7 @@ describe('SnackbarErrorComponent', () => {
 
   beforeEach(async () => {
     TestBed.configureTestingModule({
-      imports: [MatIconModule],
-      declarations: [SnackbarErrorComponent, MockComponent(SnackbarCloseButtonComponent)],
+      imports: [MatIconModule, SnackbarErrorComponent, MockComponent(SnackbarCloseButtonComponent)],
       providers: [
         {
           provide: MAT_SNACK_BAR_DATA,
diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts
index 19a27fa8e545a2a41163231130c27e314c36546e..06b3709ca34f4d498af78de05fd014f6051fa089 100644
--- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts
+++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts
@@ -21,20 +21,21 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Inject } from '@angular/core';
+import { Component, inject } from '@angular/core';
 import { MAT_SNACK_BAR_DATA, MatSnackBarRef } from '@angular/material/snack-bar';
+import { SnackbarCloseButtonComponent } from '../snackbar-close-button/snackbar-close-button.component';
 import { SnackBarData } from '../snackbar.model';
 
 @Component({
   selector: 'ozgcloud-snackbar-error',
   templateUrl: './snackbar-error.component.html',
   styleUrls: ['./snackbar-error.component.scss'],
+  standalone: true,
+  imports: [SnackbarCloseButtonComponent],
 })
 export class SnackbarErrorComponent {
-  constructor(
-    @Inject(MAT_SNACK_BAR_DATA) public data: SnackBarData,
-    public snackBarRef: MatSnackBarRef<SnackbarErrorComponent>,
-  ) {}
+  public snackBarRef = inject(MatSnackBarRef<SnackbarErrorComponent>);
+  public data = inject<SnackBarData>(MAT_SNACK_BAR_DATA);
 
   get message(): string {
     return this.data.message;
diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html
index 82103c833a2a75df2b91c919f2525931faffcd0e..fbf8300ce5d82495204a97a46483af9dcfe385c6 100644
--- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html
+++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html
@@ -25,14 +25,8 @@
 -->
 <div data-test-id="snackbar-message">{{ message }}</div>
 
-<button
-  *ngIf="showRevokeButton()"
-  data-test-id="snackbar-revoke-button"
-  mat-button
-  color="primary"
-  (click)="revoke()"
->
-  Rückgängig
-</button>
+@if (showRevokeButton()) {
+  <button data-test-id="snackbar-revoke-button" mat-button color="primary" (click)="revoke()">Rückgängig</button>
+}
 
 <ozgcloud-snackbar-close-button (close)="close()"></ozgcloud-snackbar-close-button>
diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts
index 55ce0007b68eb332719107661899b82c67c8cd59..62d87fd9bfd6983d7f217c6484a9ae937f237fc2 100644
--- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { mock } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatIconModule } from '@angular/material/icon';
 import { MAT_SNACK_BAR_DATA, MatSnackBarModule, MatSnackBarRef } from '@angular/material/snack-bar';
-import { mock } from '@alfa-client/test-utils';
 import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel';
 import { createCommandResource } from 'libs/command-shared/test/command';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
@@ -47,8 +47,7 @@ describe('SnackbarInfoComponent', () => {
 
   beforeEach(async () => {
     TestBed.configureTestingModule({
-      imports: [MatSnackBarModule, MatIconModule],
-      declarations: [SnackbarInfoComponent, MockComponent(SnackbarCloseButtonComponent)],
+      imports: [MatSnackBarModule, MatIconModule, SnackbarInfoComponent, MockComponent(SnackbarCloseButtonComponent)],
       providers: [
         {
           provide: MAT_SNACK_BAR_DATA,
diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts
index e1431695e2ff15b6959bf0e7d6a30623f9cb6248..cad0471768531cac51e1227280b62d528f967309 100644
--- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts
+++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts
@@ -21,22 +21,24 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Inject } from '@angular/core';
-import { MAT_SNACK_BAR_DATA, MatSnackBarRef } from '@angular/material/snack-bar';
 import { isRevokeable } from '@alfa-client/command-shared';
+import { Component, inject } from '@angular/core';
+import { MatButton } from '@angular/material/button';
+import { MAT_SNACK_BAR_DATA, MatSnackBarRef } from '@angular/material/snack-bar';
 import { isUndefined } from 'lodash-es';
+import { SnackbarCloseButtonComponent } from '../snackbar-close-button/snackbar-close-button.component';
 import { SnackBarData } from '../snackbar.model';
 
 @Component({
   selector: 'ozgcloud-snackbar-info',
   templateUrl: './snackbar-info.component.html',
   styleUrls: ['./snackbar-info.component.scss'],
+  standalone: true,
+  imports: [MatButton, SnackbarCloseButtonComponent],
 })
 export class SnackbarInfoComponent {
-  constructor(
-    @Inject(MAT_SNACK_BAR_DATA) public data: SnackBarData,
-    public snackBarRef: MatSnackBarRef<SnackbarInfoComponent>,
-  ) {}
+  public snackBarRef = inject(MatSnackBarRef<SnackbarInfoComponent>);
+  public data = inject<SnackBarData>(MAT_SNACK_BAR_DATA);
 
   get message(): string {
     return this.data.message;
diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.ts
index 98b7170fe7e634e14ac0528a86f8f1467fedaabf..6e0ecf60e609bb66d8fe6fbbf2d823fcd2208266 100644
--- a/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.ts
+++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.ts
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentType } from '@angular/cdk/overlay';
-import { Injectable } from '@angular/core';
-import { MatSnackBar, MatSnackBarConfig, MatSnackBarRef } from '@angular/material/snack-bar';
 import { CommandResource, CommandStatus } from '@alfa-client/command-shared';
 import { isNotUndefined } from '@alfa-client/tech-shared';
+import { ComponentType } from '@angular/cdk/overlay';
+import { inject, Injectable } from '@angular/core';
+import { MatSnackBar, MatSnackBarConfig, MatSnackBarRef } from '@angular/material/snack-bar';
 import { isUndefined } from 'lodash-es';
 import { Subscription } from 'rxjs';
 import { SnackbarErrorComponent } from './snackbar-error/snackbar-error.component';
@@ -33,14 +33,14 @@ import { SnackbarInfoComponent } from './snackbar-info/snackbar-info.component';
 
 @Injectable({ providedIn: 'root' })
 export class SnackBarService {
+  private snackBar = inject(MatSnackBar);
+
   private subscription: Subscription;
 
   snackBarRef: MatSnackBarRef<SnackbarInfoComponent | SnackbarErrorComponent>;
 
   private durationTime: number = 10000;
 
-  constructor(private snackBar: MatSnackBar) {}
-
   public show(commandResource: CommandResource, message: string, revokeAction?: () => void): void {
     if (commandResource.status === CommandStatus.ERROR) {
       this.showError(message);
diff --git a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.spec.ts
index 8c9259c77a6edab755a16d357e8ac422b5154e5e..7a5b60d6c39ba17230d0bab3aa5088c9c5d54e62 100644
--- a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.spec.ts
@@ -31,8 +31,7 @@ describe('AccordionComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [AccordionComponent],
-      imports: [MatAccordion],
+      imports: [MatAccordion, AccordionComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.ts b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.ts
index 36001957eb55aef18fb3bb4013e4f3eac6973149..2327c0401e3f59cef0999f8b5e263bdb5148fe69 100644
--- a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.ts
@@ -22,11 +22,14 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, Input } from '@angular/core';
+import { MatAccordion } from '@angular/material/expansion';
 
 @Component({
   selector: 'ozgcloud-accordion',
   templateUrl: './accordion.component.html',
   styleUrls: ['./accordion.component.scss'],
+  standalone: true,
+  imports: [MatAccordion],
 })
 export class AccordionComponent {
   @Input() multi: boolean = false;
diff --git a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.ts b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.ts
index 14ad27f618eb07409005dabcb61ce581a6462134..a5c00893b3fa0fe9c3745afa4a750f395f06df70 100644
--- a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.ts
@@ -22,11 +22,18 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, Input } from '@angular/core';
+import { MatIconAnchor } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
+import { MatTooltip } from '@angular/material/tooltip';
+import { RouterLink } from '@angular/router';
+import { ArrowBackIconComponent, ButtonComponent, TooltipDirective } from '@ods/system';
 
 @Component({
   selector: 'ozgcloud-back-button',
   templateUrl: './back-button.component.html',
   styleUrls: ['./back-button.component.scss'],
+  standalone: true,
+  imports: [MatIconAnchor, RouterLink, MatTooltip, MatIcon, TooltipDirective, ButtonComponent, ArrowBackIconComponent],
 })
 export class BackButtonComponent {
   @Input() label: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.spec.ts
index ec797a1c52d453daa90d440babf58f3f188a02a5..23ca3dbbc8807eff625e692c251d00cf53b93fdc 100644
--- a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.spec.ts
@@ -21,13 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
 import { MatIcon } from '@angular/material/icon';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
 import { MockComponent } from 'ng-mocks';
 import { BasicDialogComponent } from './basic-dialog.component';
 
@@ -37,8 +34,8 @@ describe('BasicDialogComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [MatDialogModule],
-      declarations: [
+      imports: [
+        MatDialogModule,
         BasicDialogComponent,
         MatIcon,
         MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
diff --git a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.ts b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.ts
index e9519e80425254082dbb78cb7c75baf6e23ebe2b..cbe53ff122890939ac29bdda8e991855e3a78a53 100644
--- a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.ts
@@ -21,20 +21,36 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Inject } from '@angular/core';
-import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
+import { CdkScrollable } from '@angular/cdk/scrolling';
+import { Component, inject } from '@angular/core';
+import {
+  MAT_DIALOG_DATA,
+  MatDialogActions,
+  MatDialogClose,
+  MatDialogContent,
+  MatDialogRef,
+  MatDialogTitle,
+} from '@angular/material/dialog';
+import { OzgcloudStrokedButtonWithSpinnerComponent } from '../ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component';
 import { BasicDialogData } from './basic-dialog-data.model';
 
 @Component({
   selector: 'ozgcloud-basic-dialog',
   templateUrl: './basic-dialog.component.html',
   styleUrls: ['./basic-dialog.component.scss'],
+  standalone: true,
+  imports: [
+    MatDialogTitle,
+    CdkScrollable,
+    MatDialogContent,
+    MatDialogActions,
+    OzgcloudStrokedButtonWithSpinnerComponent,
+    MatDialogClose,
+  ],
 })
 export class BasicDialogComponent {
-  constructor(
-    public dialogRef: MatDialogRef<BasicDialogComponent>,
-    @Inject(MAT_DIALOG_DATA) public data: BasicDialogData,
-  ) {}
+  public dialogRef = inject(MatDialogRef<BasicDialogComponent>);
+  public data = inject<BasicDialogData>(MAT_DIALOG_DATA);
 
   onNoClick(): void {
     this.dialogRef.close();
diff --git a/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.ts b/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.ts
index dfe376a9f5fb12120a0be495df47fb865610f175..cd72feef7dac8d6194e6fb83ab08e9b76e38ffa7 100644
--- a/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.ts
+++ b/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.ts
@@ -21,22 +21,19 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ApiError, isNotUndefined } from '@alfa-client/tech-shared';
+import { BasicDialogComponent, BasicDialogData, FixedDialogComponent, FixedDialogData } from '@alfa-client/ui';
 import { NoopScrollStrategy } from '@angular/cdk/overlay';
 import { ComponentType } from '@angular/cdk/portal';
-import { Injectable } from '@angular/core';
+import { inject, Injectable } from '@angular/core';
 import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
-import { ApiError, isNotUndefined } from '@alfa-client/tech-shared';
-import {
-  BasicDialogComponent,
-  BasicDialogData,
-  FixedDialogComponent,
-  FixedDialogData,
-} from '@alfa-client/ui';
 import { InternalServerErrorDialogComponent } from '../notification/internal-server-error-dialog/internal-server-error-dialog.component';
 import { RetryInTimeDialog } from './retry-in-time.dialog';
 
 @Injectable({ providedIn: 'root' })
 export class DialogService {
+  private dialog = inject(MatDialog);
+
   fixedSingleDialogRef: MatDialogRef<FixedDialogComponent>;
 
   readonly FIXED_DIALOG_CONFIG: MatDialogConfig = {
@@ -67,8 +64,6 @@ export class DialogService {
     restoreFocus: false,
   };
 
-  constructor(private dialog: MatDialog) {}
-
   public openWidely<T>(component: ComponentType<T>, config?: MatDialogConfig): MatDialogRef<T> {
     return this.open<T>(component, { ...config, ...this.WIDE_DIALOG_CONFIG });
   }
diff --git a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.spec.ts
index d1215dcb80ea593e83277a49ba20d20e7988f671..2771e503131afefce51f6073b52866178fbc34ad 100644
--- a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.spec.ts
@@ -23,8 +23,8 @@
  */
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 
-import { DownloadButtonComponent } from './download-button.component';
 import { MockComponent } from 'ng-mocks';
+import { DownloadButtonComponent } from './download-button.component';
 
 describe('DownloadButtonComponent', () => {
   let component: DownloadButtonComponent;
@@ -32,7 +32,7 @@ describe('DownloadButtonComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [DownloadButtonComponent, MockComponent(DownloadButtonComponent)],
+      imports: [DownloadButtonComponent, MockComponent(DownloadButtonComponent)],
     }).compileComponents();
 
     fixture = TestBed.createComponent(DownloadButtonComponent);
diff --git a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.ts b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.ts
index d1b4e7fed82b0d06bc0c814137c2caabe34fc01f..be55bf7f0df760e20fb83d53c81560dd255ff90d 100644
--- a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.ts
@@ -22,11 +22,17 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, Input } from '@angular/core';
+import { MatAnchor } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
+import { MatTooltip } from '@angular/material/tooltip';
+import { TooltipDirective } from '@ods/system';
 
 @Component({
   selector: 'ozgcloud-download-button',
   templateUrl: './download-button.component.html',
   styleUrls: ['./download-button.component.scss'],
+  standalone: true,
+  imports: [MatAnchor, MatTooltip, MatIcon, TooltipDirective],
 })
 export class DownloadButtonComponent {
   @Input() icon: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html
index b60743ee96c5c2e579c266efbabb320bad129ddb..43edcd913d44feaaf9af68ae7e94df89215df6b9 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html
@@ -1,26 +1,26 @@
 <!--
 
-    Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
-
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
-
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
-
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
+Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+Ministerpräsidenten des Landes Schleswig-Holstein
+Staatskanzlei
+Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
+
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
 <mat-form-field appearance="outline">
@@ -40,15 +40,16 @@
   />
 
   <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
-    <mat-option
-      *ngFor="let value of values"
-      [attr.data-test-id]="(value.label | convertForDataTest) + '-autocomplete-option'"
-      [value]="value.value"
-      (keyup.enter)="onSelection(value)"
-      (onSelectionChange)="onSelection(value)"
-    >
-      {{ value.label }}
-    </mat-option>
+    @for (value of values; track value) {
+      <mat-option
+        [attr.data-test-id]="(value.label | convertForDataTest) + '-autocomplete-option'"
+        [value]="value.value"
+        (keyup.enter)="onSelection(value)"
+        (onSelectionChange)="onSelection(value)"
+      >
+        {{ value.label }}
+      </mat-option>
+    }
   </mat-autocomplete>
 
   <mat-error>
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.spec.ts
index 609ef74f56da69e125e481e7dc187a00c383069f..c590cbe105096627b2432f84f3052e54058e09d8 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.spec.ts
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { NgControl, ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
 import { MatAutocompleteModule } from '@angular/material/autocomplete';
 import { MatFormFieldModule } from '@angular/material/form-field';
 import { MatInputModule } from '@angular/material/input';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { MockComponent } from 'ng-mocks';
 import { ValidationErrorComponent } from '../../validation-error/validation-error.component';
 import { AutocompleteEditorComponent } from './autocomplete-editor.component';
@@ -38,17 +38,15 @@ describe('AutocompleteEditorComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [
-        AutocompleteEditorComponent,
-        ConvertForDataTestPipe,
-        MockComponent(ValidationErrorComponent),
-      ],
       imports: [
         MatAutocompleteModule,
         MatFormFieldModule,
         MatInputModule,
         ReactiveFormsModule,
         BrowserAnimationsModule,
+        AutocompleteEditorComponent,
+        ConvertForDataTestPipe,
+        MockComponent(ValidationErrorComponent),
       ],
       providers: [
         {
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts
index 1cb488f0f7025cd34f7e53a541c9b430aa557082..87aba70b5394eb65499915b9a29feef3154df301 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts
@@ -21,28 +21,38 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import {
-  AfterViewInit,
-  Component,
-  ElementRef,
-  EventEmitter,
-  Input,
-  Output,
-  ViewChild,
-} from '@angular/core';
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
+import { AfterViewInit, Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatAutocomplete, MatAutocompleteTrigger } from '@angular/material/autocomplete';
+import { MatOption } from '@angular/material/core';
+import { MatError, MatFormField, MatLabel } from '@angular/material/form-field';
+import { MatInput } from '@angular/material/input';
 import { ResourceUri } from '@ngxp/rest';
 import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
 import { isEmpty, isEqual, isNil } from 'lodash-es';
+import { ValidationErrorComponent } from '../../validation-error/validation-error.component';
 
 @Component({
   selector: 'ozgcloud-autocomplete-editor',
   templateUrl: './autocomplete-editor.component.html',
   styleUrls: ['./autocomplete-editor.component.scss'],
+  standalone: true,
+  imports: [
+    MatFormField,
+    MatLabel,
+    MatInput,
+    MatAutocompleteTrigger,
+    FormsModule,
+    ReactiveFormsModule,
+    MatAutocomplete,
+    MatOption,
+    MatError,
+    ValidationErrorComponent,
+    ConvertForDataTestPipe,
+  ],
 })
-export class AutocompleteEditorComponent
-  extends FormControlEditorAbstractComponent
-  implements AfterViewInit
-{
+export class AutocompleteEditorComponent extends FormControlEditorAbstractComponent implements AfterViewInit {
   @Input() label: string;
   @Input() values: Selectable[] = [];
   @Input() required: boolean = false;
@@ -64,9 +74,7 @@ export class AutocompleteEditorComponent
   onEnter(): void {
     const selectedValue: ResourceUri = this.fieldControl.value;
 
-    isEmpty(selectedValue) ?
-      this.enterOnNoSelection.emit()
-    : this.onSelection(this.getUserProfile());
+    isEmpty(selectedValue) ? this.enterOnNoSelection.emit() : this.onSelection(this.getUserProfile());
   }
 
   private getUserProfile(): Selectable {
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.spec.ts
index 2a7caecd0e32ea384511381f74daa36eaecc7644..91a6537c22606b24f3358d8de8d5dbec08f7ba9b 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.spec.ts
@@ -21,16 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ReactiveFormsModule } from '@angular/forms';
-import { MatIcon } from '@angular/material/icon';
 import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatIcon } from '@angular/material/icon';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { MockComponent } from 'ng-mocks';
 import { IconButtonWithSpinnerComponent } from '../../icon-button-with-spinner/icon-button-with-spinner.component';
 import { CheckboxEnumEditorComponent } from './checkbox-enum-editor.component';
-import { UiModule } from '../../ui.module';
 
 describe('CheckboxEnumEditorComponent', () => {
   let component: CheckboxEnumEditorComponent;
@@ -38,13 +37,15 @@ describe('CheckboxEnumEditorComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [
+      declarations: [ConvertForDataTestPipe],
+      imports: [
+        MatFormFieldModule,
+        ReactiveFormsModule,
+        BrowserAnimationsModule,
         CheckboxEnumEditorComponent,
         MatIcon,
-        ConvertForDataTestPipe,
         MockComponent(IconButtonWithSpinnerComponent),
       ],
-      imports: [UiModule, MatFormFieldModule, ReactiveFormsModule, BrowserAnimationsModule],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.ts
index 26e505719f2ffab18108f1f278bbc984d5e79622..0943452372c17eb48ba64b6c3e97bf9ee4067ae9 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.ts
@@ -22,7 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, Input, OnInit } from '@angular/core';
-import { MatCheckboxChange } from '@angular/material/checkbox';
+import { MatCheckbox, MatCheckboxChange } from '@angular/material/checkbox';
 import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
 import { CheckboxEnumEditorItem } from './checkbox-enum-editor.model';
 
@@ -34,11 +34,10 @@ import { CheckboxEnumEditorItem } from './checkbox-enum-editor.model';
   selector: 'ozgcloud-checkbox-enum-editor',
   templateUrl: './checkbox-enum-editor.component.html',
   styleUrls: ['./checkbox-enum-editor.component.scss'],
+  standalone: true,
+  imports: [MatCheckbox],
 })
-export class CheckboxEnumEditorComponent
-  extends FormControlEditorAbstractComponent
-  implements OnInit
-{
+export class CheckboxEnumEditorComponent extends FormControlEditorAbstractComponent implements OnInit {
   @Input() label: string;
   @Input() defaultItem: CheckboxEnumEditorItem;
   @Input() checkedItem: CheckboxEnumEditorItem;
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.spec.ts
index 2af729384632e5d72440e7a4dd862b921b3aea52..e8fb9e83f6c6a820f348e86b6841ef6bf00532a3 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.spec.ts
@@ -43,12 +43,9 @@ describe('DateEditorComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [
-        DateEditorComponent,
-        ConvertForDataTestPipe,
-        MockComponent(ValidationErrorComponent),
-      ],
+      declarations: [ConvertForDataTestPipe],
       imports: [
+        ConvertForDataTestPipe,
         MatFormFieldModule,
         MatInputModule,
         MatIconModule,
@@ -56,6 +53,8 @@ describe('DateEditorComponent', () => {
         MatNativeDateModule,
         ReactiveFormsModule,
         BrowserAnimationsModule,
+        DateEditorComponent,
+        MockComponent(ValidationErrorComponent),
       ],
     }).compileComponents();
   });
@@ -75,9 +74,7 @@ describe('DateEditorComponent', () => {
       component.label = 'Ein Label';
       fixture.detectChanges();
 
-      const element: HTMLElement = fixture.nativeElement.querySelector(
-        '[data-test-id="Ein_Label-date-input"]',
-      );
+      const element: HTMLElement = fixture.nativeElement.querySelector('[data-test-id="Ein_Label-date-input"]');
 
       expect(element).toBeInstanceOf(HTMLElement);
     });
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts
index c632ccf07fb72d02712a391901d9d0cc8a0d9d9b..b7dd27fb2f94c53cf4f4acfdb6bad040798348da 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts
@@ -21,16 +21,32 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { add2000Years } from '@alfa-client/tech-shared';
+import { add2000Years, ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { Component, Input } from '@angular/core';
-import { MatDatepickerInputEvent } from '@angular/material/datepicker';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatDatepickerInputEvent, MatDatepickerModule } from '@angular/material/datepicker';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatIcon } from '@angular/material/icon';
+import { MatInputModule } from '@angular/material/input';
 import { isDate } from 'date-fns';
 import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
+import { ValidationErrorComponent } from '../../validation-error/validation-error.component';
 
 @Component({
   selector: 'ozgcloud-date-editor',
   templateUrl: './date-editor.component.html',
   styleUrls: ['./date-editor.component.scss'],
+  standalone: true,
+  imports: [
+    MatFormFieldModule,
+    MatInputModule,
+    FormsModule,
+    ReactiveFormsModule,
+    MatIcon,
+    ValidationErrorComponent,
+    MatDatepickerModule,
+    ConvertForDataTestPipe,
+  ],
 })
 export class DateEditorComponent extends FormControlEditorAbstractComponent {
   @Input() label: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html
index 123269b8cb6c410f812da2ce9cc447e9c043c7bc..c8501ddaa8dee9c1e93721b8f7408b5652903bde 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html
@@ -1,32 +1,32 @@
 <!--
 
-    Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
-
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
-
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
-
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
+Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+Ministerpräsidenten des Landes Schleswig-Holstein
+Staatskanzlei
+Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
+
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
 <ng-container [formArrayName]="parentFormArrayName">
-  <ng-container *ngFor="let hiddenInput of fileLinkControls.controls; let i = index">
+  @for (hiddenInput of fileLinkControls.controls; track hiddenInput; let i = $index) {
     <input id="file-link-{{ i }}" type="hidden" [formControlName]="i" />
-  </ng-container>
+  }
 </ng-container>
 
 <input
@@ -39,10 +39,11 @@
 />
 
 <label [attr.for]="uploadFileId" matRipple [attr.aria-label]="label">
-  <mat-icon *ngIf="!uploadInProgress.loading">attach_file</mat-icon>
+  @if (!uploadInProgress.loading) {
+    <mat-icon>attach_file</mat-icon>
+  }
 
-  <ozgcloud-spinner [stateResource]="uploadInProgress" [diameter]="22" padding="0">
-  </ozgcloud-spinner>
+  <ozgcloud-spinner [stateResource]="uploadInProgress" [diameter]="22" padding="0"> </ozgcloud-spinner>
 </label>
 
 <mat-error>
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.spec.ts
index a6c2b5c8d87ad575a680c408b349146e8f21966f..2dc06d2e3d1f7ffc486f6a8f4525427281e4247e 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.spec.ts
@@ -21,20 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ConvertForDataTestPipe, createEmptyStateResource } from '@alfa-client/tech-shared';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import {
-  AbstractControl,
-  FormGroupDirective,
-  ReactiveFormsModule,
-  UntypedFormBuilder,
-} from '@angular/forms';
+import { AbstractControl, FormGroupDirective, ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
 import { MatNativeDateModule } from '@angular/material/core';
 import { MatDatepickerModule } from '@angular/material/datepicker';
-import { MatIconModule } from '@angular/material/icon';
 import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatIconModule } from '@angular/material/icon';
 import { MatInputModule } from '@angular/material/input';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { ConvertForDataTestPipe, createEmptyStateResource } from '@alfa-client/tech-shared';
 import { MockComponent } from 'ng-mocks';
 import { SpinnerComponent } from '../../spinner/spinner.component';
 import { ValidationErrorComponent } from '../../validation-error/validation-error.component';
@@ -51,12 +46,6 @@ describe('FileUploadEditorComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [
-        FileUploadEditorComponent,
-        ConvertForDataTestPipe,
-        MockComponent(ValidationErrorComponent),
-        MockComponent(SpinnerComponent),
-      ],
       imports: [
         MatFormFieldModule,
         MatInputModule,
@@ -65,6 +54,10 @@ describe('FileUploadEditorComponent', () => {
         MatNativeDateModule,
         ReactiveFormsModule,
         BrowserAnimationsModule,
+        FileUploadEditorComponent,
+        ConvertForDataTestPipe,
+        MockComponent(ValidationErrorComponent),
+        MockComponent(SpinnerComponent),
       ],
       providers: [
         FormGroupDirective,
@@ -100,9 +93,7 @@ describe('FileUploadEditorComponent', () => {
       component.label = 'Ein Label';
       fixture.detectChanges();
 
-      const element: HTMLElement = fixture.nativeElement.querySelector(
-        '[data-test-id="Ein_Label-file-upload-input"]',
-      );
+      const element: HTMLElement = fixture.nativeElement.querySelector('[data-test-id="Ein_Label-file-upload-input"]');
 
       expect(element).toBeInstanceOf(HTMLElement);
     });
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts
index 148f7d0dd06e17e7b790ff81139f1fbca85ffc52..5c75b22163ad44971eb6bef5821b66b717336d51 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts
@@ -21,36 +21,44 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { StateResource } from '@alfa-client/tech-shared';
-import {
-  Component,
-  ElementRef,
-  EventEmitter,
-  HostListener,
-  Input,
-  OnInit,
-  Output,
-  ViewChild,
-} from '@angular/core';
+import { ConvertForDataTestPipe, StateResource } from '@alfa-client/tech-shared';
+import { Component, ElementRef, EventEmitter, HostListener, inject, Input, OnInit, Output, ViewChild } from '@angular/core';
 import {
   ControlContainer,
   FormGroupDirective,
+  FormsModule,
+  ReactiveFormsModule,
   UntypedFormArray,
   UntypedFormControl,
 } from '@angular/forms';
+import { MatRipple } from '@angular/material/core';
+import { MatError } from '@angular/material/form-field';
+import { MatIcon } from '@angular/material/icon';
 import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
 import { uniqueId } from 'lodash-es';
+import { SpinnerComponent } from '../../spinner/spinner.component';
+import { ValidationErrorComponent } from '../../validation-error/validation-error.component';
 
 @Component({
   selector: 'ozgcloud-file-upload-editor',
   templateUrl: './file-upload-editor.component.html',
   styleUrls: ['./file-upload-editor.component.scss'],
   viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }],
+  standalone: true,
+  imports: [
+    FormsModule,
+    ReactiveFormsModule,
+    MatRipple,
+    MatIcon,
+    SpinnerComponent,
+    MatError,
+    ValidationErrorComponent,
+    ConvertForDataTestPipe,
+  ],
 })
-export class FileUploadEditorComponent
-  extends FormControlEditorAbstractComponent
-  implements OnInit
-{
+export class FileUploadEditorComponent extends FormControlEditorAbstractComponent implements OnInit {
+  public parentForm = inject(FormGroupDirective);
+
   @Input() label: string = '';
   @Input() parentFormArrayName: string;
   @Input() accept: string = '*/*';
@@ -72,19 +80,13 @@ export class FileUploadEditorComponent
     this.setErrors();
   }
 
-  constructor(public parentForm: FormGroupDirective) {
-    super(null);
-  }
-
   override ngOnInit(): void {
     this.fileLinkControls = this.parentForm.form.get(this.parentFormArrayName) as UntypedFormArray;
   }
 
   buildFormArray(fileLinkList: string[]): void {
     this.fileLinkControls.clear();
-    fileLinkList.forEach((link: string) =>
-      this.fileLinkControls.push(new UntypedFormControl(link)),
-    );
+    fileLinkList.forEach((link: string) => this.fileLinkControls.push(new UntypedFormControl(link)));
   }
 
   resetInput(): void {
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/ozgcloud-text-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/ozgcloud-text-editor.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..8dab6eb918bef8d15c6a555ef6ab253f27942700
--- /dev/null
+++ b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/ozgcloud-text-editor.component.html
@@ -0,0 +1,66 @@
+<!--
+
+Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+Ministerpräsidenten des Landes Schleswig-Holstein
+Staatskanzlei
+Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
+
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<mat-form-field
+  [subscriptSizing]="subscriptSizing"
+  class="compact-input"
+  appearance="{{ appearance }}"
+  [floatLabel]="readOnly || autoFocus ? 'always' : 'auto'"
+>
+  <mat-label>{{ label }}</mat-label>
+  <div class="wrapper">
+    <input
+      #inputElement
+      matInput
+      placeholder="{{ placeholder }}"
+      [formControl]="fieldControl"
+      [autocomplete]="autocomplete"
+      [readonly]="readOnly"
+      (blur)="touch()"
+      [required]="required"
+      [attr.data-test-id]="(label | convertForDataTest) + '-text-input'"
+      [class.with-clear-button]="showClearButton$ | async"
+    />
+    @if (showClearButton$ | async) {
+      <button
+        data-test-id="clear-button"
+        class="clear-button"
+        type="button"
+        (click)="onClear()"
+        mat-icon-button
+        aria-label="Leeren"
+      >
+        <mat-icon>close</mat-icon>
+      </button>
+    }
+  </div>
+  <mat-error>
+    <ozgcloud-validation-error
+      [attr.data-test-id]="(getPlaceholderLabel() | convertForDataTest) + '-text-error'"
+      [invalidParams]="invalidParams"
+      [label]="getPlaceholderLabel()"
+    ></ozgcloud-validation-error>
+  </mat-error>
+</mat-form-field>
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.scss b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/ozgcloud-text-editor.component.scss
similarity index 100%
rename from alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.scss
rename to alfa-client/libs/ui/src/lib/ui/editor/text-editor/ozgcloud-text-editor.component.scss
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/ozgcloud-text-editor.component.spec.ts
similarity index 84%
rename from alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.spec.ts
rename to alfa-client/libs/ui/src/lib/ui/editor/text-editor/ozgcloud-text-editor.component.spec.ts
index e2000c8388d7734d74f703d0748d531580e7454d..52c2e538297a8d30167ad14f5760bf8a79888cd9 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/ozgcloud-text-editor.component.spec.ts
@@ -29,18 +29,26 @@ import { MatInputModule } from '@angular/material/input';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 import { MockComponent } from 'ng-mocks';
 import { ValidationErrorComponent } from '../../validation-error/validation-error.component';
-import { TextEditorComponent } from './text-editor.component';
+import { OzgcloudTextEditorComponent } from './ozgcloud-text-editor.component';
 
-describe('TextEditorComponent', () => {
-  let component: TextEditorComponent;
-  let fixture: ComponentFixture<TextEditorComponent>;
+describe('OzgcloudTextEditorComponent', () => {
+  let component: OzgcloudTextEditorComponent;
+  let fixture: ComponentFixture<OzgcloudTextEditorComponent>;
 
   const input: string = '[data-test-id="Ein_Label-text-input"]';
 
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      declarations: [TextEditorComponent, ConvertForDataTestPipe, MockComponent(ValidationErrorComponent)],
-      imports: [MatFormFieldModule, MatInputModule, ReactiveFormsModule, BrowserAnimationsModule],
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      declarations: [
+        OzgcloudTextEditorComponent,
+        MatFormFieldModule,
+        MatInputModule,
+        ReactiveFormsModule,
+        BrowserAnimationsModule,
+        ConvertForDataTestPipe,
+        MockComponent(ValidationErrorComponent),
+      ],
+      imports: [],
       providers: [
         {
           provide: NgControl,
@@ -51,7 +59,7 @@ describe('TextEditorComponent', () => {
   });
 
   beforeEach(() => {
-    fixture = TestBed.createComponent(TextEditorComponent);
+    fixture = TestBed.createComponent(OzgcloudTextEditorComponent);
     component = fixture.componentInstance;
     component.label = 'Ein Label';
     fixture.detectChanges();
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/ozgcloud-text-editor.component.ts
similarity index 69%
rename from alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.ts
rename to alfa-client/libs/ui/src/lib/ui/editor/text-editor/ozgcloud-text-editor.component.ts
index 5e3227127c9e7b3cc451ad530262da5f36fe1cf5..9e1294a6059d8baa85f7faccdf45401af6a08c6e 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/ozgcloud-text-editor.component.ts
@@ -21,21 +21,38 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { hasContent } from '@alfa-client/tech-shared';
+import { ConvertForDataTestPipe, hasContent } from '@alfa-client/tech-shared';
+import { AsyncPipe } from '@angular/common';
 import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
-import { SubscriptSizing } from '@angular/material/form-field';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatIconButton } from '@angular/material/button';
+import { MatError, MatFormField, MatLabel, SubscriptSizing } from '@angular/material/form-field';
+import { MatIcon } from '@angular/material/icon';
+import { MatInput } from '@angular/material/input';
 import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
 import { Observable, map, startWith } from 'rxjs';
+import { ValidationErrorComponent } from '../../validation-error/validation-error.component';
 
 @Component({
   selector: 'ozgcloud-text-editor',
-  templateUrl: './text-editor.component.html',
-  styleUrls: ['./text-editor.component.scss'],
+  templateUrl: './ozgcloud-text-editor.component.html',
+  styleUrls: ['./ozgcloud-text-editor.component.scss'],
+  standalone: true,
+  imports: [
+    MatFormField,
+    MatLabel,
+    MatInput,
+    FormsModule,
+    ReactiveFormsModule,
+    MatIconButton,
+    MatIcon,
+    MatError,
+    ValidationErrorComponent,
+    AsyncPipe,
+    ConvertForDataTestPipe,
+  ],
 })
-export class TextEditorComponent
-  extends FormControlEditorAbstractComponent
-  implements OnInit, AfterViewInit
-{
+export class OzgcloudTextEditorComponent extends FormControlEditorAbstractComponent implements OnInit, AfterViewInit {
   @ViewChild('inputElement') inputElement: ElementRef;
 
   @Input() label: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.html
deleted file mode 100644
index 303e1315d5e643ebce97e74e5f9477b1ca105866..0000000000000000000000000000000000000000
--- a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!--
-
-    Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
-
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
-
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
-
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
-
--->
-<mat-form-field
-  [subscriptSizing]="subscriptSizing"
-  class="compact-input"
-  appearance="{{ appearance }}"
-  [floatLabel]="readOnly || autoFocus ? 'always' : 'auto'"
->
-  <mat-label>{{ label }}</mat-label>
-  <div class="wrapper">
-    <input
-      #inputElement
-      matInput
-      placeholder="{{ placeholder }}"
-      [formControl]="fieldControl"
-      [autocomplete]="autocomplete"
-      [readonly]="readOnly"
-      (blur)="touch()"
-      [required]="required"
-      [attr.data-test-id]="(label | convertForDataTest) + '-text-input'"
-      [class.with-clear-button]="showClearButton$ | async"
-    />
-    <button
-      *ngIf="showClearButton$ | async"
-      data-test-id="clear-button"
-      class="clear-button"
-      type="button"
-      (click)="onClear()"
-      mat-icon-button
-      aria-label="Leeren"
-    >
-      <mat-icon>close</mat-icon>
-    </button>
-  </div>
-  <mat-error>
-    <ozgcloud-validation-error
-      [attr.data-test-id]="(getPlaceholderLabel() | convertForDataTest) + '-text-error'"
-      [invalidParams]="invalidParams"
-      [label]="getPlaceholderLabel()"
-    ></ozgcloud-validation-error>
-  </mat-error>
-</mat-form-field>
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.spec.ts
index 49217b8c8117ce625d8e2ff8edd9e9ab82dab845..670590d080bda2dfd50caa88d4b5894c729416a6 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.spec.ts
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { NgControl, ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
 import { MatFormFieldModule } from '@angular/material/form-field';
 import { MatInputModule } from '@angular/material/input';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { MockComponent } from 'ng-mocks';
 import { ValidationErrorComponent } from '../../validation-error/validation-error.component';
 import { TextAreaEditorComponent } from './textarea-editor.component';
@@ -37,12 +37,15 @@ describe('TextAreaEditorComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [
+      imports: [
+        MatFormFieldModule,
+        MatInputModule,
+        ReactiveFormsModule,
+        BrowserAnimationsModule,
         TextAreaEditorComponent,
         ConvertForDataTestPipe,
         MockComponent(ValidationErrorComponent),
       ],
-      imports: [MatFormFieldModule, MatInputModule, ReactiveFormsModule, BrowserAnimationsModule],
       providers: [
         {
           provide: NgControl,
@@ -67,9 +70,7 @@ describe('TextAreaEditorComponent', () => {
     component.label = 'Ein Label';
     fixture.detectChanges();
 
-    const element: HTMLElement = fixture.nativeElement.querySelector(
-      '[data-test-id="Ein_Label-textarea-input"]',
-    );
+    const element: HTMLElement = fixture.nativeElement.querySelector('[data-test-id="Ein_Label-textarea-input"]');
 
     expect(element).toBeInstanceOf(HTMLElement);
   });
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts
index 27644f18242584d91fa7adf2008ed2de99e02857..a58f6a04d44fcf30053bc0a931d9920500165897 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts
@@ -21,19 +21,33 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { CdkTextareaAutosize } from '@angular/cdk/text-field';
 import { AfterViewInit, Component, Input, ViewChild } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatError, MatFormField, MatLabel } from '@angular/material/form-field';
+import { MatInput } from '@angular/material/input';
 import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
+import { ValidationErrorComponent } from '../../validation-error/validation-error.component';
 
 @Component({
   selector: 'ozgcloud-textarea-editor',
   templateUrl: './textarea-editor.component.html',
   styleUrls: ['./textarea-editor.component.scss'],
+  standalone: true,
+  imports: [
+    MatFormField,
+    MatLabel,
+    MatInput,
+    CdkTextareaAutosize,
+    FormsModule,
+    ReactiveFormsModule,
+    MatError,
+    ValidationErrorComponent,
+    ConvertForDataTestPipe,
+  ],
 })
-export class TextAreaEditorComponent
-  extends FormControlEditorAbstractComponent
-  implements AfterViewInit
-{
+export class TextAreaEditorComponent extends FormControlEditorAbstractComponent implements AfterViewInit {
   @ViewChild('autosize') autosize: CdkTextareaAutosize;
 
   @Input() placeholder: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.spec.ts
index 4f5bc141b8ff9bbb08eaf3969caa702a88c12ec7..f8b285231242f9377479de52bdb11307422cb136 100644
--- a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.spec.ts
@@ -23,12 +23,7 @@
  */
 import { PortalModule } from '@angular/cdk/portal';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import {
-  MatAccordion,
-  MatExpansionPanel,
-  MatExpansionPanelHeader,
-  MatExpansionPanelTitle,
-} from '@angular/material/expansion';
+import { MatAccordion, MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle } from '@angular/material/expansion';
 import { MatIcon } from '@angular/material/icon';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 import { ExpansionPanelComponent } from './expansion-panel.component';
@@ -47,8 +42,8 @@ describe('VorgangDetailExpansionPanelComponent', () => {
         MatAccordion,
         MatIcon,
         MatExpansionPanelHeader,
+        ExpansionPanelComponent,
       ],
-      declarations: [ExpansionPanelComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.ts b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.ts
index 451efa23326b6f5d0cfbed82263a40282170c1fa..c1056c852eeb7440011bf8d9c3aa0ccf03f3764a 100644
--- a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.ts
@@ -21,12 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { NgStyle } from '@angular/common';
 import { Component, Input } from '@angular/core';
+import { MatIconButton } from '@angular/material/button';
+import { MatAccordion, MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle } from '@angular/material/expansion';
+import { MatIcon } from '@angular/material/icon';
 
 @Component({
   selector: 'ozgcloud-expansion-panel',
   templateUrl: './expansion-panel.component.html',
   styleUrls: ['./expansion-panel.component.scss'],
+  standalone: true,
+  imports: [MatAccordion, MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle, MatIconButton, MatIcon, NgStyle],
 })
 export class ExpansionPanelComponent {
   @Input() headline: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.html b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.html
index 3421e957279595f13a6c27001c7437ef9416ebb6..6cd69f6200e7cfb864bce83488cf60467d90aad3 100644
--- a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.html
@@ -1,40 +1,34 @@
 <!--
 
-    Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+Ministerpräsidenten des Landes Schleswig-Holstein
+Staatskanzlei
+Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
 
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
 
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
 
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container *ngIf="uploadInProgress$ | async as uploadInProgress">
-  <input
-    data-test-id="file-upload-input"
-    [id]="myId"
-    type="file"
-    [accept]="accept"
-    (change)="onFileChanged($event)"
-  />
+@if (uploadInProgress$ | async; as uploadInProgress) {
+  <input data-test-id="file-upload-input" [id]="myId" type="file" [accept]="accept" (change)="onFileChanged($event)" />
   <label [attr.for]="myId" matRipple aria-label="Anhang hinzufügen">
-    <mat-icon *ngIf="!uploadInProgress.loading">attach_file</mat-icon>
-
-    <ozgcloud-spinner [stateResource]="uploadInProgress" [diameter]="22" padding="0">
-    </ozgcloud-spinner>
+    @if (!uploadInProgress.loading) {
+      <mat-icon>attach_file</mat-icon>
+    }
+    <ozgcloud-spinner [stateResource]="uploadInProgress" [diameter]="22" padding="0"> </ozgcloud-spinner>
   </label>
-</ng-container>
+}
diff --git a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.spec.ts
index b823f373c545cdc4aeee52bf6a8948914942608c..a8ead2a90d69f7d2c78fab8d2f929b20d0b21c50 100644
--- a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.spec.ts
@@ -23,10 +23,10 @@
  */
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 
-import { FileUploadComponent } from './file-upload.component';
+import { SpinnerComponent } from '@alfa-client/ui';
 import { MatIcon } from '@angular/material/icon';
 import { MockComponent } from 'ng-mocks';
-import { SpinnerComponent } from '@alfa-client/ui';
+import { FileUploadComponent } from './file-upload.component';
 
 describe('FileUploadComponent', () => {
   let component: FileUploadComponent;
@@ -34,7 +34,7 @@ describe('FileUploadComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [FileUploadComponent, MatIcon, MockComponent(SpinnerComponent)],
+      imports: [FileUploadComponent, MatIcon, MockComponent(SpinnerComponent)],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.ts b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.ts
index cfafed7120d1cc08ad23b9a6e9ccee79067d6d62..37c1e62075effcb3be1de49b949d143e7e439cc7 100644
--- a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.ts
@@ -21,15 +21,21 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, EventEmitter, Input, Output } from '@angular/core';
 import { StateResource } from '@alfa-client/tech-shared';
+import { AsyncPipe } from '@angular/common';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { MatRipple } from '@angular/material/core';
+import { MatIcon } from '@angular/material/icon';
 import { uniqueId } from 'lodash-es';
 import { Observable } from 'rxjs';
+import { SpinnerComponent } from '../spinner/spinner.component';
 
 @Component({
   selector: 'ozgcloud-file-upload',
   templateUrl: './file-upload.component.html',
   styleUrls: ['./file-upload.component.scss'],
+  standalone: true,
+  imports: [MatRipple, MatIcon, SpinnerComponent, AsyncPipe],
 })
 export class FileUploadComponent {
   @Input() accept: string = '*/*';
diff --git a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.spec.ts
index f74f63c0b94e179f81f32830d8ef6af5d26d7b31..119257aa82d807ddea222ba3f2534ff3a348484d 100644
--- a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.spec.ts
@@ -32,8 +32,7 @@ describe('FixedDialogComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [MatDialogModule, MatIcon],
-      declarations: [FixedDialogComponent],
+      imports: [MatDialogModule, MatIcon, FixedDialogComponent],
       providers: [
         {
           provide: MatDialogRef,
diff --git a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.ts b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.ts
index 0a0d03890fdb4837814cc105643b81ce5277239d..a4bb9d6af8e17ec21ca27cab2fdc2027ea4d3595 100644
--- a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.ts
@@ -21,26 +21,32 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Inject, Injector } from '@angular/core';
-import { MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { CdkScrollable } from '@angular/cdk/scrolling';
+import { NgClass, NgComponentOutlet } from '@angular/common';
+import { Component, inject, Injector, OnInit } from '@angular/core';
+import { MatIconButton } from '@angular/material/button';
+import { MAT_DIALOG_DATA, MatDialogClose, MatDialogContent, MatDialogTitle } from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
 import { FixedDialogData } from './fixed-dialog-data.model';
 
 @Component({
   selector: 'ozgcloud-fixed-dialog',
   templateUrl: './fixed-dialog.component.html',
+  standalone: true,
+  imports: [MatDialogTitle, MatIconButton, NgClass, MatIcon, MatDialogClose, CdkScrollable, MatDialogContent, NgComponentOutlet],
 })
-export class FixedDialogComponent {
+export class FixedDialogComponent implements OnInit {
+  public data = inject<FixedDialogData>(MAT_DIALOG_DATA);
+  private injector = inject(Injector);
+
   componentInjector: Injector;
 
   isMinimized: boolean;
 
-  constructor(
-    @Inject(MAT_DIALOG_DATA) public data: FixedDialogData,
-    injector: Injector,
-  ) {
+  ngOnInit(): void {
     this.componentInjector = Injector.create({
       providers: [],
-      parent: injector,
+      parent: this.injector,
     });
   }
 
diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.spec.ts
index 29d0ea1951593261b40071943e1f45a5016a9371..650e50ec93147e8958d2727ec40dc1ebc0fd906b 100644
--- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.spec.ts
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatDialogModule } from '@angular/material/dialog';
 import { MatIcon } from '@angular/material/icon';
-import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { MockComponent } from 'ng-mocks';
 import { ConnectionTimeoutRetryDialogComponent } from './connection-timeout-retry-dialog.component';
 
@@ -34,8 +34,8 @@ describe('ConnectionTimeoutRetryDialogComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [MatDialogModule],
-      declarations: [
+      imports: [
+        MatDialogModule,
         ConnectionTimeoutRetryDialogComponent,
         MatIcon,
         MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.ts b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.ts
index eb209e7c7b10c791b2252a93823748739558a813..c2cc728cf695acc35facdf24b8f87e6e6fd8bdf9 100644
--- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.ts
@@ -21,11 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { CdkScrollable } from '@angular/cdk/scrolling';
 import { Component } from '@angular/core';
+import { MatDialogContent, MatDialogTitle } from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
 
 @Component({
   selector: 'ozgcloud-connection-timeout-retry-dialog',
   templateUrl: './connection-timeout-retry-dialog.component.html',
   styleUrls: ['./connection-timeout-retry-dialog.component.scss'],
+  standalone: true,
+  imports: [MatDialogTitle, MatIcon, CdkScrollable, MatDialogContent],
 })
 export class ConnectionTimeoutRetryDialogComponent {}
diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.spec.ts
index 42d3c9febfeeb164d2561b4d68dbbbb5f49dd895..6c41b694c5489b832e31696fe38554ce0cb76011 100644
--- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.spec.ts
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatDialogModule } from '@angular/material/dialog';
 import { MatIcon } from '@angular/material/icon';
-import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { MockComponent } from 'ng-mocks';
 import { ConnectionTimeoutRetryFailDialogComponent } from './connection-timeout-retry-fail-dialog.component';
 
@@ -34,8 +34,8 @@ describe('ConnectionTimeoutRetryFailDialogComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [MatDialogModule],
-      declarations: [
+      imports: [
+        MatDialogModule,
         ConnectionTimeoutRetryFailDialogComponent,
         MatIcon,
         MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.ts b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.ts
index 858098b7e7ded139ba3b18ecf5baa1c4aef4b92c..62646a5aadf7797653253d18a866b7a33d09fe7d 100644
--- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.ts
@@ -21,12 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { CdkScrollable } from '@angular/cdk/scrolling';
 import { Component } from '@angular/core';
+import { MatDialogContent, MatDialogTitle } from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
+import { OzgcloudStrokedButtonWithSpinnerComponent } from '../../ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component';
 
 @Component({
   selector: 'ozgcloud-connection-timeout-retry-fail-dialog',
   templateUrl: './connection-timeout-retry-fail-dialog.component.html',
   styleUrls: ['./connection-timeout-retry-fail-dialog.component.scss'],
+  standalone: true,
+  imports: [MatDialogTitle, MatIcon, CdkScrollable, MatDialogContent, OzgcloudStrokedButtonWithSpinnerComponent],
 })
 export class ConnectionTimeoutRetryFailDialogComponent {
   reload(): void {
diff --git a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.html b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.html
index 1bb8fb6c9424bb9fb420a5f0007d61a88ffe6beb..ce20ce0990fb781b6eb31e3ce4247c1b3a4f9ca2 100644
--- a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.html
@@ -33,11 +33,15 @@
   (click)="clickEmitter.emit($event)"
   type="button"
 >
-  <mat-icon *ngIf="icon" data-test-class="icon" [style.visibility]="isDisabled ? 'hidden' : 'visible'">
-    {{ icon }}
-  </mat-icon>
+  @if (icon) {
+    <mat-icon data-test-class="icon" [style.visibility]="isDisabled ? 'hidden' : 'visible'">
+      {{ icon }}
+    </mat-icon>
+  }
 
-  <mat-icon *ngIf="svgIcon" data-test-class="icon" [svgIcon]="svgIcon" [style.visibility]="isDisabled ? 'hidden' : 'visible'" />
+  @if (svgIcon) {
+    <mat-icon data-test-class="icon" [svgIcon]="svgIcon" [style.visibility]="isDisabled ? 'hidden' : 'visible'" />
+  }
 
   <ozgcloud-spinner [stateResource]="getStateResource()" [diameter]="22" [show]="showSpinner" padding="0" />
 </button>
diff --git a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.spec.ts
index 7cf06e5752ca8ebf4c3b0b797b97631bc3e04c25..365f71d7a8d7a2f24ddbe67e18e6a785b445f9a2 100644
--- a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.spec.ts
@@ -26,7 +26,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatIcon } from '@angular/material/icon';
 import { MatMenuModule } from '@angular/material/menu';
 import { TooltipDirective } from '@ods/system';
-import { MockComponent, MockDirective, MockModule } from 'ng-mocks';
+import { MockComponent, MockDirective } from 'ng-mocks';
 import { SpinnerComponent } from '../spinner/spinner.component';
 import { IconButtonWithSpinnerComponent } from './icon-button-with-spinner.component';
 
@@ -37,15 +37,10 @@ describe('IconButtonWithSpinnerComponent', () => {
   const buttonSelector = '[data-test-class="icon-button"]';
   const iconSelector = '[data-test-class="icon"]';
 
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      declarations: [
-        IconButtonWithSpinnerComponent,
-        MatIcon,
-        MockComponent(SpinnerComponent),
-        MockDirective(TooltipDirective),
-        MockModule(MatMenuModule),
-      ],
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      imports: [IconButtonWithSpinnerComponent, MatIcon, MatMenuModule],
+      declarations: [MockComponent(SpinnerComponent), MockDirective(TooltipDirective)],
     });
   });
 
diff --git a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.ts b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.ts
index e2b8c90813ed8a2a6bf5a29ed86055569895b5ef..f83e6bfcc75341f27eaa8baa149a9c65f3fa7c57 100644
--- a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.ts
@@ -23,13 +23,21 @@
  */
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
 import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { MatIconButton } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
+import { MatMenuTrigger } from '@angular/material/menu';
+import { MatTooltip } from '@angular/material/tooltip';
 import { Resource } from '@ngxp/rest';
+import { TooltipDirective } from '@ods/system';
 import { isNil } from 'lodash-es';
+import { SpinnerComponent } from '../spinner/spinner.component';
 
 @Component({
   selector: 'ozgcloud-icon-button-with-spinner',
   templateUrl: './icon-button-with-spinner.component.html',
   styleUrls: ['./icon-button-with-spinner.component.scss'],
+  standalone: true,
+  imports: [MatIconButton, MatTooltip, MatMenuTrigger, MatIcon, SpinnerComponent, TooltipDirective],
 })
 export class IconButtonWithSpinnerComponent {
   @Input() icon: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.html b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.html
index 3ffd5acf9942d680fec448cb79b10ed6017e7b9f..7c9621388efb76c4ae8bea4640288b1ac1264150 100644
--- a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.html
@@ -1,26 +1,26 @@
 <!--
 
-    Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+Ministerpräsidenten des Landes Schleswig-Holstein
+Staatskanzlei
+Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
 
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
 
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
 
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
 <h1 mat-dialog-title>
@@ -30,14 +30,13 @@
 <mat-dialog-content>
   <p data-test-id="error-message" class="error-message">
     Wir sind nicht ganz sicher, was schiefgelaufen ist. Der Fehler
-    <span *ngIf="showId()">(ID: {{ data.issues[0].exceptionId }})</span> wurde unserem Support
-    gemeldet. Bitte starten sie die Anwendung neu.
+    @if (showId()) {
+      <span>(ID: {{ data.issues[0].exceptionId }})</span>
+    }
+    wurde unserem Support gemeldet. Bitte starten sie die Anwendung neu.
   </p>
   <a href="/" tabindex="-1" class="button">
-    <ozgcloud-stroked-button-with-spinner
-      icon="refresh"
-      text="Neu starten"
-    ></ozgcloud-stroked-button-with-spinner>
+    <ozgcloud-stroked-button-with-spinner icon="refresh" text="Neu starten"></ozgcloud-stroked-button-with-spinner>
   </a>
   <ozgcloud-stroked-button-with-spinner
     icon="logout"
diff --git a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.spec.ts
index ebc6907e4a0ecc725e963035137e93c5649ef558..3eb87f3f9084ad31fbd7bd508b208ec917edee1d 100644
--- a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.spec.ts
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { mock } from '@alfa-client/test-utils';
+import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
 import { MatIcon } from '@angular/material/icon';
 import { faker } from '@faker-js/faker';
-import { mock } from '@alfa-client/test-utils';
-import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { OAuthService } from 'angular-oauth2-oidc';
 import { createIssue } from 'libs/tech-shared/test/error';
 import { MockComponent } from 'ng-mocks';
@@ -40,12 +40,12 @@ describe('InternalServerErrorDialogComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [
+      imports: [
+        MatDialogModule,
         InternalServerErrorDialogComponent,
         MatIcon,
         MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
       ],
-      imports: [MatDialogModule],
       providers: [
         {
           provide: MatDialogRef,
@@ -83,9 +83,7 @@ describe('InternalServerErrorDialogComponent', () => {
       dialogData = { error: { ...{ issues: [createIssue()] }, id: exceptionId } };
       fixture.detectChanges();
 
-      expect(fixture.nativeElement).not.toHaveTextContent(
-        `ID: ${dialogData.error.issues[0].exceptionId}`,
-      );
+      expect(fixture.nativeElement).not.toHaveTextContent(`ID: ${dialogData.error.issues[0].exceptionId}`);
     });
   });
 });
diff --git a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.ts b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.ts
index cfcbff45dbacdbb63cff491fec6ac4226bbca0e5..e55158c9e1e892cd4d863842d64897b7aa82341c 100644
--- a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.ts
@@ -21,21 +21,24 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Inject } from '@angular/core';
-import { MAT_DIALOG_DATA } from '@angular/material/dialog';
 import { ApiError, hasExceptionId } from '@alfa-client/tech-shared';
+import { CdkScrollable } from '@angular/cdk/scrolling';
+import { Component, inject } from '@angular/core';
+import { MAT_DIALOG_DATA, MatDialogContent, MatDialogTitle } from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
 import { OAuthService } from 'angular-oauth2-oidc';
+import { OzgcloudStrokedButtonWithSpinnerComponent } from '../../ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component';
 
 @Component({
   selector: 'ozgcloud-internal-server-error-dialog',
   templateUrl: './internal-server-error-dialog.component.html',
   styleUrls: ['./internal-server-error-dialog.component.scss'],
+  standalone: true,
+  imports: [MatDialogTitle, MatIcon, CdkScrollable, MatDialogContent, OzgcloudStrokedButtonWithSpinnerComponent],
 })
 export class InternalServerErrorDialogComponent {
-  constructor(
-    @Inject(MAT_DIALOG_DATA) public data: ApiError,
-    public authService: OAuthService,
-  ) {}
+  public data: ApiError = inject<ApiError>(MAT_DIALOG_DATA);
+  public authService = inject(OAuthService);
 
   showId(): boolean {
     return hasExceptionId(this.data);
diff --git a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.spec.ts
index f5fbf2d6c35beb79bccaf3e8c87c0e62f0fd3e00..b53d242247b71270aa5585099561d595492f51cd 100644
--- a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.spec.ts
@@ -23,8 +23,8 @@
  */
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 
-import { OpenUrlButtonComponent } from './open-url-button.component';
 import { MockComponent } from 'ng-mocks';
+import { OpenUrlButtonComponent } from './open-url-button.component';
 
 describe('OpenUrlButtonComponent', () => {
   let component: OpenUrlButtonComponent;
@@ -32,7 +32,7 @@ describe('OpenUrlButtonComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [OpenUrlButtonComponent, MockComponent(OpenUrlButtonComponent)],
+      imports: [OpenUrlButtonComponent, MockComponent(OpenUrlButtonComponent)],
     }).compileComponents();
 
     fixture = TestBed.createComponent(OpenUrlButtonComponent);
diff --git a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.ts b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.ts
index 4663a18ab9485c6db0358a3ad4f2203c950548f4..f080acaa278a60d150fa32083f2be3ecd8325b69 100644
--- a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.ts
@@ -22,11 +22,16 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, Input } from '@angular/core';
+import { MatAnchor } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
+import { MatTooltip } from '@angular/material/tooltip';
 
 @Component({
   selector: 'ozgcloud-open-url-button',
   templateUrl: './open-url-button.component.html',
   styleUrls: ['./open-url-button.component.scss'],
+  standalone: true,
+  imports: [MatAnchor, MatTooltip, MatIcon],
 })
 export class OpenUrlButtonComponent {
   @Input() icon: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.spec.ts
index ee97fa55891a3b5ea04917c80ea255458f58d68b..5447abd13a916be618548326cef55e254a232963 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.spec.ts
@@ -41,7 +41,7 @@ describe('OzgcloudButtonWithSpinnerComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [
+      imports: [
         MatButton,
         MatRipple,
         OzgcloudButtonWithSpinnerComponent,
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.ts
index 497704e4b948a92527d4cdaf02050658142a1aaf..fb46489bd43247e86059d332972cabfd88db9364 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.ts
@@ -21,15 +21,21 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { MatButton } from '@angular/material/button';
+import { MatTooltip } from '@angular/material/tooltip';
 import { Resource } from '@ngxp/rest';
+import { TooltipDirective } from '@ods/system';
 import { isNil } from 'lodash-es';
+import { OzgcloudButtonContentComponent } from '../shared/ozgcloud-button-content/ozgcloud-button-content.component';
 
 @Component({
   selector: 'ozgcloud-button-with-spinner',
   templateUrl: './ozgcloud-button-with-spinner.component.html',
   styleUrls: ['./ozgcloud-button-with-spinner.component.scss'],
+  standalone: true,
+  imports: [MatButton, MatTooltip, OzgcloudButtonContentComponent, TooltipDirective],
 })
 export class OzgcloudButtonWithSpinnerComponent implements OnInit {
   @Input() icon: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.spec.ts
index 976c0b0c396b7dfc68b3f7e53148d1d75cf1baa8..48f65db0143ecaf0c0e6a564f1f6cd1619092934 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.spec.ts
@@ -61,10 +61,7 @@ describe('IconButtonPrimaryWithSpinnerComponent', () => {
     it('should create aria label', () => {
       component.ngOnInit();
 
-      expect(createAriaLabelForIconButtonMock).toHaveBeenCalledWith(
-        component.tooltip,
-        component.svgIcon,
-      );
+      expect(createAriaLabelForIconButtonMock).toHaveBeenCalledWith(component.tooltip, component.svgIcon);
     });
 
     it('should set aria label', () => {
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.ts
index f6dd2b5094a3d5521945be70c70d6d2ac88192dd..d5fc959cc46fcc27629b9e8c48555d26cb877146 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.ts
@@ -21,14 +21,20 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
 import { createAriaLabelForIconButton, StateResource } from '@alfa-client/tech-shared';
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { MatIconButton } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
+import { MatTooltip } from '@angular/material/tooltip';
 import { Resource } from '@ngxp/rest';
+import { TooltipDirective } from '@ods/system';
 
 @Component({
   selector: 'ozgcloud-icon-button-primary',
   templateUrl: './ozgcloud-icon-button-primary.component.html',
   styleUrls: ['./ozgcloud-icon-button-primary.component.scss'],
+  standalone: true,
+  imports: [MatIconButton, MatTooltip, MatIcon, TooltipDirective],
 })
 export class OzgcloudIconButtonPrimaryComponent implements OnInit {
   @Input() svgIcon: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.spec.ts
index 208868555e600c7fd81f6edc4bd1e8fd541827e6..ac0307f0125ad487682e40acba742c9245774b94 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.spec.ts
@@ -41,7 +41,7 @@ describe('OzgcloudStrokedButtonWithSpinnerComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [
+      imports: [
         MatButton,
         MatRipple,
         OzgcloudStrokedButtonWithSpinnerComponent,
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.ts
index 218915f94f34808e4423af8fbffec4ee4c180349..36f102a0d7d92d5953a97f1a7b47caa9988b4591 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.ts
@@ -21,15 +21,21 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { MatButton } from '@angular/material/button';
+import { MatTooltip } from '@angular/material/tooltip';
 import { Resource } from '@ngxp/rest';
+import { TooltipDirective } from '@ods/system';
 import { isNil } from 'lodash-es';
+import { OzgcloudButtonContentComponent } from '../shared/ozgcloud-button-content/ozgcloud-button-content.component';
 
 @Component({
   selector: 'ozgcloud-stroked-button-with-spinner',
   templateUrl: './ozgcloud-stroked-button-with-spinner.component.html',
   styleUrls: ['./ozgcloud-stroked-button-with-spinner.component.scss'],
+  standalone: true,
+  imports: [MatButton, MatTooltip, OzgcloudButtonContentComponent, TooltipDirective],
 })
 export class OzgcloudStrokedButtonWithSpinnerComponent implements OnInit {
   @Input() icon: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.html
index 168a6bfdaae0891449b9dd1d88b57edb7662325d..88d174c6a844f216987f40801c6e7c6cfcc35b76 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.html
@@ -1,47 +1,46 @@
 <!--
 
-    Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
-
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
-
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
-
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
+Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+Ministerpräsidenten des Landes Schleswig-Holstein
+Staatskanzlei
+Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
+
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<mat-icon
-  *ngIf="icon"
-  data-test-class="icon"
-  [class.with-text]="text"
-  [style.visibility]="isDisabled ? 'hidden' : 'visible'"
->
-  {{ icon }}
-</mat-icon>
-
-<mat-icon
-  *ngIf="svgIcon"
-  data-test-class="icon"
-  [class.with-text]="text"
-  [svgIcon]="svgIcon"
-  [style.visibility]="isDisabled ? 'hidden' : 'visible'"
->
-</mat-icon>
-
-<span *ngIf="text" class="text-sm" data-test-class="button-with-spinner-text">{{ text }}</span>
-
-<ozgcloud-spinner [diameter]="22" padding="0" [stateResource]="stateResource" [show]="showSpinner">
-</ozgcloud-spinner>
+@if (icon) {
+  <mat-icon data-test-class="icon" [class.with-text]="text" [style.visibility]="isDisabled ? 'hidden' : 'visible'">
+    {{ icon }}
+  </mat-icon>
+}
+
+@if (svgIcon) {
+  <mat-icon
+    data-test-class="icon"
+    [class.with-text]="text"
+    [svgIcon]="svgIcon"
+    [style.visibility]="isDisabled ? 'hidden' : 'visible'"
+  >
+  </mat-icon>
+}
+
+@if (text) {
+  <span class="text-sm" data-test-class="button-with-spinner-text">{{ text }}</span>
+}
+
+<ozgcloud-spinner [diameter]="22" padding="0" [stateResource]="stateResource" [show]="showSpinner"> </ozgcloud-spinner>
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.spec.ts
index 0a313a7ef672ecb3b215ce916ed709cb9aa83cb4..14e079e54c2bc4faa5cb355342b24850d15e9acc 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.spec.ts
@@ -37,7 +37,7 @@ describe('OzgcloudButtonContentComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [MatIcon, MockComponent(SpinnerComponent), OzgcloudButtonContentComponent],
+      imports: [MatIcon, MockComponent(SpinnerComponent), OzgcloudButtonContentComponent],
     }).compileComponents();
 
     fixture = TestBed.createComponent(OzgcloudButtonContentComponent);
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.ts
index 32283456c72d2ffd653f89880ac1f42c789f9a79..4e2b5fec9f852c47df972ecaaa22531ca7a25069 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.ts
@@ -21,14 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
 import { StateResource } from '@alfa-client/tech-shared';
+import { Component, Input } from '@angular/core';
+import { MatIcon } from '@angular/material/icon';
 import { Resource } from '@ngxp/rest';
+import { SpinnerComponent } from '../../../spinner/spinner.component';
 
 @Component({
   selector: 'ozgcloud-button-content',
   templateUrl: './ozgcloud-button-content.component.html',
   styleUrls: ['./ozgcloud-button-content.component.scss'],
+  standalone: true,
+  imports: [MatIcon, SpinnerComponent],
 })
 export class OzgcloudButtonContentComponent {
   @Input() icon: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts
index da2fb2923e846b00101f7dca2dab0500a8a5c971..077780a3e1d01c0e198efc1de9f12244315b1194 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts
@@ -23,13 +23,15 @@
  */
 import { Dialog, DialogConfig, DialogRef } from '@angular/cdk/dialog';
 import { ComponentType } from '@angular/cdk/portal';
-import { Injectable, ViewContainerRef } from '@angular/core';
+import { inject, Injectable, ViewContainerRef } from '@angular/core';
 import { isNil } from 'lodash-es';
 
 @Injectable({
   providedIn: 'root',
 })
 export class OzgcloudDialogService {
+  private dialog = inject(Dialog);
+
   readonly WIZARD_DIALOG_CONFIG: DialogConfig = {
     width: '1000px',
     restoreFocus: false,
@@ -41,8 +43,6 @@ export class OzgcloudDialogService {
     disableClose: true,
   };
 
-  constructor(private dialog: Dialog) {}
-
   public openWizard<C, D, R = unknown>(component: ComponentType<C>, data?: D): DialogRef<R> {
     return this.openDialog<C, R>(component, this.buildDialogConfigWithData<D>(data, this.WIZARD_DIALOG_CONFIG));
   }
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.spec.ts
index 2f46c2cd4b354c756077397db94a28bb07382214..348a842ef697927273e2af4f7fe4337735b53e6f 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.spec.ts
@@ -31,8 +31,7 @@ describe('OzgcloudIconComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [OzgcloudIconComponent],
-      imports: [MatIcon],
+      imports: [MatIcon, OzgcloudIconComponent],
     }).compileComponents();
 
     fixture = TestBed.createComponent(OzgcloudIconComponent);
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.ts
index 888c31801bbcf6a6c03fda6f6ed43d9529fbd0bb..b2e99d1f83445d4f007910fe6986c749f2600808 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.ts
@@ -22,11 +22,14 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, Input } from '@angular/core';
+import { MatIcon } from '@angular/material/icon';
 
 @Component({
   selector: 'ozgcloud-icon',
   templateUrl: './ozgcloud-icon.component.html',
   styleUrls: ['./ozgcloud-icon.component.scss'],
+  standalone: true,
+  imports: [MatIcon],
 })
 export class OzgcloudIconComponent {
   @Input() icon: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.spec.ts
index e967e79c2ae45c7305d4255e199f52f27220fa4e..454e44cb8d1cbbb063e1228cda44e601a1423053 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.spec.ts
@@ -31,8 +31,7 @@ describe('OzgcloudMenuComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [OzgcloudMenuComponent],
-      imports: [MatMenuModule],
+      imports: [MatMenuModule, OzgcloudMenuComponent],
     }).compileComponents();
 
     fixture = TestBed.createComponent(OzgcloudMenuComponent);
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.ts
index bd007c306911e007bc515da3fab56fcc2ebc9a52..d267a8ffe01c0d07ff12b0e83d699140856b25bf 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.ts
@@ -28,6 +28,8 @@ import { MatMenu } from '@angular/material/menu';
   selector: 'ozgcloud-menu',
   templateUrl: './ozgcloud-menu.component.html',
   styleUrls: ['./ozgcloud-menu.component.scss'],
+  standalone: true,
+  imports: [MatMenu],
 })
 export class OzgcloudMenuComponent {
   @ViewChild('menu', { static: true }) matMenu: MatMenu;
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.html
index 604b9441202c5c72a07489dc8715d69c339cb489..f6dd97a4e59aad87b62bc7cfa87277a51dbdd9e5 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.html
@@ -1,34 +1,35 @@
 <!--
 
-    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+Ministerpräsidenten des Landes Schleswig-Holstein
+Staatskanzlei
+Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
 
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
 
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
 
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ozgcloud-icon-button-primary
-  *ngIf="isPasteSupported"
-  [tooltip]="tooltip"
-  svgIcon="paste_from_clipboard"
-  class="paste_icon"
-  (clickEmitter)="onPaste()"
-  data-test-id="paste_from_clipboard"
->
-</ozgcloud-icon-button-primary>
+@if (isPasteSupported) {
+  <ozgcloud-icon-button-primary
+    [tooltip]="tooltip"
+    svgIcon="paste_from_clipboard"
+    class="paste_icon"
+    (clickEmitter)="onPaste()"
+    data-test-id="paste_from_clipboard"
+  >
+  </ozgcloud-icon-button-primary>
+}
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.spec.ts
index e91b91840bb1f855e5821d6eaac5949bc815181c..918ec8d7c1c8122a7f8fbf5489f3031e66f664bf 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.spec.ts
@@ -50,8 +50,8 @@ describe('OzgcloudPasteTextButtonComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [MatIconTestingModule],
-      declarations: [
+      imports: [
+        MatIconTestingModule,
         OzgcloudPasteTextButtonComponent,
         MockComponent(MatIcon),
         MockComponent(OzgcloudIconButtonPrimaryComponent),
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.ts
index de10060dbe49cd7f048adbf90f267b26a357d65f..3fa9c14b0b00126d3074923b4871ecf52594a4b1 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.ts
@@ -21,13 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
 import { isClipboardReadSupported } from '@alfa-client/tech-shared';
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { OzgcloudIconButtonPrimaryComponent } from '../ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component';
 
 @Component({
   selector: 'ozgcloud-paste-text-button',
   templateUrl: './ozgcloud-paste-text-button.component.html',
   styleUrls: ['./ozgcloud-paste-text-button.component.scss'],
+  standalone: true,
+  imports: [OzgcloudIconButtonPrimaryComponent],
 })
 export class OzgcloudPasteTextButtonComponent implements OnInit {
   @Input() tooltip: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.spec.ts
index e29ecd69fcee6fb293c466bdb7ff426d83666b4d..b789f1e69acc310ec87cedebd84a2cb2f3dad0a4 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.spec.ts
@@ -31,8 +31,7 @@ describe('OzgcloudRoutingButtonComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [OzgcloudRoutingButtonComponent],
-      imports: [RouterTestingModule],
+      imports: [RouterTestingModule, OzgcloudRoutingButtonComponent],
     }).compileComponents();
 
     fixture = TestBed.createComponent(OzgcloudRoutingButtonComponent);
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.ts
index fa61fa8f609a3cc7129eaad33e8656bba754d345..92d82c8800f117c3bb8b1c9256880294c6cbc9cf 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.ts
@@ -22,11 +22,15 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, Input } from '@angular/core';
+import { MatAnchor } from '@angular/material/button';
+import { RouterLink } from '@angular/router';
 
 @Component({
   selector: 'ozgcloud-routing-button',
   templateUrl: './ozgcloud-routing-button.component.html',
   styleUrls: ['./ozgcloud-routing-button.component.scss'],
+  standalone: true,
+  imports: [MatAnchor, RouterLink],
 })
 export class OzgcloudRoutingButtonComponent {
   @Input() routerLinkPath: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.spec.ts
index 734f2aa0c6dabdf0b55381f37365e4f23a6002f6..6189dfc0e3720ac7d4dcfcaff706f181af7474e2 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.spec.ts
@@ -31,8 +31,7 @@ describe('OzgcloudSvgIconBigComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [OzgcloudSvgIconBigComponent],
-      imports: [MatIcon],
+      imports: [MatIcon, OzgcloudSvgIconBigComponent],
     }).compileComponents();
 
     fixture = TestBed.createComponent(OzgcloudSvgIconBigComponent);
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.ts
index e99ad4a83f0a0bd6344267d353e06f994640f37b..5d7c397f0a5b0c8b0693da1b5ed8f012ec23b75b 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.ts
@@ -22,11 +22,14 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, Input } from '@angular/core';
+import { MatIcon } from '@angular/material/icon';
 
 @Component({
   selector: 'ozgcloud-svgicon-big',
   templateUrl: './ozgcloud-svgicon-big.component.html',
   styleUrls: ['./ozgcloud-svgicon-big.component.scss'],
+  standalone: true,
+  imports: [MatIcon],
 })
 export class OzgcloudSvgIconBigComponent {
   @Input() svgIcon: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.spec.ts
index 9ce6d63d48290d7145975d7ef01d570759571aa9..d3f63f4b2c1cb7be217ce69efbd180891efb496f 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.spec.ts
@@ -31,8 +31,7 @@ describe('OzgcloudSvgIconComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [OzgcloudSvgIconComponent],
-      imports: [MatIcon],
+      imports: [MatIcon, OzgcloudSvgIconComponent],
     }).compileComponents();
 
     fixture = TestBed.createComponent(OzgcloudSvgIconComponent);
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.ts
index 7aa1d869fca7f17ad41926120aa9c5bf088bd5e8..c35c9ab18d1b5ede13f37f06f980dd88c0d2ce24 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.ts
@@ -22,11 +22,14 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, Input } from '@angular/core';
+import { MatIcon } from '@angular/material/icon';
 
 @Component({
   selector: 'ozgcloud-svgicon',
   templateUrl: './ozgcloud-svgicon.component.html',
   styleUrls: ['./ozgcloud-svgicon.component.scss'],
+  standalone: true,
+  imports: [MatIcon],
 })
 export class OzgcloudSvgIconComponent {
   @Input() svgIcon: string;
diff --git a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html
index 6f992fe024c1d15d17114491373d81a50b8c0c20..3a7dda71335ccefb8982d0452826a35d8032de5d 100644
--- a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html
@@ -1,28 +1,30 @@
 <!--
 
-    Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+Ministerpräsidenten des Landes Schleswig-Holstein
+Staatskanzlei
+Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
 
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
 
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
 
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<div *ngIf="isVisible" class="progressbar-overlay" data-test-class="progressbar-overlay">
-  <mat-progress-bar data-test-id="progress-bar" mode="indeterminate"></mat-progress-bar>
-</div>
+@if (isVisible) {
+  <div class="progressbar-overlay" data-test-class="progressbar-overlay">
+    <mat-progress-bar data-test-id="progress-bar" mode="indeterminate"></mat-progress-bar>
+  </div>
+}
diff --git a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.spec.ts
index 87b2dca90e9adc2001bd595db8b24c924d93c9a4..a98db10dc48b1241047e761fd2f05a5d962d6c34 100644
--- a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.spec.ts
@@ -34,8 +34,7 @@ describe('ProgressBarComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [ProgressBarComponent],
-      imports: [MatProgressBar],
+      imports: [MatProgressBar, ProgressBarComponent],
     });
   });
 
diff --git a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.ts b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.ts
index 69bf1807b1661c741d23ae7747d964a8c699d366..185fa2810d9fcae9d2d9a3e710e140a441fcc617 100644
--- a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.ts
@@ -21,14 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
 import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
+import { Component, Input } from '@angular/core';
+import { MatProgressBarModule } from '@angular/material/progress-bar';
 import { Resource } from '@ngxp/rest';
 
 @Component({
   selector: 'ozgcloud-progress-bar',
   templateUrl: './progress-bar.component.html',
   styleUrls: ['./progress-bar.component.scss'],
+  standalone: true,
+  imports: [MatProgressBarModule],
 })
 export class ProgressBarComponent {
   @Input() stateResource: StateResource<Resource> = createEmptyStateResource<Resource>();
diff --git a/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.ts b/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.ts
index 951d47620e165deecf550d90f43930cb30405653..862f4c7ec87f24a558689fca192955ba6e95fc9c 100644
--- a/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.ts
@@ -21,13 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, EventEmitter, Input, Output } from '@angular/core';
 import { EMPTY_STRING } from '@alfa-client/tech-shared';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { MatSlideToggle } from '@angular/material/slide-toggle';
+import { MatTooltip } from '@angular/material/tooltip';
+import { TooltipDirective } from '@ods/system';
 
 @Component({
   selector: 'ozgcloud-slide-toggle',
   templateUrl: './slide-toggle.component.html',
   styleUrls: ['./slide-toggle.component.scss'],
+  standalone: true,
+  imports: [MatSlideToggle, MatTooltip, TooltipDirective],
 })
 export class SlideToggleComponent {
   @Input() checked: boolean = false;
diff --git a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.html b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.html
index fa88c4170ccd839d86ed250e89eef62cccf7101f..488dfee2c9a4a858064cca4461e25ceeb64a43b9 100644
--- a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.html
@@ -1,35 +1,32 @@
 <!--
 
-    Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+Ministerpräsidenten des Landes Schleswig-Holstein
+Staatskanzlei
+Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
 
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
 
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
 
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<div
-  *ngIf="showSpinner"
-  data-test-class="spinner-transparency"
-  class="spinner"
-  [style.padding]="'16px'"
->
-  <mat-spinner [diameter]="70"></mat-spinner>
-</div>
-
-<ng-content *ngIf="!showSpinner" data-test-class="spinner-transparency-content"></ng-content>
+@if (showSpinner) {
+  <div data-test-class="spinner-transparency" class="spinner" [style.padding]="'16px'">
+    <mat-spinner [diameter]="70"></mat-spinner>
+  </div>
+} @else {
+  <ng-content data-test-class="spinner-transparency-content"></ng-content>
+}
diff --git a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.spec.ts
index 2c1395076163f92d48f781151f13cfa4c7967888..c5c81db6154375f630b88bc874dee34a3a16ad22 100644
--- a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.spec.ts
@@ -38,8 +38,7 @@ describe('SpinnerTransparencyComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [SpinnerTransparencyComponent, SpinnerComponent],
-      imports: [MatIcon, MatProgressSpinner],
+      imports: [MatIcon, MatProgressSpinner, SpinnerTransparencyComponent, SpinnerComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.ts b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.ts
index bf70ce6a7764c20ab9c2bce95f7191182ec920a2..34fa02963b6363318252902d45fe6b0853fe9334 100644
--- a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.ts
@@ -21,14 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
+import { Component, Input } from '@angular/core';
+import { MatProgressSpinner } from '@angular/material/progress-spinner';
 import { Resource } from '@ngxp/rest';
 
 @Component({
   selector: 'ozgcloud-spinner-transparency',
   templateUrl: './spinner-transparency.component.html',
   styleUrls: ['./spinner-transparency.component.scss'],
+  standalone: true,
+  imports: [MatProgressSpinner],
 })
 export class SpinnerTransparencyComponent {
   @Input() stateResource: StateResource<Resource> = createEmptyStateResource<Resource>();
diff --git a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.html b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.html
index eaa2ab439802985584c0b7595703072d095dcae9..5a426212ea07aa4413b5f7105c1790e7498ba8a6 100644
--- a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.html
@@ -1,31 +1,37 @@
 <!--
 
-    Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+Ministerpräsidenten des Landes Schleswig-Holstein
+Staatskanzlei
+Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
 
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
 
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
 
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<div *ngIf="showSpinner" class="spinner" [style.padding]="padding + 'px'">
-  <mat-spinner [diameter]="diameter" data-test-class="spinner"> </mat-spinner>
-  <span *ngIf="text">{{ text }}</span>
-</div>
+@if (showSpinner) {
+  <div class="spinner" [style.padding]="padding + 'px'">
+    <mat-spinner [diameter]="diameter" data-test-class="spinner"> </mat-spinner>
+    @if (text) {
+      <span>{{ text }}</span>
+    }
+  </div>
+}
 
-<ng-content *ngIf="!showSpinner" data-test-class="spinner-content"></ng-content>
+@if (!showSpinner) {
+  <ng-content data-test-class="spinner-content"></ng-content>
+}
diff --git a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.spec.ts
index 8bc40b8d5ba9850a5c36c603e91fcc13827d4420..27b80e6f55c7fa9994ebaba67688ff5417f6272b 100644
--- a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.spec.ts
@@ -37,8 +37,7 @@ describe('SpinnerComponent', () => {
 
   beforeEach(async () => {
     TestBed.configureTestingModule({
-      declarations: [SpinnerComponent],
-      imports: [MatIcon, MatProgressSpinner],
+      imports: [MatIcon, MatProgressSpinner, SpinnerComponent],
     });
   });
 
diff --git a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.ts b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.ts
index cfd3cfd4d3d6b17b4d046826c700c288bcb6cfe7..15350296561bdd96791a7b97e448e8be0ab6183f 100644
--- a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.ts
@@ -23,11 +23,14 @@
  */
 import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
 import { Component, Input } from '@angular/core';
+import { MatProgressSpinner } from '@angular/material/progress-spinner';
 
 @Component({
   selector: 'ozgcloud-spinner',
   templateUrl: './spinner.component.html',
   styleUrls: ['./spinner.component.scss'],
+  standalone: true,
+  imports: [MatProgressSpinner],
 })
 export class SpinnerComponent {
   @Input() stateResource: StateResource<unknown> = createEmptyStateResource<unknown>();
diff --git a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.spec.ts
index b021131cd7dae57a09c8821f81b6e0c6efa37813..6586a170653c455343d86b2c44d436a4c0defeab 100644
--- a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.spec.ts
@@ -30,7 +30,7 @@ describe('SubnavigationComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [SubnavigationComponent],
+      imports: [SubnavigationComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.ts b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.ts
index 631e4713fa20d357b911ab7c3fbb5514b5847a00..1e2deca56f9669732b166fc82adb23af30b9f699 100644
--- a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.ts
@@ -27,5 +27,6 @@ import { Component } from '@angular/core';
   selector: 'ozgcloud-subnavigation',
   templateUrl: './subnavigation.component.html',
   styleUrls: ['./subnavigation.component.scss'],
+  standalone: true,
 })
 export class SubnavigationComponent {}
diff --git a/alfa-client/libs/ui/src/lib/ui/ui.module.spec.ts b/alfa-client/libs/ui/src/lib/ui/ui.module.spec.ts
deleted file mode 100644
index 1133667573970cdae3c5f413d6d064c62ca94891..0000000000000000000000000000000000000000
--- a/alfa-client/libs/ui/src/lib/ui/ui.module.spec.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { TestBed } from '@angular/core/testing';
-import { UiModule } from './ui.module';
-
-describe('UiModule', () => {
-  beforeEach(() => {
-    TestBed.configureTestingModule({
-      imports: [UiModule],
-    }).compileComponents();
-  });
-
-  it('should create', () => {
-    expect(UiModule).toBeDefined();
-  });
-});
diff --git a/alfa-client/libs/ui/src/lib/ui/ui.module.ts b/alfa-client/libs/ui/src/lib/ui/ui.module.ts
deleted file mode 100644
index e7c19b188d8e38ab7c45f080f52b4b3536550cc4..0000000000000000000000000000000000000000
--- a/alfa-client/libs/ui/src/lib/ui/ui.module.ts
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { CommonModule } from '@angular/common';
-import { HTTP_INTERCEPTORS } from '@angular/common/http';
-import { NgModule } from '@angular/core';
-import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { DateFnsAdapter, MatDateFnsModule } from '@angular/material-date-fns-adapter';
-import { MatAutocompleteModule } from '@angular/material/autocomplete';
-import { MatBadgeModule } from '@angular/material/badge';
-import { MatButtonModule } from '@angular/material/button';
-import { MatButtonToggleModule } from '@angular/material/button-toggle';
-import { MatCheckboxModule } from '@angular/material/checkbox';
-import { DateAdapter, MAT_DATE_LOCALE, MatRippleModule } from '@angular/material/core';
-import { MatDatepickerModule } from '@angular/material/datepicker';
-import { MatDialogModule } from '@angular/material/dialog';
-import { MatExpansionModule } from '@angular/material/expansion';
-import { MatFormFieldModule } from '@angular/material/form-field';
-import { MatIconModule } from '@angular/material/icon';
-import { MatInputModule } from '@angular/material/input';
-import { MatListModule } from '@angular/material/list';
-import { MatMenuModule } from '@angular/material/menu';
-import { MatProgressBarModule } from '@angular/material/progress-bar';
-import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
-import { MatSlideToggleModule } from '@angular/material/slide-toggle';
-import { MatSnackBarModule } from '@angular/material/snack-bar';
-import { MatTabsModule } from '@angular/material/tabs';
-import { RouterModule } from '@angular/router';
-import {
-  ArrowBackIconComponent,
-  ButtonComponent,
-  FileUploadButtonComponent,
-  SpinnerIconComponent,
-  TooltipDirective,
-} from '@ods/system';
-import { de } from 'date-fns/locale';
-import { AppIconComponent } from '../icon/app-icon/app-icon.component';
-import { PostfachIconComponent } from '../icon/postfach-icon/postfach-icon.component';
-import { HttpConnectionTimeoutInterceptor } from '../interceptor/http-connection-timeout.interceptor';
-import { HttpErrorInterceptor } from '../interceptor/http-error.interceptor';
-import { SnackbarCloseButtonComponent } from '../snackbar/snackbar-close-button/snackbar-close-button.component';
-import { SnackbarErrorComponent } from '../snackbar/snackbar-error/snackbar-error.component';
-import { SnackbarInfoComponent } from '../snackbar/snackbar-info/snackbar-info.component';
-import { AccordionComponent } from './accordion/accordion.component';
-import { BackButtonComponent } from './back-button/back-button.component';
-import { BasicDialogComponent } from './basic-dialog/basic-dialog.component';
-import { DownloadButtonComponent } from './download-button/download-button.component';
-import { AutocompleteEditorComponent } from './editor/autocomplete-editor/autocomplete-editor.component';
-import { CheckboxEnumEditorComponent } from './editor/checkbox-enum-editor/checkbox-enum-editor.component';
-import { DateEditorComponent } from './editor/date-editor/date-editor.component';
-import { FileUploadEditorComponent } from './editor/file-upload-editor/file-upload-editor.component';
-import { TextEditorComponent } from './editor/text-editor/text-editor.component';
-import { TextAreaEditorComponent } from './editor/textarea-editor/textarea-editor.component';
-import { ExpansionPanelComponent } from './expansion-panel/expansion-panel.component';
-import { FileUploadComponent } from './file-upload/file-upload.component';
-import { FixedDialogComponent } from './fixed-dialog/fixed-dialog.component';
-import { ConnectionTimeoutRetryDialogComponent } from './http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component';
-import { ConnectionTimeoutRetryFailDialogComponent } from './http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component';
-import { IconButtonWithSpinnerComponent } from './icon-button-with-spinner/icon-button-with-spinner.component';
-import { InternalServerErrorDialogComponent } from './notification/internal-server-error-dialog/internal-server-error-dialog.component';
-import { OpenUrlButtonComponent } from './open-url-button/open-url-button.component';
-import { OzgcloudButtonWithSpinnerComponent } from './ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component';
-import { OzgcloudIconButtonPrimaryComponent } from './ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component';
-import { OzgcloudStrokedButtonWithSpinnerComponent } from './ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component';
-import { OzgcloudButtonContentComponent } from './ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component';
-import { OzgcloudIconComponent } from './ozgcloud-icon/ozgcloud-icon.component';
-import { OzgcloudMenuComponent } from './ozgcloud-menu/ozgcloud-menu.component';
-import { OzgcloudPasteTextButtonComponent } from './ozgcloud-paste-text-button/ozgcloud-paste-text-button.component';
-import { OzgcloudRoutingButtonComponent } from './ozgcloud-routing-button/ozgcloud-routing-button.component';
-import { OzgcloudSvgIconBigComponent } from './ozgcloud-svgicon-big/ozgcloud-svgicon-big.component';
-import { OzgcloudSvgIconComponent } from './ozgcloud-svgicon/ozgcloud-svgicon.component';
-import { ProgressBarComponent } from './progress-bar/progress-bar.component';
-import { SlideToggleComponent } from './slide-toggle/slide-toggle.component';
-import { SpinnerTransparencyComponent } from './spinner-transparency/spinner-transparency.component';
-import { SpinnerComponent } from './spinner/spinner.component';
-import { SubnavigationComponent } from './subnavigation/subnavigation.component';
-import { ValidationErrorComponent } from './validation-error/validation-error.component';
-
-@NgModule({
-  declarations: [
-    SubnavigationComponent,
-    SpinnerComponent,
-    OzgcloudButtonWithSpinnerComponent,
-    OzgcloudStrokedButtonWithSpinnerComponent,
-    IconButtonWithSpinnerComponent,
-    ProgressBarComponent,
-    ExpansionPanelComponent,
-    SnackbarInfoComponent,
-    SnackbarErrorComponent,
-    FileUploadComponent,
-    DateEditorComponent,
-    TextEditorComponent,
-    TextAreaEditorComponent,
-    ValidationErrorComponent,
-    AutocompleteEditorComponent,
-    FixedDialogComponent,
-    InternalServerErrorDialogComponent,
-    FileUploadEditorComponent,
-    PostfachIconComponent,
-    AccordionComponent,
-    AppIconComponent,
-    SlideToggleComponent,
-    BackButtonComponent,
-    OzgcloudIconButtonPrimaryComponent,
-    OzgcloudIconComponent,
-    OzgcloudRoutingButtonComponent,
-    OzgcloudSvgIconComponent,
-    OzgcloudSvgIconBigComponent,
-    SpinnerTransparencyComponent,
-    OpenUrlButtonComponent,
-    DownloadButtonComponent,
-    ConnectionTimeoutRetryDialogComponent,
-    ConnectionTimeoutRetryFailDialogComponent,
-    SnackbarCloseButtonComponent,
-    BasicDialogComponent,
-    OzgcloudButtonContentComponent,
-    OzgcloudPasteTextButtonComponent,
-    CheckboxEnumEditorComponent,
-    OzgcloudMenuComponent,
-  ],
-  imports: [
-    MatButtonModule,
-    MatIconModule,
-    MatProgressBarModule,
-    MatProgressSpinnerModule,
-    MatMenuModule,
-    MatSlideToggleModule,
-    MatExpansionModule,
-    MatRippleModule,
-    MatSnackBarModule,
-    MatCheckboxModule,
-    MatFormFieldModule,
-    MatInputModule,
-    MatListModule,
-    MatDatepickerModule,
-    MatDateFnsModule,
-    FormsModule,
-    ReactiveFormsModule,
-    MatAutocompleteModule,
-    MatDialogModule,
-    MatTabsModule,
-    MatBadgeModule,
-    CommonModule,
-    TechSharedModule,
-    RouterModule,
-    MatButtonToggleModule,
-    FileUploadButtonComponent,
-    SpinnerIconComponent,
-    TooltipDirective,
-    ButtonComponent,
-    ArrowBackIconComponent,
-  ],
-  exports: [
-    MatButtonModule,
-    MatIconModule,
-    MatProgressBarModule,
-    MatProgressSpinnerModule,
-    MatMenuModule,
-    MatSlideToggleModule,
-    MatExpansionModule,
-    MatRippleModule,
-    MatSnackBarModule,
-    MatCheckboxModule,
-    MatFormFieldModule,
-    MatInputModule,
-    MatListModule,
-    MatDatepickerModule,
-    MatDateFnsModule,
-    FormsModule,
-    ReactiveFormsModule,
-    MatAutocompleteModule,
-    MatDialogModule,
-    MatTabsModule,
-    MatBadgeModule,
-    CommonModule,
-    TechSharedModule,
-    RouterModule,
-    MatButtonToggleModule,
-    SubnavigationComponent,
-    SpinnerComponent,
-    OzgcloudIconButtonPrimaryComponent,
-    OzgcloudButtonWithSpinnerComponent,
-    OzgcloudStrokedButtonWithSpinnerComponent,
-    IconButtonWithSpinnerComponent,
-    ProgressBarComponent,
-    ExpansionPanelComponent,
-    SnackbarInfoComponent,
-    SnackbarErrorComponent,
-    FileUploadComponent,
-    DateEditorComponent,
-    TextEditorComponent,
-    TextAreaEditorComponent,
-    ValidationErrorComponent,
-    AutocompleteEditorComponent,
-    FixedDialogComponent,
-    InternalServerErrorDialogComponent,
-    FileUploadEditorComponent,
-    PostfachIconComponent,
-    AccordionComponent,
-    AppIconComponent,
-    SlideToggleComponent,
-    BackButtonComponent,
-    OzgcloudIconComponent,
-    OzgcloudRoutingButtonComponent,
-    OzgcloudSvgIconComponent,
-    OzgcloudSvgIconBigComponent,
-    SpinnerTransparencyComponent,
-    OpenUrlButtonComponent,
-    DownloadButtonComponent,
-    ConnectionTimeoutRetryDialogComponent,
-    ConnectionTimeoutRetryFailDialogComponent,
-    SnackbarCloseButtonComponent,
-    BasicDialogComponent,
-    OzgcloudPasteTextButtonComponent,
-    CheckboxEnumEditorComponent,
-    FileUploadButtonComponent,
-    OzgcloudButtonContentComponent,
-    OzgcloudMenuComponent,
-  ],
-  providers: [
-    {
-      provide: HTTP_INTERCEPTORS,
-      useClass: HttpErrorInterceptor,
-      multi: true,
-    },
-    {
-      provide: HTTP_INTERCEPTORS,
-      useClass: HttpConnectionTimeoutInterceptor,
-      multi: true,
-    },
-    {
-      provide: MAT_DATE_LOCALE,
-      useValue: de,
-    },
-    {
-      provide: DateAdapter,
-      useClass: DateFnsAdapter,
-      deps: [MAT_DATE_LOCALE],
-    },
-  ],
-})
-export class UiModule {}
diff --git a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html
index cdf207ba37ef266413d4dc72d8762f1a6e1e1913..673ecf065e1b890e163cf98fab0335c180bea627 100644
--- a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html
@@ -1,26 +1,28 @@
 <!--
 
-    Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
+Ministerpräsidenten des Landes Schleswig-Holstein
+Staatskanzlei
+Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
 
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
 
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
 
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<span *ngFor="let invalidParam of invalidParams">{{ message(invalidParam) }}</span>
+@for (invalidParam of invalidParams; track invalidParam) {
+  <span>{{ message(invalidParam) }}</span>
+}
diff --git a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts
index 0b265b44ec24e326187ef0b8605fcf1a7f8f688e..2e851164cb169a9e9c085c4b1e2ca483a970d921 100644
--- a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts
@@ -33,7 +33,7 @@ describe('ValidationErrorComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [ValidationErrorComponent],
+      imports: [ValidationErrorComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts
index 285a9989ed250d9f14f62a7b2a8b5bc7834b907c..eae4c1e99487d7fe169a73fee93d07af75f55676 100644
--- a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts
@@ -28,6 +28,7 @@ import { Component, Input } from '@angular/core';
   selector: 'ozgcloud-validation-error',
   templateUrl: './validation-error.component.html',
   styleUrls: ['./validation-error.component.scss'],
+  standalone: true,
 })
 export class ValidationErrorComponent {
   @Input() label: string;
diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.html b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.html
index 0179cbc7aac26bf1464207fa7557006d3294e87a..d3f460b90b5c7c7232d01e2b4e0674ddee2a8a8c 100644
--- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.html
+++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.html
@@ -29,4 +29,4 @@
   [targetName]="'_blank'"
   [tooltip]="'Öffnet in einem neuen Tab'"
   data-test-id="open-documentation-button"
-></ozgcloud-open-url-button>
+/>
diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts
index ba0e572d4edad3c8e610cd869d31b40b186d8d5d..870deee5a210330b9a267bac71c674ddce7e3ae0 100644
--- a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts
+++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts
@@ -24,8 +24,9 @@
 import { ApiRootLinkRel } from '@alfa-client/api-root-shared';
 import { GetUrlPipe, HasLinkPipe, createStateResource } from '@alfa-client/tech-shared';
 import { getElementFromDomRoot } from '@alfa-client/test-utils';
-import { UiModule } from '@alfa-client/ui';
+import { OzgcloudIconComponent, OzgcloudMenuComponent } from '@alfa-client/ui';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatMenuTrigger } from '@angular/material/menu';
 import { NoopAnimationsModule } from '@angular/platform-browser/animations';
 import {
   DropdownMenuComponent,
@@ -34,9 +35,9 @@ import {
   FileIconComponent,
   HelpIconComponent,
 } from '@ods/system';
+import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
-import { createApiRootResource } from '../../../../../libs/api-root-shared/test/api-root';
 import { DocumentationComponent } from './documentation/documentation.component';
 import { HelpButtonComponent } from './help-button/help-button.component';
 import { HelpMenuComponent } from './help-menu.component';
@@ -54,6 +55,10 @@ describe('HelpMenuComponent', () => {
         HelpMenuComponent,
         HasLinkPipe,
         GetUrlPipe,
+        MatMenuTrigger,
+        MockComponent(OzgcloudMenuComponent),
+        MockComponent(DocumentationComponent),
+        MockComponent(OzgcloudIconComponent),
         MockComponent(DocumentationComponent),
         MockComponent(FileIconComponent),
         MockComponent(HelpIconComponent),
@@ -62,7 +67,7 @@ describe('HelpMenuComponent', () => {
         MockComponent(DropdownMenuLinkItemComponent),
         MockComponent(HelpButtonComponent),
       ],
-      imports: [NoopAnimationsModule, UiModule],
+      imports: [NoopAnimationsModule],
     }).compileComponents();
 
     fixture = TestBed.createComponent(HelpMenuComponent);
diff --git a/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts b/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts
index 1eda492b4fe8af82af049e37d1548a419912e98f..63fc01ce61325ce4935a8292df7314a550e83940 100644
--- a/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts
+++ b/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts
@@ -21,9 +21,8 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
 import { CommonModule } from '@angular/common';
+import { GetUrlPipe, HasLinkPipe } from '@alfa-client/tech-shared';
 import { NgModule } from '@angular/core';
 import {
   DropdownMenuComponent,
@@ -32,21 +31,27 @@ import {
   FileIconComponent,
   HelpIconComponent,
 } from '@ods/system';
+import { MatFabButton } from '@angular/material/button';
+import { MatMenuTrigger } from '@angular/material/menu';
 import { DocumentationComponent } from './help-menu/documentation/documentation.component';
 import { OpenDocumentationButtonComponent } from './help-menu/documentation/open-documentation-button/open-documentation-button.component';
 import { HelpButtonComponent } from './help-menu/help-button/help-button.component';
 import { HelpMenuComponent } from './help-menu/help-menu.component';
+import { OpenUrlButtonComponent } from '@alfa-client/ui';
 
 @NgModule({
   imports: [
     CommonModule,
-    TechSharedModule,
+    MatMenuTrigger,
+    HasLinkPipe,
+    GetUrlPipe,
+    MatFabButton,
     FileIconComponent,
     HelpIconComponent,
     DropdownMenuComponent,
     DropdownMenuTextItemComponent,
-    UiModule,
     DropdownMenuLinkItemComponent,
+    OpenUrlButtonComponent,
   ],
   declarations: [HelpMenuComponent, DocumentationComponent, OpenDocumentationButtonComponent, HelpButtonComponent],
   exports: [HelpMenuComponent],
diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.spec.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.spec.ts
index 844d2d4ad75212bd6cd5eb3bc6ab48b5c2b84409..9b9cc5c3f622ddf766e1a43eaccbf21ea1620efc 100644
--- a/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.spec.ts
+++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.spec.ts
@@ -22,7 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared';
-import { HttpErrorHandler, TechSharedModule } from '@alfa-client/tech-shared';
+import { HttpErrorHandler } from '@alfa-client/tech-shared';
 import { mock, mockClass, useFromMock } from '@alfa-client/test-utils';
 import {
   VorgangHeaderLinkRel,
@@ -33,10 +33,8 @@ import {
 import { ResourceFactory } from '@ngxp/rest';
 import { cold, hot } from 'jest-marbles';
 import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
-import {
-  createVorgangResource,
-  createVorgangWithEingangResource,
-} from 'libs/vorgang-shared/test/vorgang';
+import { InjectorService } from 'libs/tech-shared/src/lib/injector/injector.service';
+import { createVorgangResource, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { createUserProfileListResource, createUserProfileResource } from '../../test/user-profile';
 import { UserProfileListResource, UserProfileResource } from './user-profile.model';
 import { UserProfileRepository } from './user-profile.repository';
@@ -51,7 +49,7 @@ describe('User profile repository', () => {
   const userProfile: UserProfileResource = createUserProfileResource();
 
   beforeEach(() => {
-    const classMock = mockClass(TechSharedModule);
+    const classMock = mockClass(InjectorService);
     classMock.injector = <any>{ get: () => useFromMock(mock(HttpErrorHandler)) };
 
     repository = new UserProfileRepository(useFromMock(resourceFactory));
diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts
index 1f91ba4533ee9c3ee1b09102a7df8deb9de9b849..ab53c008163ee44d5f785b065da91de6f203363c 100644
--- a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts
+++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts
@@ -28,6 +28,7 @@ import { getUserName, UserProfileResource } from '@alfa-client/user-profile-shar
 import { EventEmitter } from '@angular/core';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatIcon } from '@angular/material/icon';
+import { MatMenuTrigger } from '@angular/material/menu';
 import { NoopAnimationsModule } from '@angular/platform-browser/animations';
 import { DropdownMenuButtonItemComponent, DropdownMenuComponent, LogoutIconComponent } from '@ods/system';
 import { getDataTestIdAttributeOf, getDataTestIdOf } from 'libs/tech-shared/test/data-test';
@@ -49,6 +50,7 @@ describe('UserProfileInHeaderComponent', () => {
       declarations: [
         UserProfileInHeaderComponent,
         MatIcon,
+        MatMenuTrigger,
         MockComponent(UserIconComponent),
         MockComponent(DropdownMenuComponent),
         MockComponent(DropdownMenuButtonItemComponent),
diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.spec.ts
index e8c3f33af47eabac0cc2b88028a83637a92384b1..9d67b5fbb32f740a2ae6928d0126bf1a1ac8def9 100644
--- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.spec.ts
+++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.spec.ts
@@ -23,9 +23,9 @@
  */
 import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import { UiModule } from '@alfa-client/ui';
 import { UserProfileResource, UserProfileService } from '@alfa-client/user-profile-shared';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatMenuTrigger } from '@angular/material/menu';
 import { MockComponent } from 'ng-mocks';
 import { BehaviorSubject } from 'rxjs';
 import { OzgcloudMenuComponent } from '../../../../../../ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component';
@@ -47,6 +47,7 @@ describe('UserProfileButtonContainerComponent', () => {
     TestBed.configureTestingModule({
       declarations: [
         UserProfileButtonContainerComponent,
+        MatMenuTrigger,
         MockComponent(UserIconComponent),
         MockComponent(UserProfileSearchContainerComponent),
         MockComponent(OzgcloudMenuComponent),
@@ -57,7 +58,6 @@ describe('UserProfileButtonContainerComponent', () => {
           useValue: userProfileService,
         },
       ],
-      imports: [UiModule],
     });
   });
 
diff --git a/alfa-client/libs/user-profile/src/lib/user-profile.module.ts b/alfa-client/libs/user-profile/src/lib/user-profile.module.ts
index 408ace4cfbf611228fe69933743b717961982f55..0f595e41c37ed96b7e0084656973cf7c4fc7dfa0 100644
--- a/alfa-client/libs/user-profile/src/lib/user-profile.module.ts
+++ b/alfa-client/libs/user-profile/src/lib/user-profile.module.ts
@@ -21,11 +21,20 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import { HasLinkPipe } from '@alfa-client/tech-shared';
+import {
+  AutocompleteEditorComponent,
+  IconButtonWithSpinnerComponent,
+  OzgcloudMenuComponent,
+  SpinnerComponent,
+} from '@alfa-client/ui';
 import { UserProfileSharedModule } from '@alfa-client/user-profile-shared';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { MatIcon } from '@angular/material/icon';
+import { MatMenuTrigger } from '@angular/material/menu';
+import { MatTooltip } from '@angular/material/tooltip';
 import { RouterModule } from '@angular/router';
 import { ButtonWithSpinnerComponent } from '@ods/component';
 import {
@@ -61,13 +70,20 @@ import { UserProfileComponent } from './user-profile/user-profile.component';
 @NgModule({
   imports: [
     CommonModule,
-    TechSharedModule,
-    UiModule,
     UserProfileSharedModule,
     RouterModule,
     OdsUserIconComponent,
     LogoutIconComponent,
     ErrorIconComponent,
+    IconButtonWithSpinnerComponent,
+    HasLinkPipe,
+    MatTooltip,
+    SpinnerComponent,
+    MatMenuTrigger,
+    OzgcloudMenuComponent,
+    MatIcon,
+    AutocompleteEditorComponent,
+    ReactiveFormsModule,
     DropdownMenuComponent,
     DropdownMenuItemComponent,
     DropdownMenuButtonItemComponent,
diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.spec.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.spec.ts
index de1ccc1a69c0a17b62d37208226bc6ca96feb68c..f40d240d635937892fe39335610f9f599986b724 100644
--- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.spec.ts
+++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.spec.ts
@@ -22,7 +22,6 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { HasLinkPipe, createEmptyStateResource } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { NoopAnimationsModule } from '@angular/platform-browser/animations';
 import { DropdownMenuComponent } from '@ods/system';
@@ -37,7 +36,7 @@ describe('UserSettingsComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [NoopAnimationsModule, UiModule],
+      imports: [NoopAnimationsModule],
       declarations: [
         HasLinkPipe,
         UserSettingsComponent,
diff --git a/alfa-client/libs/user-settings/src/lib/user-settings.module.ts b/alfa-client/libs/user-settings/src/lib/user-settings.module.ts
index bafeb748dc5a3c6c145397e031924740372c07be..fce1e22c3ef1c4ba98c956b33bd3504545dc49ae 100644
--- a/alfa-client/libs/user-settings/src/lib/user-settings.module.ts
+++ b/alfa-client/libs/user-settings/src/lib/user-settings.module.ts
@@ -21,7 +21,8 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { UiModule } from '@alfa-client/ui';
+import { HasLinkPipe } from '@alfa-client/tech-shared';
+import { SlideToggleComponent } from '@alfa-client/ui';
 import { UserSettingsSharedModule } from '@alfa-client/user-settings-shared';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
@@ -35,7 +36,15 @@ import { UserSettingsEmailBenachrichtigungComponent } from './user-settings-cont
 import { UserSettingsComponent } from './user-settings-container/user-settings/user-settings.component';
 
 @NgModule({
-  imports: [CommonModule, UiModule, UserSettingsSharedModule, DropdownMenuComponent, CloseIconComponent, SettingsIconComponent],
+  imports: [
+    CommonModule,
+    UserSettingsSharedModule,
+    DropdownMenuComponent,
+    CloseIconComponent,
+    SettingsIconComponent,
+    SlideToggleComponent,
+    HasLinkPipe,
+  ],
   declarations: [
     UserSettingsContainerComponent,
     UserSettingsEmailBenachrichtigungComponent,
diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.spec.ts
index ebf2fa64f17b56d95828a63bb475020d4178ab76..174d105fae1120efbb26eee2df3cd12c779db4a5 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.spec.ts
@@ -21,45 +21,28 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { AktenzeichenEditDialogComponent } from './aktenzeichen-edit-dialog.component';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { COMMAND_ERROR_MESSAGES, CommandErrorMessage, hasCommandError, isSuccessfulDone } from '@alfa-client/command-shared';
+import { createEmptyStateResource, hasContent, isClipboardReadSupported } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
 import {
   OzgcloudPasteTextButtonComponent,
   OzgcloudStrokedButtonWithSpinnerComponent,
+  OzgcloudTextEditorComponent,
   SnackBarService,
-  TextEditorComponent,
 } from '@alfa-client/ui';
-import { MockComponent, MockDirective } from 'ng-mocks';
 import { VorgangService } from '@alfa-client/vorgang-shared';
-import {
-  MAT_DIALOG_DATA,
-  MatDialogActions,
-  MatDialogContent,
-  MatDialogRef,
-} from '@angular/material/dialog';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormBuilder, ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
+import { MAT_DIALOG_DATA, MatDialogActions, MatDialogContent, MatDialogRef } from '@angular/material/dialog';
 import { MatIcon } from '@angular/material/icon';
+import { cold, hot } from 'jest-marbles';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
-import {
-  createEmptyStateResource,
-  hasContent,
-  isClipboardReadSupported,
-} from '@alfa-client/tech-shared';
+import { MockComponent, MockDirective } from 'ng-mocks';
 import { EMPTY, NEVER } from 'rxjs';
-import { FormBuilder, ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
-import { cold, hot } from 'jest-marbles';
-import {
-  createCommandErrorResource,
-  createCommandResource,
-} from '../../../../command-shared/test/command';
-import {
-  COMMAND_ERROR_MESSAGES,
-  CommandErrorMessage,
-  hasCommandError,
-  isSuccessfulDone,
-} from '@alfa-client/command-shared';
-import { AktenzeichenEditDialogMessages } from './aktenzeichen-edit-dialog.message';
+import { createCommandErrorResource, createCommandResource } from '../../../../command-shared/test/command';
+import { AktenzeichenEditDialogComponent } from './aktenzeichen-edit-dialog.component';
 import { AktenzeichenEditDialogFormservice } from './aktenzeichen-edit-dialog.formservice';
+import { AktenzeichenEditDialogMessages } from './aktenzeichen-edit-dialog.message';
 
 jest.mock('@alfa-client/tech-shared');
 const isClipboardReadSupportedMock = isClipboardReadSupported as jest.Mock;
@@ -99,7 +82,7 @@ describe('AktenzeichenEditDialogComponent', () => {
         MockDirective(MatDialogContent),
         MockDirective(MatDialogActions),
         MockComponent(MatIcon),
-        MockComponent(TextEditorComponent),
+        MockComponent(OzgcloudTextEditorComponent),
         MockComponent(OzgcloudPasteTextButtonComponent),
         MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
       ],
diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.ts
index 79dce7d7da127e4e47ae8086e912dcba4d95b8ae..d4744fd1411a9d59360b7e003d2f01958f2ba7ad 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.ts
@@ -21,27 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import {
-  COMMAND_ERROR_MESSAGES,
-  CommandResource,
-  hasCommandError,
-  isSuccessfulDone,
-} from '@alfa-client/command-shared';
-import {
-  createEmptyStateResource,
-  hasContent,
-  isClipboardReadSupported,
-  StateResource,
-} from '@alfa-client/tech-shared';
+import { COMMAND_ERROR_MESSAGES, CommandResource, hasCommandError, isSuccessfulDone } from '@alfa-client/command-shared';
+import { createEmptyStateResource, hasContent, isClipboardReadSupported, StateResource } from '@alfa-client/tech-shared';
 import { SnackBarService } from '@alfa-client/ui';
 import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { Component, Inject, OnInit } from '@angular/core';
+import { UntypedFormGroup } from '@angular/forms';
 import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
 import { map, Observable, of, startWith, tap } from 'rxjs';
 import { AktenzeichenEditDialogData } from './aktenzeichen-edit-dialog.data';
-import { AktenzeichenEditDialogMessages } from './aktenzeichen-edit-dialog.message';
-import { UntypedFormGroup } from '@angular/forms';
 import { AktenzeichenEditDialogFormservice } from './aktenzeichen-edit-dialog.formservice';
+import { AktenzeichenEditDialogMessages } from './aktenzeichen-edit-dialog.message';
 
 @Component({
   selector: 'alfa-aktenzeichen-edit-dialog',
@@ -52,9 +42,7 @@ import { AktenzeichenEditDialogFormservice } from './aktenzeichen-edit-dialog.fo
 export class AktenzeichenEditDialogComponent implements OnInit {
   vorgang: VorgangWithEingangResource;
 
-  setAktenzeichenPending$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  setAktenzeichenPending$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
   hasAktenzeichen$: Observable<boolean>;
   isPasteSupported = false;
 
@@ -73,10 +61,7 @@ export class AktenzeichenEditDialogComponent implements OnInit {
   ngOnInit(): void {
     this.isPasteSupported = isClipboardReadSupported();
     this.formService.setAktenzeichen(this.vorgang.aktenzeichen);
-    this.hasAktenzeichen$ = this.formService
-      .valueChanges()
-      .pipe(startWith(this.vorgang.aktenzeichen))
-      .pipe(map(hasContent));
+    this.hasAktenzeichen$ = this.formService.valueChanges().pipe(startWith(this.vorgang.aktenzeichen)).pipe(map(hasContent));
   }
 
   public onCancel(): void {
@@ -88,11 +73,7 @@ export class AktenzeichenEditDialogComponent implements OnInit {
     this.setAktenzeichenPending$ = this.formService
       .submit()
       .pipe(startWith(createEmptyStateResource<CommandResource>(true)))
-      .pipe(
-        tap((commandStateResource: StateResource<CommandResource>) =>
-          this.onResponse(commandStateResource.resource),
-        ),
-      );
+      .pipe(tap((commandStateResource: StateResource<CommandResource>) => this.onResponse(commandStateResource.resource)));
   }
 
   onResponse(commandResource: CommandResource) {
@@ -111,10 +92,7 @@ export class AktenzeichenEditDialogComponent implements OnInit {
   }
 
   getErrorMessage(commandResource: CommandResource): string {
-    return (
-      COMMAND_ERROR_MESSAGES[commandResource.errorMessage] ||
-      AktenzeichenEditDialogMessages.SET_FAILED
-    );
+    return COMMAND_ERROR_MESSAGES[commandResource.errorMessage] || AktenzeichenEditDialogMessages.SET_FAILED;
   }
 
   paste(clipboardContent: string) {
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts
index 1cd92c64d9b07060f04273c6007ac1c8920ca8d4..3db736ad9d3f16f89f8d4f0abe6a5a50ba44d208 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts
@@ -21,26 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { BescheidWizardContainerComponent } from '@alfa-client/bescheid';
 import { BescheidResource, BescheidService, BescheidWizardDialogResult } from '@alfa-client/bescheid-shared';
 import { CommandResource } from '@alfa-client/command-shared';
 import { createEmptyStateResource, createStateResource, HasLinkPipe, StateResource } from '@alfa-client/tech-shared';
-import {
-  getElementComponentFromFixtureByCss,
-  getMockComponent,
-  Mock,
-  mock,
-  notExistsAsHtmlElement,
-  tooltipExistsWithText,
-  triggerEvent,
-} from '@alfa-client/test-utils';
+import { createDialogRefMock, DialogRefMock, getElementComponentFromFixtureByCss, getMockComponent, Mock, mock, notExistsAsHtmlElement, tooltipExistsWithText, triggerEvent, } from '@alfa-client/test-utils';
 import { OzgcloudDialogService } from '@alfa-client/ui';
 import { BescheidenDialogData } from '@alfa-client/vorgang-detail';
-import {
-  VorgangCommandService,
-  VorgangService,
-  VorgangWithEingangLinkRel,
-  VorgangWithEingangResource,
-} from '@alfa-client/vorgang-shared';
+import { VorgangCommandService, VorgangService, VorgangWithEingangLinkRel, VorgangWithEingangResource, } from '@alfa-client/vorgang-shared';
 import { DialogRef } from '@angular/cdk/dialog';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ButtonWithSpinnerComponent } from '@ods/component';
@@ -167,60 +155,58 @@ describe('BescheidenButtonComponent', () => {
       });
     });
 
-    // TODO: Use this version after completed Bescheid refactoring and delete the other version below.
-    // describe('openBescheidenWizard', () => {
-    //   let dialogRefMock: DialogRefMock<BescheidWizardDialogResult>;
-    //
-    //   beforeEach(() => {
-    //     dialogRefMock = createDialogRefMock<BescheidWizardDialogResult>();
-    //     ozgcloudDialogService.openWizard.mockReturnValue(dialogRefMock);
-    //   });
-    //
-    //   it('should open wizard dialog', () => {
-    //     const vorgang = createVorgangWithEingangResource();
-    //     component.vorgang = vorgang;
-    //
-    //     component.openBescheidenWizard();
-    //
-    //     expect(ozgcloudDialogService.openWizard).toHaveBeenCalledWith(BescheidWizardContainerComponent, {
-    //       vorgangWithEingangResource: vorgang,
-    //     });
-    //   });
-    //
-    //   it('should handleBescheidWizardClosed', () => {
-    //     component.handleBescheidWizardClosed = jest.fn();
-    //     const dialogResult: BescheidWizardDialogResult = { reloadVorgang: true };
-    //     dialogRefMock.closed = of(dialogResult);
-    //
-    //     component.openBescheidenWizard();
-    //
-    //     expect(component.handleBescheidWizardClosed).toHaveBeenCalledWith(dialogResult);
-    //   });
-    // });
+    describe('bescheiden icon button', () => {
+      beforeEach(() => {
+        component.showAsIconButton = true;
+        fixture.detectChanges();
+      });
+
+      it('should be hidden', () => {
+        component.vorgang = createVorgangWithEingangResource();
+
+        fixture.detectChanges();
+        const buttonElement = fixture.nativeElement.querySelector(bescheidenIconButton);
+
+        expect(buttonElement).not.toBeInstanceOf(HTMLElement);
+      });
+
+      it('should be visible', () => {
+        component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEIDEN]);
+
+        fixture.detectChanges();
+        const buttonElement = fixture.nativeElement.querySelector(bescheidenIconButton);
+
+        expect(buttonElement).toBeInstanceOf(HTMLElement);
+      });
+    });
 
     describe('openBescheidenWizard', () => {
-      it('should init', () => {
-        component.openBescheidenWizard();
+      let dialogRefMock: DialogRefMock<BescheidWizardDialogResult>;
 
-        expect(bescheidService.init).toHaveBeenCalled();
+      beforeEach(() => {
+        dialogRefMock = createDialogRefMock<BescheidWizardDialogResult>();
+        ozgcloudDialogService.openWizard.mockReturnValue(dialogRefMock);
       });
 
-      it('should open bescheiden dialog with existing draft', () => {
-        component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEID_DRAFT]);
-        component.openBescheidenDialogWithExistingDraft = jest.fn();
+      it('should open wizard dialog', () => {
+        const vorgang = createVorgangWithEingangResource();
+        component.vorgang = vorgang;
 
         component.openBescheidenWizard();
 
-        expect(component.openBescheidenDialogWithExistingDraft).toHaveBeenCalled();
+        expect(ozgcloudDialogService.openWizard).toHaveBeenCalledWith(BescheidWizardContainerComponent, {
+          vorgangWithEingangResource: vorgang,
+        });
       });
 
-      it('should open bescheiden dialog with new draft', () => {
-        component.vorgang = createVorgangWithEingangResource();
-        component.openBescheidDialogWithNewDraft = jest.fn();
+      it('should handleBescheidWizardClosed', () => {
+        component.handleBescheidWizardClosed = jest.fn();
+        const dialogResult: BescheidWizardDialogResult = { reloadVorgang: true };
+        dialogRefMock.closed = of(dialogResult);
 
         component.openBescheidenWizard();
 
-        expect(component.openBescheidDialogWithNewDraft).toHaveBeenCalled();
+        expect(component.handleBescheidWizardClosed).toHaveBeenCalledWith(dialogResult);
       });
     });
 
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts
index de431e7c593b4e719514f917e3325e41fab3c644..65e3c32d26e50c662463f04804b56def5f01dfca 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts
@@ -21,19 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { BescheidWizardContainerComponent } from '@alfa-client/bescheid';
 import { BescheidResource, BescheidService, BescheidWizardDialogResult } from '@alfa-client/bescheid-shared';
 import { CommandResource } from '@alfa-client/command-shared';
-import { StateResource, createEmptyStateResource, isLoaded, isNotNil } from '@alfa-client/tech-shared';
+import { createEmptyStateResource, isLoaded, isNotNil, StateResource } from '@alfa-client/tech-shared';
 import { OzgcloudDialogService } from '@alfa-client/ui';
-import {
-  VorgangCommandService,
-  VorgangService,
-  VorgangWithEingangLinkRel,
-  VorgangWithEingangResource,
-} from '@alfa-client/vorgang-shared';
+import { VorgangCommandService, VorgangService, VorgangWithEingangLinkRel, VorgangWithEingangResource, } from '@alfa-client/vorgang-shared';
+import { DialogRef } from '@angular/cdk/dialog';
 import { Component, Input, OnInit } from '@angular/core';
 import { hasLink } from '@ngxp/rest';
-import { Observable, filter, first, map, of } from 'rxjs';
+import { filter, first, map, Observable, of } from 'rxjs';
 import { BescheidenDialogData } from '../../vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.model';
 import { VorgangDetailBescheidenComponent } from '../../vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component';
 
@@ -86,16 +83,15 @@ export class BescheidenButtonComponent implements OnInit {
     );
   }
 
-  // TODO: Use this version after completed Bescheid refactoring and delete the other version below.
-  // public openBescheidenWizard(): void {
-  //   const dialogData: BescheidenDialogData = { vorgangWithEingangResource: this.vorgang };
-  //   const dialogRef: DialogRef<BescheidWizardDialogResult> = this.ozgcloudDialogService.openWizard<
-  //     BescheidWizardContainerComponent,
-  //     BescheidenDialogData,
-  //     BescheidWizardDialogResult
-  //   >(BescheidWizardContainerComponent, dialogData);
-  //   dialogRef.closed.subscribe((dialogResult: BescheidWizardDialogResult) => this.handleBescheidWizardClosed(dialogResult));
-  // }
+  public openBescheidenWizard(): void {
+    const dialogData: BescheidenDialogData = { vorgangWithEingangResource: this.vorgang };
+    const dialogRef: DialogRef<BescheidWizardDialogResult> = this.ozgcloudDialogService.openWizard<
+      BescheidWizardContainerComponent,
+      BescheidenDialogData,
+      BescheidWizardDialogResult
+    >(BescheidWizardContainerComponent, dialogData);
+    dialogRef.closed.subscribe((dialogResult: BescheidWizardDialogResult) => this.handleBescheidWizardClosed(dialogResult));
+  }
 
   handleBescheidWizardClosed(dialogResult: BescheidWizardDialogResult): void {
     if (isNotNil(dialogResult) && dialogResult.reloadVorgang) {
@@ -103,15 +99,6 @@ export class BescheidenButtonComponent implements OnInit {
     }
   }
 
-  public openBescheidenWizard(): void {
-    this.bescheidService.init();
-    if (hasLink(this.vorgang, VorgangWithEingangLinkRel.BESCHEID_DRAFT)) {
-      this.openBescheidenDialogWithExistingDraft();
-    } else {
-      this.openBescheidDialogWithNewDraft();
-    }
-  }
-
   openBescheidenDialogWithExistingDraft(): void {
     this.bescheidService
       .getBescheidDraftIfExists()
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-step-title/vorgang-detail-bescheiden-step-title.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-step-title/vorgang-detail-bescheiden-step-title.component.html
index 31596875ea050b030f15b2960650a111764a15a1..8a82e62b23b248ab3ba1b6521b34f0b6eba6538f 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-step-title/vorgang-detail-bescheiden-step-title.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-step-title/vorgang-detail-bescheiden-step-title.component.html
@@ -23,6 +23,6 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<div class="my-2 text-base font-bold text-primary-600" data-test-id="step-caption">
+<div class="text-base font-bold text-primary-600" data-test-id="step-caption">
   {{ label }}
 </div>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-dokumente-hinzufuegen/vorgang-detail-bescheiden-dokument-hochladen/vorgang-detail-bescheiden-dokument-hochladen.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-dokumente-hinzufuegen/vorgang-detail-bescheiden-dokument-hochladen/vorgang-detail-bescheiden-dokument-hochladen.component.spec.ts
index 471467b8ea09fd329b97ba5a71b353556501d909..5b089dac014abc5a0da5991e964ba167b50edcf9 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-dokumente-hinzufuegen/vorgang-detail-bescheiden-dokument-hochladen/vorgang-detail-bescheiden-dokument-hochladen.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-dokumente-hinzufuegen/vorgang-detail-bescheiden-dokument-hochladen/vorgang-detail-bescheiden-dokument-hochladen.component.spec.ts
@@ -22,7 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { BescheidService } from '@alfa-client/bescheid-shared';
-import { HasLinkPipe, TechSharedModule } from '@alfa-client/tech-shared';
+import { HasLinkPipe } from '@alfa-client/tech-shared';
 import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
@@ -59,7 +59,7 @@ describe('VorgangDetailBescheidenDokumentHochladenComponent', () => {
         MockComponent(SingleFileUploadEditorComponent),
         MockComponent(SpinnerIconComponent),
       ],
-      imports: [ReactiveFormsModule, TechSharedModule],
+      imports: [ReactiveFormsModule],
       providers: [
         {
           provide: BescheidenFormService,
@@ -119,10 +119,7 @@ describe('VorgangDetailBescheidenDokumentHochladenComponent', () => {
 
       component.uploadFile(file);
 
-      expect(bescheidService.uploadBescheidDocument).toHaveBeenCalledWith(
-        bescheidStateResource.resource,
-        file,
-      );
+      expect(bescheidService.uploadBescheidDocument).toHaveBeenCalledWith(bescheidStateResource.resource, file);
     });
   });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
index 32aba2314074dfd4c1db59679594e9cd00767f4e..df1ec6563ff01d6130ab2cf54e144c5bfc970465 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
@@ -31,8 +31,22 @@ import { LoeschAnforderungModule } from '@alfa-client/loesch-anforderung';
 import { LoeschAnforderungSharedModule } from '@alfa-client/loesch-anforderung-shared';
 import { PostfachModule } from '@alfa-client/postfach';
 import { PostfachSharedModule } from '@alfa-client/postfach-shared';
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import { ConvertForDataTestPipe, ConvertProblemDetailToErrorMessagesPipe, HasLinkPipe } from '@alfa-client/tech-shared';
+import {
+  BackButtonComponent,
+  DateEditorComponent,
+  ExpansionPanelComponent,
+  IconButtonWithSpinnerComponent,
+  OzgcloudIconButtonPrimaryComponent,
+  OzgcloudIconComponent,
+  OzgcloudMenuComponent,
+  OzgcloudPasteTextButtonComponent,
+  OzgcloudStrokedButtonWithSpinnerComponent,
+  OzgcloudTextEditorComponent,
+  SpinnerComponent,
+  SpinnerTransparencyComponent,
+  SubnavigationComponent,
+} from '@alfa-client/ui';
 import { UserProfileModule } from '@alfa-client/user-profile';
 import { UserProfileSharedModule } from '@alfa-client/user-profile-shared';
 import { VorgangSharedModule } from '@alfa-client/vorgang-shared';
@@ -40,13 +54,18 @@ import { VorgangSharedUiModule } from '@alfa-client/vorgang-shared-ui';
 import { WiedervorlageModule } from '@alfa-client/wiedervorlage';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { MatDialogActions, MatDialogContent } from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
+import { MatMenuTrigger } from '@angular/material/menu';
+import { MatTab, MatTabContent, MatTabGroup } from '@angular/material/tabs';
 import { RouterModule, Routes } from '@angular/router';
 import {
   ButtonWithSpinnerComponent,
   FileUploadEditorComponent,
   SingleFileUploadEditorComponent,
-  TextEditorComponent,
   TextareaEditorComponent,
+  TextEditorComponent,
 } from '@ods/component';
 import {
   ArchiveIconComponent,
@@ -76,6 +95,8 @@ import {
   TooltipDirective,
   UndoIconComponent,
 } from '@ods/system';
+import { NotHasAnyLinkPipe } from '../../../tech-shared/src/lib/pipe/not-has-any-link.pipe';
+import { ProgressBarComponent } from '../../../ui/src/lib/ui/progress-bar/progress-bar.component';
 import { AktenzeichenEditDialogComponent } from './aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component';
 import { AktenzeichenEditableComponent } from './aktenzeichen-editable/aktenzeichen-editable.component';
 import { AbschliessenButtonComponent } from './buttons/abschliessen-button/abschliessen-button.component';
@@ -141,8 +162,6 @@ const routes: Routes = [
     CommonModule,
     RouterModule.forChild(routes),
     VorgangSharedModule,
-    UiModule,
-    TechSharedModule,
     WiedervorlageModule,
     BinaryFileModule,
     ForwardingModule,
@@ -182,6 +201,31 @@ const routes: Routes = [
     ArchiveIconComponent,
     CheckCircleIconComponent,
     CheckIconComponent,
+    MatDialogContent,
+    ReactiveFormsModule,
+    MatIcon,
+    OzgcloudPasteTextButtonComponent,
+    MatDialogActions,
+    OzgcloudStrokedButtonWithSpinnerComponent,
+    OzgcloudIconButtonPrimaryComponent,
+    HasLinkPipe,
+    IconButtonWithSpinnerComponent,
+    ExpansionPanelComponent,
+    MatTabGroup,
+    MatTab,
+    NotHasAnyLinkPipe,
+    BackButtonComponent,
+    ConvertForDataTestPipe,
+    ConvertProblemDetailToErrorMessagesPipe,
+    DateEditorComponent,
+    MatMenuTrigger,
+    OzgcloudIconComponent,
+    OzgcloudMenuComponent,
+    SubnavigationComponent,
+    ProgressBarComponent,
+    SpinnerTransparencyComponent,
+    SpinnerComponent,
+    OzgcloudTextEditorComponent,
     DropdownMenuComponent,
     DropdownMenuTextItemComponent,
     MoreIconComponent,
@@ -190,6 +234,7 @@ const routes: Routes = [
     TooltipDirective,
     EditIconComponent,
     DiscardVorgangIconComponent,
+    MatTabContent,
   ],
   declarations: [
     VorgangDetailPageComponent,
diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.ts
index a6549aff7c59fa5979d55f7fbb7bb130b9c068fc..96348a1634f974b37b2626bc204283a10f82bb09 100644
--- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.ts
+++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.ts
@@ -21,11 +21,23 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import {
+  ConvertForDataTestPipe,
+  EnumToLabelPipe,
+  FormatToPrettyDatePipe,
+  HasLinkPipe,
+  ToEmbeddedResourcesPipe,
+} from '@alfa-client/tech-shared';
+import { OzgcloudSvgIconComponent, SpinnerComponent } from '@alfa-client/ui';
 import { VorgangSharedModule } from '@alfa-client/vorgang-shared';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { MatAutocomplete, MatAutocompleteTrigger, MatOption } from '@angular/material/autocomplete';
+import { MatButtonModule } from '@angular/material/button';
+import { MatFormField, MatFormFieldModule } from '@angular/material/form-field';
+import { MatIcon, MatIconModule } from '@angular/material/icon';
+import { MatInputModule } from '@angular/material/input';
 import { RouterModule } from '@angular/router';
 import { TooltipDirective } from '@ods/system';
 import { AktenzeichenComponent } from './aktenzeichen/aktenzeichen.component';
@@ -39,7 +51,29 @@ import { VorgangStatusTextComponent } from './vorgang-status-text/vorgang-status
 import { WiedervorlageIconComponent } from './wiedervorlage-icon/wiedervorlage-icon.component';
 
 @NgModule({
-  imports: [CommonModule, VorgangSharedModule, UiModule, RouterModule, TechSharedModule, TooltipDirective],
+  imports: [
+    CommonModule,
+    VorgangSharedModule,
+    RouterModule,
+    FormatToPrettyDatePipe,
+    MatIcon,
+    MatIconModule,
+    MatInputModule,
+    MatFormField,
+    MatButtonModule,
+    MatFormFieldModule,
+    ReactiveFormsModule,
+    MatAutocompleteTrigger,
+    MatAutocomplete,
+    SpinnerComponent,
+    MatOption,
+    ToEmbeddedResourcesPipe,
+    HasLinkPipe,
+    ConvertForDataTestPipe,
+    EnumToLabelPipe,
+    OzgcloudSvgIconComponent,
+    TooltipDirective,
+  ],
   declarations: [
     VorgangSearchContainerComponent,
     VorgangSearchComponent,
diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.spec.ts
index fc9be609db475e87f46dad098cf66db0129cef8e..9b833b88003f980053c56d8787bd94dfbe46aab2 100644
--- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.spec.ts
+++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.spec.ts
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { EnumToLabelPipe } from '@alfa-client/tech-shared';
 import { VorgangResource } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangResource } from 'libs/vorgang-shared/test/vorgang';
 import { VorgangStatusDotComponent } from './vorgang-status-dot.component';
@@ -37,7 +37,8 @@ describe('VorgangStatusDotComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [VorgangStatusDotComponent, EnumToLabelPipe],
+      imports: [EnumToLabelPipe],
+      declarations: [VorgangStatusDotComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.spec.ts
index c49336ccf22b1bb28fdbe874b9f898f9d1b21cf7..ec5f8e7063df5a226688de7e69752b20d5d17696 100644
--- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.spec.ts
+++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.spec.ts
@@ -37,7 +37,8 @@ describe('VorgangStatusTextComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [EnumToLabelPipe, VorgangStatusTextComponent],
+      imports: [EnumToLabelPipe],
+      declarations: [VorgangStatusTextComponent],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.spec.ts
index fa699a030e07f79ddd830ef5b171ce14be24cdc3..f322aa355155dfd54fc231023a4f7b349382b1b4 100644
--- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.spec.ts
+++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.spec.ts
@@ -21,34 +21,22 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';
 import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared';
-import {
-  ContentType,
-  GetRequestOptions,
-  HttpErrorHandler,
-  HttpHeader,
-} from '@alfa-client/tech-shared';
+import { BlobWithFileName, ContentType, GetRequestOptions, HttpErrorHandler, HttpHeader } from '@alfa-client/tech-shared';
 import { mock, mockClass, useFromMock } from '@alfa-client/test-utils';
+import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';
 import { LinkRel, ResourceFactory, ResourceUri, getUrl } from '@ngxp/rest';
-import { cold, hot } from 'jest-marbles';
 import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
-import { TechSharedModule } from 'libs/tech-shared/src/lib/tech-shared.module';
+import { InjectorService } from 'libs/tech-shared/src/lib/injector/injector.service';
 import {
   createVorgangListResource,
   createVorgangResource,
   createVorgangWithEingangResource,
 } from 'libs/vorgang-shared/test/vorgang';
-import {
-  VorgangHeaderLinkRel,
-  VorgangListLinkRel,
-  VorgangWithEingangLinkRel,
-} from './../vorgang.linkrel';
-import {
-  VorgangListResource,
-  VorgangResource,
-  VorgangWithEingangResource,
-} from './../vorgang.model';
+import { Observable } from 'rxjs';
+import { singleCold, singleHot } from '../../../../tech-shared/test/marbles';
+import { VorgangHeaderLinkRel, VorgangListLinkRel, VorgangWithEingangLinkRel } from './../vorgang.linkrel';
+import { VorgangListResource, VorgangResource, VorgangWithEingangResource } from './../vorgang.model';
 import { VorgangRepository } from './vorgang.repository';
 
 describe('VorgangRepository', () => {
@@ -70,7 +58,7 @@ describe('VorgangRepository', () => {
     const linkRel: string = 'dummyLinkRel';
 
     beforeEach(() => {
-      resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource }));
+      resourceWrapper.get.mockReturnValue(singleHot(vorgangListResource));
     });
 
     it('should call resourceFactory with resource', () => {
@@ -86,20 +74,17 @@ describe('VorgangRepository', () => {
     });
 
     it('should return result', () => {
-      let result = repository.loadVorgangList(apiRootResource, linkRel);
+      let result: Observable<VorgangListResource> = repository.loadVorgangList(apiRootResource, linkRel);
 
-      expect(result).not.toBeNull();
-      expect(result).toBeObservable(cold('a', { a: vorgangListResource }));
+      expect(result).toBeObservable(singleCold(vorgangListResource));
     });
   });
 
   describe('getNextVorgangListPage', () => {
-    const vorgangListResource: VorgangListResource = createVorgangListResource([
-      VorgangListLinkRel.NEXT,
-    ]);
+    const vorgangListResource: VorgangListResource = createVorgangListResource([VorgangListLinkRel.NEXT]);
 
     beforeEach(() => {
-      resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource }));
+      resourceWrapper.get.mockReturnValue(singleHot(vorgangListResource));
     });
 
     it('should call resourceFactory with resource', () => {
@@ -115,29 +100,22 @@ describe('VorgangRepository', () => {
     });
 
     it('should return result', () => {
-      let result = repository.getNextVorgangListPage(vorgangListResource);
+      let result: Observable<VorgangListResource> = repository.getNextVorgangListPage(vorgangListResource);
 
-      expect(result).not.toBeNull();
-      expect(result).toBeObservable(cold('a', { a: vorgangListResource }));
+      expect(result).toBeObservable(singleCold(vorgangListResource));
     });
   });
 
   describe('getVorgangWithEingang', () => {
-    const vorgangResource: VorgangResource = createVorgangResource([
-      VorgangHeaderLinkRel.VORGANG_WITH_EINGANG,
-    ]);
-    const vorgangWithEingangUrl = getUrl(
-      vorgangResource,
-      VorgangHeaderLinkRel.VORGANG_WITH_EINGANG,
-    );
-    const vorgangWithEingangResource: VorgangWithEingangResource =
-      createVorgangWithEingangResource();
+    const vorgangResource: VorgangResource = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]);
+    const vorgangWithEingangUrl: string = getUrl(vorgangResource, VorgangHeaderLinkRel.VORGANG_WITH_EINGANG);
+    const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource();
 
     beforeEach(() => {
-      const classMock = mockClass(TechSharedModule);
+      const classMock = mockClass(InjectorService);
       classMock.injector = <any>{ get: () => useFromMock(mock(HttpErrorHandler)) };
 
-      resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangWithEingangResource }));
+      resourceWrapper.get.mockReturnValue(singleHot(vorgangWithEingangResource));
     });
 
     it('should call resourceFactory with resource', () => {
@@ -155,18 +133,17 @@ describe('VorgangRepository', () => {
     it('should return result', () => {
       let result = repository.getVorgang(vorgangWithEingangUrl);
 
-      expect(result).not.toBeNull();
-      expect(result).toBeObservable(cold('a', { a: vorgangWithEingangResource }));
+      expect(result).toBeObservable(singleCold(vorgangWithEingangResource));
     });
   });
 
   describe('getAttachments', () => {
-    const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource(
-      [VorgangWithEingangLinkRel.ATTACHMENTS],
-    );
+    const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource([
+      VorgangWithEingangLinkRel.ATTACHMENTS,
+    ]);
 
     beforeEach(() => {
-      resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangWithEingangResource }));
+      resourceWrapper.get.mockReturnValue(singleHot(vorgangWithEingangResource));
     });
 
     it('should call resourceFactory with resource', () => {
@@ -185,7 +162,7 @@ describe('VorgangRepository', () => {
       let result = repository.getAttachments(vorgangWithEingangResource);
 
       expect(result).not.toBeNull();
-      expect(result).toBeObservable(cold('a', { a: vorgangWithEingangResource }));
+      expect(result).toBeObservable(singleCold(vorgangWithEingangResource));
     });
   });
 
@@ -194,7 +171,7 @@ describe('VorgangRepository', () => {
     const apiRootResource: ApiRootResource = createApiRootResource();
 
     beforeEach(() => {
-      resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource }));
+      resourceWrapper.get.mockReturnValue(singleHot(vorgangListResource));
       repository.buildSearchByUrl = jest.fn();
     });
 
@@ -213,19 +190,9 @@ describe('VorgangRepository', () => {
     it('should call buildSearchByUrl', () => {
       const searchString: string = 'i search for...';
       const limit: number = 7;
-      repository.searchVorgaengeBy(
-        apiRootResource,
-        searchString,
-        ApiRootLinkRel.SEARCH_ALLE,
-        limit,
-      );
-
-      expect(repository.buildSearchByUrl).toHaveBeenCalledWith(
-        apiRootResource,
-        searchString,
-        ApiRootLinkRel.SEARCH_ALLE,
-        limit,
-      );
+      repository.searchVorgaengeBy(apiRootResource, searchString, ApiRootLinkRel.SEARCH_ALLE, limit);
+
+      expect(repository.buildSearchByUrl).toHaveBeenCalledWith(apiRootResource, searchString, ApiRootLinkRel.SEARCH_ALLE, limit);
     });
   });
 
@@ -242,11 +209,7 @@ describe('VorgangRepository', () => {
         _links,
       };
 
-      const searchUrl: ResourceUri = repository.buildSearchByUrl(
-        apiRootResource,
-        'searchParam',
-        ApiRootLinkRel.SEARCH_ALLE,
-      );
+      const searchUrl: ResourceUri = repository.buildSearchByUrl(apiRootResource, 'searchParam', ApiRootLinkRel.SEARCH_ALLE);
 
       expect(searchUrl).toEqual(baseUrl + '&' + VorgangRepository.SEARCH_PARAM + '=searchParam');
     });
@@ -254,11 +217,7 @@ describe('VorgangRepository', () => {
     it('should ignore unused, optional parameters', () => {
       const apiRoot: ApiRootResource = buildLinksWithSearch(baseUrl + '{&searchBy,limit}');
 
-      const searchUrl: ResourceUri = repository.buildSearchByUrl(
-        apiRoot,
-        'search',
-        ApiRootLinkRel.SEARCH_ALLE,
-      );
+      const searchUrl: ResourceUri = repository.buildSearchByUrl(apiRoot, 'search', ApiRootLinkRel.SEARCH_ALLE);
 
       expect(searchUrl).toEqual(baseUrl + '&' + VorgangRepository.SEARCH_PARAM + '=search');
     });
@@ -267,16 +226,9 @@ describe('VorgangRepository', () => {
       const limit = 5;
       const res = buildLinksWithSearch(baseUrl + '{&searchBy,limit}');
 
-      const searchUrl: ResourceUri = repository.buildSearchByUrl(
-        res,
-        'search',
-        ApiRootLinkRel.SEARCH_ALLE,
-        limit,
-      );
+      const searchUrl: ResourceUri = repository.buildSearchByUrl(res, 'search', ApiRootLinkRel.SEARCH_ALLE, limit);
 
-      expect(searchUrl).toEqual(
-        baseUrl + '&' + VorgangRepository.SEARCH_PARAM + '=search&limit=' + limit,
-      );
+      expect(searchUrl).toEqual(baseUrl + '&' + VorgangRepository.SEARCH_PARAM + '=search&limit=' + limit);
     });
 
     function buildLinksWithSearch(searchHref: string): ApiRootResource {
@@ -288,21 +240,16 @@ describe('VorgangRepository', () => {
 
   describe('loadMeineVorgaengeList', () => {
     const vorgangListResource: VorgangListResource = createVorgangListResource();
-    const apiRootResource: ApiRootResource = createApiRootResource([
-      ApiRootLinkRel.MEINE_VORGAENGE,
-    ]);
+    const apiRootResource: ApiRootResource = createApiRootResource([ApiRootLinkRel.MEINE_VORGAENGE]);
 
     beforeEach(() => {
-      resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource }));
+      resourceWrapper.get.mockReturnValue(singleHot(vorgangListResource));
     });
 
     it('should call resourceFactory with uri', () => {
       repository.loadMeineVorgaengeList(apiRootResource);
 
-      const urlWithoutParameter: URL = repository.getUrlWithoutParameter(
-        apiRootResource,
-        ApiRootLinkRel.MEINE_VORGAENGE,
-      );
+      const urlWithoutParameter: URL = repository.getUrlWithoutParameter(apiRootResource, ApiRootLinkRel.MEINE_VORGAENGE);
       expect(resourceFactory.fromId).toHaveBeenCalledWith(urlWithoutParameter.href);
     });
 
@@ -313,17 +260,14 @@ describe('VorgangRepository', () => {
     });
 
     it('should return result', () => {
-      let result = repository.loadMeineVorgaengeList(apiRootResource);
+      let result: Observable<VorgangListResource> = repository.loadMeineVorgaengeList(apiRootResource);
 
-      expect(result).not.toBeNull();
-      expect(result).toBeObservable(cold('a', { a: vorgangListResource }));
+      expect(result).toBeObservable(singleCold(vorgangListResource));
     });
   });
 
   describe('export', () => {
-    const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([
-      VorgangWithEingangLinkRel.EXPORT,
-    ]);
+    const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.EXPORT]);
 
     const body: Blob = new Blob();
     const fileName: string = '927ee047-0123-4c36-911c-52e984accc87_Abgabe.Abgabe.0401.xdomea';
@@ -331,7 +275,7 @@ describe('VorgangRepository', () => {
     const httpResponse: HttpResponse<Blob> = <any>{ body, headers: { get: () => headerString } };
 
     beforeEach(() => {
-      httpClient.get.mockReturnValue(hot('a', { a: httpResponse }));
+      httpClient.get.mockReturnValue(singleHot(httpResponse));
     });
 
     it('should call httpClient', () => {
@@ -341,16 +285,13 @@ describe('VorgangRepository', () => {
 
       repository.export(vorgangWithEingang);
 
-      expect(httpClient.get).toHaveBeenCalledWith(
-        getUrl(vorgangWithEingang, VorgangWithEingangLinkRel.EXPORT),
-        requestOptions,
-      );
+      expect(httpClient.get).toHaveBeenCalledWith(getUrl(vorgangWithEingang, VorgangWithEingangLinkRel.EXPORT), requestOptions);
     });
 
     it('should return value', () => {
-      const result = repository.export(vorgangWithEingang);
+      const result: Observable<BlobWithFileName> = repository.export(vorgangWithEingang);
 
-      expect(result).toBeObservable(cold('b', { b: { blob: body, fileName } }));
+      expect(result).toBeObservable(singleCold({ blob: body, fileName }));
     });
   });
 
diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.ts
index 57caef25627930944e573e0a19fa44715c2df489..b2dd59e65837996bceeedffe8e605c8d2911813f 100644
--- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.ts
+++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.ts
@@ -24,7 +24,6 @@
 import { BinaryFileSharedModule } from '@alfa-client/binary-file-shared';
 import { CommandSharedModule } from '@alfa-client/command-shared';
 import { NavigationSharedModule } from '@alfa-client/navigation-shared';
-import { TechSharedModule } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
 import { RouterModule } from '@angular/router';
@@ -41,7 +40,6 @@ import * as fromVorgang from './+state/vorgang.reducer';
   imports: [
     CommonModule,
     RestModule,
-    TechSharedModule,
     CommandSharedModule,
     BinaryFileSharedModule,
     RouterModule,
diff --git a/alfa-client/libs/vorgang/src/lib/vorgang.module.ts b/alfa-client/libs/vorgang/src/lib/vorgang.module.ts
index cf3421cb9ed957b151e3cf8948828bde38b7f6b1..d1668cea27cf0e97e402293ebfdbf49d4c396980 100644
--- a/alfa-client/libs/vorgang/src/lib/vorgang.module.ts
+++ b/alfa-client/libs/vorgang/src/lib/vorgang.module.ts
@@ -22,8 +22,15 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { HintModule } from '@alfa-client/hint';
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import {
+  ConvertForDataTestPipe,
+  FormatDateWithoutYearWithTimePipe,
+  FormatDateWithTimePipe,
+  FormatToPrettyDatePipe,
+  HasLinkPipe,
+  ToResourceUriPipe,
+} from '@alfa-client/tech-shared';
+import { OzgcloudIconComponent, OzgcloudRoutingButtonComponent, PostfachIconComponent, SpinnerComponent } from '@alfa-client/ui';
 import { UserProfileModule } from '@alfa-client/user-profile';
 import { VorgangSharedModule } from '@alfa-client/vorgang-shared';
 import { VorgangSharedUiModule } from '@alfa-client/vorgang-shared-ui';
@@ -31,9 +38,13 @@ import { WiedervorlageModule } from '@alfa-client/wiedervorlage';
 import { ScrollingModule } from '@angular/cdk/scrolling';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
 import { MatButtonToggleModule } from '@angular/material/button-toggle';
+import { MatIcon, MatIconModule } from '@angular/material/icon';
+import { MatTooltip } from '@angular/material/tooltip';
 import { RouterModule, Routes } from '@angular/router';
 import { ButtonToggleGroupComponent } from '@ods/component';
+import { HasAnyLinkPipe } from '../../../tech-shared/src/lib/pipe/has-any-link.pipe';
 import { ArchiveIconComponent, ButtonToggleComponent, TooltipDirective } from '@ods/system';
 import { vorgangFilterViewGuard } from './vorgang-filter-view.guard';
 import { VorgangListContainerComponent } from './vorgang-list-container/vorgang-list-container.component';
@@ -169,9 +180,7 @@ const routes: Routes = [
 @NgModule({
   imports: [
     CommonModule,
-    TechSharedModule,
     ScrollingModule,
-    UiModule,
     RouterModule.forChild(routes),
     VorgangSharedModule,
     WiedervorlageModule,
@@ -182,6 +191,21 @@ const routes: Routes = [
     ButtonToggleComponent,
     ButtonToggleGroupComponent,
     ArchiveIconComponent,
+    FormatDateWithTimePipe,
+    FormatDateWithoutYearWithTimePipe,
+    MatIcon,
+    MatTooltip,
+    MatIconModule,
+    FormatToPrettyDatePipe,
+    ToResourceUriPipe,
+    ConvertForDataTestPipe,
+    HasLinkPipe,
+    PostfachIconComponent,
+    SpinnerComponent,
+    ReactiveFormsModule,
+    OzgcloudRoutingButtonComponent,
+    OzgcloudIconComponent,
+    HasAnyLinkPipe,
     TooltipDirective,
   ],
   declarations: [
diff --git a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html
index c0d873acccd4aa1879d455928b7dbaa386bac5e7..231640ded0433d236945ca15247c90bdc3273231 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html
+++ b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html
@@ -26,21 +26,22 @@
 @if (showAsIconButton) {
   <ods-button-with-spinner
     [stateResource]="submitInProgress$ | async"
+    (clickEmitter)="submit()"
     [tooltip]="'Wiedervorlage speichern'"
     tooltipAriaType="aria-labelledby"
     variant="ghost"
     size="fit"
-    (clickEmitter)="submit()"
+    dataTestId="speichern-icon-button"
   >
     <ods-save-icon icon class="fill-text" />
   </ods-button-with-spinner>
 } @else {
   <ods-button-with-spinner
-    data-test-id="speichern-button"
     [stateResource]="submitInProgress$ | async"
+    (clickEmitter)="submit()"
     text="Speichern"
     variant="outline"
-    (clickEmitter)="submit()"
+    dataTestId="speichern-button"
   >
     <ods-save-icon icon />
   </ods-button-with-spinner>
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts
index 2d573153c6a323f3a4d30f421a75af0e10cfb818..f7dfb80e9b4ab4478fc2063574cda7411e15498d 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts
@@ -21,18 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { SimpleChanges } from '@angular/core';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { UntypedFormBuilder, ReactiveFormsModule } from '@angular/forms';
 import { BinaryFileAttachmentContainerComponent } from '@alfa-client/binary-file';
 import { BinaryFileListResource } from '@alfa-client/binary-file-shared';
 import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
-import { DateEditorComponent, TextAreaEditorComponent, TextEditorComponent } from '@alfa-client/ui';
-import {
-  WiedervorlageLinkRel,
-  WiedervorlageResource,
-  WiedervorlageService,
-} from '@alfa-client/wiedervorlage-shared';
+import { DateEditorComponent, OzgcloudTextEditorComponent, TextAreaEditorComponent } from '@alfa-client/ui';
+import { WiedervorlageLinkRel, WiedervorlageResource, WiedervorlageService } from '@alfa-client/wiedervorlage-shared';
+import { SimpleChanges } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
 import { createBinaryFileListResource } from 'libs/binary-file-shared/test/binary-file';
 import { createWiedervorlageResource } from 'libs/wiedervorlage-shared/test/wiedervorlage';
 import { MockComponent } from 'ng-mocks';
@@ -45,10 +41,7 @@ describe('WiedervorlageFormComponent', () => {
   let component: WiedervorlageFormComponent;
   let fixture: ComponentFixture<WiedervorlageFormComponent>;
 
-  const formService = new WiedervorlageFormService(
-    new UntypedFormBuilder(),
-    useFromMock(mock(WiedervorlageService)),
-  );
+  const formService = new WiedervorlageFormService(new UntypedFormBuilder(), useFromMock(mock(WiedervorlageService)));
   const wiedervorlageService: Mock<WiedervorlageService> = mock(WiedervorlageService);
   const wiedervorlage: WiedervorlageResource = createWiedervorlageResource();
 
@@ -57,7 +50,7 @@ describe('WiedervorlageFormComponent', () => {
       declarations: [
         WiedervorlageFormComponent,
         MockComponent(DateEditorComponent),
-        MockComponent(TextEditorComponent),
+        MockComponent(OzgcloudTextEditorComponent),
         MockComponent(TextAreaEditorComponent),
         MockComponent(BinaryFileAttachmentContainerComponent),
         MockComponent(SubmitWiedervorlageButtonComponent),
@@ -118,16 +111,12 @@ describe('WiedervorlageFormComponent', () => {
     });
 
     it('should call wiedervorlage service to get attachments if links exists', () => {
-      const wiedervorlageWithAttachments: WiedervorlageResource = createWiedervorlageResource([
-        WiedervorlageLinkRel.ATTACHMENTS,
-      ]);
+      const wiedervorlageWithAttachments: WiedervorlageResource = createWiedervorlageResource([WiedervorlageLinkRel.ATTACHMENTS]);
       component.wiedervorlage = wiedervorlageWithAttachments;
 
       component.updateAttachments();
 
-      expect(wiedervorlageService.getAttachmentList).toHaveBeenCalledWith(
-        wiedervorlageWithAttachments,
-      );
+      expect(wiedervorlageService.getAttachmentList).toHaveBeenCalledWith(wiedervorlageWithAttachments);
     });
 
     it('should NOT call wiedervorlage service if link is not present', () => {
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.spec.ts
index ab2dd54f9740cb097bff0679157bc920bf8e762e..86383128c2a8cf444467208cd4b0fab3acdfb3fa 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.spec.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.spec.ts
@@ -35,8 +35,8 @@ describe('WiedervorlageStatusComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [WiedervorlageStatusComponent, ToTrafficLightPipe],
-      imports: [MatIcon],
+      declarations: [WiedervorlageStatusComponent],
+      imports: [MatIcon, ToTrafficLightPipe],
     }).compileComponents();
   });
 
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts
index 7729ab5f2f68770e3b6e2e850fc9279f3a731406..2057849d9d85c3365877c9d58fd022a8137029dc 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts
@@ -22,13 +22,34 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { BinaryFileModule } from '@alfa-client/binary-file';
-import { TechSharedModule } from '@alfa-client/tech-shared';
-import { UiModule } from '@alfa-client/ui';
+import {
+  ConvertForDataTestPipe,
+  FormatToPrettyDatePipe,
+  HasLinkPipe,
+  ToEmbeddedResourcesPipe,
+  ToResourceUriPipe,
+  ToTrafficLightPipe,
+  ToTrafficLightTooltipPipe,
+} from '@alfa-client/tech-shared';
+import {
+  BackButtonComponent,
+  DateEditorComponent,
+  ExpansionPanelComponent,
+  IconButtonWithSpinnerComponent,
+  OzgcloudStrokedButtonWithSpinnerComponent,
+  OzgcloudTextEditorComponent,
+  SpinnerComponent,
+  SubnavigationComponent,
+  TextAreaEditorComponent,
+} from '@alfa-client/ui';
 import { UserProfileModule } from '@alfa-client/user-profile';
 import { VorgangSharedModule } from '@alfa-client/vorgang-shared';
 import { VorgangSharedUiModule } from '@alfa-client/vorgang-shared-ui';
 import { CommonModule, DatePipe } from '@angular/common';
 import { NgModule } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { MatIcon } from '@angular/material/icon';
+import { MatTooltip } from '@angular/material/tooltip';
 import { RouterModule, Routes } from '@angular/router';
 import { ButtonWithSpinnerComponent } from '@ods/component';
 import {
@@ -71,12 +92,29 @@ const routes: Routes = [
   imports: [
     CommonModule,
     RouterModule.forChild(routes),
-    UiModule,
     VorgangSharedModule,
-    TechSharedModule,
     VorgangSharedUiModule,
     BinaryFileModule,
     UserProfileModule,
+    HasLinkPipe,
+    IconButtonWithSpinnerComponent,
+    OzgcloudStrokedButtonWithSpinnerComponent,
+    MatIcon,
+    MatTooltip,
+    ToTrafficLightTooltipPipe,
+    ToResourceUriPipe,
+    FormatToPrettyDatePipe,
+    SpinnerComponent,
+    ExpansionPanelComponent,
+    ToEmbeddedResourcesPipe,
+    BackButtonComponent,
+    ReactiveFormsModule,
+    OzgcloudTextEditorComponent,
+    TextAreaEditorComponent,
+    DateEditorComponent,
+    SubnavigationComponent,
+    ToTrafficLightPipe,
+    ConvertForDataTestPipe,
     ButtonWithSpinnerComponent,
     TooltipDirective,
     UpdateIconComponent,
diff --git a/alfa-client/libs/zustaendige-stelle-shared/src/lib/organisations-einheit/organisations-einheit.model.ts b/alfa-client/libs/zustaendige-stelle-shared/src/lib/organisations-einheit/organisations-einheit.model.ts
index a802fe79f851232dcb9c8e27beae5c64f8db2b01..2658c1475c9ca56179e0590d511a948ce3f3adf7 100644
--- a/alfa-client/libs/zustaendige-stelle-shared/src/lib/organisations-einheit/organisations-einheit.model.ts
+++ b/alfa-client/libs/zustaendige-stelle-shared/src/lib/organisations-einheit/organisations-einheit.model.ts
@@ -27,6 +27,7 @@ import { Resource } from '@ngxp/rest';
 export interface OrganisationsEinheit {
   name: string;
   anschrift: Anschrift;
+  organisationEinheitId: string;
 }
 
 export interface Anschrift {
diff --git a/alfa-client/libs/zustaendige-stelle-shared/test/organisations-einheit.ts b/alfa-client/libs/zustaendige-stelle-shared/test/organisations-einheit.ts
index 2257be08968edef9d5287bf9913a6025fe57dd78..d4aa69a51af006f51b1c1ec551f5d212c1e6e647 100644
--- a/alfa-client/libs/zustaendige-stelle-shared/test/organisations-einheit.ts
+++ b/alfa-client/libs/zustaendige-stelle-shared/test/organisations-einheit.ts
@@ -45,6 +45,7 @@ export function createOrganisationsEinheit(): OrganisationsEinheit {
   return {
     name: faker.word.sample(),
     anschrift: createAnschrift(),
+    organisationEinheitId: faker.string.uuid(),
   };
 }
 
diff --git a/alfa-client/libs/zustaendige-stelle/src/lib/zustaendige-stelle.module.ts b/alfa-client/libs/zustaendige-stelle/src/lib/zustaendige-stelle.module.ts
index 0ca329814a60a3bcc0ef1724dd6e82e3cd93b162..820da330c99f8e0d184b5c6b38096db8c03604bb 100644
--- a/alfa-client/libs/zustaendige-stelle/src/lib/zustaendige-stelle.module.ts
+++ b/alfa-client/libs/zustaendige-stelle/src/lib/zustaendige-stelle.module.ts
@@ -21,7 +21,6 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { TechSharedModule } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@@ -50,7 +49,6 @@ import { ZustaendigeStelleHeaderComponent } from './zustaendige-stelle-header/zu
     CommonModule,
     ButtonComponent,
     CloseIconComponent,
-    TechSharedModule,
     InstantSearchComponent,
     FormsModule,
     ReactiveFormsModule,
diff --git a/alfa-client/nx.json b/alfa-client/nx.json
index 45e3e58f414b34a448360de13c8e82e818c03c45..4153173c1960cf6aeb57131d786bfb1554f09e83 100644
--- a/alfa-client/nx.json
+++ b/alfa-client/nx.json
@@ -103,6 +103,7 @@
     }
   },
   "useInferencePlugins": false,
+  "defaultBase": "main",
   "release": {
     "projects": ["admin", "alfa", "info"],
     "projectsRelationship": "independent"
diff --git a/alfa-client/tsconfig.base.json b/alfa-client/tsconfig.base.json
index 6850f74e4eb7c031308a264a51e8a4782fa9613b..f6bb4c8b2657d8acef026b997d32794971be5656 100644
--- a/alfa-client/tsconfig.base.json
+++ b/alfa-client/tsconfig.base.json
@@ -22,6 +22,7 @@
       "@admin-client/organisations-einheit-shared": ["libs/admin/organisations-einheit-shared/src/index.ts"],
       "@admin-client/postfach": ["libs/admin/postfach/src/index.ts"],
       "@admin-client/postfach-shared": ["libs/admin/postfach-shared/src/index.ts"],
+      "@admin-client/reporting-shared": ["libs/admin/reporting-shared/src/index.ts"],
       "@admin-client/settings-shared": ["libs/admin/settings-shared/src/index.ts"],
       "@admin-client/shared": ["libs/admin/shared/src/index.ts"],
       "@admin-client/statistik": ["libs/admin/statistik/src/index.ts"],