Skip to main content
Page Creation Wizard
From Concept to Core
@ TYPO3 Developer Days 2026
Andreas Nedbal
ABOUT ME
Andreas Nedbal


Senior Frontend Developer @ in2code GmbH

TYPO3 Core Merger
PHOTO
Early 2026 State of Things
It’s January and redesign work is in full progress after
T3CON showcase

Clear that capacity is not enough and more developers
are needed

Florian reaches out to the TYPO3 GmbH which asks
around the partner network for developers ready to
develop crucial features at a low hourly rate.
in2code and DFAU are up for the task, and together with the GmbH offering
mentoring the team is assembled!
PROJECT MANAGER
Florian Keitgen
B13 GmbH
PROJECT MANAGER
Florian Keitgen
B13 GmbH
DEVELOPERS
Andreas Nedbal
in2code GmbH
MENTORS
Benjamin Kott
TYPO3 GmbH
Tobias Wojtylak
DFAU GmbH
Benjamin Franzke
TYPO3 GmbH
Bastien Lutz
in2code GmbH
The Workflow
Dailies

Reporting of tasks

Thorough documentation down to the concepts (in Forge, etc. ...)

In-/External reviews (via Gerrit)
Why do we need it?
PROBLEM
UX generally is suboptimal
Creating a page usually doesn’t take you where you want to be

Editors want to add content after creating a new page

Not newcomer friendly

In default configurations users are overwhelmed with tens of fields at once

even though only a handful fields are required to set up a page
PROBLEM
Little to no validation
Initial page creation “bypasses” validation so that context-specific creation worked

This generally is not an issue, but for custom page types with non-title required
fields you end up with invalid pages 

(invalid = editing it for the first time yields error fields)
Design
REFERENCE
Designing TYPO3 14’s Backend: Our Vision 

for a Modern, Expandable Foundation
AUTHOR
B13 GmbH
Laura Heine
Concept / Planning
Our Tasks
Dissecting the design and creating a concept from it

Figuring out what’s viable to implement within the deadline

Defining the tasks needed before implementation

Creating an Epic in Forge to hold all sub-issues

Visualizing the concept with graphs
tte e se xee
tos so et osstet e oess fo et es to ee ests tot
to te oex Tse setts
e ots
stt to ests o eess stes
te oo fo e tes
eo Tse exetse ee fo s set
esst esose es
e t to es s tefe tt foos esst e oe e sts
e ots
.ot esst fo te ete oo
esose ot
oo ext e
t so e osse to stt te fo eet et ots te e t eee
etes ee o otext. et te es so so e sote
Lots of Text...
Lots of Graphs...
QUOTE
In 20 years of building things for the

TYPO3 Core I think this is one of the most
thoroughly planned TYPO3 features 

I have yet seen. AUTHOR
TYPO3 Co-Lead
Oliver Hader
Implementation
ROLES
Andreas Nedbal
FormEngine + Frontend
Tobias Wojtylak
Frontend
Bastien Lutz
Backend (DI / DataHandler)
PROBLEM
Localization in Modals
Remember my talk about jQuery and module loading across contexts in Modals? 

We’re back with more modal issues!


lll() in JS accesses window.TYPO3.lang


Top frame TYPO3.lang (Modal opener) != content frame (executing script) TYPO3.lang
SOLUTION
JS Label API
import labels from ‘~labels/core.common’;


labels.get(‘label.identifier’);


Dynamically fetches locales from the Backend using the same identifiers you can use in
TYPO3 v14.
PROBLEM
Using FormEngine in Modals
...or anywhere outside of controllers, really.


Especially getting used assets like required JS/CSS files, language files etc.

They are also directly handed off to the page renderer, with no easy way

of preventing that.
SOLUTION
DTOs from FormEngine
FormEngine now hands off DTOs and there are more classes to handle these results.


FormResultFactory creates FormResult

FormResultCompiler previously added assets from raw nodes to PageRenderer

now FormResultHandler for this
PROBLEM
Required field combinations
For shortcut pages, shortcut mode 0 (“Selected page”) requires you to select a page to
link to.


However, TYPO3 never checked for this in FormEngine.
PROPOSAL
New...REQUIREDCOND?
Similar to DISPLAYCOND, what about adding REQUIREDCOND to conditionally require

other fields once others are filled with (specific) values?


This idea was scrapped because we didn’t want to add another custom condition

syntax (and rewriting DISPLAYCOND as Symfony Expression Language is breaking)
SOLUTION
A new renderType
As a solution we added a new renderType to shortcut mode which adds a snippet of

JavaScript that validates the shortcut value depending on the selected shortcut mode.


The proposals are not out of the picture, this was just the quickest/best solution

with our time constraints.
SOLUTION
PROBLEM
Drag & Drop UX/A11y
The “power user” way of creating pages via drag & drop in the page tree is sometimes
quite finicky and also not accessible.


We can’t remove it as it is a power user feature.
ENHANCEMENT
Drag & Drop UX/A11y
Page creation button added

Drag & Drop not removed, provides context to Page Creation Wizard
ENHANCEMENT
STATISTICS
2

Epics
66

Subtasks
10,310

Additions
53

Patches
5,423

Deletions
23rd March, merged!

8 days ahead of Feature Freeze
Extending

Adding page wizard steps to your own doktypes
TCA
'types' => [

'123' => 

'wizardSteps' => [

'setup' => [

'title' => 'backend.wizards.page:step.setup',

'fields' => ['title', 'slug', 'nav_title', 'hidden', 'nav_hide'],

],

],

],

],
Making your own Wizards
Future-proofDesign✨️
ThePageCreationWizardisnotastaticone-timeimplementation,theunderlying 

wizardlogicisgeneric,allowingdeveloperstoimplementandregistertheirown.
Dependency Injection
Implement the WizardProviderInterface and make it a tagged item with a named index

and you’re good to go!


use SymfonyComponentDependencyInjectionAttributeAsTaggedItem;

use TYPO3CMSBackendWizardWizardProviderInterface;


#[AsTaggedItem(index: 'my_wizard')]

class MyWizardProvider implements WizardProviderInterface

{

...

}
Configuration / Steps
use TYPO3CMSBackendWizardDTOConfiguration;

use TYPO3CMSBackendWizardDTOStep;


public function getConfiguration(ServerRequestInterface $serverRequest): Configuration

{

return Configuration::create([

Step::create('@myext/my-step.js')

->withConfigurationData([

'title' => 'My custom step',

'value' => 'Some custom data!',

]),

]);

}
Handling Submissions
public function handleSubmit(ServerRequestInterface $serverRequest): SubmissionResult

{

try {

// persist data

} catch (Exception $e) {

return SubmissionResult::createErrorResult([$e->getMessage()]);

}


return SubmissionResult::createSuccessResult(

Finisher::createRedirectFinisher(...)

->withResetButton(‘reset button label’)

);

}
The JavaScript Part

We’ll just take a quick look at the reference implementation
Verdict
QUOTE
What I particularly like about the Page Creation Wizard is that it improves
the existing workflow without replacing it. 


That was the goal from the very beginning — and seeing it make its way
into the core, developed by Tobias, Andreas, and Bastien with mentoring
from Benji and Franzke, is exactly what makes contributing to TYPO3 so
rewarding.
AUTHOR
Project Manager
Florian “Flix” Keitgen
QUOTE
Collaborating on this TYPO3 feature was really fun!


It was interesting and exciting to gain more insights into the
project. The support we received from the community while
working on this feature also made work on it so much easier,
thanks for that! AUTHOR
Developer
Tobias Wojtylak
THANKS
Presets
Bug Fixes

& Refinements
The Future
Record

Wizard
More Wizards
Content Element

Wizard
...and maybe your
wizards?
Any Questions?
Thank you for listening!

Hope you enjoyed this talk :)
Feedback? Further questions?
Fediverse (Mastodon/…):

@pixel@icosahedron.website


Bluesky:

@pixelde.su


TYPO3 Slack:

@pixeldesu
URLs of referenced blog articles

and source code sections here!

Later today I’ll also publish the slides