Building a member area on Core dna: who a member is in the data, the sign-in flows and their templates, single sign-on and passkeys, the my-account routing convention, members-only content, sessions and the page cache, and the security checks to run before launch.
L2
Unit 02 · Registration, sign-in and password recovery
Restyling the account screens
Registration, sign-in and password recoveryPage 14 of 36Updated
The account screens are restyled by writing templates at the paths the routes render, as one set: the pages, the shared input partials, the messages and the emails. The full list of files, a field partial that handles its own errors, and what differs on a Twig site.
Who this is for. The theme developer restyling sign-in, registration and the password screens as a set. Afterwards you have the list of files to write and a way to write each field once.
How overriding works
Each route renders a fixed template path. A file at that path in your site's templates/ folder is used instead of the framework's; where the framework has no file, yours is the only one (Template resolution order). Nothing is registered in the admin. The framework's own copies are plain Smarty, so they show the variables each screen has, not a design to keep.
Give every screen the site's own base template, and print the messages on each: several routes report their result only as a message after a redirect.
Shared input partials
The framework's account templates build their fields from small partials in users/inputs/: input-field.html, a labelled input that shows its own error from _validation; select.html, for a list of options; and select-entity.html, for a list of records such as countries or address types. Keep the same idea in your site: one partial per kind of field, included from every screen, so a change to how fields look or report errors is made once.
Write your own copy at the same path, and escape the value and label in it, as the example below does. A Twig site writes its own in any case, since the framework's partials are Smarty.
{% set type = type ?? 'text' %}
{% set value = value ?? '' %}
{% set hasError = _validation is defined and _validation.hasFieldError(fieldName) %}
<div class="field{{ hasError ? ' field--error' : '' }}">
<label for="{{ id }}">{{ label|e }}</label>
<input id="{{ id }}" name="{{ fieldName }}" type="{{ type }}" value="{{ value|e }}"{{ isRequired ?? false ? ' required' : '' }}{% if hasError %} aria-invalid="true" aria-describedby="{{ id }}-error"{% endif %}>
{% if hasError %}<p class="field__error" id="{{ id }}-error">{{ _validation.getFieldErrorMessage(fieldName) }}</p>{% endif %}
</div>
{% include 'users/inputs/input-field.html' with {fieldName: 'person[email]', id: 'email', type: 'email', label: 'Email', isRequired: true, value: user.getPerson().getEmail()} %}
The error message comes from the platform and is printed as it is. An included file sees the including template's variables in both engines (a Twig include passes the current context by default), so _validation reaches the partial with no extra work.
On a Twig site
Write every account template, the sign-in page included: the framework's copies are Smarty and cannot render on a Twig site.
The remember-me prompt has a Twig version the framework ships, o-auth/frontend/remember-me-twig.html; override that name.
The provider error page is looked for as errors/oauth-twig.html and then errors/oauth.html, so either name works.
The reset email must be supplied as users/emails/reset-password-twig.html: the framework ships only the Smarty version.
Checking the set
Before launch, open each screen in its states: signed out and signed in; with each form submitted empty, with a wrong value and correctly; and on a narrow screen. A screen whose template is missing shows only "Template not found" on a Smarty site, so walking the list once confirms every screen has its template (When a template is missing).