Skip to content

The dashboard

/dashboard is the first screen behind the login, and it ships with something on it rather than as an empty grid. Everything it draws is a fact the kit already records: no table was added for it, and nothing on it calls a payment provider.

It has two shapes, and which one a visitor gets is decided by the server.

With an active organization

The team's screen. Four counters across the top, then four cards.

PieceWhere the number comes from
PlanBilling::plan() and Billing::subscription() for whoever this installation charges
SeatsSeats::summary(), which is the same count that refuses the next invitation
MembersOrganization::members()
Pending invitesInvitations that have not been accepted and have not expired
Recent membersThe last three membership rows, newest first, with avatar and role
Recent activityMembers joining and invitations being sent, merged and sorted

The activity feed is derived, not recorded. A membership row already knows when it was written and an invitation already knows when it was created, so the feed is those two columns read back in order. That is deliberately not an audit trail: laraspring/admin owns the audit trail, it is about the whole installation, and it is for administrators rather than for a team's own history.

Two things a plain member does not see: the pending-invites counter, and invitations in the activity feed. A list of addresses a colleague has been emailed is not every member's business, and the members screen already draws that line.

With no organization

The account's screen: the same plan card, plus a short checklist of the things somebody has usually not finished — a second factor, a profile photo, a verified address — and a card explaining why the team half is empty, with the way out of it. It appears when this installation bills individuals (billable = user), and when a user simply has no organization active yet.

The second-factor row disappears entirely when laraspring-auth.features.two_factor is off, rather than offering a button whose route was never registered.

Making it yours

Two files per edition, and no package to touch.

PieceFile
Propsapp/Http/Controllers/DashboardController.php
Pageresources/js/pages/dashboard.tsx · dashboard.vue
Stringslang/{locale}/app.php, under dashboard
Routeroutes/web.php, named dashboard

The controller is ordinary application code and is meant to be edited. Each card is fed by one private method, so removing a card is deleting a method and the markup that reads it; adding one is the reverse.

Adding a counter. Return the number from the controller, then copy one of the existing stat cards. In React they are <Stat /> in the page itself; in Vue they are components/dashboard/StatCard.vue. Both take a label, a value, a caption and an icon, so a fifth is a few lines rather than a layout to work out.

Every string goes through a translation file. The cards read app.dashboard.*, and role names come from organizations.roles.* so they match the members screen. A key added to lang/en/app.php and forgotten in lang/es/app.php fails TranslationParityTest rather than shipping.

Dates and money are formatted in the browser, in the language the page is in rather than the browser's. That is what locale from useTranslations() is for. In Vue it is a computed ref, so it needs .value inside <script setup>.

The "make it yours" card is written for whoever bought the kit. It is markup like any other; delete it once your dashboard is your own.

On a public demo

DemoSeeder spreads memberships and invitations across the last thirty days, so the activity feed reads as a history rather than as a batch written in one second. All three one-click accounts land on a dashboard with content: the owner and the administrator each run an organization with pending invitations, and the member sees their team without the invitation list.

See Running a public demo.

Laraspring is a commercial starter kit. Buying it gets you the source.