All features

Client portal

The client signs in to your app

A contact person at your client gets a login into your own branded app. They see the marketing overview you composed for them, their published reports, their own issued invoices and the tasks they may comment on. Everything else is invisible because it never reaches them, not because somebody remembered a checkbox.

Invite from the person's own page

The portal has no settings screen of its own and no nav item: you grant access on the contact person's own page, on the card "Klantportaal". One button creates the account, gives it the Klant role and sends a set-password invitation in your own branding. The card then shows a status (Geen toegang, Uitgenodigd, Actief or Uitgeschakeld), and while the invitation is still unused a button appears to send it again. Two things have to be true first: the contact needs an email address, and they must be linked to at least one client, because that link is exactly what decides what they will see.

  • An address that already belongs to an existing account is refused with an explanation: a portal login needs its own address.
  • If outgoing email isn't configured yet, the card says the access is ready but the invitation could not be sent.
  • Managing a client login is the same capability as inviting a colleague; someone without it never sees the card at all.

What the client sees

The client signs in on the same host, in the same branded shell, and lands on "Jouw dashboard": a widget board carrying the marketing overview you composed for that company and their most recent published report. When the contact belongs to more than one company, a company switcher sits above it; the company's own logo appears on the dashboard while your brand stays in the shell. They can also open their own issued invoices, overdue status included, and download the same PDF you would send. What goes into the marketing overview stays your call — hidden tiles never leave the API, so the client only rearranges within what you exposed.

  • Never a draft invoice, never another company's invoice.
  • Never a report that has not been published.
  • No team calendar, no settings, no task templates or checklist library belonging to the agency.

The write surface is deliberately small

Everything a client login may write fits in one sentence: comments on their own tasks, the layout of their own dashboard and menu, and their own notification inbox. Nothing else. That isn't because these are "portal screens" — they are the very screens your team uses. Every control that writes checks its own permission against the API rather than asking whether the visitor happens to be a client, so a detail page can compose panels and shared rows exactly as it always did, with no filter left to forget.

Switching access off is reversible

"Toegang uitschakelen" turns the login off and deletes nothing: the account, the membership and the whole history stay, and the button then reads "Toegang opnieuw inschakelen". There is deliberately no button to delete a login, because a trail that vanishes the moment someone leaves is not a trail. A client login attached to no company sees nothing at all, whatever the roles say; Instellingen → Team & gebruikers badges such an account "Ziet geen klanten", and the client themselves gets an explanation instead of an empty page. Turn the whole module off and only new invitations stop: existing sessions stay exactly as contained as they were.

Sign in as this contact person

When a client says "I can't find that report", you press "Inloggen als deze contactpersoon" on the same card and look at exactly their screen: the same dashboard, the same companies, the same missing tile. Your own session stays open, because the grant is its own short-lived cookie beside your normal login; it lapses after half an hour and the installation puts a hard ceiling on it regardless. A banner sits on every screen saying who is signed in as whom, with a Stoppen button, and stopping puts you back on the contact you started from. It is its own permission ("Inloggen als de portaallogin van een klant", admin-only by default) and it never comes along with managing the login: inviting someone and being them are two different acts.

  • The session is capped to the intersection of what the client and you each hold, so you never see more than you already could.
  • If the session shows less than the client actually has, the banner says so — an unlabelled partial view lies about someone else's account.
  • Nested sessions are refused, and stopping always works, even after a licence has lapsed.

Everything lands in the trail, and what the module costs

Every flip of the access lands on the contact's activity trail under the name of whoever flipped it: portal access granted, portal access revoked, invitation resent, plus the start and the end of every session signed in as them. Anything you write during such a session carries your name beside it, so the client is never recorded as the author of something you did. The client portal is an extension module: the core of schakl. is open source (AGPL), and modules like this one run on a licence key you install under Instellingen → Licentie. When the key expires the module goes read-only rather than away — existing client logins keep working and keep their restriction, and only new invitations wait for a new key.

  • Without the permission the card isn't there; without the licence it shows a padlock and an explanation, because a padlock belongs only on something you can open yourself.
  • On your own server that padlock points at Instellingen → Licentie, and only the owner of the installation sees that button.
  • A fresh install runs in full for the first two weeks, so you can try the portal before you buy a key.

Want to know more?

The documentation describes every module in detail, from installation to permissions.

The demo is on its way

The live demo isn't ready yet. We're working hard on it and are excited to share it here as soon as it's done.

Go to the docs

More features