Free · Craft CMS 5
An account area your members can't talk their way around
Registration, profile fields, member photos and member directories, built in the control panel and rendered on the front end. No custom controller, no template surgery. Memberz reads only what a form asks for, decides privacy in exactly one place, and keeps every member's email address on your server.
Features
A form a stranger can submit has to be safe by construction rather than by a list of things to block. Everything else follows from that.
The form is the allow-list
A submission is saved by walking the rows of the form it names and reading the one parameter each row asks for. The POST body is never iterated, and Craft's setFieldValuesFromRequest() is never called. So admin, groups, permissions and suspended do nothing: they aren't rows, so nothing reads them.
- No list of forbidden keys to keep in step with Craft
- Group assignment comes from the form's settings, not the submission
One privacy verdict
Each field has a ceiling the site sets and a preference the member picks, and whichever is stricter applies. A hostile form post can only tighten a setting. When several profile forms name the same field, the strictest of them wins, so adding a looser form can't widen what a directory already publishes.
- The profile page, directory cards and Twig all ask the same function
- A private profile is a 404, not a 403, so its URL can't confirm the account exists
Directories that answer only what they offer
Searchable, filterable, sortable member listings. A URL can send any ?sort= or ?f[…]= it likes, but Memberz only answers names that appear in the directory's own lists. ?sort=password never becomes an ORDER BY.
- Members can unlist themselves, filtered in SQL so every page is full
- Works as a plain GET form, with an optional script to filter in place
Photos checked by what they are
Front-end uploads are checked for size, then extension, then what the bytes actually are, so an SVG renamed to .png is refused. Accepted files are re-encoded and scaled, which strips EXIF and anything riding along. With no photo, initials are drawn on your server, coloured from the member's UID.
- No Gravatar, so no member's email address leaves your server
- Stored in the volume Craft's own user settings name
Craft stays in charge
Public registration, email verification and activation are Craft's settings, and Memberz reads them rather than replacing them. If the site owner has switched registration off, a registration form is refused and the refusal is logged. Changing an email or password asks for the current password first.
- New accounts are saved pending and activated the way Craft's own registration does it
- Works alongside Verbb Auth for social sign-in and Headcount for paid membership
Plain HTML on the front end
Craft's own user fields are drawn as plain front-end inputs, with no control-panel JavaScript on your site. There are fifteen supported field types. Anything else, Matrix included, is reported in the form builder rather than approximated as a text box that loses what the member typed.
- No build step and no runtime dependencies
- The optional script is only included when a template asks for it
Build it in the control panel, place it with one line
Forms and directories live in project config, so they deploy with the fields they render. Memberz routes /account and /members/<slug> for you, and a route your site already declares always wins. Everything on craft.memberz reads. Nothing in a template can save anything.
{# Registration only runs when Craft itself allows it #}
{% if craft.memberz.registrationIsOpen() %}
{{ craft.memberz.form('register') }}
{% else %}
<p>Registration is closed at the moment.</p>
{% endif %}
{# A member directory: search, filters and sort from its own lists #}
{{ craft.memberz.directory('members') }}
{{ craft.memberz.js() }}
{# The account area and a public profile, routed for you #}
<a href="{{ craft.memberz.accountUrl() }}">Your account</a>
<a href="{{ craft.memberz.profileUrl(user) }}">
{{ craft.memberz.avatar(user, 48) }} {{ user.fullName }}
</a>
Privacy you can't forget to check
value(), canSee() and fields() go through the same verdict as the profile page and the directory card. Craft's own accessor does not, because it knows nothing about a member's settings. Draw your own cards and the query tells you which members to list, while canSee() tells you which of their fields you may print.
{# Respects the member's settings. Returns null if this visitor may not see it. #}
{{ craft.memberz.value(member, 'jobTitle') }}
{# Publishes it regardless of who is looking. #}
{{ member.jobTitle }}
{# Your own directory cards #}
{% set query = craft.memberz.members('members') %}
{% if query %}
{% paginate query.limit(24) as pageInfo, members %}
{% for member in members %}
<article>
{{ craft.memberz.avatar(member, 64) }}
<h3>{{ member.fullName }}</h3>
{% if craft.memberz.canSee(member, 'jobTitle') %}
<p>{{ craft.memberz.value(member, 'jobTitle') }}</p>
{% endif %}
</article>
{% endfor %}
{% endif %}
Frequently Asked Questions
Where Memberz stops, and what picks up.
Yes. There's one edition with everything switched on, and no licence key.
No. Craft does. Use Craft's own users/login action exactly as you would without this plugin. Memberz only signs a member in straight after registration if you ask it to, and only for an account Craft actually activated. Signing somebody in on an address they haven't verified is the thing verification exists to stop.
That's Verbb Auth, and the two work together with nothing to configure. Auth creates and authenticates the account. Memberz draws the profile, the account area and the directory around it. An account that arrived through Auth gets a profile slug the first time one is asked for, like any other.
No, and that's deliberate. Subscriptions, tiers, content gating and drip content belong to Headcount. Memberz holds no price, no plan and no paywall. The two are built to sit on the same site: Headcount decides what a member may read, and Memberz draws the account area around it.
Almost always it's one of Craft's own settings, under Settings → Users → User Settings. Either public registration is off, in which case every submission is refused and the refusal is logged, or email-as-username is off and the form has no Username row. Memberz refuses to save a form like that, so you should find out while you're building it rather than from a visitor who couldn't sign up.
No. The setting in force is the stricter of the site's ceiling and the member's own choice, so a posted value can only tighten it. Owners always see their own fields, and admins see everything, as they already can in the control panel.
A 403 confirms the account exists. That turns the profile URL into a way of testing whether a username is registered, and a member who set their profile to private asked not to be discoverable. If the username in the profile URL matters on your site, profile URLs can be built from a random string instead.
Memberz renders plain front-end HTML rather than Craft's control-panel inputs, and there's no honest plain-HTML version of a Matrix field. Fifteen field types are supported, from Plain Text and Dropdown to Date, Color and Country. Anything else is reported in the form builder rather than rendered as a text box that loses what the member typed.
No. There's no Gravatar call, no analytics and no licence phone-home. A member with no photo gets initials or a silhouette, drawn on your server and coloured from their UID so they look the same across every deployment.
Not through Memberz. Deleting a Craft account has consequences this plugin can't see, such as content transfer and Commerce orders. Members can hide their profile and remove themselves from directories. Deletion goes through the site owner.
No. Plugin settings and project config are both already deployable, so a third place to configure it would only be a third place for the answer to disagree with itself.
Accounts, their fields and their photos are untouched. They're Craft's data, and Memberz never kept a copy. The memberz_profiles table goes, taking members' privacy preferences and profile slugs with it, and the forms and directories are removed from project config.
Craft CMS 5.3+ and PHP 8.2+. There are no runtime dependencies and no build step.
A registration form, a profile form, and you're done
Free, single edition, no licence key. Build a registration form and a profile form in the control panel, visit /account, and you have a working account area. Everything after that is shaping it.