How we designed Stackmodo's interface rules
By Simon
Why marketing, admin and client storefronts need different design rules, how semantic tokens keep those rules consistent, and why an empty or denied screen needs as much care as a populated one.

AI-generated conceptual illustration of paired light and dark semantic tokens and repeatable component standards, not a product screenshot.
Someone deciding whether to buy Stackmodo needs a different interface from someone publishing a page. A customer buying from one of our clients needs something different again. Giving all three the same dashboard might look consistent, but it wouldn't help them do their jobs.
Stackmodo connects content, commerce and customers around a brand, with setup and ongoing team support. We wrote separate design rules for the marketing site, authenticated admin and client storefronts because each has different work to do.
These are design requirements, not a report of a verified release. The September 2026 handoff leaves authenticated implementation and testing as separate work. That distinction matters throughout this article: a rule in a design file isn't proof that the application follows it.
Where the interfaces differ
The marketing site helps visitors understand the offer and decide whether to start a conversation. It shares Stackmodo's indigo, typography and light/dark direction, but has more space than the admin. Visitors shouldn't have to work through an operational interface just to understand the product.
The authenticated admin is where people work. Its design contract puts navigation, site context, account identity, theme and global recovery in the shared shell. Individual routes own their page content and actions. A page editor shouldn't need to recreate the site selector or invent another account menu.
Client storefronts have their own visual briefs and design sources. They're for the client's audience, so making every business look like Stackmodo would miss the point. As the FAQ explains, Stackmodo supports independently branded frontends with site-specific content and access.
We kept those distinctions in the implementation rules too. Marketing uses Shadcnblocks-derived presentation. The admin contract requires native Payload UI and supported extension points, without shadcn/ui or Shadcnblocks. A component that works well on a marketing page isn't automatically suitable for changing an authenticated workflow.
Use tokens that describe the job
The admin contract uses semantic tokens: a component asks for a primary text colour, a surface or a selected state. Hard-coding a pale background because it looked right in one frame leaves the next theme or state to chance.
Light and Dark are equal design states. The contract defines both, along with System preference and an explicit user override. Under those rules, a component isn't finished if it only works in the theme used to design it.
The surface rules are quite specific. Depth, fill contrast, spacing and radius establish hierarchy; an outline isn't the default treatment for every card. Borders stay where they communicate something, such as an input boundary, selection, validation, a separator or keyboard focus. We want fewer decorative borders without losing the cues people need to operate the interface.
Inter is the admin font, including headings and technical labels. Inter Tight is reserved for intentional brand typography, and functional icons use authentic Lucide vectors. Storefronts only adopt those choices if their own briefs call for them.
This gives implementers fewer local styling decisions to make and a place to look when something is wrong. If a panel looks wrong in Dark mode, check the semantic surface token before adding a one-off colour. Otherwise the next panel can end up with the same problem and a different fix.
A blank area can mean several things
An empty collection, an unfinished request and a denied request can all leave much of a screen blank. The person using it needs to know which one they're looking at.
Our admin contract includes loading, permissions pending, valid empty, degraded, denied and missing-site states. It explicitly prohibits inventing successful context, records, permissions or recovery.
Consider a hypothetical orders page. "No orders yet" is appropriate only once the application knows the user can view those orders and the result is empty. If access was denied, that sentence gives the user false information about the business. If the request failed, it reports a fault as a commercial result.
The copy should identify the context and state, explain the practical impact and offer an action that exists. Use "Try again" when there's a retry. Use "Contact your administrator" when that's the actual recovery route. Neither belongs beneath a warning icon just because the layout needs a button or another line of text.
View full-size imageIllustrative review checklist based on the admin design contract, not a screenshot of the live application.
State: Loading or permissions pending
Establish before showing it: The request or access decision is unresolved
Useful response: Explain what is pending without exposing restricted destinations
Avoid: Showing protected navigation while permissions load
State: Valid empty
Establish before showing it: The user has access and the result contains no records
Useful response: Explain the empty result and offer an allowed next step
Avoid: Treating a failed request as zero records
State: Degraded
Establish before showing it: Some information or service is unavailable
Useful response: Explain the limitation; show last-known information only when truthful
Avoid: Presenting stale data as current
State: Denied
Establish before showing it: Runtime authorization refuses access
Useful response: Explain the access boundary without restricted details
Avoid: Suggesting a refresh will grant permission
State: No site assigned
Establish before showing it: The account has no usable site assignment
Useful response: Provide the defined request-access path
Avoid: Inventing a default site
State: No site selected
Establish before showing it: Selection is allowed but incomplete
Useful response: Offer the available selection action
Avoid: Confusing selection with missing permission
These states need accessible implementations too. W3C's guidance on status messages explains how changes can be exposed to assistive technology without moving focus. Seeing a message on screen doesn't establish that behaviour. Our contract also requires keyboard access, persistent visible focus, non-colour state cues and reduced-motion handling. All of that needs testing in the application, not just drawing in a design file.
Resolving disagreements between design and implementation
Our process assigns different decisions to different sources. Penpot decides appearance. The design repository records intent, component contracts and boundaries. The owning Payload repository decides runtime implementation and behaviour.
View full-size imageDesign authority and runtime authority have different responsibilities. A disagreement requires reconciliation before implementation continues.
A design can specify what a denied state looks like, but it can't grant or revoke access. Runtime authorization makes that decision. Hiding a navigation item doesn't protect a route someone opens directly either.
When the sources disagree, the handoff rule is to stop and reconcile them. If supported extension points can't accommodate an appearance requirement, document the conflict and return it for a design decision. Quietly approximating it leaves the next person guessing whether the design or the implementation was intentional.
What still needs testing
The documented review process starts with shared components or semantic tokens, then checks affected instances, themes, breakpoints and states. Polishing one screenshot while neighbouring routes drift wouldn't satisfy it.
Runtime acceptance requires the real authenticated application. A Penpot export can show appearance, and a local mock can help review a proposed interaction. Neither proves that permissions work, the correct site is selected or keyboard focus returns after a mobile drawer closes.
If you're reviewing a business platform, ask to see the cases that make the work awkward. Open an empty collection. Try an account with restricted access, change the viewport and check what happens when a request fails. Have someone complete the task with a keyboard.
Give those cases as much attention as the populated pages. By the end of the demonstration, you should know what each state means, what the user can do next and which behaviours still need verification.