diff --git a/Classes/Controller/Ajax/UploadController.php b/Classes/Controller/Ajax/UploadController.php
index 86508a06d571c59fb8df1d3d34d35c7a1280b77b..f17b00e0d810fa2d2a3806915cdd19fa3ebcc27c 100644
--- a/Classes/Controller/Ajax/UploadController.php
+++ b/Classes/Controller/Ajax/UploadController.php
@@ -26,6 +26,7 @@
 
 namespace SGalinski\SgJobs\Controller\Ajax;
 
+use Psr\Http\Message\ResponseInterface;
 use SGalinski\SgAjax\Controller\Ajax\AbstractAjaxController;
 use SGalinski\SgJobs\Service\FileAndFolderService;
 use TYPO3\CMS\Core\Core\Environment;
@@ -85,37 +86,40 @@ class UploadController extends AbstractAjaxController {
 	/**
 	 * Uploads a new cover letter.
 	 *
-	 * @return void
+	 * @return ResponseInterface
 	 * @throws ExistingTargetFolderException
 	 * @throws InsufficientFolderAccessPermissionsException
 	 * @throws InsufficientFolderWritePermissionsException
 	 */
-	public function uploadCoverletterAction(): void {
+	public function uploadCoverletterAction(): ResponseInterface {
 		$this->handleAnyDropZoneUpload();
+		return $this->htmlResponse();
 	}
 
 	/**
 	 * Uploads a new cd.
 	 *
-	 * @return void
+	 * @return ResponseInterface
 	 * @throws ExistingTargetFolderException
 	 * @throws InsufficientFolderAccessPermissionsException
 	 * @throws InsufficientFolderWritePermissionsException
 	 */
-	public function uploadCvAction(): void {
+	public function uploadCvAction(): ResponseInterface {
 		$this->handleAnyDropZoneUpload();
+		return $this->htmlResponse();
 	}
 
 	/**
 	 * Uploads a new certificate.
 	 *
-	 * @return void
+	 * @return ResponseInterface
 	 * @throws ExistingTargetFolderException
 	 * @throws InsufficientFolderAccessPermissionsException
 	 * @throws InsufficientFolderWritePermissionsException
 	 */
-	public function uploadCertificateAction(): void {
+	public function uploadCertificateAction(): ResponseInterface {
 		$this->handleAnyDropZoneUpload();
+		return $this->htmlResponse();
 	}
 
 	/**
@@ -146,6 +150,7 @@ class UploadController extends AbstractAjaxController {
 			} else {
 				$folder = $storage->getFolder($this->jobFolderPath);
 			}
+
 			// if temp folder is not existing, create one
 			if ($folder && !$storage->hasFolderInFolder(self::JOB_APPLICATION_TEMP_FOLDER, $folder)) {
 				$storage->createFolder(self::JOB_APPLICATION_TEMP_FOLDER, $folder);
diff --git a/Classes/Controller/BackendController.php b/Classes/Controller/BackendController.php
index 928a5ed6e08877dab98fc6a331f6057cc05ac43c..55b293603bb0ab47d2a42175237491497b32cb1b 100644
--- a/Classes/Controller/BackendController.php
+++ b/Classes/Controller/BackendController.php
@@ -26,19 +26,20 @@
 
 namespace SGalinski\SgJobs\Controller;
 
+use Doctrine\DBAL\Exception;
 use Psr\Http\Message\ResponseInterface;
 use SGalinski\SgJobs\Domain\Repository\CompanyRepository;
 use SGalinski\SgJobs\Domain\Repository\JobRepository;
 use SGalinski\SgJobs\Pagination\Pagination;
 use SGalinski\SgJobs\Service\BackendService;
 use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent;
+use TYPO3\CMS\Backend\Template\ModuleTemplate;
+use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Messaging\FlashMessage;
+use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\VersionNumberUtility;
 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
-use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException;
 use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException;
 use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
@@ -52,36 +53,43 @@ class BackendController extends ActionController {
 	 *
 	 * @var DocHeaderComponent
 	 */
-	protected $docHeaderComponent;
+	protected DocHeaderComponent $docHeaderComponent;
 
 	/**
 	 * @var CompanyRepository
 	 *
 	 */
-	protected $companyRepository;
+	protected CompanyRepository $companyRepository;
 
 	/**
 	 * @var JobRepository
 	 *
 	 */
-	protected $jobRepository;
+	protected JobRepository $jobRepository;
 
 	/**
-	 * Inject the CompanyRepository
-	 *
-	 * @param CompanyRepository $companyRepository
+	 * @var ModuleTemplateFactory
 	 */
-	public function injectCompanyRepository(CompanyRepository $companyRepository): void {
-		$this->companyRepository = $companyRepository;
-	}
+	protected ModuleTemplateFactory $moduleTemplateFactory;
 
 	/**
-	 * Inject the JobRepository
-	 *
-	 * @param JobRepository $jobRepository
+	 * @var ModuleTemplate
 	 */
-	public function injectJobRepository(JobRepository $jobRepository): void {
+	protected ModuleTemplate $moduleTemplate;
+
+	public function __construct(
+		CompanyRepository $companyRepository,
+		JobRepository $jobRepository,
+		ModuleTemplateFactory $moduleTemplateFactory
+	) {
+		$this->companyRepository = $companyRepository;
 		$this->jobRepository = $jobRepository;
+		$this->moduleTemplateFactory = $moduleTemplateFactory;
+	}
+
+	public function initializeAction(): void {
+		parent::initializeAction();
+		$this->moduleTemplate = $this->moduleTemplateFactory->create($this->request);
 	}
 
 	/**
@@ -89,11 +97,12 @@ class BackendController extends ActionController {
 	 *
 	 * @param array $filters
 	 * @param int $currentPage
-	 * @return ResponseInterface|null
-	 * @throws InvalidQueryException|NoSuchArgumentException
+	 * @return ResponseInterface
+	 * @throws InvalidQueryException
+	 * @throws Exception
 	 */
-	public function indexAction(array $filters = [], int $currentPage = 1): ?ResponseInterface {
-		$pageUid = (int) GeneralUtility::_GP('id');
+	public function indexAction(array $filters = [], int $currentPage = 1): ResponseInterface {
+		$pageUid = $this->request->getQueryParams()['id'] ?? 0;
 		$itemsPerPage = 10;
 		/** @var BackendUserAuthentication $backendUser */
 		$backendUser = $GLOBALS['BE_USER'];
@@ -112,47 +121,33 @@ class BackendController extends ActionController {
 		$this->docHeaderComponent = GeneralUtility::makeInstance(DocHeaderComponent::class);
 		$this->docHeaderComponent->setMetaInformation($pageInfo);
 		BackendService::makeButtons($this->docHeaderComponent, $this->request);
-		$this->view->assign('docHeader', $this->docHeaderComponent->docHeaderContent());
+		$this->moduleTemplate->assign('docHeader', $this->docHeaderComponent->docHeaderContent());
 
-		$this->view->assign('pageUid', $pageUid);
-		$this->view->assign('pages', BackendService::getPagesWithJobRecords());
+		$this->moduleTemplate->assign('pageUid', $pageUid);
+		$this->moduleTemplate->assign('pages', BackendService::getPagesWithJobRecords());
 
 		$jobsQueryResult = $this->jobRepository->findBackendJobs($pageUid, $filters, $itemsPerPage);
 		$pagination = GeneralUtility::makeInstance(Pagination::class, $jobsQueryResult, $currentPage, $itemsPerPage);
-		$this->view->assign('pagination', $pagination);
+		$this->moduleTemplate->assign('pagination', $pagination);
 
 		$totalJobCount = $pagination->getTotalItems();
-		$this->view->assign('totalJobCount', $totalJobCount);
+		$this->moduleTemplate->assign('totalJobCount', $totalJobCount);
 		// get all Locations
 		/** @noinspection PhpUndefinedMethodInspection */
 		/** @var QueryResultInterface $companies */
 		$companies = $this->companyRepository->findByPid($pageUid);
-		$this->view->assign('locationOptions', $companies);
+		$this->moduleTemplate->assign('locationOptions', $companies);
 
-		$this->view->assign('isAdmin', $GLOBALS['BE_USER']->isAdmin());
-		$this->view->assign('filters', $filters);
+		$this->moduleTemplate->assign('isAdmin', $GLOBALS['BE_USER']->isAdmin());
+		$this->moduleTemplate->assign('filters', $filters);
 		if (!$totalJobCount && $pageUid) {
 			$this->addFlashMessage(
 				LocalizationUtility::translate('backend.notice.noRecords', 'SgJobs'),
 				'',
-				FlashMessage::INFO
+				ContextualFeedbackSeverity::INFO
 			);
 		}
-		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) {
-			$this->view->assign('V11', FALSE);
-			return NULL;
-		}
-
-		$this->view->assign('V11', TRUE);
-		return $this->createBackendResponse();
-	}
 
-	/**
-	 * Use the ModuleTemplateResponse to create a response object for the backend
-	 *
-	 * @return  ResponseInterface
-	 */
-	protected function createBackendResponse(): ResponseInterface {
-		return $this->htmlResponse($this->view->render());
+		return $this->moduleTemplate->renderResponse('Index');
 	}
 }
diff --git a/Classes/Controller/JobTeaserController.php b/Classes/Controller/JobTeaserController.php
index 63ef1058cbd73d6c62cf7d43dd452f55adbf400f..ddff567265cacff4ca51d1d17aa84923eedb37fc 100644
--- a/Classes/Controller/JobTeaserController.php
+++ b/Classes/Controller/JobTeaserController.php
@@ -57,26 +57,26 @@ class JobTeaserController extends ActionController {
 		if (isset($this->settings['filterByDepartment']) && $this->settings['filterByDepartment'] !== '') {
 			$filters['filterByDepartment'] = $this->settings['filterByDepartment'];
 		}
+
 		if (isset($this->settings['filterByExperienceLevel']) && $this->settings['filterByExperienceLevel'] !== '') {
 			$filters['filterByExperienceLevel'] = $this->settings['filterByExperienceLevel'];
 		}
+
 		if (isset($this->settings['filterByLocation']) && $this->settings['filterByLocation'] !== '') {
 			$filters['filterByLocation'] = $this->settings['filterByLocation'];
 		}
 
-		// TODO: Remove this on the next breaking change
-		// Used for backwards compatibility but is the same as 'filterByLocation' above
-		if (isset($this->settings['location']) && $this->settings['location'] !== '') {
-			$filters['filterByLocation'] = $this->settings['location'];
-		}
-
 		foreach ($filters as &$filter) {
 			$filter = $filter ? GeneralUtility::trimExplode(',', $filter) : NULL;
 			foreach ($filter as &$value) {
 				$value = (int) $value;
 			}
+
+			unset($value);
 		}
 
+		unset($filter);
+
 		$totalAmountOfOffers = $this->jobRepository->countAll($filters);
 
 		$querySettings = $this->jobRepository->createQuery()->getQuerySettings();
@@ -88,22 +88,6 @@ class JobTeaserController extends ActionController {
 		$this->view->assign('filters', $filters);
 		$this->view->assign('featuredOffers', $featuredOffers);
 
-		if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) {
-			return NULL;
-		}
-
 		return $this->htmlResponse();
 	}
-
-	/**
-	 * Build Typo3 11 Response
-	 *
-	 * @param string|NULL $html
-	 * @return ResponseInterface
-	 */
-	protected function htmlResponse(string $html = NULL): ResponseInterface {
-		return $this->responseFactory->createResponse()
-			->withHeader('Content-Type', 'text/html; charset=utf-8')
-			->withBody($this->streamFactory->createStream($html ?? $this->view->render()));
-	}
 }
diff --git a/Classes/Controller/JoblistController.php b/Classes/Controller/JoblistController.php
index d187952c861906268b25a6cac3e5219f93538b47..a5bbd8f0d5f133113c7c1095f4b24a070e6d4cc3 100644
--- a/Classes/Controller/JoblistController.php
+++ b/Classes/Controller/JoblistController.php
@@ -27,7 +27,6 @@
 namespace SGalinski\SgJobs\Controller;
 
 use Psr\Http\Message\ResponseInterface;
-use SGalinski\ProjectBase\Domain\Repository\CountryRepository;
 use SGalinski\SgJobs\Controller\Ajax\UploadController;
 use SGalinski\SgJobs\Domain\Model\Company;
 use SGalinski\SgJobs\Domain\Model\Job;
@@ -39,12 +38,14 @@ use SGalinski\SgJobs\Domain\Repository\JobApplicationRepository;
 use SGalinski\SgJobs\Domain\Repository\JobRepository;
 use SGalinski\SgJobs\Service\FileAndFolderService;
 use SGalinski\SgMail\Service\MailTemplateService;
+use SGalinski\SgSeo\Service\HeadTagService;
 use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException;
 use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException;
 use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
 use TYPO3\CMS\Core\Core\Environment;
+use TYPO3\CMS\Core\Country\CountryProvider;
 use TYPO3\CMS\Core\Error\Http\PageNotFoundException;
 use TYPO3\CMS\Core\Exception\SiteNotFoundException;
 use TYPO3\CMS\Core\Http\ImmediateResponseException;
@@ -61,16 +62,17 @@ use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\PathUtility;
-use TYPO3\CMS\Core\Utility\VersionNumberUtility;
 use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
+use TYPO3\CMS\Extbase\Http\ForwardResponse;
 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
 use TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentNameException;
 use TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException;
-use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
+use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException;
 use TYPO3\CMS\Extbase\Property\Exception\TypeConverterException;
 use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
 use TYPO3\CMS\Extbase\Validation\Validator\ConjunctionValidator;
 use TYPO3\CMS\Extbase\Validation\Validator\GenericObjectValidator;
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
 use TYPO3\CMS\Frontend\Controller\ErrorController;
 use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons;
 
@@ -193,13 +195,13 @@ class JoblistController extends ActionController {
 	 */
 	public function initializeIndexAction(): void {
 		$currentPageBrowserPage = 0;
-		$parameters = GeneralUtility::_GP('tx_sgjobs_pagebrowser');
+		$parameters = $this->request->getQueryParams()['tx_sgjobs_pagebrowser'] ?? 0;
 		if (is_array($parameters)) {
 			$currentPageBrowserPage = (int) $parameters['currentPage'] ?: 0;
 		}
 
 		if ($currentPageBrowserPage > 0) {
-			$this->request->setArgument('currentPageBrowserPage', $currentPageBrowserPage);
+			$this->request = $this->request->withArgument('currentPageBrowserPage', $currentPageBrowserPage);
 		}
 	}
 
@@ -209,7 +211,7 @@ class JoblistController extends ActionController {
 	 * @param array $filters
 	 * @param int|null $jobId
 	 * @param int $currentPageBrowserPage
-	 * @return ResponseInterface|null
+	 * @return ResponseInterface
 	 * @throws ImmediateResponseException
 	 * @throws AspectNotFoundException
 	 * @throws PageNotFoundException
@@ -218,7 +220,7 @@ class JoblistController extends ActionController {
 		array $filters = [],
 		int $jobId = NULL,
 		int $currentPageBrowserPage = 0
-	): ?ResponseInterface {
+	): ResponseInterface {
 		if ($filters) {
 			$this->view->assign('selectedCountry', $filters['filterCountry'] ?? '');
 			$this->view->assign('selectedCompany', $filters['filterCompany'] ?? '');
@@ -243,9 +245,11 @@ class JoblistController extends ActionController {
 				foreach ($filter as &$value) {
 					$value = (int) $value;
 				}
+
 				unset($value);
 			}
 		}
+
 		unset($filter);
 
 		$storagePids = GeneralUtility::trimExplode(
@@ -268,7 +272,7 @@ class JoblistController extends ActionController {
 
 			if (ExtensionManagementUtility::isLoaded('sg_seo')) {
 				$headTagService = GeneralUtility::makeInstance(
-					\SGalinski\SgSeo\Service\HeadTagService::class,
+					HeadTagService::class,
 					TRUE,
 					$job->getTitle(),
 					$job->getDescription(),
@@ -315,10 +319,6 @@ class JoblistController extends ActionController {
 		$this->view->assign('limit', $jobLimit);
 		$this->view->assign('numberOfPages', $numberOfPages);
 
-		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) {
-			return NULL;
-		}
-
 		return $this->htmlResponse();
 	}
 
@@ -328,9 +328,8 @@ class JoblistController extends ActionController {
 	 * @param JobApplication|null $applyData
 	 * @param string $error
 	 * @param int|null $jobId
-	 * @return ResponseInterface|null
+	 * @return ResponseInterface
 	 * @throws AspectNotFoundException
-	 * @throws StopActionException
 	 * @throws SiteNotFoundException
 	 * @throws InvalidArgumentNameException
 	 */
@@ -338,10 +337,10 @@ class JoblistController extends ActionController {
 		JobApplication $applyData = NULL,
 		string $error = '',
 		int $jobId = NULL
-	): ?ResponseInterface {
+	): ResponseInterface {
 		if ($error !== '') {
 			$this->view->assign('internalError', $error);
-			$this->request->setArgument('error', NULL);
+			$this->request = $this->request->withArgument('error', NULL);
 		}
 
 		if ($jobId === NULL && $this->settings['disallowUnsolicitedApplication']) {
@@ -362,8 +361,9 @@ class JoblistController extends ActionController {
 
 		if ($folderName === NULL) {
 			$folderName = \md5(\uniqid('sgjobs-', TRUE));
-			$this->request->setArgument('folderName', $folderName);
+			$this->request = $this->request->withArgument('folderName', $folderName);
 		}
+
 		$this->view->assign('folderName', $folderName);
 
 		$job = NULL;
@@ -373,7 +373,7 @@ class JoblistController extends ActionController {
 			if ($job) {
 				if (ExtensionManagementUtility::isLoaded('sg_seo')) {
 					$headTagService = GeneralUtility::makeInstance(
-						\SGalinski\SgSeo\Service\HeadTagService::class,
+						HeadTagService::class,
 						FALSE,
 						$job->getTitle(),
 						$job->getDescription(),
@@ -389,6 +389,7 @@ class JoblistController extends ActionController {
 					$this->view->assign('relatedJobs', $relatedJobs);
 				}
 			}
+
 			$this->view->assign('job', $job);
 		} else {
 			$storagePids = GeneralUtility::trimExplode(
@@ -408,9 +409,10 @@ class JoblistController extends ActionController {
 			->getLanguageById($sysLanguageUid);
 		$countries = [];
 		if (ExtensionManagementUtility::isLoaded('project_base')) {
-			$countryRepository = $this->objectManager->get(CountryRepository::class);
-			$countries = $countryRepository->findAllOrderedByLanguage($site->getTwoLetterIsoCode());
+			$countryProvider = GeneralUtility::makeInstance(CountryProvider::class);
+			$countries = $countryProvider->getAll();
 		}
+
 		$this->view->assign('countries', $countries);
 		$this->view->assign('sysLanguageUid', $sysLanguageUid);
 
@@ -420,7 +422,8 @@ class JoblistController extends ActionController {
 		$this->view->assign('allowedFileExtensions', $allowedFileExtensions);
 
 		if ($applyData === NULL) {
-			$applyData = $this->objectManager->get(JobApplication::class);
+			/** @var JobApplication $applyData */
+			$applyData = GeneralUtility::makeInstance(JobApplication::class);
 			if ($job) {
 				$applyData->setJobId($job->getJobId());
 			}
@@ -438,11 +441,7 @@ class JoblistController extends ActionController {
 		$arguments = $this->request->getArguments();
 		if (isset($arguments['applyData']) && $arguments['applyData']) {
 			$arguments['applyData'] = (string) $arguments['applyData'];
-			$this->request->setArguments($arguments);
-		}
-
-		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) {
-			return NULL;
+			$this->request = $this->request->withArguments($arguments);
 		}
 
 		return $this->htmlResponse();
@@ -454,10 +453,9 @@ class JoblistController extends ActionController {
 	 * @param JobApplication $applicationData
 	 * @param string $folderName
 	 * @return void
-	 * @throws StopActionException
 	 */
 	protected function createCsvSummary(JobApplication $applicationData, string $folderName): void {
-		$resourceFactory = $this->objectManager->get(ResourceFactory::class);
+		$resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
 		$newName = \date('Ymd-His') . '_' . $applicationData->getJobId() . '-' . $applicationData->getFirstName()
 			. '-' . $applicationData->getLastName();
 		$storage = $resourceFactory->getStorageObject(1);
@@ -525,7 +523,6 @@ class JoblistController extends ActionController {
 	 * Pre-apply action setup, configures model-property mapping and handles file upload
 	 *
 	 * @throws NoSuchArgumentException
-	 * @throws StopActionException
 	 */
 	protected function initializeApplyAction(): void {
 		$propertyMappingConfiguration = $this->arguments->getArgument('applyData')->getPropertyMappingConfiguration();
@@ -537,9 +534,8 @@ class JoblistController extends ActionController {
 		foreach ($validator->getValidators() as $subValidator) {
 			/** @var GenericObjectValidator $subValidatorSub */
 			foreach ($subValidator->getValidators() as $subValidatorSub) {
-				$subValidatorSub->getPropertyValidators('job')->removeAll(
-					$subValidatorSub->getPropertyValidators('job')
-				);
+				$subValidatorsSub = $subValidatorSub->getPropertyValidators();
+				unset($subValidatorsSub['job']);
 			}
 		}
 	}
@@ -548,13 +544,12 @@ class JoblistController extends ActionController {
 	 * Saves the application send by the applyFormAction
 	 *
 	 * @param JobApplication $applyData
-	 * @return ResponseInterface|null
-	 * @throws NoSuchArgumentException
-	 * @throws StopActionException
+	 * @return ResponseInterface
 	 * @throws ExtensionConfigurationExtensionNotConfiguredException
 	 * @throws ExtensionConfigurationPathDoesNotExistException
+	 * @throws IllegalObjectTypeException
 	 */
-	public function applyAction(JobApplication $applyData): ?ResponseInterface {
+	public function applyAction(JobApplication $applyData): ResponseInterface {
 		$folderName = $this->request->getArgument('folderName');
 		$enableApplicantMail = (bool) GeneralUtility::makeInstance(ExtensionConfiguration::class)
 			->get('sg_jobs', 'enableApplicantMail');
@@ -592,8 +587,8 @@ class JoblistController extends ActionController {
 			$this->moveTmpFolder($folderName, $applyData);
 			$this->createCsvSummary($applyData, $folderName);
 
-			/** @noinspection PhpParamsInspection */
-			$mailService = $this->objectManager->get(
+			/** @var MailTemplateService $mailService */
+			$mailService = GeneralUtility::makeInstance(
 				MailTemplateService::class,
 				'application_mail',
 				'sg_jobs',
@@ -605,8 +600,8 @@ class JoblistController extends ActionController {
 			$mailService->setPid($site->getRootPageId());
 
 			if ($enableApplicantMail) {
-				/** @noinspection PhpParamsInspection */
-				$applicantMailService = $this->objectManager->get(
+				/** @var MailTemplateService $applicantMailService */
+				$applicantMailService = GeneralUtility::makeInstance(
 					MailTemplateService::class,
 					'applicant_mail',
 					'sg_jobs',
@@ -671,36 +666,26 @@ class JoblistController extends ActionController {
 
 			$redirectPageUid = (int) $this->settings['redirectPage'];
 			if ($redirectPageUid) {
-				$contentObject = $this->configurationManager->getContentObject();
+				$contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
 				if ($contentObject) {
-					$url = $contentObject->getTypoLink_URL($redirectPageUid);
+					$url = $contentObject->typoLink_URL(['params' => $redirectPageUid]);
 					$this->redirectToUri($url);
 				}
 			}
 
 			$this->redirect('applyForm');
 		} catch (\Exception $exception) {
-			if ($exception instanceof StopActionException) {
-				return NULL;
-			}
 			$this->deleteTmpFolder($folderName);
 			$job = $applyData->getJob();
-			$jobId = $job !== NULL ? $job->getUid() : NULL;
+			$jobId = $job?->getUid();
 			// remove application, since there was an exception (e.g. upload filetype mismatch @see: moveTmpFolder())
 			$this->jobApplicationRepository->remove($applyData);
-			$this->request->setArgument('folderName', $folderName);
-			$this->forward(
-				'applyForm',
-				NULL,
-				NULL,
+			$this->request = $this->request->withArgument('folderName', $folderName);
+			return (new ForwardResponse('applyForm'))->withArguments(
 				['applyData' => $applyData, 'error' => $exception->getMessage(), 'jobId' => $jobId]
 			);
 		}
 
-		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) {
-			return NULL;
-		}
-
 		return $this->htmlResponse();
 	}
 
@@ -831,6 +816,7 @@ class JoblistController extends ActionController {
 				if (!$usableFile) {
 					throw new \RuntimeException('File not found (' . $singleFilePostKey . ')!');
 				}
+
 				$usableFile = $storage->copyFile($usableFile, $newFolder, $newFilename);
 			} elseif (!$newFolder->hasFile($newFilename)) {
 				// when we reload, etc. this image might already be moved.
@@ -841,6 +827,7 @@ class JoblistController extends ActionController {
 				/** @noinspection PhpUnreachableStatementInspection */
 				$usableFile = $this->getFileInFolder($newFilename, $newFolder);
 			}
+
 			$fileReference = $this->fileAndFolderService->createFileReferenceFromFalFileObject($usableFile);
 
 			if ($singleFilePostKey === 'coverLetter') {
@@ -862,22 +849,12 @@ class JoblistController extends ActionController {
 	/**
 	 * Gets a file in a folder.
 	 *
-	 * (Backwards compatible with TYPO3 10, where the Folder did not have a getFile() method yet).
-	 *
 	 * @param string $fileName
 	 * @param Folder $folder
 	 * @return File|null
 	 */
 	protected function getFileInFolder(string $fileName, Folder $folder): ?File {
-		if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '>=')) {
-			return $folder->getFile($fileName);
-		}
-
-		if ($folder->getStorage()->hasFileInFolder($fileName, $folder)) {
-			return $folder->getStorage()->getFileInFolder($fileName, $folder);
-		}
-
-		return NULL;
+		return $folder->getFile($fileName);
 	}
 
 	/**
@@ -896,7 +873,7 @@ class JoblistController extends ActionController {
 	 */
 	protected function deleteTmpFolder(string $folderName): void {
 		/** @var ResourceFactory $resourceFactory */
-		$resourceFactory = $this->objectManager->get(ResourceFactory::class);
+		$resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
 		$storage = $resourceFactory->getStorageObject(1);
 		try {
 			$tempFolder = $storage->getFolder('/JobApplication/' . $folderName);
@@ -910,9 +887,8 @@ class JoblistController extends ActionController {
 	 * If for any reason something goes wrong, delete the tmp upload folder
 	 *
 	 * @return ResponseInterface
-	 * @throws NoSuchArgumentException
 	 */
-	public function errorAction() {
+	public function errorAction(): ResponseInterface {
 		if ($this->request->hasArgument('folderName')) {
 			$folderName = $this->request->getArgument('folderName');
 			$this->deleteTmpFolder($folderName);
@@ -920,16 +896,4 @@ class JoblistController extends ActionController {
 
 		return parent::errorAction();
 	}
-
-	/**
-	 * Build TYPO3 11 Response
-	 *
-	 * @param string|NULL $html
-	 * @return ResponseInterface
-	 */
-	protected function htmlResponse(string $html = NULL): ResponseInterface {
-		return $this->responseFactory->createResponse()
-			->withHeader('Content-Type', 'text/html; charset=utf-8')
-			->withBody($this->streamFactory->createStream($html ?? $this->view->render()));
-	}
 }
diff --git a/Classes/Domain/Model/Contact.php b/Classes/Domain/Model/Contact.php
index 065c5de305fb0f1b5eb6def3da718b52c4c5f4b1..60578858459042d913ea297dc8130829a55de65c 100644
--- a/Classes/Domain/Model/Contact.php
+++ b/Classes/Domain/Model/Contact.php
@@ -26,6 +26,7 @@
 
 namespace SGalinski\SgJobs\Domain\Model;
 
+use TYPO3\CMS\Extbase\Annotation\ORM\Lazy;
 use TYPO3\CMS\Extbase\Domain\Model\FileReference;
 use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
 use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy;
@@ -85,9 +86,9 @@ class Contact extends AbstractEntity {
 	protected $country = '';
 
 	/**
-	 * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
-	 * @var FileReference
-	 */
+  * @var FileReference
+  */
+	#[Lazy]
 	protected $image;
 
 	/**
diff --git a/Classes/Domain/Model/Job.php b/Classes/Domain/Model/Job.php
index 44e283b5365f2a54e49e53af4e1a0acbed02f10c..cb2976f8d6d73d9a2cba4946fb1bb4d38647f764 100644
--- a/Classes/Domain/Model/Job.php
+++ b/Classes/Domain/Model/Job.php
@@ -26,6 +26,8 @@
 
 namespace SGalinski\SgJobs\Domain\Model;
 
+use TYPO3\CMS\Extbase\Annotation\ORM\Lazy;
+use TYPO3\CMS\Extbase\Domain\Model\FileReference;
 use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
 use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy;
 use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
@@ -45,9 +47,9 @@ class Job extends AbstractEntity {
 	protected $jobId = '';
 
 	/**
-	 * @var ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference>
-	 * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
+	 * @var ObjectStorage<FileReference>
 	 */
+	#[Lazy]
 	protected $attachment;
 
 	/**
@@ -103,20 +105,20 @@ class Job extends AbstractEntity {
 
 	/**
 	 * @var ObjectStorage<Company>
-	 * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
 	 */
+	#[Lazy]
 	protected $company;
 
 	/**
-	 * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
 	 * @var ObjectStorage<Job>
 	 */
+	#[Lazy]
 	protected $relatedJobs;
 
 	/**
-	 * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
 	 * @var ObjectStorage<ExperienceLevel>
 	 */
+	#[Lazy]
 	protected $experienceLevel;
 
 	/**
@@ -186,9 +188,14 @@ class Job extends AbstractEntity {
 	 * Job constructor.
 	 */
 	public function __construct() {
+		$this->initializeObject();
+	}
+
+	public function initializeObject() {
 		$this->attachment = new ObjectStorage();
 		$this->company = new ObjectStorage();
 		$this->relatedJobs = new ObjectStorage();
+		$this->experienceLevel = new ObjectStorage();
 	}
 
 	/**
@@ -596,7 +603,6 @@ class Job extends AbstractEntity {
 		$this->experienceLevel = $experienceLevel;
 	}
 
-
 	/**
 	 * @param ExperienceLevel $experienceLevel
 	 * @return void
diff --git a/Classes/Domain/Model/JobApplication.php b/Classes/Domain/Model/JobApplication.php
index d2274f61b901ee71e99c14f2e457379e7d4f8609..afbf630c17a4663cd0afe8f52dbdb7d3130afeb1 100644
--- a/Classes/Domain/Model/JobApplication.php
+++ b/Classes/Domain/Model/JobApplication.php
@@ -26,6 +26,9 @@
 
 namespace SGalinski\SgJobs\Domain\Model;
 
+use TYPO3\CMS\Extbase\Annotation\ORM\Lazy;
+use TYPO3\CMS\Extbase\Annotation\Validate;
+use TYPO3\CMS\Extbase\Domain\Model\FileReference;
 use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
 use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy;
 use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
@@ -48,9 +51,9 @@ class JobApplication extends AbstractEntity {
 
 	/**
 	 * @var ObjectStorage<Company>
-	 * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
 	 */
-	protected $company = '';
+	#[Lazy]
+	protected $company;
 
 	/**
 	 * @var Job $job
@@ -59,68 +62,68 @@ class JobApplication extends AbstractEntity {
 
 	/**
 	 * @var string $gender
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
 	protected $gender = '';
 
 	/**
 	 * @var string $firstName
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
 	protected $firstName = '';
 
 	/**
 	 * @var string $lastName
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
 	protected $lastName = '';
 
 	/**
 	 * @var string $street
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
 	protected $street = '';
 
 	/**
 	 * @var string $city
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
 	protected $city = '';
 
 	/**
 	 * @var string $zip
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
 	protected $zip = '';
 
 	/**
 	 * @var string $country
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
 	protected $country = '';
 
 	/**
 	 * @var string $nationality
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
 	protected $nationality = '';
 
 	/**
 	 * @var string $education
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
 	protected $education = '';
 
 	/**
 	 * @var string $birthDate
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
 	protected $birthDate = '';
 
 	/**
 	 * @var string $phone
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
 	protected $phone = '';
 
 	/**
@@ -130,23 +133,23 @@ class JobApplication extends AbstractEntity {
 
 	/**
 	 * @var string $email
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("NotEmpty")
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("EmailAddress")
 	 */
+	#[Validate(['validator' => 'NotEmpty'])]
+	#[Validate(['validator' => 'EmailAddress'])]
 	protected $email = '';
 
 	/**
-	 * @var \TYPO3\CMS\Extbase\Domain\Model\FileReference $coverLetter
+	 * @var FileReference $coverLetter
 	 */
 	protected $coverLetter;
 
 	/**
-	 * @var \TYPO3\CMS\Extbase\Domain\Model\FileReference $cv
+	 * @var FileReference $cv
 	 */
 	protected $cv;
 
 	/**
-	 * @var \TYPO3\CMS\Extbase\Domain\Model\FileReference $certificate
+	 * @var FileReference $certificate
 	 */
 	protected $certificate;
 
@@ -157,8 +160,8 @@ class JobApplication extends AbstractEntity {
 
 	/**
 	 * @var bool
-	 * @TYPO3\CMS\Extbase\Annotation\Validate("Boolean", options={"is": TRUE})
 	 */
+	#[Validate(['validator' => 'Boolean', 'options' => ['is' => TRUE]])]
 	protected $privacyPolicy = FALSE;
 
 	/**
@@ -390,44 +393,44 @@ class JobApplication extends AbstractEntity {
 	}
 
 	/**
-	 * @return \TYPO3\CMS\Extbase\Domain\Model\FileReference
+	 * @return FileReference
 	 */
 	public function getCoverLetter() {
 		return $this->coverLetter;
 	}
 
 	/**
-	 * @param \TYPO3\CMS\Extbase\Domain\Model\FileReference $coverLetter
+	 * @param FileReference $coverLetter
 	 */
-	public function setCoverLetter(\TYPO3\CMS\Extbase\Domain\Model\FileReference $coverLetter = NULL) {
+	public function setCoverLetter(FileReference $coverLetter = NULL) {
 		$this->coverLetter = $coverLetter;
 	}
 
 	/**
-	 * @return \TYPO3\CMS\Extbase\Domain\Model\FileReference
+	 * @return FileReference
 	 */
 	public function getCv() {
 		return $this->cv;
 	}
 
 	/**
-	 * @param \TYPO3\CMS\Extbase\Domain\Model\FileReference $cv
+	 * @param FileReference $cv
 	 */
-	public function setCV(\TYPO3\CMS\Extbase\Domain\Model\FileReference $cv = NULL) {
+	public function setCV(FileReference $cv = NULL) {
 		$this->cv = $cv;
 	}
 
 	/**
-	 * @return \TYPO3\CMS\Extbase\Domain\Model\FileReference
+	 * @return FileReference
 	 */
 	public function getCertificate() {
 		return $this->certificate;
 	}
 
 	/**
-	 * @param \TYPO3\CMS\Extbase\Domain\Model\FileReference $certificate
+	 * @param FileReference $certificate
 	 */
-	public function setCertificate(\TYPO3\CMS\Extbase\Domain\Model\FileReference $certificate = NULL) {
+	public function setCertificate(FileReference $certificate = NULL) {
 		$this->certificate = $certificate;
 	}
 
diff --git a/Classes/Domain/Repository/CompanyRepository.php b/Classes/Domain/Repository/CompanyRepository.php
index 0d5b8fc90e63bf6b42432513518ce01ebbd34f41..e57dc2f987b958e7b095f87905c3167a4d0fb42d 100644
--- a/Classes/Domain/Repository/CompanyRepository.php
+++ b/Classes/Domain/Repository/CompanyRepository.php
@@ -129,13 +129,14 @@ class CompanyRepository extends Repository {
 		foreach ($pageUids as $pageUid) {
 			$hash .= $pageUid . '_' . implode('-', $filters);
 		}
+
 		if (!isset($this->cache[$hash])) {
 			$companyConstraints = [];
 			$query = $this->createQuery();
 			$querySettings = $query->getQuerySettings();
 			$querySettings->setStoragePageIds($pageUids);
-			$querySettings->setLanguageUid(
-				GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'id', 0)
+			$querySettings->setLanguageAspect(
+				GeneralUtility::makeInstance(Context::class)->getAspect('language')
 			);
 			$query->setQuerySettings($querySettings);
 
@@ -151,10 +152,11 @@ class CompanyRepository extends Repository {
 				foreach ($filters as $filter) {
 					$constraints[] = $query->equals('uid', $filter);
 				}
-				$companyConstraints[] = $query->logicalOr($constraints);
+
+				$companyConstraints[] = $query->logicalOr(...$constraints);
 			}
 
-			$query->matching($query->logicalAnd($companyConstraints));
+			$query->matching($query->logicalAnd(...$companyConstraints));
 			$this->cache[$hash] = $query->execute();
 		}
 
diff --git a/Classes/Domain/Repository/DepartmentRepository.php b/Classes/Domain/Repository/DepartmentRepository.php
index d1d2e2ae806b499b299e359de4d478347b51e43f..9ecce30bb6b3bbe5861c77eae066fe8ad51f3f02 100644
--- a/Classes/Domain/Repository/DepartmentRepository.php
+++ b/Classes/Domain/Repository/DepartmentRepository.php
@@ -37,9 +37,6 @@ use TYPO3\CMS\Extbase\Persistence\Repository;
  * @author Kevin Ditscheid <kevin.ditscheid@sgalinski.de>
  */
 class DepartmentRepository extends Repository {
-	/**
-	 * @var array
-	 */
 	protected $defaultOrderings = [
 		'sorting' => QueryInterface::ORDER_ASCENDING,
 		'title' => QueryInterface::ORDER_ASCENDING
@@ -62,7 +59,7 @@ class DepartmentRepository extends Repository {
 			$constraints[] = $query->equals('uid', $filter);
 		}
 
-		$query->matching($query->logicalOr($constraints));
+		$query->matching($query->logicalOr(...$constraints));
 		return $query->execute();
 	}
 }
diff --git a/Classes/Domain/Repository/ExperienceLevelRepository.php b/Classes/Domain/Repository/ExperienceLevelRepository.php
index 3fe083a2009d7ea2b72264b4f6a7454c4ce63557..4ba16c0d8a8acf132ffdeffd880f244ff8ce5e75 100644
--- a/Classes/Domain/Repository/ExperienceLevelRepository.php
+++ b/Classes/Domain/Repository/ExperienceLevelRepository.php
@@ -37,9 +37,6 @@ use TYPO3\CMS\Extbase\Persistence\Repository;
  * @author Johannes Kreiner <jkreiner@sgalinski.de>
  */
 class ExperienceLevelRepository extends Repository {
-	/**
-	 * @var array
-	 */
 	protected $defaultOrderings = [
 		'sorting' => QueryInterface::ORDER_ASCENDING,
 		'title' => QueryInterface::ORDER_ASCENDING
@@ -62,7 +59,7 @@ class ExperienceLevelRepository extends Repository {
 			$constraints[] = $query->equals('uid', $filter);
 		}
 
-		$query->matching($query->logicalOr($constraints));
+		$query->matching($query->logicalOr(...$constraints));
 		return $query->execute();
 	}
 }
diff --git a/Classes/Domain/Repository/JobRepository.php b/Classes/Domain/Repository/JobRepository.php
index 8012f4fd730ab820f249c37bdc14022732275078..7c1acccd61c05aa7779c7220986252e90ea503f9 100644
--- a/Classes/Domain/Repository/JobRepository.php
+++ b/Classes/Domain/Repository/JobRepository.php
@@ -27,12 +27,8 @@
 namespace SGalinski\SgJobs\Domain\Repository;
 
 use SGalinski\SgJobs\Domain\Model\Job;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
-use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
-use TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException;
-use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
-use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
+use TYPO3\CMS\Core\Context\LanguageAspect;
+use TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException;
 use TYPO3\CMS\Extbase\Persistence\QueryInterface;
 use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
 use TYPO3\CMS\Extbase\Persistence\QueryResultInterface as ExtbaseQueryResultInterface;
@@ -54,7 +50,7 @@ class JobRepository extends Repository {
 	 * @param int $limit
 	 * @param int $offset
 	 * @return ExtbaseQueryResultInterface|object[]
-	 * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
+	 * @throws InvalidQueryException
 	 */
 	public function findBackendJobs(int $recordPageId, array $filters = [], int $limit = 0, int $offset = 0) {
 		$query = $this->createQuery();
@@ -87,7 +83,7 @@ class JobRepository extends Repository {
 		}
 
 		if (\count($constraints) > 1) {
-			return $query->matching($query->logicalAnd($constraints))->execute();
+			return $query->matching($query->logicalAnd(...$constraints))->execute();
 		}
 
 		if (\count($constraints) > 0) {
@@ -121,6 +117,7 @@ class JobRepository extends Repository {
 			// if no record storage page has been selected in the plugin, ignore it
 			$querySettings->setRespectStoragePage(FALSE);
 		}
+
 		$this->setDefaultQuerySettings($querySettings);
 
 		$constraints = [];
@@ -132,13 +129,14 @@ class JobRepository extends Repository {
 					$companyConstraints[] = $query->equals('uid', $jobId);
 				}
 			}
+
 			if (\count($companyConstraints)) {
-				$constraints[] = $query->logicalOr($companyConstraints);
+				$constraints[] = $query->logicalOr(...$companyConstraints);
 			}
 		}
 
 		if (\count($constraints)) {
-			$query->matching($query->logicalAnd($constraints));
+			$query->matching($query->logicalAnd(...$constraints));
 		}
 
 		if ($limit > 0) {
@@ -159,6 +157,7 @@ class JobRepository extends Repository {
 	 * @param int $limit
 	 * @param int $offset
 	 * @param int $ordering
+	 * @param array $explicitFilters
 	 * @return ExtbaseQueryResultInterface
 	 */
 	public function findJobsByFilter(
@@ -173,11 +172,16 @@ class JobRepository extends Repository {
 
 		// we always want to show all jobs if the strict mode is used (translated or
 		// created in the specific language w/o default)
-		$querySettings = $query->getQuerySettings();
-		if ($querySettings->getLanguageOverlayMode() === 'hideNonTranslated') {
-			$querySettings->setLanguageOverlayMode(FALSE);
+		$languageAspect = $query->getQuerySettings()->getLanguageAspect();
+		if ($languageAspect->getOverlayType() === LanguageAspect::OVERLAYS_ON) {
+			$newLanguageAspect = new LanguageAspect(
+				$languageAspect->getId(),
+				$languageAspect->getContentId(),
+				LanguageAspect::OVERLAYS_OFF,
+				$languageAspect->getFallbackChain()
+			);
+			$query->getQuerySettings()->setLanguageAspect($newLanguageAspect);
 		}
-		$query->setQuerySettings($querySettings);
 
 		if (empty($storagePageIds)) {
 			// if no record storage page has been selected in the plugin, ignore it
@@ -214,10 +218,10 @@ class JobRepository extends Repository {
 		}
 
 		if (isset($filters['filterRemote']) && $filters['filterRemote'] !== '') {
-			$constraints[] = $query->logicalAnd([
+			$constraints[] = $query->logicalAnd(
 				$query->equals('telecommutePossible', TRUE),
 				$query->equals('office_work_possible', FALSE)
-			]);
+			);
 		}
 
 		if (isset($filters['filterLocation']) && $filters['filterLocation'] !== '0') {
@@ -229,8 +233,9 @@ class JobRepository extends Repository {
 			foreach ($filters['filterByLocation'] as $companyFilter) {
 				$companyConstraints[] = $query->equals('company.uid', $companyFilter);
 			}
+
 			if (\count($companyConstraints) > 0) {
-				$constraints[] = $query->logicalOr($companyConstraints);
+				$constraints[] = $query->logicalOr(...$companyConstraints);
 			}
 		}
 
@@ -241,8 +246,9 @@ class JobRepository extends Repository {
 			foreach ($filters['filterByDepartment'] as $departmentFilter) {
 				$departmentConstraints[] = $query->equals('department', $departmentFilter);
 			}
+
 			if (\count($departmentConstraints) > 0) {
-				$constraints[] = $query->logicalOr($departmentConstraints);
+				$constraints[] = $query->logicalOr(...$departmentConstraints);
 			}
 		}
 
@@ -253,13 +259,14 @@ class JobRepository extends Repository {
 			foreach ($filters['filterByExperienceLevel'] as $experienceFilter) {
 				$experienceConstraints[] = $query->equals('experienceLevel', $experienceFilter);
 			}
+
 			if (\count($experienceConstraints) > 0) {
-				$constraints[] = $query->logicalOr($experienceConstraints);
+				$constraints[] = $query->logicalOr(...$experienceConstraints);
 			}
 		}
 
 		if (\count($constraints)) {
-			$query->matching($query->logicalAnd($constraints));
+			$query->matching($query->logicalAnd(...$constraints));
 		}
 
 		if ($limit > 0) {
@@ -331,6 +338,7 @@ class JobRepository extends Repository {
 			// if no record storage page has been selected in the plugin, ignore it
 			$query->getQuerySettings()->setRespectStoragePage(FALSE);
 		}
+
 		$company = $job->getCompany();
 		$department = $job->getDepartment();
 
@@ -356,7 +364,7 @@ class JobRepository extends Repository {
 		}
 
 		if (\count($constraints)) {
-			$query->matching($query->logicalAnd($constraints));
+			$query->matching($query->logicalAnd(...$constraints));
 		}
 
 		return $query;
@@ -379,7 +387,7 @@ class JobRepository extends Repository {
 
 		if (count($filters) > 0) {
 			$constraints = $this->getFilterConstraints($query, $filters);
-			$query->matching($query->logicalAnd($constraints));
+			$query->matching($query->logicalAnd(...$constraints));
 		}
 
 		return $query->execute()->count();
@@ -403,7 +411,7 @@ class JobRepository extends Repository {
 
 		if (count($filters) > 0) {
 			$constraints = $this->getFilterConstraints($query, $filters);
-			$query->matching($query->logicalAnd($constraints));
+			$query->matching($query->logicalAnd(...$constraints));
 		}
 
 		$query->setOrderings(['featured_offer' => QueryInterface::ORDER_DESCENDING]);
@@ -426,6 +434,7 @@ class JobRepository extends Repository {
 			foreach ($filters['filterByLocation'] as $companyFilter) {
 				$companyConstraints[] = $query->equals('company.uid', $companyFilter);
 			}
+
 			if (\count($companyConstraints) > 0) {
 				$constraints[] = $query->logicalOr($companyConstraints);
 			}
@@ -436,6 +445,7 @@ class JobRepository extends Repository {
 			foreach ($filters['filterByDepartment'] as $departmentFilter) {
 				$departmentConstraints[] = $query->equals('department', $departmentFilter);
 			}
+
 			if (\count($departmentConstraints) > 0) {
 				$constraints[] = $query->logicalOr($departmentConstraints);
 			}
@@ -446,6 +456,7 @@ class JobRepository extends Repository {
 			foreach ($filters['filterByExperienceLevel'] as $experienceFilter) {
 				$experienceConstraints[] = $query->equals('experienceLevel', $experienceFilter);
 			}
+
 			if (\count($experienceConstraints) > 0) {
 				$constraints[] = $query->logicalOr($experienceConstraints);
 			}
diff --git a/Classes/Event/Listener/AccessPageListEventListener.php b/Classes/Event/Listener/AccessPageListEventListener.php
index 0cddb17ea17b20eca28f76da40aa15f28e0d1a99..e14d24fd1d809ffc1cd871786d8f87b35751d389 100644
--- a/Classes/Event/Listener/AccessPageListEventListener.php
+++ b/Classes/Event/Listener/AccessPageListEventListener.php
@@ -28,6 +28,7 @@ namespace SGalinski\SgJobs\Event\Listener;
 
 use SGalinski\SgJobs\Service\SitemapService;
 use SGalinski\SgSeo\Events\AccessPageListEvent;
+use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
 
 /**
@@ -52,6 +53,7 @@ class AccessPageListEventListener {
 
 	/**
 	 * @param AccessPageListEvent $event
+	 * @throws AspectNotFoundException
 	 */
 	public function __invoke(AccessPageListEvent $event) {
 		$pageList = $event->getPageList();
diff --git a/Classes/EventListeners/PageContentPreviewRenderingEventListener.php b/Classes/EventListeners/PageContentPreviewRenderingEventListener.php
new file mode 100644
index 0000000000000000000000000000000000000000..eab6758bc41a8cfc0616cd66666b950d27db5045
--- /dev/null
+++ b/Classes/EventListeners/PageContentPreviewRenderingEventListener.php
@@ -0,0 +1,60 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) sgalinski Internet Services (https://www.sgalinski.de)
+ *
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+namespace SGalinski\SgJobs\EventListeners;
+
+use SGalinski\SgJobs\Preview\PreviewService;
+use TYPO3\CMS\Backend\View\Event\PageContentPreviewRenderingEvent;
+
+class PageContentPreviewRenderingEventListener {
+	protected PreviewService $previewService;
+
+	public function __construct(PreviewService $previewService) {
+		$this->previewService = $previewService;
+	}
+
+	public function __invoke(PageContentPreviewRenderingEvent $event): void {
+		if ($event->getTable() === 'tt_content') {
+			$record = $event->getRecord();
+			switch ($record['list_type']) {
+				case 'sgjobs_jobapplication':
+					$event->setPreviewContent(
+						$this->previewService->getApplicationView($record)->render('JobApplication')
+					);
+					break;
+				case 'sgjobs_joblist':
+					$event->setPreviewContent(
+						$this->previewService->getJoblistView($record)->render('Joblist')
+					);
+					break;
+				case 'sgjobs_jobteaser':
+					$event->setPreviewContent(
+						$this->previewService->getTeaserView($record)->render('JobTeaser')
+					);
+					break;
+			}
+		}
+	}
+}
diff --git a/Classes/Hooks/PageLayoutView/PluginRenderer.php b/Classes/Hooks/PageLayoutView/PluginRenderer.php
deleted file mode 100644
index 95186eb4fc07f10bec5078f15efbf4c00c7d3229..0000000000000000000000000000000000000000
--- a/Classes/Hooks/PageLayoutView/PluginRenderer.php
+++ /dev/null
@@ -1,122 +0,0 @@
-<?php
-
-/***************************************************************
- *  Copyright notice
- *  (c) sgalinski Internet Services (https://www.sgalinski.de)
- *  All rights reserved
- *  This script is part of the TYPO3 project. The TYPO3 project is
- *  free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *  The GNU General Public License can be found at
- *  http://www.gnu.org/copyleft/gpl.html.
- *  This script is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *  This copyright notice MUST APPEAR in all copies of the script!
- ***************************************************************/
-
-namespace SGalinski\SgJobs\Hooks\PageLayoutView;
-
-use SGalinski\SgJobs\Preview\PreviewService;
-use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Backend\View\PageLayoutView;
-use TYPO3\CMS\Core\Localization\LanguageService;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-
-/**
- * Class PluginRenderer - Renders backend previews for plugins.
- *
- * @package SGalinski\SgJobs\Hooks\PageLayoutView
- */
-class PluginRenderer implements \TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface {
-	/**
-	 * @var PreviewService $previewService
-	 */
-	protected $previewService;
-
-	public function init() {
-		$this->previewService = GeneralUtility::makeInstance(PreviewService::class);
-	}
-
-	/**
-	 * @inheritDoc
-	 * @noinspection ReferencingObjectsInspection
-	 */
-	public function preProcess(
-		PageLayoutView &$parentObject,
-		&$drawItem,
-		&$headerContent,
-		&$itemContent,
-		array &$row
-	): void {
-		$this->init();
-		switch ($row['list_type']) {
-			case 'sgjobs_jobapplication':
-				$drawItem = FALSE;
-				$this->adaptPluginHeaderContent($headerContent, $row);
-
-				$view = $this->previewService->getApplicationView($row);
-				$itemContent .= $view->render();
-				break;
-
-			case 'sgjobs_joblist':
-				$drawItem = FALSE;
-				$this->adaptPluginHeaderContent($headerContent, $row);
-
-				$view = $this->previewService->getJoblistView($row);
-
-				$itemContent .= $view->render();
-				break;
-
-			case 'sgjobs_jobteaser':
-				$drawItem = FALSE;
-				$this->adaptPluginHeaderContent($headerContent, $row);
-
-				$view = $this->previewService->getTeaserView($row);
-				$itemContent .= $view->render();
-				break;
-
-			default:
-				// No need to do anything
-		}
-	}
-
-	/**
-	 * Adapts the given $headerContent.
-	 * To be used in all plugin previews so the Header Contents appear similarly.
-	 *
-	 * @param string $headerContent
-	 * @param array $row
-	 */
-	protected function adaptPluginHeaderContent(&$headerContent, $row): void {
-		$headerContent = '<h4>' . $this->getPluginNameForHeaderContent(
-			(int) $row['pid'],
-			$row['list_type']
-		) . $headerContent . '</h4>';
-	}
-
-	/**
-	 * Finds the label of the given $listType element on the page with the given $pid
-	 * and returns it wrapped for use in the backend preview's header content.
-	 *
-	 * @param int $pid
-	 * @param string $listType
-	 * @return string
-	 */
-	protected function getPluginNameForHeaderContent(int $pid, string $listType): string {
-		$languageService = GeneralUtility::makeInstance(LanguageService::class);
-
-		$pluginName = $languageService->sL(
-			BackendUtility::getLabelFromItemListMerged(
-				$pid,
-				'tt_content',
-				'list_type',
-				$listType
-			)
-		);
-		return '<span class="label label-primary">' . $pluginName . '</span>&nbsp;';
-	}
-}
diff --git a/Classes/Pagination/Pagination.php b/Classes/Pagination/Pagination.php
index a53d3bda51093f9ff0c31c1e8f5628067421aaba..07e191d7e6019774ebf652e0f7653344c07614d4 100644
--- a/Classes/Pagination/Pagination.php
+++ b/Classes/Pagination/Pagination.php
@@ -100,8 +100,6 @@ class Pagination {
 	 * Reconfigure the query builder to fetch the total count of items
 	 *
 	 * @return int
-	 * @throws \Doctrine\DBAL\DBALException
-	 * @throws \Doctrine\DBAL\Driver\Exception
 	 */
 	private function fetchTotalItemCount(): int {
 		$query = clone $this->queryResult->getQuery();
@@ -113,8 +111,6 @@ class Pagination {
 	 * Reconfigure the queryResult to fetch the items for the configured currentPage
 	 *
 	 * @return array
-	 * @throws \Doctrine\DBAL\DBALException
-	 * @throws \Doctrine\DBAL\Driver\Exception
 	 */
 	private function fetchItems(): array {
 		$query = clone $this->queryResult->getQuery();
diff --git a/Classes/Preview/PreviewRenderer.php b/Classes/Preview/PreviewRenderer.php
deleted file mode 100644
index 73c643c4290ad5fd0a19b8d2fa428bd158d5de06..0000000000000000000000000000000000000000
--- a/Classes/Preview/PreviewRenderer.php
+++ /dev/null
@@ -1,110 +0,0 @@
-<?php
-
-/***************************************************************
- *  Copyright notice
- *  (c) sgalinski Internet Services (https://www.sgalinski.de)
- *  All rights reserved
- *  This script is part of the TYPO3 project. The TYPO3 project is
- *  free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *  The GNU General Public License can be found at
- *  http://www.gnu.org/copyleft/gpl.html.
- *  This script is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *  This copyright notice MUST APPEAR in all copies of the script!
- ***************************************************************/
-
-namespace SGalinski\SgJobs\Preview;
-
-use TYPO3\CMS\Backend\Preview\PreviewRendererInterface;
-use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem;
-use TYPO3\CMS\Core\Localization\LanguageService;
-
-/**
- *
- */
-class PreviewRenderer implements PreviewRendererInterface {
-	/**
-	 * @var LanguageService $languageService
-	 */
-	protected $languageService;
-
-	/**
-	 * @var PreviewService $previewService
-	 */
-	protected $previewService;
-
-	public function __construct(LanguageService $languageService, PreviewService $previewService) {
-		$this->languageService = $languageService;
-		$this->previewService = $previewService;
-	}
-
-	/**
-	 * Dedicated method for rendering preview header HTML for
-	 * the page module only. Receives $item which is an instance of
-	 * GridColumnItem which has a getter method to return the record.
-	 *
-	 * @param GridColumnItem $item
-	 * @return string
-	 */
-	public function renderPageModulePreviewHeader(GridColumnItem $item): string {
-		// @todo: when v12 hits, add header from PluginRenderer
-		return '';
-	}
-
-	/**
-	 * Dedicated method for rendering preview body HTML for
-	 * the page module only.
-	 *
-	 * @param GridColumnItem $item
-	 * @return string
-	 */
-	public function renderPageModulePreviewContent(GridColumnItem $item): string {
-		$row = $item->getRecord();
-		switch ($row['list_type']) {
-			case 'sgjobs_jobapplication':
-				$view = $this->previewService->getApplicationView($row);
-				return $view->render();
-
-			case 'sgjobs_joblist':
-				$view = $this->previewService->getJoblistView($row);
-				return $view->render();
-
-			case 'sgjobs_jobteaser':
-				$view = $this->previewService->getTeaserView($row);
-				return $view->render();
-
-			default:
-				// No need to do anything
-		}
-
-		return '';
-	}
-
-	/**
-	 * Render a footer for the record to display in page module below
-	 * the body of the item's preview.
-	 *
-	 * @param GridColumnItem $item
-	 * @return string
-	 */
-	public function renderPageModulePreviewFooter(GridColumnItem $item): string {
-		return '';
-	}
-
-	/**
-	 * Dedicated method for wrapping a preview header and body HTML.
-	 *
-	 * @param string $previewHeader
-	 * @param string $previewContent
-	 * @param GridColumnItem $item
-	 * @return string
-	 */
-	public function wrapPageModulePreview(string $previewHeader, string $previewContent, GridColumnItem $item): string {
-		return $previewHeader . $previewContent;
-	}
-}
diff --git a/Classes/Preview/PreviewService.php b/Classes/Preview/PreviewService.php
index 9d3371fb1d68075019d33ea46535b95ccb09a521..70b8ac457cb0e8487b3173523e522c52e521e8b6 100644
--- a/Classes/Preview/PreviewService.php
+++ b/Classes/Preview/PreviewService.php
@@ -43,7 +43,7 @@ class PreviewService {
 	 * @return StandaloneView
 	 */
 	public function getApplicationView(array $row): StandaloneView {
-		$view = $this->createViewWithTemplate('JobApplication');
+		$view = $this->createView();
 		$view->assign('uid', $row['uid']);
 
 		// Get available plugin settings and their values from flexform
@@ -62,6 +62,13 @@ class PreviewService {
 		];
 
 		$view->assign('data', $templateData);
+		$view->assign('headerLabel', BackendUtility::getLabelFromItemListMerged(
+			$row['pid'],
+			'tt_content',
+			'list_type',
+			$row['list_type'],
+			$row
+		));
 		return $view;
 	}
 
@@ -72,7 +79,7 @@ class PreviewService {
 	 * @return StandaloneView
 	 */
 	public function getJoblistView(array $row): StandaloneView {
-		$view = $this->createViewWithTemplate('Joblist');
+		$view = $this->createView();
 		$view->assign('uid', $row['uid']);
 
 		// Get available plugin settings and their values from flexform
@@ -113,11 +120,18 @@ class PreviewService {
 			) : ''
 		);
 		$view->assign('recursive', $row['recursive']);
+		$view->assign('headerLabel', BackendUtility::getLabelFromItemListMerged(
+			$row['pid'],
+			'tt_content',
+			'list_type',
+			$row['list_type'],
+			$row
+		));
 		return $view;
 	}
 
 	public function getTeaserView(array $row): StandaloneView {
-		$view = $this->createViewWithTemplate('JobTeaser');
+		$view = $this->createView();
 		$view->assign('uid', $row['uid']);
 
 		// Get available plugin settings and their values from flexform
@@ -146,6 +160,13 @@ class PreviewService {
 		];
 
 		$view->assign('data', $templateData);
+		$view->assign('headerLabel', BackendUtility::getLabelFromItemListMerged(
+			$row['pid'],
+			'tt_content',
+			'list_type',
+			$row['list_type'],
+			$row
+		));
 		return $view;
 	}
 
@@ -172,18 +193,13 @@ class PreviewService {
 	 * Creates a new StandaloneView object with template and partial root paths,
 	 * attaches the template with the given name to it and returns it.
 	 *
-	 * @param string $templateName
 	 * @return StandaloneView
 	 */
-	protected function createViewWithTemplate(string $templateName): StandaloneView {
+	protected function createView(): StandaloneView {
 		$view = GeneralUtility::makeInstance(StandaloneView::class);
 		$view->setTemplateRootPaths(['EXT:sg_jobs/Resources/Private/Backend/Templates/']);
 		$view->setPartialRootPaths(['EXT:sg_jobs/Resources/Private/Backend/Partials/']);
 		$view->setLayoutRootPaths(['EXT:sg_jobs/Resources/Private/Backend/Layouts/']);
-		if (!str_ends_with($templateName, '.html')) {
-			$templateName .= '.html';
-		}
-		$view->setTemplate($templateName);
 		return $view;
 	}
 
@@ -214,6 +230,7 @@ class PreviewService {
 
 			$recordsWithTitlesArray[] = $record[$field] . ' [' . $recordId . ']';
 		}
+
 		return implode(', ', $recordsWithTitlesArray);
 	}
 }
diff --git a/Classes/Service/BackendService.php b/Classes/Service/BackendService.php
index 26d4f3cdf18e4020f77ccaa2fd4dd95d27b14775..3fa90cd45908f02a94f0e29db526781329754234 100644
--- a/Classes/Service/BackendService.php
+++ b/Classes/Service/BackendService.php
@@ -26,6 +26,7 @@
 
 namespace SGalinski\SgJobs\Service;
 
+use Doctrine\DBAL\Exception;
 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
 use TYPO3\CMS\Backend\Template\Components\DocHeaderComponent;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
@@ -45,17 +46,22 @@ class BackendService {
 	 * Get all pages the be user has access to
 	 *
 	 * @return array
-	 * @throws \InvalidArgumentException
+	 * @throws Exception
 	 */
 	public static function getPages(): array {
 		$out = [];
-		$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
-		$queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+		$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+			->getQueryBuilderForTable('pages');
+		$queryBuilder->getRestrictions()->removeAll()
+			->add(GeneralUtility::makeInstance(DeletedRestriction::class));
 		$rows = $queryBuilder->select('*')
 			->from('pages')
 			->where(
-				$queryBuilder->expr()->eq('is_siteroot', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
-			)->execute()->fetchAll();
+				$queryBuilder->expr()->eq(
+					'is_siteroot',
+					$queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)
+				)
+			)->executeQuery()->fetchAllAssociative();
 
 		foreach ($rows as $row) {
 			$pageInfo = BackendUtility::readPageAccess($row['uid'], $GLOBALS['BE_USER']->getPagePermsClause(1));
@@ -66,10 +72,12 @@ class BackendService {
 				foreach ($rootline as $page) {
 					$path .= '/p' . dechex($page['uid']);
 				}
+
 				$pageInfo['path'] = $path;
 				$out[] = $pageInfo;
 			}
 		}
+
 		return $out;
 	}
 
@@ -82,7 +90,6 @@ class BackendService {
 	 * @throws \UnexpectedValueException
 	 */
 	public static function makeButtons($docHeaderComponent, $request): void {
-		/** @var ButtonBar $buttonBar */
 		$buttonBar = $docHeaderComponent->getButtonBar();
 		/** @var IconFactory $iconFactory */
 		$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
@@ -101,24 +108,23 @@ class BackendService {
 
 		// shortcut button
 		$shortcutButton = $buttonBar->makeShortcutButton()
-			->setModuleName($request->getPluginName())
-			->setGetVariables(
+			->setDisplayName('Shortcut')
+			->setRouteIdentifier($request->getPluginName())
+			->setArguments(
 				[
-					'id',
-					'M'
+					'id' => [],
+					'M' => []
 				]
-			)
-			->setSetVariables([]);
+			);
 
 		$buttonBar->addButton($shortcutButton, ButtonBar::BUTTON_POSITION_RIGHT);
-		$docHeaderComponent->getButtonBar();
 	}
 
 	/**
 	 * Returns the uids of the pages with job records
 	 *
 	 * @return array
-	 * @throws \InvalidArgumentException
+	 * @throws Exception
 	 */
 	public static function getPagesWithJobRecords(): array {
 		$out = [];
@@ -129,7 +135,7 @@ class BackendService {
 		$rows = $queryBuilder->select('pid')
 			->from('tx_sgjobs_domain_model_job')
 			->groupBy('pid')
-			->execute()->fetchAll();
+			->executeQuery()->fetchAllAssociative();
 		foreach ($rows as $row) {
 			$pageInfo = BackendUtility::readPageAccess($row['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1));
 			if ($pageInfo) {
@@ -139,10 +145,12 @@ class BackendService {
 				foreach ($rootline as $page) {
 					$path .= '/p' . dechex($page['uid']);
 				}
+
 				$pageInfo['path'] = $path;
 				$out[] = $pageInfo;
 			}
 		}
+
 		return $out;
 	}
 }
diff --git a/Classes/Service/FileAndFolderService.php b/Classes/Service/FileAndFolderService.php
index b60db5d520ea2379821c46f567728d2156124bf7..834fde4b4a521cf62a59f4f26d76351d7085b214 100644
--- a/Classes/Service/FileAndFolderService.php
+++ b/Classes/Service/FileAndFolderService.php
@@ -28,6 +28,9 @@ namespace SGalinski\SgJobs\Service;
 
 use TYPO3\CMS\Core\Charset\CharsetConverter;
 use TYPO3\CMS\Core\Core\Environment;
+use TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException;
+use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException;
+use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException;
 use TYPO3\CMS\Core\Resource\File as FalFile;
 use TYPO3\CMS\Core\Resource\FileReference as FalFileReference;
 use TYPO3\CMS\Core\Resource\Folder;
@@ -39,28 +42,12 @@ use TYPO3\CMS\Core\SingletonInterface;
 use TYPO3\CMS\Core\Utility\File\BasicFileUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Domain\Model\FileReference;
-use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
 use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
 
 /**
  * Service for diverse file operations
  */
 class FileAndFolderService implements SingletonInterface {
-	/**
-	 *
-	 * @var ObjectManagerInterface
-	 */
-	protected $objectManager;
-
-	/**
-	 * Inject the ObjectManager
-	 *
-	 * @param ObjectManagerInterface $objectManager
-	 */
-	public function injectObjectManager(ObjectManagerInterface $objectManager) {
-		$this->objectManager = $objectManager;
-	}
-
 	/**
 	 *
 	 * @var BasicFileUtility
@@ -186,15 +173,13 @@ class FileAndFolderService implements SingletonInterface {
 	 * @param int $storageUid
 	 * @return Folder
 	 * @throws \InvalidArgumentException
-	 * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException
-	 * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
-	 * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException
+	 * @throws InsufficientFolderWritePermissionsException
+	 * @throws InsufficientFolderAccessPermissionsException
+	 * @throws ExistingTargetFolderException
 	 * @throws \Exception
 	 */
 	protected function createFolder($folderIdentifier, $storageUid): Folder {
-		/** @var ResourceStorage $storage */
-		$storage = $this->getStorage($storageUid);
-		return $storage->createFolder($folderIdentifier);
+		return $this->getStorage($storageUid)->createFolder($folderIdentifier);
 	}
 
 	/**
@@ -235,7 +220,7 @@ class FileAndFolderService implements SingletonInterface {
 					continue;
 				}
 
-				if ($fileTypes !== '' && \substr($fileTypes, -1) !== ',') {
+				if ($fileTypes !== '' && !str_ends_with($fileTypes, ',')) {
 					$fileTypes .= ',';
 				}
 
@@ -265,14 +250,13 @@ class FileAndFolderService implements SingletonInterface {
 	 *
 	 * @param string $folderIdentifier
 	 * @return Folder
-	 * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException
+	 * @throws InsufficientFolderWritePermissionsException
 	 * @throws \InvalidArgumentException
 	 * @throws \Exception
-	 * @throws \TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
-	 * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFolderException
+	 * @throws InsufficientFolderAccessPermissionsException
+	 * @throws ExistingTargetFolderException
 	 */
 	public function getFolder($folderIdentifier): Folder {
-		/** @var ResourceStorage $storage */
 		$storage = $this->getStorage();
 
 		if ($storage->hasFolder($folderIdentifier)) {
@@ -363,12 +347,11 @@ EOT;
 	): FileReference {
 		if ($resourcePointer === NULL) {
 			/** @var FileReference $fileReference */
-			$fileReference = $this->objectManager->get(FileReference::class);
+			$fileReference = GeneralUtility::makeInstance(FileReference::class);
 		} else {
 			$fileReference = $this->persistenceManager->getObjectByIdentifier(
 				$resourcePointer,
-				FileReference::class,
-				FALSE
+				FileReference::class
 			);
 		}
 
diff --git a/Classes/Service/SitemapService.php b/Classes/Service/SitemapService.php
index afd49f7a58687484b4acea9966cbb187a343974a..362627c1923ee707a704a875201447d4d04d0b3b 100644
--- a/Classes/Service/SitemapService.php
+++ b/Classes/Service/SitemapService.php
@@ -26,10 +26,13 @@
 
 namespace SGalinski\SgJobs\Service;
 
+use Doctrine\DBAL\Exception;
 use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Context\Exception\AspectNotFoundException;
 use TYPO3\CMS\Core\Context\LanguageAspect;
 use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Domain\Repository\PageRepository;
 use TYPO3\CMS\Core\Exception\SiteNotFoundException;
 use TYPO3\CMS\Core\Site\SiteFinder;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
@@ -52,7 +55,8 @@ class SitemapService {
 	 * @param int $sysLanguageUid
 	 * @param int $rootPageId
 	 * @return array
-	 * @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException
+	 * @throws Exception
+	 * @throws AspectNotFoundException
 	 */
 	public function generatePagesList(int $sysLanguageUid, int $rootPageId = 0): array {
 		$pageList = [];
@@ -69,13 +73,13 @@ class SitemapService {
 				AND pages.no_search = 0'
 			)
 			->where(
-				$queryBuilder->expr()->andX(
+				$queryBuilder->expr()->and(
 					$queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('list')),
 					$queryBuilder->expr()->eq(
 						'list_type',
 						$queryBuilder->createNamedParameter(self::PLUGIN_NAME)
 					),
-					$queryBuilder->expr()->orX(
+					$queryBuilder->expr()->or(
 						$queryBuilder->expr()->eq('tt_content.sys_language_uid', -1),
 						$queryBuilder->expr()->eq(
 							'tt_content.sys_language_uid',
@@ -84,15 +88,16 @@ class SitemapService {
 					)
 				)
 			)
-			->execute();
+			->executeQuery();
 
 		$context = GeneralUtility::makeInstance(Context::class);
-		while ($row = $databaseResource->fetch()) {
+		while ($row = $databaseResource->fetchAssociative()) {
 			try {
 				$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($row['pid']);
 				if ($rootPageId > 0 && $site->getRootPageId() !== $rootPageId) {
 					continue;
 				}
+
 				$jobs = $this->getJobsByPid($row['pages'], $sysLanguageUid);
 				foreach ($jobs as $job) {
 					$url = $site->getRouter($context)->generateUri(
@@ -114,6 +119,7 @@ class SitemapService {
 				// No site configuration for the page found
 			}
 		}
+
 		return $pageList;
 	}
 
@@ -123,6 +129,8 @@ class SitemapService {
 	 * @param string $pageList
 	 * @param int $sysLanguageUid
 	 * @return array|null
+	 * @throws AspectNotFoundException
+	 * @throws Exception
 	 */
 	private function getJobsByPid(string $pageList, int $sysLanguageUid): ?array {
 		$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
@@ -130,31 +138,32 @@ class SitemapService {
 		$databaseResource = $queryBuilder->select('*')
 			->from('tx_sgjobs_domain_model_job')
 			->where(
-				$queryBuilder->expr()->andX(
+				$queryBuilder->expr()->and(
 					$queryBuilder->expr()->in('pid', $queryBuilder->createNamedParameter($pageList)),
 					$queryBuilder->expr()->in('sys_language_uid', '-1,0')
 				)
 			)
-			->execute();
+			->executeQuery();
 
 		$visibleRows = [];
-		$rows = $databaseResource->fetchAll();
-		$pageRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Domain\Repository\PageRepository::class);
+		$rows = $databaseResource->fetchAllAssociative();
+		/** @var PageRepository $pageRepository */
+		$pageRepository = GeneralUtility::makeInstance(PageRepository::class);
 		$isLanguageVisibilityLoaded = ExtensionManagementUtility::isLoaded('languagevisibility');
 		$languageAspect = GeneralUtility::makeInstance(Context::class)->getAspect('language');
-		$overlayType = $languageAspect->getLegacyOverlayType();
+		$frontendServices = GeneralUtility::makeInstance(FrontendServices::class);
 		foreach ($rows as $row) {
 			$table = 'tx_sgjobs_domain_model_job';
 
 			// get languagevisibility uid that is available (check for the correct uid to fall back to)
 			if ($isLanguageVisibilityLoaded) {
 				try {
-					$element = FrontendServices::getElement($row, $table);
+					$element = $frontendServices->getElement($row, $table);
 				} catch (TableNotSupportedException $exception) {
 					continue;
 				}
 
-				$languageId = FrontendServices::getOverlayLanguageIdForElement($element, $sysLanguageUid);
+				$languageId = $frontendServices->getOverlayLanguageIdForElement($element, $sysLanguageUid);
 				if ($languageId === FALSE) {
 					continue;
 				}
@@ -164,7 +173,12 @@ class SitemapService {
 
 			if ($languageId > 0) {
 				/** @var LanguageAspect $languageAspect */
-				$row = $pageRepository->getRecordOverlay($table, $row, $languageId, $overlayType);
+				$newLanguageAspect = new LanguageAspect(
+					$languageId,
+					$languageAspect->getContentId(),
+					$languageAspect->getOverlayType()
+				);
+				$row = $pageRepository->getLanguageOverlay($table, $row, $newLanguageAspect);
 				if (!is_array($row) || !count($row)) {
 					continue;
 				}
diff --git a/Classes/Updates/DepartmentUpdateWizard.php b/Classes/Updates/DepartmentUpdateWizard.php
deleted file mode 100644
index 37b60f9748a07dc93a85468737a11c8338eaae2a..0000000000000000000000000000000000000000
--- a/Classes/Updates/DepartmentUpdateWizard.php
+++ /dev/null
@@ -1,226 +0,0 @@
-<?php
-
-/**
- * Copyright notice
- *
- * (c) sgalinski Internet Services (https://www.sgalinski.de)
- *
- * All rights reserved
- *
- * This script is part of the TYPO3 project. The TYPO3 project is
- * free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * The GNU General Public License can be found at
- * http://www.gnu.org/copyleft/gpl.html.
- *
- * This script is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This copyright notice MUST APPEAR in all copies of the script!
- */
-
-namespace SGalinski\SgJobs\Updates;
-
-use TYPO3\CMS\Core\Database\Connection;
-use TYPO3\CMS\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Install\Updates\DatabaseUpdatedPrerequisite;
-use TYPO3\CMS\Install\Updates\UpgradeWizardInterface;
-
-/**
- * Class DepartmentUpdateWizard
- */
-class DepartmentUpdateWizard implements UpgradeWizardInterface {
-	/**
-	 * The wizard identifier
-	 */
-	public const IDENTIFIER = 'tx_sgjobs_departmentupdatewizward';
-
-	/**
-	 * Check if the job table has a deleted area field
-	 *
-	 * @return bool
-	 */
-	protected function hasDeletedAreaField(): bool {
-		return $this->hasField('zzz_deleted_area');
-	}
-
-	/**
-	 * Check if the job table has an area field
-	 *
-	 * @return bool
-	 */
-	protected function hasAreaField(): bool {
-		return $this->hasField('area');
-	}
-
-	/**
-	 * Check if the job database table has a field with the given name in it
-	 *
-	 * @param string $fieldName
-	 * @return bool
-	 */
-	protected function hasField(string $fieldName): bool {
-		$connection = $this->getDatabaseConnection();
-		$tableColumns = $connection->getSchemaManager()->listTableColumns('tx_sgjobs_domain_model_job');
-		if (\array_key_exists($fieldName, $tableColumns)) {
-			return TRUE;
-		}
-		return FALSE;
-	}
-
-	/**
-	 * Get the database query builder
-	 *
-	 * @return Connection
-	 */
-	protected function getDatabaseConnection(): Connection {
-		$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
-		return $connectionPool->getConnectionForTable('tx_sgjobs_domain_model_job');
-	}
-
-	/**
-	 * @return string
-	 */
-	public function getIdentifier(): string {
-		return self::IDENTIFIER;
-	}
-
-	/**
-	 * @return string
-	 */
-	public function getTitle(): string {
-		return 'Migrate old fulltext job areas to department records';
-	}
-
-	/**
-	 * @return string
-	 */
-	public function getDescription(): string {
-		return '';
-	}
-
-	/**
-	 * @return bool
-	 */
-	public function executeUpdate(): bool {
-		$connection = $this->getDatabaseConnection();
-		$queryBuilder = $connection->createQueryBuilder();
-		$field = $this->hasDeletedAreaField() ? 'zzz_deleted_area' : 'area';
-		$queryBuilder->getRestrictions()->removeAll();
-		/**
-		 * @var array $jobs
-		 */
-		$jobs = $queryBuilder->select('uid', 'pid', 'sys_language_uid', $field)
-			->from('tx_sgjobs_domain_model_job')
-			->execute()
-			->fetchAll();
-
-		$newDepartments = [];
-		if (\count($jobs) > 0) {
-			foreach ($jobs as $index => $job) {
-				if ($job[$field]) {
-					$identifier = $job[$field] . '-' . $job['pid'] . '-' . $job['sys_language_uid'];
-					$newDepartments[$identifier] = [
-						'title' => $job[$field],
-						'pid' => $job['pid'],
-						'sys_language_uid' => $job['sys_language_uid']
-					];
-				} else {
-					unset($jobs[$index]);
-				}
-			}
-
-			if (\count($jobs) > 0) {
-				\array_walk(
-					$newDepartments,
-					function ($department) use (&$dbQueries, $connection) {
-						$queryBuilder = $connection->createQueryBuilder();
-						$queryBuilder->insert('tx_sgjobs_domain_model_department')->values($department)->execute();
-						$dbQueries[] = $queryBuilder->getSQL();
-					}
-				);
-
-				$queryBuilder = $connection->createQueryBuilder();
-				$departments = $queryBuilder->select('uid', 'pid', 'sys_language_uid', 'title')
-					->from('tx_sgjobs_domain_model_department')
-					->execute()
-					->fetchAll();
-
-				$identifiedDepartments = [];
-				foreach ($departments as $department) {
-					$identifier = $department['title'] . '-' . $department['pid'] . '-' . $department['sys_language_uid'];
-					$identifiedDepartments[$identifier] = $department;
-				}
-
-				$dbQueries[] = $queryBuilder->getSQL();
-
-				foreach ($jobs as $index => $job) {
-					$identifier = $job[$field] . '-' . $job['pid'] . '-' . $job['sys_language_uid'];
-					if (isset($identifiedDepartments[$identifier])) {
-						$jobs[$index]['department'] = $identifiedDepartments[$identifier]['uid'];
-						unset($jobs[$index][$field]);
-					} else {
-						unset($jobs[$index]);
-					}
-				}
-
-				if (\count($jobs) > 0) {
-					\array_walk(
-						$jobs,
-						function ($job) use ($connection) {
-							$queryBuilder = $connection->createQueryBuilder();
-							$queryBuilder->update('tx_sgjobs_domain_model_job')
-								->set('department', (int) $job['department'])
-								->where(
-									$queryBuilder->expr()->eq(
-										'uid',
-										$queryBuilder->createNamedParameter($job['uid'], \PDO::PARAM_INT)
-									)
-								)->execute();
-						}
-					);
-				}
-			}
-		}
-
-		return TRUE;
-	}
-
-	/**
-	 * @return bool
-	 */
-	public function updateNecessary(): bool {
-		if (
-			!GeneralUtility::makeInstance(ConnectionPool::class)
-				->getConnectionForTable('tx_sgjobs_domain_model_department')
-				->getSchemaManager()
-				->tablesExist(['tx_sgjobs_domain_model_department'])
-		) {
-			return FALSE;
-		}
-
-		if (
-			$this->hasAreaField() ||
-			$this->hasDeletedAreaField()
-		) {
-			return TRUE;
-		}
-
-		return FALSE;
-	}
-
-	/**
-	 * @return array|string[]
-	 */
-	public function getPrerequisites(): array {
-		return [
-			DatabaseUpdatedPrerequisite::class
-		];
-	}
-}
diff --git a/Classes/ViewHelpers/AbstractViewHelper.php b/Classes/ViewHelpers/AbstractViewHelper.php
deleted file mode 100644
index 2e44b10451b38c63194bd55018f821a5a797dc63..0000000000000000000000000000000000000000
--- a/Classes/ViewHelpers/AbstractViewHelper.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-/***************************************************************
- *  Copyright notice
- *
- *  (c) sgalinski Internet Services (https://www.sgalinski.de)
- *
- *  All rights reserved
- *
- *  This script is part of the TYPO3 project. The TYPO3 project is
- *  free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  The GNU General Public License can be found at
- *  http://www.gnu.org/copyleft/gpl.html.
- *
- *  This script is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  This copyright notice MUST APPEAR in all copies of the script!
- ***************************************************************/
-
-namespace SGalinski\SgJobs\ViewHelpers;
-
-use TYPO3\CMS\Fluid\ViewHelpers\Be\AbstractBackendViewHelper;
-
-/**
- * Abstract view helper
- */
-class AbstractViewHelper extends AbstractBackendViewHelper {
-	/**
-	 * Returns the base url of the site
-	 *
-	 * Note: Works only in frontend mode
-	 *
-	 * @return string
-	 */
-	public function getBaseUrl(): string {
-		if ($GLOBALS['TSFE']->absRefPrefix !== '') {
-			$baseUrl = $GLOBALS['TSFE']->absRefPrefix;
-		} else {
-			$baseUrl = $GLOBALS['TSFE']->baseUrl;
-		}
-
-		return $baseUrl;
-	}
-}
diff --git a/Classes/ViewHelpers/Backend/CompanyLabelViewHelper.php b/Classes/ViewHelpers/Backend/CompanyLabelViewHelper.php
index 3282e45b345627e349a7fff80fe690665bcb2268..c6a7bdfb4bfbb2d4754bffcdde5f6e169d493f28 100644
--- a/Classes/ViewHelpers/Backend/CompanyLabelViewHelper.php
+++ b/Classes/ViewHelpers/Backend/CompanyLabelViewHelper.php
@@ -26,12 +26,13 @@
 
 namespace SGalinski\SgJobs\ViewHelpers\Backend;
 
+use Doctrine\DBAL\Exception;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
 
 /**
- * Class ControlViewHelper
+ * Class CompanyLabelViewHelper
  **/
 class CompanyLabelViewHelper extends AbstractViewHelper {
 	/**
@@ -47,6 +48,7 @@ class CompanyLabelViewHelper extends AbstractViewHelper {
 	 * Renders the control buttons for the specified record
 	 *
 	 * @return string
+	 * @throws Exception
 	 */
 	public function render(): string {
 		$addedCompanies = explode(',', $this->arguments['companyraw']);
@@ -59,8 +61,8 @@ class CompanyLabelViewHelper extends AbstractViewHelper {
 				$queryBilder->expr()->in('uid', $addedCompanies)
 			)
 			->setMaxResults(1)
-			->execute()
-			->fetch();
+			->executeQuery()
+			->fetchAssociative();
 
 		return $firstJob ? $firstJob['name'] . ', ' . $firstJob['city'] : '';
 	}
diff --git a/Classes/ViewHelpers/Backend/ControlViewHelper.php b/Classes/ViewHelpers/Backend/ControlViewHelper.php
index ee242d31b7725e92cc3d3dd8e436f70e180c675b..5e0e47847c53258991b8f392ece0141cf9a08931 100644
--- a/Classes/ViewHelpers/Backend/ControlViewHelper.php
+++ b/Classes/ViewHelpers/Backend/ControlViewHelper.php
@@ -27,10 +27,10 @@
 namespace SGalinski\SgJobs\ViewHelpers\Backend;
 
 use SGalinski\SgJobs\Domain\Model\Job;
+use TYPO3\CMS\Backend\RecordList\DatabaseRecordList;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Core\Page\PageRenderer;
+use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Recordlist\RecordList\DatabaseRecordList;
 use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
 
 /**
@@ -59,25 +59,13 @@ class ControlViewHelper extends AbstractViewHelper {
 		$row = $this->arguments['row'];
 		$row = BackendUtility::getRecord('tx_sgjobs_domain_model_job', $row['uid']);
 
-		// force reading of core file into $GLOBALS['LANG'], because the ->labels array will be empty otherwise
-		$GLOBALS['LANG']->includeLLFile('EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf');
-
+		/** @var DatabaseRecordList $databaseRecordList */
 		$databaseRecordList = GeneralUtility::makeInstance(DatabaseRecordList::class);
+		$databaseRecordList->setRequest($this->renderingContext->getRequest());
 		$pageInfo = BackendUtility::readPageAccess($row['pid'], $GLOBALS['BE_USER']->getPagePermsClause(1));
-		if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) {
-			$databaseRecordList->calcPerms = $GLOBALS['BE_USER']->calcPerms($pageInfo);
-		} else {
-			$databaseRecordList->calcPerms = new \TYPO3\CMS\Core\Type\Bitmask\Permission(
-				$GLOBALS['BE_USER']->calcPerms($pageInfo)
-			);
-		}
-		$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
-		$pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/AjaxDataHandler');
-		$pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf');
-		$languageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Localization\LanguageService::class);
-		$languageService->includeLLFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf');
+		$databaseRecordList->calcPerms = new Permission($GLOBALS['BE_USER']->calcPerms($pageInfo));
 
-		// DatabaseRecordList has a $prevPrevUid, which might track back a page. We wont do that, 1st+last record are always
+		// DatabaseRecordList has a $prevPrevUid, which might track back a page. We won't do that, 1st+last record are
 		// not sortable in one direction
 		$uidPrev = FALSE;
 		$uidNext = FALSE;
@@ -85,9 +73,11 @@ class ControlViewHelper extends AbstractViewHelper {
 		if (!$iterator['isFirst'] && $iterator['index'] !== 1) {
 			$uidPrev = '-' . $this->arguments['allItems'][$iterator['index'] - 2]['uid'];
 		}
+
 		if ($iterator['index'] === 1) {
 			$uidPrev = $row['pid'];
 		}
+
 		if (!$iterator['isLast']) {
 			$uidNext = '-' . $this->arguments['allItems'][$iterator['index'] + 1]['uid'];
 		}
@@ -107,6 +97,7 @@ class ControlViewHelper extends AbstractViewHelper {
 				]
 			];
 		}
+
 		if (!$uidNext) {
 			$newCurrentTableArr = [
 				'prev' => [
@@ -114,6 +105,7 @@ class ControlViewHelper extends AbstractViewHelper {
 				]
 			];
 		}
+
 		$databaseRecordList->id = $row['pid'];
 		$databaseRecordList->currentTable = $newCurrentTableArr;
 
diff --git a/Classes/ViewHelpers/Backend/IconViewHelper.php b/Classes/ViewHelpers/Backend/IconViewHelper.php
index 5e3db077138aef149c033a9f09cc0f83c768d476..d1dd9692bf8374b5596d5d2a60ca283ce5bb119c 100644
--- a/Classes/ViewHelpers/Backend/IconViewHelper.php
+++ b/Classes/ViewHelpers/Backend/IconViewHelper.php
@@ -58,7 +58,7 @@ class IconViewHelper extends AbstractViewHelper {
 		$table = $this->arguments['table'];
 		$clickMenu = $this->arguments['clickMenu'];
 		$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
-		$toolTip = BackendUtility::getRecordToolTip($row, $table);
+		$toolTip = BackendUtility::getRecordIconAltText($row, $table);
 		$iconImg = '<span ' . $toolTip . '>'
 			. $iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render()
 			. '</span>';
diff --git a/Classes/ViewHelpers/ExplodeStringViewHelper.php b/Classes/ViewHelpers/ExplodeStringViewHelper.php
index e54d920a945690fea6d895f0705c41e668a9063f..22c06f79b376cccf9851c05c2d1a2fd5068db486 100644
--- a/Classes/ViewHelpers/ExplodeStringViewHelper.php
+++ b/Classes/ViewHelpers/ExplodeStringViewHelper.php
@@ -27,12 +27,11 @@
 namespace SGalinski\SgJobs\ViewHelpers;
 
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
 
 /**
  * Takes a string containing multiple values separated by a delimiter and returns an array of these values.
  *
- * @TODO: Replace this ViewHelper with a VHS ViewHelper when updating to TYPO3 11!
- *
  * Example:
  * {namespace jobs=SGalinski\SgJobs\ViewHelpers}
  * <jobs:explodeString string="1,2,3,4" delimiter=","/>
diff --git a/Classes/ViewHelpers/Form/UploadViewHelper.php b/Classes/ViewHelpers/Form/UploadViewHelper.php
index 7a911134f1aa45e9219e68bcc3f47d63f0197f78..a8bf8c036a99d2f6b3d29af011ec99aa1e81d130 100644
--- a/Classes/ViewHelpers/Form/UploadViewHelper.php
+++ b/Classes/ViewHelpers/Form/UploadViewHelper.php
@@ -30,11 +30,12 @@ namespace SGalinski\SgJobs\ViewHelpers\Form;
 
 use TYPO3\CMS\Extbase\Property\PropertyMapper;
 use TYPO3\CMS\Extbase\Security\Cryptography\HashService;
+use TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper;
 
 /**
  * Class UploadViewHelper
  */
-class UploadViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\UploadViewHelper {
+class UploadViewHelper extends AbstractFormFieldViewHelper {
 	/**
 	 * @var HashService
 	 *
@@ -47,6 +48,11 @@ class UploadViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\UploadViewHelpe
 	 */
 	protected $propertyMapper;
 
+	/**
+	 * @var string
+	 */
+	protected $tagName = 'input';
+
 	/**
 	 * Inject the HashService
 	 *
@@ -68,8 +74,13 @@ class UploadViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\UploadViewHelpe
 	/**
 	 * Register the ViewHelper arguments
 	 */
-	public function initializeArguments() {
+	public function initializeArguments(): void {
 		parent::initializeArguments();
+		$this->registerTagAttribute('disabled', 'string', 'Specifies that the input element should be disabled when the page loads');
+		$this->registerTagAttribute('multiple', 'string', 'Specifies that the file input element should allow multiple selection of files');
+		$this->registerTagAttribute('accept', 'string', 'Specifies the allowed file extensions to upload via comma-separated list, example ".png,.gif"');
+		$this->registerArgument('errorClass', 'string', 'CSS class to set if there are errors for this ViewHelper', FALSE, 'f3-form-error');
+		$this->registerUniversalTagAttributes();
 		$this->registerArgument('resourceName', 'string', 'The name of the resource', FALSE, 'resource');
 	}
 
@@ -93,7 +104,21 @@ class UploadViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\UploadViewHelpe
 			$output .= $this->renderChildren();
 		}
 
-		$output .= parent::render();
+		$name = $this->getName();
+		$allowedFields = ['name', 'type', 'tmp_name', 'error', 'size'];
+		foreach ($allowedFields as $fieldName) {
+			$this->registerFieldNameForFormTokenGeneration($name . '[' . $fieldName . ']');
+		}
+		$this->tag->addAttribute('type', 'file');
+
+		if (isset($this->arguments['multiple'])) {
+			$this->tag->addAttribute('name', $name . '[]');
+		} else {
+			$this->tag->addAttribute('name', $name);
+		}
+
+		$this->setErrorClassAttribute();
+		$output .= $this->tag->render();
 		return $output;
 	}
 
diff --git a/Classes/ViewHelpers/PageBrowserViewHelper.php b/Classes/ViewHelpers/PageBrowserViewHelper.php
index a192355ee9a653a5d3ee338dbd572b48afcabab5..a15cc0f842fa74e9ce16caf0a3e51164229d156c 100644
--- a/Classes/ViewHelpers/PageBrowserViewHelper.php
+++ b/Classes/ViewHelpers/PageBrowserViewHelper.php
@@ -26,6 +26,7 @@
 
 namespace SGalinski\SgJobs\ViewHelpers;
 
+use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Core\TypoScript\TypoScriptService;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Fluid\View\StandaloneView;
@@ -76,7 +77,9 @@ class PageBrowserViewHelper extends AbstractViewHelper {
 		$view->setTemplate('PageBrowser/Index');
 
 		$currentPage = 0;
-		$pageBrowserVars = GeneralUtility::_GP('tx_sgjobs_pagebrowser');
+		/** @var ServerRequestInterface $request */
+		$request = $GLOBALS['TYPO3_REQUEST'];
+		$pageBrowserVars = $request->getQueryParams()['tx_sgjobs_pagebrowser'] ?? [];
 		if (isset($pageBrowserVars['currentPage']) && (int) $pageBrowserVars['currentPage'] > 0) {
 			$currentPage = (int) $pageBrowserVars['currentPage'];
 		}
diff --git a/Classes/ViewHelpers/SetViewHelper.php b/Classes/ViewHelpers/SetViewHelper.php
index 1ce0363e9a4b607e75696e6e9672a33921cd0416..39b5cdb3477d2eaba97f8d4530a85b5b0684f868 100644
--- a/Classes/ViewHelpers/SetViewHelper.php
+++ b/Classes/ViewHelpers/SetViewHelper.php
@@ -54,10 +54,12 @@ class SetViewHelper extends AbstractViewHelper {
 		if (NULL === $value) {
 			$value = $this->renderChildren();
 		}
-		if (FALSE === \strpos($name, '.')) {
+
+		if (!str_contains($name, '.')) {
 			if (TRUE === $this->templateVariableContainer->exists($name)) {
 				$this->templateVariableContainer->remove($name);
 			}
+
 			$this->templateVariableContainer->add($name, $value);
 		} elseif (1 === \substr_count($name, '.')) {
 			$parts = \explode('.', $name);
@@ -76,6 +78,7 @@ class SetViewHelper extends AbstractViewHelper {
 				return NULL;
 			}
 		}
+
 		return NULL;
 	}
 }
diff --git a/Classes/ViewHelpers/Widget/UriViewHelper.php b/Classes/ViewHelpers/Widget/UriViewHelper.php
deleted file mode 100644
index da68dc66035f5162f856b4aa5f3f1f7d23fed0f2..0000000000000000000000000000000000000000
--- a/Classes/ViewHelpers/Widget/UriViewHelper.php
+++ /dev/null
@@ -1,161 +0,0 @@
-<?php
-
-/***************************************************************
- *  Copyright notice
- *
- *  (c) sgalinski Internet Services (https://www.sgalinski.de)
- *
- *  All rights reserved
- *
- *  This script is part of the TYPO3 project. The TYPO3 project is
- *  free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  The GNU General Public License can be found at
- *  http://www.gnu.org/copyleft/gpl.html.
- *
- *  This script is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  This copyright notice MUST APPEAR in all copies of the script!
- ***************************************************************/
-
-namespace SGalinski\SgJobs\ViewHelpers\Widget;
-
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
-use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
-use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
-use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
-
-/**
- * Class UriViewHelper
- */
-class UriViewHelper extends AbstractViewHelper {
-	use CompileWithRenderStatic;
-
-	/**
-	 * @var boolean
-	 */
-	protected $escapeOutput = FALSE;
-
-	/**
-	 * @var boolean
-	 */
-	protected $escapeChildren = FALSE;
-
-	/**
-	 * Initialize arguments
-	 */
-	public function initializeArguments(): void {
-		$this->registerArgument('addQueryStringMethod', 'string', 'Method to be used for query string');
-		$this->registerArgument('action', 'string', 'Target action');
-		$this->registerArgument('arguments', 'array', 'Arguments', FALSE, []);
-		$this->registerArgument('section', 'string', 'The anchor to be added to the URI', FALSE, '');
-		$this->registerArgument('format', 'string', 'The requested format, e.g. ".html', FALSE, '');
-		$this->registerArgument(
-			'ajax',
-			'bool',
-			'TRUE if the URI should be to an AJAX widget, FALSE otherwise.',
-			FALSE,
-			FALSE
-		);
-	}
-
-	/**
-	 * @param array $arguments
-	 * @param \Closure $renderChildrenClosure
-	 * @param RenderingContextInterface $renderingContext
-	 * @return string
-	 */
-	public static function renderStatic(
-		array $arguments,
-		\Closure $renderChildrenClosure,
-		RenderingContextInterface $renderingContext
-	): string {
-		$ajax = $arguments['ajax'];
-		if ($ajax === TRUE) {
-			return static::getAjaxUri($renderingContext, $arguments);
-		}
-		return static::getWidgetUri($renderingContext, $arguments);
-	}
-
-	/**
-	 * Render the Uri.
-	 *
-	 * @return string The rendered link
-	 * @api
-	 */
-	public function render(): string {
-		$ajax = $this->arguments['ajax'];
-
-		if ($ajax === TRUE) {
-			return static::getAjaxUri($this->renderingContext, $this->arguments);
-		}
-		return static::getWidgetUri($this->renderingContext, $this->arguments);
-	}
-
-	/**
-	 * Get the URI for an AJAX Request.
-	 *
-	 * @param RenderingContextInterface $renderingContext
-	 * @param array $arguments
-	 * @return string the AJAX URI
-	 */
-	protected static function getAjaxUri(RenderingContextInterface $renderingContext, array $arguments): string {
-		/** @var ControllerContext $controllerContext */
-		$controllerContext = $renderingContext->getControllerContext();
-		$action = $arguments['action'];
-		$arguments = $arguments['arguments'];
-		if ($action === NULL) {
-			$action = $controllerContext->getRequest()->getControllerActionName();
-		}
-
-		$arguments['id'] = $GLOBALS['TSFE']->id;
-		// @todo page type should be configurable
-		$arguments['type'] = 7076;
-		$arguments['fluid-widget-id'] = $controllerContext->getRequest()->getWidgetContext()->getAjaxWidgetIdentifier();
-		$arguments['action'] = $action;
-		return '?' . http_build_query($arguments, NULL, '&');
-	}
-
-	/**
-	 * Get the URI for a non-AJAX Request.
-	 *
-	 * @param RenderingContextInterface $renderingContext
-	 * @param array $arguments
-	 * @return string the Widget URI
-	 */
-	protected static function getWidgetUri(RenderingContextInterface $renderingContext, array $arguments): string {
-		/** @var ControllerContext $controllerContext */
-		$controllerContext = $renderingContext->getControllerContext();
-		$uriBuilder = $controllerContext->getUriBuilder();
-		$argumentPrefix = $controllerContext->getRequest()->getArgumentPrefix();
-		$parentNamespace = $controllerContext->getRequest()->getWidgetContext()->getParentPluginNamespace();
-		$parentArguments = GeneralUtility::_GP($parentNamespace);
-		$allArguments = [$argumentPrefix => $arguments['arguments']] ?? [];
-		if ($parentArguments && isset($parentArguments['filters'])) {
-			$allArguments[$parentNamespace . '[filters]'] = $parentArguments['filters'];
-		}
-
-		if ($arguments['action'] ?? FALSE) {
-			$allArguments[$argumentPrefix]['action'] = $arguments['action'];
-		}
-
-		if (($arguments['format'] ?? '') !== '') {
-			$allArguments[$argumentPrefix]['format'] = $arguments['format'];
-		}
-
-		return $uriBuilder->reset()
-			->setArguments($allArguments)
-			->setSection($arguments['section'])
-			->setAddQueryString(TRUE)
-			->setArgumentsToBeExcludedFromQueryString([$argumentPrefix, 'cHash'])
-			->setFormat($arguments['format'])
-			->build();
-	}
-}
diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php
new file mode 100644
index 0000000000000000000000000000000000000000..19e49d51a3ff3e8ae8bead1e53278d83faff6518
--- /dev/null
+++ b/Configuration/Backend/Modules.php
@@ -0,0 +1,19 @@
+<?php
+
+use SGalinski\SgJobs\Controller\BackendController;
+
+return [
+	'web_SgJobs_backend' => [
+		'parent' => 'web',
+		'position' => ['after' => ''],
+		'access' => 'user,group',
+		'workspaces' => 'live',
+		'path' => '/module/web/sg_jobs_backend',
+		'labels' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_backend.xlf',
+		'iconIdentifier' => 'extension-sg_jobs-module',
+		'extensionName' => 'SgJobs',
+		'controllerActions' => [
+			BackendController::class => ['index']
+		]
+	]
+];
diff --git a/Configuration/Extbase/Persistence/Classes.php b/Configuration/Extbase/Persistence/Classes.php
index 1c70c6a38d7145cf482790e59efbe53f4b1d67d6..8b7caeb8a298b1093d4666397efb70e9e535a216 100644
--- a/Configuration/Extbase/Persistence/Classes.php
+++ b/Configuration/Extbase/Persistence/Classes.php
@@ -4,14 +4,18 @@ declare(strict_types=1);
 
 // if you need to change this, keep in mind the changes need to be done in
 // Configuration/TypoScript/Common/setup.typoscript for TYPO3 9, too
+use SGalinski\SgJobs\Domain\Model\ExperienceLevel;
+use SGalinski\SgJobs\Domain\Model\FileReference;
+use SGalinski\SgJobs\Domain\Model\JobApplication;
+
 return [
-	\SGalinski\SgJobs\Domain\Model\FileReference::class => [
+	FileReference::class => [
 		'tableName' => 'sys_file_reference'
 	],
-	\SGalinski\SgJobs\Domain\Model\JobApplication::class => [
+	JobApplication::class => [
 		'tableName' => 'tx_sgjobs_domain_model_job_application'
 	],
-	\SGalinski\SgJobs\Domain\Model\ExperienceLevel::class => [
+	ExperienceLevel::class => [
 		'tableName' => 'tx_sgjobs_domain_model_experience_level'
 	]
 ];
diff --git a/Configuration/FlexForms/Joblist.xml b/Configuration/FlexForms/Joblist.xml
index ea7352bbe46f2334baa911d945af77bfc42acc48..597065f280b0a7bd89e56b1e6eb5b3b95a58ecae 100644
--- a/Configuration/FlexForms/Joblist.xml
+++ b/Configuration/FlexForms/Joblist.xml
@@ -1,109 +1,121 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <T3DataStructure>
 	<sheets>
 		<sDEF>
 			<ROOT>
-				<TCEforms>
-					<sheetTitle>LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.plugin_options</sheetTitle>
-				</TCEforms>
+				<sheetTitle>
+					LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.plugin_options
+				</sheetTitle>
 				<type>array</type>
 				<el>
 					<settings.applyPage>
-						<TCEforms>
-							<label>LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.application_form_page</label>
-							<config>
-								<type>group</type>
-								<internal_type>db</internal_type>
-								<allowed>pages</allowed>
-								<size>1</size>
-								<maxitems>1</maxitems>
-								<minitems>0</minitems>
-								<show_thumbs>1</show_thumbs>
-								<wizards>
-									<suggest>
-										<type>suggest</type>
-									</suggest>
-								</wizards>
-							</config>
-						</TCEforms>
+						<label>
+							LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.application_form_page
+						</label>
+						<config>
+							<type>group</type>
+							<internal_type>db</internal_type>
+							<allowed>pages</allowed>
+							<size>1</size>
+							<maxitems>1</maxitems>
+							<minitems>0</minitems>
+							<show_thumbs>1</show_thumbs>
+							<wizards>
+								<suggest>
+									<type>suggest</type>
+								</suggest>
+							</wizards>
+						</config>
 					</settings.applyPage>
 					<settings.jobLimit>
-						<TCEforms>
-							<label>LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.jobLimit</label>
-							<config>
-								<type>input</type>
-								<size>5</size>
-								<eval>int</eval>
-								<default>5</default>
-							</config>
-						</TCEforms>
+						<label>
+							LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.jobLimit
+						</label>
+						<config>
+							<type>number</type>
+							<size>5</size>
+							<default>5</default>
+						</config>
 					</settings.jobLimit>
 					<settings.orderBy>
-						<TCEforms>
-							<label>LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.orderBy</label>
-							<config>
-								<type>select</type>
-								<renderType>selectSingle</renderType>
-								<items type="array">
-									<numIndex index="0" type="array">
-										<numIndex index="0">LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.orderBy_0</numIndex>
-										<numIndex index="1">0</numIndex>
-									</numIndex>
-									<numIndex index="1" type="array">
-										<numIndex index="0">LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.orderBy_1</numIndex>
-										<numIndex index="1">1</numIndex>
-									</numIndex>
-									<numIndex index="2" type="array">
-										<numIndex index="0">LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.orderBy_2</numIndex>
-										<numIndex index="1">2</numIndex>
-									</numIndex>
-								</items>
-							</config>
-						</TCEforms>
+						<label>
+							LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.orderBy
+						</label>
+						<config>
+							<type>select</type>
+							<renderType>selectSingle</renderType>
+							<items type="array">
+								<numIndex index="0" type="array">
+									<label>
+										LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.orderBy_0
+									</label>
+									<value>0</value>
+								</numIndex>
+								<numIndex index="1" type="array">
+									<label>
+										LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.orderBy_1
+									</label>
+									<value>1</value>
+								</numIndex>
+								<numIndex index="2" type="array">
+									<label>
+										LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.orderBy_2
+									</label>
+									<value>2</value>
+								</numIndex>
+							</items>
+						</config>
 					</settings.orderBy>
 					<settings.filterByLocation>
-						<TCEforms>
-							<label>LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.teaser_locations</label>
-							<description>LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.teaser_locations.description</description>
-							<config>
-								<type>select</type>
-								<renderType>selectMultipleSideBySide</renderType>
-								<foreign_table>tx_sgjobs_domain_model_company</foreign_table>
-								<foreign_table_where>AND tx_sgjobs_domain_model_company.sys_language_uid IN (0,-1) ORDER BY tx_sgjobs_domain_model_company.name ASC</foreign_table_where>
-								<wizards>
-									<suggest>
-										<type>suggest</type>
-									</suggest>
-								</wizards>
-							</config>
-						</TCEforms>
+						<label>
+							LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.teaser_locations
+						</label>
+						<description>
+							LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.teaser_locations.description
+						</description>
+						<config>
+							<type>select</type>
+							<renderType>selectMultipleSideBySide</renderType>
+							<foreign_table>tx_sgjobs_domain_model_company</foreign_table>
+							<foreign_table_where>AND tx_sgjobs_domain_model_company.sys_language_uid IN (0,-1) ORDER BY
+								tx_sgjobs_domain_model_company.name ASC
+							</foreign_table_where>
+							<wizards>
+								<suggest>
+									<type>suggest</type>
+								</suggest>
+							</wizards>
+						</config>
 					</settings.filterByLocation>
 					<settings.filterByDepartment>
-						<TCEforms>
-							<label>LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_department.filter</label>
-							<config>
-								<type>select</type>
-								<renderType>selectMultipleSideBySide</renderType>
-								<foreign_table>tx_sgjobs_domain_model_department</foreign_table>
-								<foreign_table_where>AND tx_sgjobs_domain_model_department.sys_language_uid IN (0,-1) ORDER BY tx_sgjobs_domain_model_department.title ASC</foreign_table_where>
-								<wizards>
-									<suggest>
-										<type>suggest</type>
-									</suggest>
-								</wizards>
-							</config>
-						</TCEforms>
+						<label>
+							LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_department.filter
+						</label>
+						<config>
+							<type>select</type>
+							<renderType>selectMultipleSideBySide</renderType>
+							<foreign_table>tx_sgjobs_domain_model_department</foreign_table>
+							<foreign_table_where>AND tx_sgjobs_domain_model_department.sys_language_uid IN (0,-1) ORDER
+								BY tx_sgjobs_domain_model_department.title ASC
+							</foreign_table_where>
+							<wizards>
+								<suggest>
+									<type>suggest</type>
+								</suggest>
+							</wizards>
+						</config>
 					</settings.filterByDepartment>
 					<settings.filterByExperienceLevel>
-						<TCEforms>
-							<label>LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.experienceLevel</label>
-							<config>
-								<type>select</type>
-								<renderType>selectMultipleSideBySide</renderType>
-								<foreign_table>tx_sgjobs_domain_model_experience_level</foreign_table>
-								<foreign_table_where>AND tx_sgjobs_domain_model_experience_level.sys_language_uid IN (0,-1) ORDER BY tx_sgjobs_domain_model_experience_level.sorting ASC</foreign_table_where>
-							</config>
-						</TCEforms>
+						<label>
+							LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.experienceLevel
+						</label>
+						<config>
+							<type>select</type>
+							<renderType>selectMultipleSideBySide</renderType>
+							<foreign_table>tx_sgjobs_domain_model_experience_level</foreign_table>
+							<foreign_table_where>AND tx_sgjobs_domain_model_experience_level.sys_language_uid IN (0,-1)
+								ORDER BY tx_sgjobs_domain_model_experience_level.sorting ASC
+							</foreign_table_where>
+						</config>
 					</settings.filterByExperienceLevel>
 				</el>
 			</ROOT>
diff --git a/Configuration/Icons.php b/Configuration/Icons.php
index 4fad03d9adf0ba9ed701499c679ac13a358caf55..621beb0c2afb468bae35e403647db5a0186d5095 100644
--- a/Configuration/Icons.php
+++ b/Configuration/Icons.php
@@ -6,6 +6,8 @@
  * Either use a closure here, or do not call your variable $icons.
  */
 
+use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;
+
 $iconList = [];
 $sgJobsIcons = [
 	'extension-sg_jobs-module' => 'module-sgjobs.svg',
@@ -13,7 +15,7 @@ $sgJobsIcons = [
 
 foreach ($sgJobsIcons as $identifier => $path) {
 	$iconList[$identifier] = [
-		'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
+		'provider' => SvgIconProvider::class,
 		'source' => 'EXT:sg_jobs/Resources/Public/Icons/' . $path,
 	];
 }
diff --git a/Configuration/Services.php b/Configuration/Services.php
index eff1747fea2bf59b7a9d8addf665945a610d4751..4c6537332d6fa2787ed0383dc1bed48d0841722f 100644
--- a/Configuration/Services.php
+++ b/Configuration/Services.php
@@ -1,34 +1,13 @@
 <?php
 
-/***************************************************************
- *  Copyright notice
- *
- *  (c) sgalinski Internet Services (https://www.sgalinski.de)
- *  All rights reserved
- *
- *  This script is part of the TYPO3 project. The TYPO3 project is
- *  free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  The GNU General Public License can be found at
- *  http://www.gnu.org/copyleft/gpl.html.
- *
- *  This script is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  This copyright notice MUST APPEAR in all copies of the script!
- ***************************************************************/
-
 use SGalinski\SgJobs\Event\Listener\AccessPageListEventListener;
 use SGalinski\SgJobs\Event\Listener\ExcludeFromReferenceIndexListener;
-use SGalinski\SgJobs\Preview\PreviewRenderer;
+use SGalinski\SgJobs\EventListeners\PageContentPreviewRenderingEventListener;
 use SGalinski\SgJobs\Service\BackendService;
 use SGalinski\SgJobs\Service\SitemapService;
+use SGalinski\SgSeo\Events\AccessPageListEvent;
 use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
+use TYPO3\CMS\Backend\View\Event\PageContentPreviewRenderingEvent;
 use TYPO3\CMS\Core\DataHandling\Event\IsTableExcludedFromReferenceIndexEvent;
 
 return static function (ContainerConfigurator $containerConfigurator): void {
@@ -41,13 +20,12 @@ return static function (ContainerConfigurator $containerConfigurator): void {
 
 	$services->set(SitemapService::class)->public();
 	$services->set(BackendService::class)->public();
-	$services->set(PreviewRenderer::class)->public();
 
-	if (class_exists('\SGalinski\SgSeo\Events\AccessPageListEvent')) {
+	if (class_exists(AccessPageListEvent::class)) {
 		$services->set(AccessPageListEventListener::class)
 			->tag('event.listener', [
 				'identifier' => 'accessPageListEvent',
-				'event' => 'SGalinski\SgSeo\Events\AccessPageListEvent'
+				'event' => AccessPageListEvent::class
 			]);
 	}
 
@@ -56,4 +34,9 @@ return static function (ContainerConfigurator $containerConfigurator): void {
 			'identifier' => 'sg-jobs/excludeFromRefIndex',
 			'event' => IsTableExcludedFromReferenceIndexEvent::class
 		]);
+
+	$services->set(PageContentPreviewRenderingEventListener::class)
+		->tag('event.listener', [
+			'event' => PageContentPreviewRenderingEvent::class
+		]);
 };
diff --git a/Configuration/SgMail/ApplicantMail.php b/Configuration/SgMail/ApplicantMail.php
index 41266520d13ac0ad45cad3d94b43f27b32f63f02..f83256bc39da121c2fcf9cf974158cc69d8d0512 100644
--- a/Configuration/SgMail/ApplicantMail.php
+++ b/Configuration/SgMail/ApplicantMail.php
@@ -1,5 +1,7 @@
 <?php
 
+use SGalinski\SgMail\Service\MailTemplateService;
+
 return [
 	'extension_key' => 'sg_jobs',
 	'template_key' => 'applicant_mail',
@@ -19,97 +21,97 @@ EOT
 	'markers' => [
 		[
 			'marker' => 'application.jobTitle',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Webdeveloper',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.jobtitle'
 		],
 		[
 			'marker' => 'application.company.location',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'München',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.location'
 		],
 		[
 			'marker' => 'application.gender',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => '0',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.gender'
 		],
 		[
 			'marker' => 'application.firstName',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Max',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.firstname'
 		],
 		[
 			'marker' => 'application.lastName',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Mustermann',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.lastname'
 		],
 		[
 			'marker' => 'application.street',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Musterstraße 16',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.street'
 		],
 		[
 			'marker' => 'application.zip',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => '99999',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.zip'
 		],
 		[
 			'marker' => 'application.city',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'München',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.city'
 		],
 		[
 			'marker' => 'application.country',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Deutschland',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.country'
 		],
 		[
 			'marker' => 'application.nationality',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Deutschland',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.nationality'
 		],
 		[
 			'marker' => 'application.education',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Bachelor',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.education'
 		],
 		[
 			'marker' => 'application.birthDate',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => '01.01.1983',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.birthdate'
 		],
 		[
 			'marker' => 'application.phone',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => '099-555 555',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.phone'
 		],
 		[
 			'marker' => 'application.mobile',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => '0199 - 55 5551',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.mobile'
 		],
 		[
 			'marker' => 'application.email',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'max.mustermann@example.org',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.email'
 		],
 		[
 			'marker' => 'application.message',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore...',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.message'
 		],
diff --git a/Configuration/SgMail/ApplicationMail.php b/Configuration/SgMail/ApplicationMail.php
index 143d27c787b306678eb1e1ad10fbb9766af92f36..a0e9197c07b9c5b2ce96412b6871bd0bb175e9b3 100644
--- a/Configuration/SgMail/ApplicationMail.php
+++ b/Configuration/SgMail/ApplicationMail.php
@@ -1,5 +1,7 @@
 <?php
 
+use SGalinski\SgMail\Service\MailTemplateService;
+
 return [
 	'extension_key' => 'sg_jobs',
 	'template_key' => 'application_mail',
@@ -44,97 +46,97 @@ EOT
 	'markers' => [
 		[
 			'marker' => 'application.jobTitle',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Webdeveloper',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.jobtitle'
 		],
 		[
 			'marker' => 'application.company.location',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'München',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.location'
 		],
 		[
 			'marker' => 'application.gender',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => '0',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.gender'
 		],
 		[
 			'marker' => 'application.firstName',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Max',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.firstname'
 		],
 		[
 			'marker' => 'application.lastName',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Mustermann',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.lastname'
 		],
 		[
 			'marker' => 'application.street',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Musterstraße 16',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.street'
 		],
 		[
 			'marker' => 'application.zip',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => '99999',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.zip'
 		],
 		[
 			'marker' => 'application.city',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'München',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.city'
 		],
 		[
 			'marker' => 'application.country',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Deutschland',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.country'
 		],
 		[
 			'marker' => 'application.nationality',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Deutschland',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.nationality'
 		],
 		[
 			'marker' => 'application.education',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Bachelor',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.education'
 		],
 		[
 			'marker' => 'application.birthDate',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => '01.01.1983',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.birthdate'
 		],
 		[
 			'marker' => 'application.phone',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => '099-555 555',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.phone'
 		],
 		[
 			'marker' => 'application.mobile',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => '0199 - 55 5551',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.mobile'
 		],
 		[
 			'marker' => 'application.email',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'max.mustermann@example.org',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.email'
 		],
 		[
 			'marker' => 'application.message',
-			'type' => \SGalinski\SgMail\Service\MailTemplateService::MARKER_TYPE_STRING,
+			'type' => MailTemplateService::MARKER_TYPE_STRING,
 			'value' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore...',
 			'description' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang.xlf:application_mail.marker.message'
 		],
diff --git a/Configuration/TCA/Overrides/sys_template.php b/Configuration/TCA/Overrides/sys_template.php
index 641c18aaa4e5c47d66be54f136674ee264922917..5b5fb8eac2cdf49d388f05979dc83b5ee00e34aa 100644
--- a/Configuration/TCA/Overrides/sys_template.php
+++ b/Configuration/TCA/Overrides/sys_template.php
@@ -1,33 +1,9 @@
 <?php
 
-defined('TYPO3') or die();
-/**
- *
- * Copyright notice
- *
- * (c) sgalinski Internet Services (https://www.sgalinski.de)
- *
- * All rights reserved
- *
- * This script is part of the TYPO3 project. The TYPO3 project is
- * free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * The GNU General Public License can be found at
- * http://www.gnu.org/copyleft/gpl.html.
- *
- * This script is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This copyright notice MUST APPEAR in all copies of the script!
- */
-
 // Adds the static TypoScript template.
-\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile(
+use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
+
+ExtensionManagementUtility::addStaticFile(
 	'sg_jobs',
 	'Configuration/TypoScript/Frontend',
 	'SgJobs - Configuration'
diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php
index 613a289588919f1a9f86bfb4eca9ead2c6862f90..4ecddf379b505509073d73bc8fb6779e7f6b8a28 100644
--- a/Configuration/TCA/Overrides/tt_content.php
+++ b/Configuration/TCA/Overrides/tt_content.php
@@ -1,70 +1,43 @@
 <?php
 
-defined('TYPO3') or die();
-/**
- *
- * Copyright notice
- *
- * (c) sgalinski Internet Services (https://www.sgalinski.de)
- *
- * All rights reserved
- *
- * This script is part of the TYPO3 project. The TYPO3 project is
- * free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * The GNU General Public License can be found at
- * http://www.gnu.org/copyleft/gpl.html.
- *
- * This script is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This copyright notice MUST APPEAR in all copies of the script!
- */
-
 // Register frontend plugins
-\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
+use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
+use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
+
+ExtensionUtility::registerPlugin(
 	'sg_jobs',
 	'Joblist',
 	'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_backend.xlf:listPlugin'
 );
 
 // Register frontend plugins
-\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
+ExtensionUtility::registerPlugin(
 	'sg_jobs',
 	'JobApplication',
 	'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_backend.xlf:applyPlugin'
 );
 
 // Register frontend plugins
-\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
+ExtensionUtility::registerPlugin(
 	'sg_jobs',
 	'JobTeaser',
 	'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_backend.xlf:teaserPlugin'
 );
 
 $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['sgjobs_joblist'] = 'pi_flexform';
-\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue(
+ExtensionManagementUtility::addPiFlexFormValue(
 	'sgjobs_joblist',
 	'FILE:EXT:sg_jobs/Configuration/FlexForms/Joblist.xml'
 );
 
 $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['sgjobs_jobapplication'] = 'pi_flexform';
-\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue(
+ExtensionManagementUtility::addPiFlexFormValue(
 	'sgjobs_jobapplication',
 	'FILE:EXT:sg_jobs/Configuration/FlexForms/JobApplication.xml'
 );
 
 $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['sgjobs_jobteaser'] = 'pi_flexform';
-\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue(
+ExtensionManagementUtility::addPiFlexFormValue(
 	'sgjobs_jobteaser',
 	'FILE:EXT:sg_jobs/Configuration/FlexForms/JobTeaser.xml'
 );
-
-$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgjobs_joblist'] = \SGalinski\SgJobs\Preview\PreviewRenderer::class;
-$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgjobs_jobapplication'] = \SGalinski\SgJobs\Preview\PreviewRenderer::class;
-$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgjobs_jobteaser'] = \SGalinski\SgJobs\Preview\PreviewRenderer::class;
diff --git a/Configuration/TCA/tx_sgjobs_domain_model_company.php b/Configuration/TCA/tx_sgjobs_domain_model_company.php
index a5d830d318787a1597c040424d6af17bfaa44b84..fe2064f48ae45a770135ff5de6c2795511e36ff6 100644
--- a/Configuration/TCA/tx_sgjobs_domain_model_company.php
+++ b/Configuration/TCA/tx_sgjobs_domain_model_company.php
@@ -1,28 +1,4 @@
 <?php
-/**
- *
- * Copyright notice
- *
- * (c) sgalinski Internet Services (https://www.sgalinski.de)
- *
- * All rights reserved
- *
- * This script is part of the TYPO3 project. The TYPO3 project is
- * free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * The GNU General Public License can be found at
- * http://www.gnu.org/copyleft/gpl.html.
- *
- * This script is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This copyright notice MUST APPEAR in all copies of the script!
- */
 
 $columns = [
 	'ctrl' => [
@@ -30,7 +6,6 @@ $columns = [
 		'label' => 'name',
 		'tstamp' => 'tstamp',
 		'crdate' => 'crdate',
-		'cruser_id' => 'cruser_id',
 		'searchFields' => 'job_id, zip, city, state, country, description, name, street, contact',
 		'versioningWS' => 2,
 		'versioning_followPages' => TRUE,
@@ -45,12 +20,15 @@ $columns = [
 			'endtime' => 'endtime',
 		],
 		'sortby' => 'sorting',
-		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_company.svg'
+		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_company.svg',
+		'security' => [
+			'ignorePageTypeRestriction' => TRUE
+		]
 	],
 	'interface' => [],
 	'types' => [
 		'1' => [
-			'showitem' => '--palette--;;sysLanguageAndHidden,job_id,zip,city,street,name,state,country,description,contact,--palette--,--div--;LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tca.seo_tab,identifying_url,--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access,starttime,endtime',
+			'showitem' => '--palette--;;sysLanguageAndHidden,job_id,zip,city,street,name,state,country,description,contact,--palette--,--div--;LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tca.seo_tab,identifying_url,--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access,starttime,endtime,hidden',
 		],
 	],
 	'palettes' => [
@@ -63,19 +41,7 @@ $columns = [
 		'sys_language_uid' => [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
-			'config' => [
-				'type' => 'select',
-				'renderType' => 'selectSingle',
-				'special' => 'languages',
-				'default' => 0,
-				'items' => [
-					[
-						'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-						-1,
-						'flags-multiple'
-					]
-				]
-			],
+			'config' => ['type' => 'language'],
 		],
 		'l10n_parent' => [
 			'displayCond' => 'FIELD:sys_language_uid:>:0',
@@ -84,7 +50,7 @@ $columns = [
 				'type' => 'select',
 				'renderType' => 'selectSingle',
 				'items' => [
-					['', 0],
+					['label' => '', 'value' => 0],
 				],
 				'foreign_table' => 'tx_sgjobs_domain_model_company',
 				'foreign_table_where' => 'AND tx_sgjobs_domain_model_company.pid=###CURRENT_PID### AND tx_sgjobs_domain_model_company.sys_language_uid IN (-1,0)',
@@ -114,14 +80,10 @@ $columns = [
 			'l10n_mode' => 'mergeIfNotBlank',
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
 			'config' => [
-				'type' => 'input',
+				'type' => 'datetime',
+				'format' => 'datetime',
 				'size' => 13,
-				'eval' => 'datetime,int',
-				'checkbox' => 0,
-				'default' => 0,
-				'range' => [
-					'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
-				],
+				'default' => 0
 			],
 		],
 		'endtime' => [
@@ -129,14 +91,10 @@ $columns = [
 			'l10n_mode' => 'mergeIfNotBlank',
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
 			'config' => [
-				'type' => 'input',
+				'type' => 'datetime',
 				'size' => 13,
-				'eval' => 'datetime,int',
-				'checkbox' => 0,
-				'default' => 0,
-				'range' => [
-					'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
-				],
+				'format' => 'datetime',
+				'default' => 0
 			],
 		],
 		'zip' => [
@@ -217,9 +175,8 @@ $columns = [
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.contact',
 			'config' => [
 				'type' => 'select',
-				'items' => [['None', 0]],
+				'items' => [['label' => 'None', 'value' => 0]],
 				'renderType' => 'selectSingle',
-				'internal_type' => 'db',
 				'foreign_table' => 'tx_sgjobs_domain_model_contact',
 				'foreign_table_where' => 'tx_sgjobs_domain_model_contact.hidden = FALSE',
 				'size' => 1,
@@ -239,16 +196,15 @@ $columns = [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_company.identifyingUrl',
 			'config' => [
-				'type' => 'input',
-				'renderType' => 'inputLink',
-				'fieldControl' => [
-					'linkPopup' => [
-						'options' => [
-							'blindLinkFields' => 'class,target,title',
-							'blindLinkOptions' => 'file,folder,mail,spec'
-						],
-					],
+				'type' => 'link',
+				'allowedTypes' => [
+					'page', 'url', 'record'
 				],
+				'appearence' => [
+					'allowedOptions' => [
+						'params', 'rel'
+					]
+				]
 			],
 		],
 	],
diff --git a/Configuration/TCA/tx_sgjobs_domain_model_contact.php b/Configuration/TCA/tx_sgjobs_domain_model_contact.php
index 4569f013274911c6d97285adf1f33b5e0f562ee1..4fc88aa0a351e0c8e7cc0ba596a10dc557064512 100644
--- a/Configuration/TCA/tx_sgjobs_domain_model_contact.php
+++ b/Configuration/TCA/tx_sgjobs_domain_model_contact.php
@@ -1,28 +1,4 @@
 <?php
-/**
- *
- * Copyright notice
- *
- * (c) sgalinski Internet Services (https://www.sgalinski.de)
- *
- * All rights reserved
- *
- * This script is part of the TYPO3 project. The TYPO3 project is
- * free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * The GNU General Public License can be found at
- * http://www.gnu.org/copyleft/gpl.html.
- *
- * This script is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This copyright notice MUST APPEAR in all copies of the script!
- */
 
 $columns = [
 	'ctrl' => [
@@ -32,7 +8,6 @@ $columns = [
 		'label_alt_force' => 1,
 		'tstamp' => 'tstamp',
 		'crdate' => 'crdate',
-		'cruser_id' => 'cruser_id',
 		'searchFields' => 'title, first_name, last_name, email, phone, zip, city, state, country, street',
 		'versioningWS' => 2,
 		'versioning_followPages' => TRUE,
@@ -47,7 +22,10 @@ $columns = [
 			'endtime' => 'endtime',
 		],
 		'sortby' => 'sorting',
-		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_contact.svg'
+		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_contact.svg',
+		'security' => [
+			'ignorePageTypeRestriction' => TRUE
+		]
 	],
 	'interface' => [],
 	'types' => [
@@ -65,19 +43,7 @@ $columns = [
 		'sys_language_uid' => [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
-			'config' => [
-				'type' => 'select',
-				'renderType' => 'selectSingle',
-				'special' => 'languages',
-				'default' => 0,
-				'items' => [
-					[
-						'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-						-1,
-						'flags-multiple'
-					]
-				]
-			],
+			'config' => ['type' => 'language'],
 		],
 		'l10n_parent' => [
 			'displayCond' => 'FIELD:sys_language_uid:>:0',
@@ -86,7 +52,7 @@ $columns = [
 				'type' => 'select',
 				'renderType' => 'selectSingle',
 				'items' => [
-					['', 0],
+					['label' => '', 'value' => 0],
 				],
 				'foreign_table' => 'tx_sgjobs_domain_model_contact',
 				'foreign_table_where' => 'AND tx_sgjobs_domain_model_contact.pid=###CURRENT_PID### AND tx_sgjobs_domain_model_contact.sys_language_uid IN (-1,0)',
@@ -116,14 +82,10 @@ $columns = [
 			'l10n_mode' => 'mergeIfNotBlank',
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
 			'config' => [
-				'type' => 'input',
+				'type' => 'datetime',
+				'format' => 'datetime',
 				'size' => 13,
-				'eval' => 'datetime,int',
-				'checkbox' => 0,
-				'default' => 0,
-				'range' => [
-					'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
-				],
+				'default' => 0
 			],
 		],
 		'endtime' => [
@@ -131,14 +93,10 @@ $columns = [
 			'l10n_mode' => 'mergeIfNotBlank',
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
 			'config' => [
-				'type' => 'input',
+				'type' => 'datetime',
 				'size' => 13,
-				'eval' => 'datetime,int',
-				'checkbox' => 0,
-				'default' => 0,
-				'range' => [
-					'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
-				],
+				'format' => 'datetime',
+				'default' => 0
 			],
 		],
 		'title' => [
@@ -171,16 +129,11 @@ $columns = [
 		'image' => [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_contact.image',
-			'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(
-				'image',
-				[
-					'appearance' => [
-						'useSortable' => TRUE,
-					],
-					'minitems' => 0,
-					'maxitems' => 1,
-				]
-			),
+			'config' => [
+				'type' => 'file',
+				'minitems' => 0,
+				'maxitems' => 1,
+			]
 		],
 		'phone' => [
 			'exclude' => TRUE,
diff --git a/Configuration/TCA/tx_sgjobs_domain_model_department.php b/Configuration/TCA/tx_sgjobs_domain_model_department.php
index 25b1531d47be4bea5749df4a371de7596d394306..04deda3053611122c17e0d19c0f9f20c52da3b27 100644
--- a/Configuration/TCA/tx_sgjobs_domain_model_department.php
+++ b/Configuration/TCA/tx_sgjobs_domain_model_department.php
@@ -1,27 +1,4 @@
 <?php
-/**
- * Copyright notice
- *
- * (c) sgalinski Internet Services (https://www.sgalinski.de)
- *
- * All rights reserved
- *
- * This script is part of the TYPO3 project. The TYPO3 project is
- * free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * The GNU General Public License can be found at
- * http://www.gnu.org/copyleft/gpl.html.
- *
- * This script is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This copyright notice MUST APPEAR in all copies of the script!
- */
 
 $columns = [
 	'ctrl' => [
@@ -30,7 +7,6 @@ $columns = [
 		'label_alt_force' => 1,
 		'tstamp' => 'tstamp',
 		'crdate' => 'crdate',
-		'cruser_id' => 'cruser_id',
 		'searchFields' => 'title',
 		'versioningWS' => 2,
 		'versioning_followPages' => TRUE,
@@ -45,7 +21,10 @@ $columns = [
 			'endtime' => 'endtime',
 		],
 		'sortby' => 'sorting',
-		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_department.svg'
+		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_department.svg',
+		'security' => [
+			'ignorePageTypeRestriction' => TRUE
+		]
 	],
 	'interface' => [],
 	'types' => [
@@ -63,19 +42,7 @@ $columns = [
 		'sys_language_uid' => [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
-			'config' => [
-				'type' => 'select',
-				'renderType' => 'selectSingle',
-				'special' => 'languages',
-				'default' => 0,
-				'items' => [
-					[
-						'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-						-1,
-						'flags-multiple'
-					]
-				]
-			],
+			'config' => ['type' => 'language'],
 		],
 		'l10n_parent' => [
 			'displayCond' => 'FIELD:sys_language_uid:>:0',
@@ -84,7 +51,7 @@ $columns = [
 				'type' => 'select',
 				'renderType' => 'selectSingle',
 				'items' => [
-					['', 0],
+					['label' => '', 'value' => 0],
 				],
 				'foreign_table' => 'tx_sgjobs_domain_model_department',
 				'foreign_table_where' => 'AND tx_sgjobs_domain_model_department.pid=###CURRENT_PID### AND tx_sgjobs_domain_model_department.sys_language_uid IN (-1,0)',
@@ -114,14 +81,10 @@ $columns = [
 			'l10n_mode' => 'mergeIfNotBlank',
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
 			'config' => [
-				'type' => 'input',
+				'type' => 'datetime',
+				'format' => 'datetime',
 				'size' => 13,
-				'eval' => 'datetime,int',
-				'checkbox' => 0,
-				'default' => 0,
-				'range' => [
-					'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
-				],
+				'default' => 0
 			],
 		],
 		'endtime' => [
@@ -129,14 +92,10 @@ $columns = [
 			'l10n_mode' => 'mergeIfNotBlank',
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
 			'config' => [
-				'type' => 'input',
+				'type' => 'datetime',
 				'size' => 13,
-				'eval' => 'datetime,int',
-				'checkbox' => 0,
-				'default' => 0,
-				'range' => [
-					'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
-				],
+				'format' => 'datetime',
+				'default' => 0
 			],
 		],
 		'title' => [
@@ -145,7 +104,8 @@ $columns = [
 			'config' => [
 				'type' => 'input',
 				'size' => 30,
-				'eval' => 'trim,required'
+				'eval' => 'trim',
+				'required' => TRUE
 			],
 		]
 	],
diff --git a/Configuration/TCA/tx_sgjobs_domain_model_experience_level.php b/Configuration/TCA/tx_sgjobs_domain_model_experience_level.php
index 2d8beddf0aa109f87028c1e7961adb4cd5cb5338..41b60fddcb55a3a542bf5415f44459e94bd06b8f 100644
--- a/Configuration/TCA/tx_sgjobs_domain_model_experience_level.php
+++ b/Configuration/TCA/tx_sgjobs_domain_model_experience_level.php
@@ -1,27 +1,4 @@
 <?php
-/**
- * Copyright notice
- *
- * (c) sgalinski Internet Services (https://www.sgalinski.de)
- *
- * All rights reserved
- *
- * This script is part of the TYPO3 project. The TYPO3 project is
- * free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * The GNU General Public License can be found at
- * http://www.gnu.org/copyleft/gpl.html.
- *
- * This script is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This copyright notice MUST APPEAR in all copies of the script!
- */
 
 $columns = [
 	'ctrl' => [
@@ -30,7 +7,6 @@ $columns = [
 		'label_alt_force' => 1,
 		'tstamp' => 'tstamp',
 		'crdate' => 'crdate',
-		'cruser_id' => 'cruser_id',
 		'searchFields' => 'title',
 		'versioningWS' => 2,
 		'versioning_followPages' => TRUE,
@@ -45,7 +21,10 @@ $columns = [
 			'endtime' => 'endtime',
 		],
 		'sortby' => 'sorting',
-		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_experience_level.svg'
+		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_experience_level.svg',
+		'security' => [
+			'ignorePageTypeRestriction' => TRUE
+		]
 	],
 	'interface' => [],
 	'types' => [
@@ -63,19 +42,7 @@ $columns = [
 		'sys_language_uid' => [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
-			'config' => [
-				'type' => 'select',
-				'renderType' => 'selectSingle',
-				'special' => 'languages',
-				'default' => 0,
-				'items' => [
-					[
-						'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-						-1,
-						'flags-multiple'
-					]
-				]
-			],
+			'config' => ['type' => 'language'],
 		],
 		'l10n_parent' => [
 			'displayCond' => 'FIELD:sys_language_uid:>:0',
@@ -84,7 +51,7 @@ $columns = [
 				'type' => 'select',
 				'renderType' => 'selectSingle',
 				'items' => [
-					['', 0],
+					['label' => '', 'value' => 0],
 				],
 				'foreign_table' => 'tx_sgjobs_domain_model_experience_level',
 				'foreign_table_where' => 'AND tx_sgjobs_domain_model_experience_level.pid=###CURRENT_PID### AND tx_sgjobs_domain_model_experience_level.sys_language_uid IN (-1,0)',
@@ -114,14 +81,10 @@ $columns = [
 			'l10n_mode' => 'mergeIfNotBlank',
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
 			'config' => [
-				'type' => 'input',
+				'type' => 'datetime',
+				'format' => 'datetime',
 				'size' => 13,
-				'eval' => 'datetime,int',
-				'checkbox' => 0,
-				'default' => 0,
-				'range' => [
-					'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
-				],
+				'default' => 0
 			],
 		],
 		'endtime' => [
@@ -129,14 +92,10 @@ $columns = [
 			'l10n_mode' => 'mergeIfNotBlank',
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
 			'config' => [
-				'type' => 'input',
+				'type' => 'datetime',
 				'size' => 13,
-				'eval' => 'datetime,int',
-				'checkbox' => 0,
-				'default' => 0,
-				'range' => [
-					'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
-				],
+				'format' => 'datetime',
+				'default' => 0
 			],
 		],
 		'title' => [
@@ -145,7 +104,8 @@ $columns = [
 			'config' => [
 				'type' => 'input',
 				'size' => 30,
-				'eval' => 'trim,required'
+				'eval' => 'trim',
+				'required' => TRUE
 			],
 		]
 	],
diff --git a/Configuration/TCA/tx_sgjobs_domain_model_job.php b/Configuration/TCA/tx_sgjobs_domain_model_job.php
index 4f46369926ad128edbf70741fcabd6593c60da65..dc086e2343498e2cca079c9dea883bdb11f5a0a2 100644
--- a/Configuration/TCA/tx_sgjobs_domain_model_job.php
+++ b/Configuration/TCA/tx_sgjobs_domain_model_job.php
@@ -1,30 +1,8 @@
 <?php
-/**
- *
- * Copyright notice
- *
- * (c) sgalinski Internet Services (https://www.sgalinski.de)
- *
- * All rights reserved
- *
- * This script is part of the TYPO3 project. The TYPO3 project is
- * free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * The GNU General Public License can be found at
- * http://www.gnu.org/copyleft/gpl.html.
- *
- * This script is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This copyright notice MUST APPEAR in all copies of the script!
- */
 
-\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes(
+use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
+
+ExtensionManagementUtility::addToAllTCAtypes(
 	'tx_sgjobs_domain_model_job',
 	''
 );
@@ -34,7 +12,6 @@ $columns = [
 		'label' => 'title',
 		'tstamp' => 'tstamp',
 		'crdate' => 'crdate',
-		'cruser_id' => 'cruser_id',
 		'searchFields' => 'title, job_id, path_segment, start_date, alternative_start_date, location, apply_external_link, description, task, qualification',
 		'versioningWS' => 2,
 		'versioning_followPages' => TRUE,
@@ -49,7 +26,10 @@ $columns = [
 			'endtime' => 'endtime',
 		],
 		'sortby' => 'sorting',
-		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_job.svg'
+		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_job.svg',
+		'security' => [
+			'ignorePageTypeRestriction' => TRUE
+		]
 	],
 	'interface' => [],
 	'types' => [
@@ -87,19 +67,7 @@ $columns = [
 		'sys_language_uid' => [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
-			'config' => [
-				'type' => 'select',
-				'renderType' => 'selectSingle',
-				'special' => 'languages',
-				'default' => 0,
-				'items' => [
-					[
-						'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-						-1,
-						'flags-multiple'
-					]
-				]
-			],
+			'config' => ['type' => 'language'],
 		],
 		'l10n_parent' => [
 			'displayCond' => 'FIELD:sys_language_uid:>:0',
@@ -108,7 +76,7 @@ $columns = [
 				'type' => 'select',
 				'renderType' => 'selectSingle',
 				'items' => [
-					['', 0],
+					['label' => '', 'value' => 0],
 				],
 				'foreign_table' => 'tx_sgjobs_domain_model_job',
 				'foreign_table_where' => 'AND tx_sgjobs_domain_model_job.pid=###CURRENT_PID### AND tx_sgjobs_domain_model_job.sys_language_uid IN (-1,0)',
@@ -145,9 +113,7 @@ $columns = [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
 			'config' => [
-				'type' => 'input',
-				'renderType' => 'inputDateTime',
-				'eval' => 'datetime,int',
+				'type' => 'datetime',
 				'default' => 0
 			],
 			'l10n_mode' => 'exclude',
@@ -157,9 +123,7 @@ $columns = [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
 			'config' => [
-				'type' => 'input',
-				'renderType' => 'inputDateTime',
-				'eval' => 'datetime,int',
+				'type' => 'datetime',
 				'default' => 0,
 				'range' => [
 					'upper' => mktime(0, 0, 0, 1, 1, 2038)
@@ -206,11 +170,11 @@ $columns = [
 		'attachment' => [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.attachment',
-			'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(
-				'attachment',
-				['maxitems' => 1],
-				'pdf'
-			)
+			'config' => [
+				'type' => 'file',
+				'maxitems' => 1,
+				'allowed' => ['pdf']
+			]
 		],
 		'department' => [
 			'exclude' => TRUE,
@@ -281,11 +245,9 @@ $columns = [
 			'l10n_mode' => 'exclude',
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.start_date',
 			'config' => [
-				'type' => 'input',
-				'renderType' => 'inputDateTime',
+				'type' => 'datetime',
 				'size' => 13,
-				'max' => 20,
-				'eval' => 'date'
+				'format' => 'date'
 			],
 		],
 		'alternative_start_date' => [
@@ -411,14 +373,14 @@ $columns = [
 				'type' => 'select',
 				'renderType' => 'selectMultipleSideBySide',
 				'items' => [
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.full_time', 'FULL_TIME'],
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.part_time', 'PART_TIME'],
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.contractor', 'CONTRACTOR'],
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.temporary', 'TEMPORARY'],
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.intern', 'INTERN'],
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.volunteer', 'VOLUNTEER'],
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.per_diem', 'PER_DIEM'],
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.other', 'OTHER']
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.full_time', 'value' => 'FULL_TIME'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.part_time', 'value' => 'PART_TIME'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.contractor', 'value' => 'CONTRACTOR'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.temporary', 'value' => 'TEMPORARY'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.intern', 'value' => 'INTERN'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.volunteer', 'value' => 'VOLUNTEER'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.per_diem', 'value' => 'PER_DIEM'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.employment_types.other', 'value' => 'OTHER']
 				]
 			]
 		],
@@ -427,9 +389,8 @@ $columns = [
 			'l10n_mode' => 'exclude',
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.date_posted',
 			'config' => [
-				'type' => 'input',
-				'renderType' => 'inputDateTime',
-				'eval' => 'date'
+				'type' => 'datetime',
+				'format' => 'date'
 			],
 		],
 		'valid_through' => [
@@ -437,9 +398,8 @@ $columns = [
 			'l10n_mode' => 'exclude',
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.valid_through',
 			'config' => [
-				'type' => 'input',
-				'renderType' => 'inputDateTime',
-				'eval' => 'date'
+				'type' => 'datetime',
+				'format' => 'date'
 			],
 		],
 		'salary_currency' => [
@@ -460,11 +420,11 @@ $columns = [
 				'type' => 'select',
 				'renderType' => 'selectSingle',
 				'items' => [
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.salary_unit.hour', 'HOUR'],
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.salary_unit.day', 'DAY'],
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.salary_unit.week', 'WEEK'],
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.salary_unit.month', 'MONTH'],
-					['LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.salary_unit.year', 'YEAR'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.salary_unit.hour', 'value' => 'HOUR'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.salary_unit.day', 'value' => 'DAY'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.salary_unit.week', 'value' => 'WEEK'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.salary_unit.month', 'value' => 'MONTH'],
+					['label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.salary_unit.year', 'value' => 'YEAR'],
 				]
 			]
 		],
@@ -472,18 +432,18 @@ $columns = [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.base_salary',
 			'config' => [
-				'type' => 'input',
-				'eval' => 'double2',
+				'type' => 'number',
 				'max' => 15,
+				'format' => 'decimal',
 			],
 		],
 		'max_salary' => [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.max_salary',
 			'config' => [
-				'type' => 'input',
-				'eval' => 'double2',
+				'type' => 'number',
 				'max' => 15,
+				'format' => 'decimal',
 			],
 		],
 		'apply_external_link' => [
@@ -501,7 +461,6 @@ $columns = [
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job.related_jobs',
 			'config' => [
 				'type' => 'group',
-				'internal_type' => 'db',
 				'allowed' => 'tx_sgjobs_domain_model_job',
 				'size' => 5,
 				'minitems' => 0,
diff --git a/Configuration/TCA/tx_sgjobs_domain_model_job_application.php b/Configuration/TCA/tx_sgjobs_domain_model_job_application.php
index ef216edaffd9c402d425b37751fb1b0b17ac422e..89030fc132d683831044dddd5101b1aad2aabfee 100644
--- a/Configuration/TCA/tx_sgjobs_domain_model_job_application.php
+++ b/Configuration/TCA/tx_sgjobs_domain_model_job_application.php
@@ -1,28 +1,4 @@
 <?php
-/**
- *
- * Copyright notice
- *
- * (c) sgalinski Internet Services (https://www.sgalinski.de)
- *
- * All rights reserved
- *
- * This script is part of the TYPO3 project. The TYPO3 project is
- * free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * The GNU General Public License can be found at
- * http://www.gnu.org/copyleft/gpl.html.
- *
- * This script is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This copyright notice MUST APPEAR in all copies of the script!
- */
 
 $columns = [
 	'ctrl' => [
@@ -32,7 +8,6 @@ $columns = [
 		'label_alt_force' => 1,
 		'tstamp' => 'tstamp',
 		'crdate' => 'crdate',
-		'cruser_id' => 'cruser_id',
 		'searchFields' => 'job_id, job, job_title, company, gender, first_name, last_name, street, city, zip, country, nationality, education, birth_date, phone, mobile, email, message, cover_letter, certificate, cv',
 		'versioningWS' => 2,
 		'versioning_followPages' => TRUE,
@@ -47,7 +22,10 @@ $columns = [
 			'endtime' => 'endtime',
 		],
 		'sortby' => 'sorting',
-		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_job.svg'
+		'iconfile' => 'EXT:sg_jobs/Resources/Public/Icons/tx_sgjobs_domain_model_job.svg',
+		'security' => [
+			'ignorePageTypeRestriction' => TRUE
+		]
 	],
 	'interface' => [],
 	'types' => [
@@ -65,19 +43,7 @@ $columns = [
 		'sys_language_uid' => [
 			'exclude' => TRUE,
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
-			'config' => [
-				'type' => 'select',
-				'renderType' => 'selectSingle',
-				'special' => 'languages',
-				'default' => 0,
-				'items' => [
-					[
-						'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.allLanguages',
-						-1,
-						'flags-multiple'
-					]
-				]
-			],
+			'config' => ['type' => 'language'],
 		],
 		'l10n_parent' => [
 			'displayCond' => 'FIELD:sys_language_uid:>:0',
@@ -86,7 +52,7 @@ $columns = [
 				'type' => 'select',
 				'renderType' => 'selectSingle',
 				'items' => [
-					['', 0],
+					['label' => '', 'value' => 0],
 				],
 				'foreign_table' => 'tx_sgjobs_domain_model_job_application',
 				'foreign_table_where' => 'AND tx_sgjobs_domain_model_job_application.pid=###CURRENT_PID### AND tx_sgjobs_domain_model_job_application.sys_language_uid IN (-1,0)',
@@ -116,14 +82,10 @@ $columns = [
 			'l10n_mode' => 'mergeIfNotBlank',
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
 			'config' => [
-				'type' => 'input',
+				'type' => 'datetime',
+				'format' => 'datetime',
 				'size' => 13,
-				'eval' => 'datetime,int',
-				'checkbox' => 0,
-				'default' => 0,
-				'range' => [
-					'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
-				],
+				'default' => 0
 			],
 		],
 		'endtime' => [
@@ -131,14 +93,10 @@ $columns = [
 			'l10n_mode' => 'mergeIfNotBlank',
 			'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
 			'config' => [
-				'type' => 'input',
+				'type' => 'datetime',
 				'size' => 13,
-				'eval' => 'datetime,int',
-				'checkbox' => 0,
-				'default' => 0,
-				'range' => [
-					'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
-				],
+				'format' => 'datetime',
+				'default' => 0
 			],
 		],
 		'job_id' => [
@@ -156,7 +114,6 @@ $columns = [
 			'config' => [
 				'type' => 'select',
 				'renderType' => 'selectSingle',
-				'internal_type' => 'db',
 				'foreign_table' => 'tx_sgjobs_domain_model_job',
 				'size' => 1,
 				'maxitems' => 1,
@@ -329,29 +286,32 @@ $columns = [
 		'cover_letter' => [
 			'exclude' => FALSE,
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job_application.cover_letter',
-			'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(
-				'cover_letter',
-				['maxitems' => 1, 'minitems' => 1],
-				'pdf'
-			),
+			'config' => [
+				'type' => 'file',
+				'maxitems' => 1,
+				'minitems' => 1,
+				'allowed' => ['pdf']
+			]
 		],
 		'certificate' => [
 			'exclude' => FALSE,
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job_application.certificate',
-			'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(
-				'certificate',
-				['maxitems' => 1, 'minitems' => 1],
-				'pdf'
-			),
+			'config' => [
+				'type' => 'file',
+				'maxitems' => 1,
+				'minitems' => 1,
+				'allowed' => ['pdf']
+			]
 		],
 		'cv' => [
 			'exclude' => FALSE,
 			'label' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_db.xlf:tx_sgjobs_domain_model_job_application.cv',
-			'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig(
-				'cv',
-				['maxitems' => 1, 'minitems' => 1],
-				'pdf'
-			),
+			'config' => [
+				'type' => 'file',
+				'maxitems' => 1,
+				'minitems' => 1,
+				'allowed' => ['pdf']
+			]
 		],
 		'privacy_policy' => [
 			'exclude' => FALSE,
diff --git a/Configuration/TypoScript/Common/setup.typoscript b/Configuration/TypoScript/Common/setup.typoscript
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/Resources/Private/Backend/Layouts/Default.html b/Resources/Private/Backend/Layouts/Default.html
deleted file mode 100644
index 1f8de183d2127a4debd6ba833db7c94caa591005..0000000000000000000000000000000000000000
--- a/Resources/Private/Backend/Layouts/Default.html
+++ /dev/null
@@ -1,52 +0,0 @@
-{namespace core = TYPO3\CMS\Core\ViewHelpers}
-{namespace sg=SGalinski\SgJobs\ViewHelpers}
-
-
-<f:be.container
-	includeCssFiles="{0: '{f:uri.resource(path: \'StyleSheets/backend.css\')}'}"
-	includeRequireJsModules="{
-0: 'TYPO3/CMS/Backend/ContextMenu',
-1: 'TYPO3/CMS/Backend/Tooltip',
-2: 'TYPO3/CMS/SgJobs/Backend/SgJobs'}">
-	<div class="module" data-module-id="" data-module-name="">
-		<div class="module-docheader t3js-module-docheader">
-			<div
-				class="module-docheader-bar module-docheader-bar-navigation t3js-module-docheader-bar t3js-module-docheader-bar-navigation">
-				<div class="module-docheader-bar-column-left">
-				</div>
-				<div class="module-docheader-bar-column-right">
-			<span class="typo3-docheader-pagePath">
-				<f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.path"/>: <f:format.raw>{docHeader.metaInformation.path}</f:format.raw>
-			</span>
-					<f:format.raw>{docHeader.metaInformation.recordInformation}</f:format.raw>
-				</div>
-			</div>
-			<div
-				class="module-docheader-bar module-docheader-bar-buttons t3js-module-docheader-bar t3js-module-docheader-bar-buttons">
-				<div class="module-docheader-bar-column-left">
-					<div class="btn-toolbar" role="toolbar" aria-label="">
-						<f:render section="iconButtons"/>
-					</div>
-				</div>
-				<div class="module-docheader-bar-column-right">
-					<f:render partial="ButtonBar" arguments="{buttons:docHeader.buttons.right}"/>
-				</div>
-			</div>
-		</div>
-	<f:if condition="{V11}">
-		<f:then>
-			<div class="module-body t3js-module-body">
-		</f:then>
-		<f:else>
-			<div id="typo3-docbody">
-		</f:else>
-	</f:if>
-		<div id="typo3-inner-docbody">
-			<h1>
-				<f:render section="headline"/>
-			</h1>
-			<f:render section="main"/>
-		</div>
-	</div>
-	</div>
-</f:be.container>
diff --git a/Resources/Private/Backend/Partials/Error.html b/Resources/Private/Backend/Partials/Error.html
deleted file mode 100644
index a611c0d4dff3c8ed0989b07b5e747d3abe6deb8e..0000000000000000000000000000000000000000
--- a/Resources/Private/Backend/Partials/Error.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<div class="alert alert-danger">
-  <strong>Error:</strong> <f:translate key="backend.message.error" />
-</div>
\ No newline at end of file
diff --git a/Resources/Private/Backend/Templates/JobApplication.html b/Resources/Private/Backend/Templates/JobApplication.html
index edcf36b3e3ad9e90042278705c100632f1d0ed90..d4cdfdd69894fa54c93ecfd3a541140e476314e6 100644
--- a/Resources/Private/Backend/Templates/JobApplication.html
+++ b/Resources/Private/Backend/Templates/JobApplication.html
@@ -3,6 +3,10 @@
 <f:asset.css identifier="sg_jobs-pluginpreview" href="EXT:sg_jobs/Resources/Public/StyleSheets/pluginpreview.css" />
 
 <be:link.editRecord table="tt_content" uid="{uid}">
+	<h4>
+		<span class="badge text-bg-primary"><f:translate key="{headerLabel}" /></span>
+	</h4>
+
 	<br/>
 
 	<table class="table table-striped table-bordered sg_jobs-backend-preview-table">
diff --git a/Resources/Private/Backend/Templates/JobTeaser.html b/Resources/Private/Backend/Templates/JobTeaser.html
index db52dd988fe2c2f7a45a9aab3484e1cdb86e9b37..6c84ffd29fe2280c56e177b00ef60e84fa92a0ba 100644
--- a/Resources/Private/Backend/Templates/JobTeaser.html
+++ b/Resources/Private/Backend/Templates/JobTeaser.html
@@ -3,6 +3,10 @@
 <f:asset.css identifier="sg_jobs-pluginpreview" href="EXT:sg_jobs/Resources/Public/StyleSheets/pluginpreview.css" />
 
 <be:link.editRecord table="tt_content" uid="{uid}">
+	<h4>
+		<span class="badge text-bg-primary"><f:translate key="{headerLabel}" /></span>
+	</h4>
+
 	<br/>
 
 	<table class="table table-striped table-bordered sg_jobs-backend-preview-table">
diff --git a/Resources/Private/Backend/Templates/Joblist.html b/Resources/Private/Backend/Templates/Joblist.html
index 4d8317ed1c44b7d68f25d20c443b411dea8aa5ff..cd53d70e06f0bd4fd462425cf3b6a7de5b06e396 100644
--- a/Resources/Private/Backend/Templates/Joblist.html
+++ b/Resources/Private/Backend/Templates/Joblist.html
@@ -3,6 +3,10 @@
 <f:asset.css identifier="sg_jobs-pluginpreview" href="EXT:sg_jobs/Resources/Public/StyleSheets/pluginpreview.css" />
 
 <be:link.editRecord table="tt_content" uid="{uid}">
+	<h4>
+		<span class="badge text-bg-primary"><f:translate key="{headerLabel}" /></span>
+	</h4>
+
 	<br/>
 
 	<table class="table table-striped table-bordered sg_jobs-backend-preview-table">
diff --git a/Resources/Private/Layouts/Backend.html b/Resources/Private/Layouts/Backend.html
new file mode 100644
index 0000000000000000000000000000000000000000..42fffa41c15d1cc6ecbf1d5bcdbe4cb58f7a94b0
--- /dev/null
+++ b/Resources/Private/Layouts/Backend.html
@@ -0,0 +1,45 @@
+{namespace core = TYPO3\CMS\Core\ViewHelpers}
+{namespace sg=SGalinski\SgJobs\ViewHelpers}
+
+<f:be.pageRenderer
+	includeCssFiles="{0: '{f:uri.resource(path: \'StyleSheets/backend.css\')}'}"
+	includeRequireJsModules="{
+		0: 'TYPO3/CMS/Backend/ContextMenu',
+		1: 'TYPO3/CMS/Backend/Tooltip',
+		2: 'TYPO3/CMS/SgJobs/Backend/SgJobs'
+	}" />
+<div class="module" data-module-id="" data-module-name="">
+	<div class="module-docheader t3js-module-docheader">
+		<div
+			class="module-docheader-bar module-docheader-bar-navigation t3js-module-docheader-bar t3js-module-docheader-bar-navigation">
+			<div class="module-docheader-bar-column-left">
+			</div>
+			<div class="module-docheader-bar-column-right">
+				<span class="typo3-docheader-pagePath">
+					<f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.path"/>:
+					<f:format.raw>{docHeader.metaInformation.path}</f:format.raw>
+				</span>
+				<f:format.raw>{docHeader.metaInformation.recordInformation}</f:format.raw>
+			</div>
+		</div>
+		<div
+			class="module-docheader-bar module-docheader-bar-buttons t3js-module-docheader-bar t3js-module-docheader-bar-buttons">
+			<div class="module-docheader-bar-column-left">
+				<div class="btn-toolbar" role="toolbar" aria-label="">
+					<f:render section="iconButtons"/>
+				</div>
+			</div>
+			<div class="module-docheader-bar-column-right">
+				<f:render partial="Backend/ButtonBar" arguments="{buttons:docHeader.buttons.right}"/>
+			</div>
+		</div>
+	</div>
+	<div class="module-body t3js-module-body">
+		<div id="typo3-inner-docbody">
+			<h1>
+				<f:render section="headline"/>
+			</h1>
+			<f:render section="main"/>
+		</div>
+	</div>
+</div>
diff --git a/Resources/Private/Backend/Partials/ButtonBar.html b/Resources/Private/Partials/Backend/ButtonBar.html
similarity index 100%
rename from Resources/Private/Backend/Partials/ButtonBar.html
rename to Resources/Private/Partials/Backend/ButtonBar.html
diff --git a/Resources/Private/Backend/Partials/CreateJob.html b/Resources/Private/Partials/Backend/CreateJob.html
similarity index 100%
rename from Resources/Private/Backend/Partials/CreateJob.html
rename to Resources/Private/Partials/Backend/CreateJob.html
diff --git a/Resources/Private/Backend/Partials/Filter.html b/Resources/Private/Partials/Backend/Filter.html
similarity index 81%
rename from Resources/Private/Backend/Partials/Filter.html
rename to Resources/Private/Partials/Backend/Filter.html
index ac0c65f0235aa6982f2e2817d8068bd186336dfe..affedb3fbb6d250b6e97bdd65e34487ccb1dc3f1 100644
--- a/Resources/Private/Backend/Partials/Filter.html
+++ b/Resources/Private/Partials/Backend/Filter.html
@@ -1,12 +1,20 @@
 {namespace be=TYPO3\CMS\Backend\ViewHelpers}
-<f:form action="index" controller="Backend" method="post" objectName="filters" object="{filters}">
+
+<f:form action="index" controller="Backend" method="post" objectName="filters">
 	<div class="row">
 		<div class="col-xs-6 col-6 col-sm-6">
 			<div class="form-group">
 				<label for="filter-locations">
 					<f:translate key="backend.filters.locations" />
 				</label>
-				<f:form.select class="form-control" multiple="1" size="4" property="locations" optionLabelField="name" optionValueField="city" options="{locationOptions}" id="filter-locations" />
+				<f:form.select class="form-control"
+							   multiple="1"
+							   size="4"
+							   property="locations"
+							   optionLabelField="name"
+							   optionValueField="city"
+							   options="{locationOptions}"
+							   id="filter-locations" />
 				<small>
 					<f:format.raw><f:translate key="backend.filters.locations.description" /></f:format.raw>
 				</small>
@@ -30,6 +38,5 @@
 				</f:form.button>
 			</div>
 		</div>
-
 	</div>
 </f:form>
diff --git a/Resources/Private/Backend/Partials/Pagination.html b/Resources/Private/Partials/Backend/Pagination.html
similarity index 100%
rename from Resources/Private/Backend/Partials/Pagination.html
rename to Resources/Private/Partials/Backend/Pagination.html
diff --git a/Resources/Private/Backend/Partials/SelectRoot.html b/Resources/Private/Partials/Backend/SelectRoot.html
similarity index 100%
rename from Resources/Private/Backend/Partials/SelectRoot.html
rename to Resources/Private/Partials/Backend/SelectRoot.html
diff --git a/Resources/Private/Backend/Templates/Index.html b/Resources/Private/Templates/Backend/Index.html
similarity index 83%
rename from Resources/Private/Backend/Templates/Index.html
rename to Resources/Private/Templates/Backend/Index.html
index 8533cc7640ab06c3edd154c205733eab01e66a0b..03f386983edcf64a514ab518deeb73ac58caf541 100644
--- a/Resources/Private/Backend/Templates/Index.html
+++ b/Resources/Private/Templates/Backend/Index.html
@@ -1,7 +1,7 @@
 {namespace sg=SGalinski\SgJobs\ViewHelpers}
 {namespace be=TYPO3\CMS\Backend\ViewHelpers}
 
-<f:layout name="Default"/>
+<f:layout name="Backend"/>
 
 <f:section name="iconButtons">
 </f:section>
@@ -14,8 +14,8 @@
 	<f:flashMessages />
 	<f:if condition="{pageUid}">
 		<f:then>
-			<f:render partial="Filter" arguments="{_all}"/>
-			<f:render partial="CreateJob" arguments="{_all}"/>
+			<f:render partial="Backend/Filter" arguments="{_all}"/>
+			<f:render partial="Backend/CreateJob" arguments="{_all}"/>
 
 			<p>
 				<f:translate key="backend.message.sorting"/>
@@ -34,7 +34,7 @@
 								<thead>
 									<tr>
 										<td class="bg-light" colspan="3">
-											<f:render partial="Pagination" arguments="{pagination: pagination}"/>
+											<f:render partial="Backend/Pagination" arguments="{pagination: pagination}"/>
 										</td>
 									</tr>
 								</thead>
@@ -67,9 +67,9 @@
 			</f:if>
 		</f:then>
 		<f:else>
-			<f:render partial="SelectRoot" arguments="{pages: pages}"/>
+			<f:render partial="Backend/SelectRoot" arguments="{pages: pages}"/>
 			<f:if condition="{isAdmin}">
-				<f:render partial="CreateJob" arguments="{pageUid: pageUid}"/>
+				<f:render partial="Backend/CreateJob" arguments="{pageUid: pageUid}"/>
 			</f:if>
 		</f:else>
 	</f:if>
diff --git a/Resources/Private/Templates/Joblist/ApplyForm.html b/Resources/Private/Templates/Joblist/ApplyForm.html
index 170e15937dfd9999f4cbbc9964f5cfc8ab81d172..68110fb631f8441946def34a2c4436dc728a928b 100644
--- a/Resources/Private/Templates/Joblist/ApplyForm.html
+++ b/Resources/Private/Templates/Joblist/ApplyForm.html
@@ -207,7 +207,7 @@
 							name="applyData" object="{applyData}" enctype="multipart/form-data">
 						<f:if condition="{job}">
 							<f:then>
-								<f:form.hidden property="job" value="{job}"/>
+								<f:form.hidden property="job" value="{job.uid}"/>
 								<f:form.hidden property="jobId" value="{job.jobId}"/>
 								<f:form.hidden property="jobTitle" value="{job.title}"/>
 							</f:then>
@@ -376,13 +376,11 @@
 								<label for="apply-country" class="smart-label">
 									<f:translate key="frontend.apply.country"/>
 								</label>
-								<f:form.select
-									value="{f:if(condition: '{sysLanguageUid} == 0', then: 'Deutschland', else: 'Germany')}"
-									property="country" id="apply-country" class="form-control"
-									options="{countries}"
-									optionLabelField="{f:if(condition: '{sysLanguageUid} == 0', then: 'cnShortDe', else: 'cnShortEn')}"
-									optionValueField="{f:if(condition: '{sysLanguageUid} == 0', then: 'cnShortDe', else: 'cnShortEn')}"
-								/>
+								<f:form.countrySelect
+									value="DE"
+									property="country"
+									id="apply-country"
+									class="form-control" />
 								<f:form.validationResults for="applyData.country">
 									<ul class="sg-jobs-validation-error parsley-errors-list filled">
 										<f:for each="{validationResults.errors}" as="error">
@@ -398,12 +396,11 @@
 								<label for="apply-nationality" class="smart-label">
 									<f:translate key="frontend.apply.nationality"/>
 								</label>
-								<f:form.select
-									value="{f:if(condition: '{sysLanguageUid} == 0', then: 'Deutschland', else: 'Germany')}"
-									property="nationality" id="apply-nationality" class="form-control" options="{countries}"
-									optionLabelField="{f:if(condition: '{sysLanguageUid} == 0', then: 'cnShortDe', else: 'cnShortEn')}"
-									optionValueField="{f:if(condition: '{sysLanguageUid} == 0', then: 'cnShortDe', else: 'cnShortEn')}"
-								/>
+								<f:form.countrySelect
+									value="DE"
+									property="nationality"
+									id="apply-nationality"
+									class="form-control" />
 								<f:form.validationResults for="applyData.nationality">
 									<ul class="sg-jobs-validation-error parsley-errors-list filled">
 										<f:for each="{validationResults.errors}" as="error">
diff --git a/UPGRADE.md b/UPGRADE.md
index 2e687dc00fa318496f3b587d7a625720f9810a42..bb436b28c289dc2a03dd28d7990a777d2196db04 100644
--- a/UPGRADE.md
+++ b/UPGRADE.md
@@ -1,3 +1,11 @@
+## Version 6 Breaking Changes
+
+- Dropped TYPO3 10 and 11 support
+- Dropped PHP 7 support
+- Removed DepartmentUpdateWizard
+- Removed widget UriViewHelper
+- Removed unused Common/setup.typoscript
+
 ## Version 5 Breaking Changes
 
 - Dropped TYPO3 9 support
diff --git a/composer.json b/composer.json
index 7e8c244c3b4859b8a9d6e3e4e3b1889639b32da9..602d86b1e3bc35ea372b9786cd3cbad76af06f72 100644
--- a/composer.json
+++ b/composer.json
@@ -6,12 +6,12 @@
 	"license": [
 		"GPL-2.0-or-later"
 	],
-	"version": "5.7.4",
+	"version": "6.0.0-dev",
 	"support": {
 		"issues": "https://gitlab.sgalinski.de/typo3/sg_jobs"
 	},
 	"require": {
-		"typo3/cms-core": "^10.4.0 || ^11.5.0",
+		"typo3/cms-core": "^12.4.0",
 		"sgalinski/sg-mail": ">=7.0.0",
 		"sgalinski/sg-ajax": ">=4.0.0"
 	},
diff --git a/ext_emconf.php b/ext_emconf.php
index e8932d5cbb5a6949e03ba4d2ed21c3da171d6288..17d74dc8f409fb03bd715e4251c7e46dd03d967b 100644
--- a/ext_emconf.php
+++ b/ext_emconf.php
@@ -4,11 +4,8 @@ $EM_CONF['sg_jobs'] = [
 	'title' => 'Jobs',
 	'description' => 'Manage and display your Job offers.',
 	'category' => 'plugin',
-	'version' => '5.7.4',
+	'version' => '6.0.0-dev',
 	'state' => 'stable',
-	'uploadfolder' => FALSE,
-	'createDirs' => '',
-	'clearcacheonload' => FALSE,
 	'author' => 'Stefan Galinski',
 	'author_email' => 'stefan@sgalinski.de',
 	'author_company' => 'sgalinski Internet Services (https://www.sgalinski.de)',
@@ -16,8 +13,8 @@ $EM_CONF['sg_jobs'] = [
 		[
 			'depends' =>
 				[
-					'typo3' => '10.4.0-11.5.99',
-					'php' => '7.3.0-8.1.99',
+					'typo3' => '12.4.0-12.4.99',
+					'php' => '8.1.0-8.3.99',
 					'sg_mail' => '>=7.0.0'
 				],
 			'conflicts' =>
diff --git a/ext_localconf.php b/ext_localconf.php
index c3fe89a895c1af0aee7670c9a7ce60064d57d883..f64a98c62bfce1ca5c1805df5e15b06e6a389dfa 100644
--- a/ext_localconf.php
+++ b/ext_localconf.php
@@ -1,64 +1,64 @@
 <?php
 
+use SGalinski\SgAjax\Service\AjaxRegistration;
+use SGalinski\SgJobs\Controller\Ajax\UploadController;
+use SGalinski\SgJobs\Controller\JoblistController;
+use SGalinski\SgJobs\Controller\JobTeaserController;
+use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
+use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
+
 call_user_func(
 	static function () {
-		\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScriptSetup(
-			'@import "EXT:sg_jobs/Configuration/TypoScript/Common/setup.typoscript"'
-		);
 		// Configure frontend plugins
-		\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+		ExtensionUtility::configurePlugin(
 			'SgJobs',
 			'Joblist',
 			[
 				// Available actions
-				\SGalinski\SgJobs\Controller\JoblistController::class => 'index'
+				JoblistController::class => 'index'
 			],
 			[
 				// Non-Cache actions
-				\SGalinski\SgJobs\Controller\JoblistController::class => 'index'
+				JoblistController::class => 'index'
 			]
 		);
-		\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+		ExtensionUtility::configurePlugin(
 			'SgJobs',
 			'JobApplication',
 			[
 				// Available actions
-				\SGalinski\SgJobs\Controller\JoblistController::class => 'applyForm, apply, empty'
+				JoblistController::class => 'applyForm, apply, empty'
 			],
 			[
 				// Non-Cache actions
-				\SGalinski\SgJobs\Controller\JoblistController::class => 'applyForm, apply, empty'
+				JoblistController::class => 'applyForm, apply, empty'
 			]
 		);
-		\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+		ExtensionUtility::configurePlugin(
 			'SgJobs',
 			'JobTeaser',
 			[
 				// Available actions
-				\SGalinski\SgJobs\Controller\JobTeaserController::class => 'index'
+				JobTeaserController::class => 'index'
 			],
 			[
 				// Non-Cache actions
-				\SGalinski\SgJobs\Controller\JobTeaserController::class => ''
+				JobTeaserController::class => ''
 			]
 		);
 
-		\SGalinski\SgAjax\Service\AjaxRegistration::configureAjaxFrontendPlugin(
+		AjaxRegistration::configureAjaxFrontendPlugin(
 			'sg_jobs',
 			[
-				\SGalinski\SgJobs\Controller\Ajax\UploadController::class => 'uploadCoverletter, uploadCv, uploadCertificate',
+				UploadController::class => 'uploadCoverletter, uploadCv, uploadCertificate',
 			]
 		);
 
-		// Backend preview for plugins
-		$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem']['sg_jobs']
-			= \SGalinski\SgJobs\Hooks\PageLayoutView\PluginRenderer::class;
-
-		\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScriptConstants(
+		ExtensionManagementUtility::addTypoScriptConstants(
 			'@import "EXT:sg_jobs/Configuration/TypoScript/Backend/constants.typoscript"'
 		);
 
-		\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScriptSetup(
+		ExtensionManagementUtility::addTypoScriptSetup(
 			'@import "EXT:sg_jobs/Configuration/TypoScript/Backend/setup.typoscript"'
 		);
 
@@ -66,28 +66,11 @@ call_user_func(
 		$GLOBALS['sg_mail']['sg_jobs']['ApplicationMail'] = 'EXT:sg_jobs/Configuration/SgMail/ApplicationMail.php';
 		$GLOBALS['sg_mail']['sg_jobs']['ApplicantMail'] = 'EXT:sg_jobs/Configuration/SgMail/ApplicantMail.php';
 
-		// Register the upgrade wizard
-		$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\SGalinski\SgJobs\Updates\DepartmentUpdateWizard::IDENTIFIER]
-			= \SGalinski\SgJobs\Updates\DepartmentUpdateWizard::class;
-
 		//include Plugin sg_jobs
-		\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPageTSConfig(
+		ExtensionManagementUtility::addPageTSConfig(
 			'@import "EXT:sg_jobs/Configuration/TsConfig/Page/NewContentElementWizard.tsconfig"'
 		);
 
 		$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['languagevisibility']['recordElementSupportedTables']['tx_sgjobs_domain_model_job'] = [];
-
-		// register icons for TYPO3 10 compatibility
-		if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo3Version(), '11.0.0', '<')) {
-			$iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
-				\TYPO3\CMS\Core\Imaging\IconRegistry::class
-			);
-
-			$iconRegistry->registerIcon(
-				'extension-sg_jobs-module',
-				\TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class,
-				['source' => 'EXT:sg_jobs/Resources/Public/Icons/module-sgjobs.svg']
-			);
-		}
 	}
 );
diff --git a/ext_tables.php b/ext_tables.php
deleted file mode 100644
index b6a5275689ff85b283f0fdf7e886fe85b61358ca..0000000000000000000000000000000000000000
--- a/ext_tables.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-call_user_func(
-	static function () {
-		\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages(
-			'tx_sgjobs_domain_model_job'
-		);
-		\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages(
-			'tx_sgjobs_domain_model_contact'
-		);
-		\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages(
-			'tx_sgjobs_domain_model_company'
-		);
-		\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages(
-			'tx_sgjobs_domain_model_job_application'
-		);
-		\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages(
-			'tx_sgjobs_domain_model_department'
-		);
-		\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages(
-			'tx_sgjobs_domain_model_experience_level'
-		);
-
-		// Register backend modules
-		\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
-			'SgJobs',
-			'web',
-			'Backend',
-			'',
-			[
-				\SGalinski\SgJobs\Controller\BackendController::class => 'index',
-			],
-			[
-				'access' => 'user,group',
-				'iconIdentifier' => 'extension-sg_jobs-module',
-				'labels' => 'LLL:EXT:sg_jobs/Resources/Private/Language/locallang_backend.xlf',
-			]
-		);
-	}
-);
diff --git a/ext_tables.sql b/ext_tables.sql
index e7dfc79cd5c152e995de7473ad92cb60e63351ac..36e1ebbda80205d9ac2394ffce099c94f3eacbe8 100644
--- a/ext_tables.sql
+++ b/ext_tables.sql
@@ -1,102 +1,102 @@
 CREATE TABLE tx_sgjobs_domain_model_job
 (
-	path_segment           text                DEFAULT ''    NOT NULL,
-	title                  text                DEFAULT ''    NOT NULL,
-	job_id                 varchar(30)         DEFAULT ''    NOT NULL,
-	attachment             int(11)             DEFAULT '0'   NOT NULL,
-	task                   text                DEFAULT ''    NOT NULL,
-	qualification          text                DEFAULT ''    NOT NULL,
-	alternative_start_date text                DEFAULT ''    NOT NULL,
-	start_date             int(11) unsigned    DEFAULT '0'   NOT NULL,
-	location               text                DEFAULT ''    NOT NULL,
-	location_requirements  text                DEFAULT ''    NOT NULL,
-	company                text                DEFAULT ''    NOT NULL,
-	telecommute_possible   tinyint(4) unsigned DEFAULT '0'   NOT NULL,
-	office_work_possible   tinyint(4) unsigned DEFAULT '1'   NOT NULL,
-	employment_types       text                DEFAULT ''    NOT NULL,
-	date_posted            int(11) unsigned    DEFAULT '0'   NOT NULL,
-	valid_through          int(11) unsigned    DEFAULT '0'   NOT NULL,
-	salary_currency        varchar(3)          DEFAULT 'EUR' NOT NULL,
-	base_salary            varchar(15)         DEFAULT ''    NOT NULL,
-	max_salary             varchar(15)         DEFAULT ''    NOT NULL,
-	salary_unit            varchar(5)          DEFAULT ''    NOT NULL,
-	description            text                DEFAULT ''    NOT NULL,
-	department             int(11)             DEFAULT '0'   NOT NULL,
-	experience_level       varchar(255)        DEFAULT '0'   NOT NULL,
-	contact                int(11) unsigned    DEFAULT '0'   NOT NULL,
-	featured_offer         tinyint(4) unsigned DEFAULT '0'   NOT NULL,
-	hide_apply_by_email    tinyint(4) unsigned DEFAULT '0'   NOT NULL,
-	hide_apply_by_postal   tinyint(4) unsigned DEFAULT '0'   NOT NULL,
-	apply_external_link    varchar(512)        DEFAULT ''    NOT NULL,
-	related_jobs           varchar(255)        DEFAULT ''    NOT NULL
+	path_segment           text,
+	title                  text,
+	job_id                 varchar(30)  DEFAULT ''    NOT NULL,
+	attachment             int(11) DEFAULT '0' NOT NULL,
+	task                   text,
+	qualification          text,
+	alternative_start_date text,
+	start_date             int(11) unsigned DEFAULT '0' NOT NULL,
+	location               text,
+	location_requirements  text,
+	company                text,
+	telecommute_possible   tinyint(4) unsigned DEFAULT '0' NOT NULL,
+	office_work_possible   tinyint(4) unsigned DEFAULT '1' NOT NULL,
+	employment_types       text,
+	date_posted            int(11) unsigned DEFAULT '0' NOT NULL,
+	valid_through          int(11) unsigned DEFAULT '0' NOT NULL,
+	salary_currency        varchar(3)   DEFAULT 'EUR' NOT NULL,
+	base_salary            varchar(15)  DEFAULT ''    NOT NULL,
+	max_salary             varchar(15)  DEFAULT ''    NOT NULL,
+	salary_unit            varchar(5)   DEFAULT ''    NOT NULL,
+	description            text,
+	department             int(11) DEFAULT '0' NOT NULL,
+	experience_level       varchar(255) DEFAULT '0'   NOT NULL,
+	contact                int(11) unsigned DEFAULT '0' NOT NULL,
+	featured_offer         tinyint(4) unsigned DEFAULT '0' NOT NULL,
+	hide_apply_by_email    tinyint(4) unsigned DEFAULT '0' NOT NULL,
+	hide_apply_by_postal   tinyint(4) unsigned DEFAULT '0' NOT NULL,
+	apply_external_link    varchar(512) DEFAULT ''    NOT NULL,
+	related_jobs           varchar(255) DEFAULT ''    NOT NULL
 );
 
 CREATE TABLE tx_sgjobs_domain_model_department
 (
-	title text DEFAULT '' NOT NULL
+	title text
 );
 
 CREATE TABLE tx_sgjobs_domain_model_experience_level
 (
-	title text DEFAULT '' NOT NULL
+	title text
 );
 
 CREATE TABLE tx_sgjobs_domain_model_company
 (
-	city            varchar(255)     DEFAULT ''  NOT NULL,
-	zip             varchar(255)     DEFAULT ''  NOT NULL,
-	name            varchar(255)     DEFAULT ''  NOT NULL,
-	street          varchar(255)     DEFAULT ''  NOT NULL,
-	state           varchar(255)     DEFAULT ''  NOT NULL,
-	country         varchar(255)     DEFAULT ''  NOT NULL,
-	description     text             DEFAULT ''  NOT NULL,
+	city            varchar(255) DEFAULT '' NOT NULL,
+	zip             varchar(255) DEFAULT '' NOT NULL,
+	name            varchar(255) DEFAULT '' NOT NULL,
+	street          varchar(255) DEFAULT '' NOT NULL,
+	state           varchar(255) DEFAULT '' NOT NULL,
+	country         varchar(255) DEFAULT '' NOT NULL,
+	description     text,
 	contact         int(11) unsigned DEFAULT '0' NOT NULL,
-	job_id          text             DEFAULT ''  NOT NULL,
-	identifying_url varchar(255)     DEFAULT ''  NOT NULL
+	job_id          text,
+	identifying_url varchar(255) DEFAULT '' NOT NULL
 );
 
 CREATE TABLE tx_sgjobs_domain_model_contact
 (
-	title      varchar(255)     DEFAULT '' NOT NULL,
-	first_name varchar(255)     DEFAULT '' NOT NULL,
-	last_name  varchar(255)     DEFAULT '' NOT NULL,
-	email      varchar(255)     DEFAULT '' NOT NULL,
-	phone      varchar(255)     DEFAULT '' NOT NULL,
-	city       varchar(255)     DEFAULT '' NOT NULL,
-	zip        varchar(255)     DEFAULT '' NOT NULL,
-	street     varchar(255)     DEFAULT '' NOT NULL,
-	state      varchar(255)     DEFAULT '' NOT NULL,
-	country    varchar(255)     DEFAULT '' NOT NULL,
+	title      varchar(255) DEFAULT '' NOT NULL,
+	first_name varchar(255) DEFAULT '' NOT NULL,
+	last_name  varchar(255) DEFAULT '' NOT NULL,
+	email      varchar(255) DEFAULT '' NOT NULL,
+	phone      varchar(255) DEFAULT '' NOT NULL,
+	city       varchar(255) DEFAULT '' NOT NULL,
+	zip        varchar(255) DEFAULT '' NOT NULL,
+	street     varchar(255) DEFAULT '' NOT NULL,
+	state      varchar(255) DEFAULT '' NOT NULL,
+	country    varchar(255) DEFAULT '' NOT NULL,
 	image      int(11) unsigned DEFAULT '0'
 );
 
 CREATE TABLE tx_sgjobs_domain_model_job_application
 (
-	job_id          text                DEFAULT ''  NOT NULL,
-	job             int(11) unsigned    DEFAULT '0' NOT NULL,
-	job_title       text                DEFAULT ''  NOT NULL,
-	company         text                DEFAULT ''  NOT NULL,
-	gender          varchar(30)         DEFAULT ''  NOT NULL,
-	first_name      text                DEFAULT ''  NOT NULL,
-	last_name       text                DEFAULT ''  NOT NULL,
-	street          text                DEFAULT ''  NOT NULL,
-	city            text                DEFAULT ''  NOT NULL,
-	zip             varchar(255)        DEFAULT ''  NOT NULL,
-	country         text                DEFAULT ''  NOT NULL,
-	nationality     text                DEFAULT ''  NOT NULL,
-	education       text                DEFAULT ''  NOT NULL,
-	birth_date      text                DEFAULT ''  NOT NULL,
-	phone           text                DEFAULT ''  NOT NULL,
-	mobile          text                DEFAULT ''  NOT NULL,
-	email           text                DEFAULT ''  NOT NULL,
-	message         text                DEFAULT ''  NOT NULL,
-	cover_letter    int(11) unsigned    DEFAULT '0' NOT NULL,
-	certificate     int(11) unsigned    DEFAULT '0' NOT NULL,
-	cv              int(11) unsigned    DEFAULT '0' NOT NULL,
+	job_id          text,
+	job             int(11) unsigned DEFAULT '0' NOT NULL,
+	job_title       text,
+	company         text,
+	gender          varchar(30)  DEFAULT '' NOT NULL,
+	first_name      text,
+	last_name       text,
+	street          text,
+	city            text,
+	zip             varchar(255) DEFAULT '' NOT NULL,
+	country         text,
+	nationality     text,
+	education       text,
+	birth_date      text,
+	phone           text,
+	mobile          text,
+	email           text,
+	message         text,
+	cover_letter    int(11) unsigned DEFAULT '0' NOT NULL,
+	certificate     int(11) unsigned DEFAULT '0' NOT NULL,
+	cv              int(11) unsigned DEFAULT '0' NOT NULL,
 	privacy_policy  tinyint(4) unsigned DEFAULT '0' NOT NULL,
-	freetext_field1 text                DEFAULT ''  NOT NULL,
-	freetext_field2 text                DEFAULT ''  NOT NULL,
-	freetext_field3 text                DEFAULT ''  NOT NULL,
-	freetext_field4 text                DEFAULT ''  NOT NULL,
-	freetext_field5 text                DEFAULT ''  NOT NULL
+	freetext_field1 text,
+	freetext_field2 text,
+	freetext_field3 text,
+	freetext_field4 text,
+	freetext_field5 text
 );