---
title: "Every business app I built needed the same four pages"
description: "Four years of internal tools and client portals, and the page structure barely changed: a homepage per user group, the boring utility pages, one entity page per object, and a detail page behind it. What goes on each, and how to decide."
date: 2026-06-03
language: en
canonical: https://gduv.club/articles/four-page-types-business-apps
source: gduv.club
---
I've built dozens of business apps over the past four years. Internal tools, CRMs, ERPs, intranets, client portals, vendor portals, deal rooms. Different companies, different data, and roughly the same set of pages every time.

Four families. They cover something like 90% of what a business app needs, and knowing them turns the hardest question at the start of a project, which pages do I actually need, into a short checklist.

[I Built Dozens of Business Apps. They All Needed These 4 Page Types](https://www.youtube.com/watch?v=dsgOwg2r4_E)

I'm talking about apps people log into. Public directories and marketing sites work differently. A business app has a narrow, defined scope: a client portal exists so clients can see their projects and tasks, and so your team can see all of them. That narrowness is what makes a small set of pages enough.

**The four families of pages in a business app: a homepage per user group, utility pages, one entity page per object, and a detail page behind each entity page.**

  <div class="dg-row dg-row--top" style="--dg-gap:0.75rem">
    <div class="dg-grow dg-box">
      <span class="dg-box__title">Homepage</span>
      <span class="dg-box__note">One per user group. Top actions, and what needs attention.</span>
    </div>
    <div class="dg-grow dg-box">
      <span class="dg-box__title">Utility</span>
      <span class="dg-box__note">Login, sign up, reset password, 404. Necessary, and not yours to design.</span>
    </div>
    <div class="dg-grow dg-box">
      <span class="dg-box__title">Entity</span>
      <span class="dg-box__note">One per object in your database. Lists records, creates new ones.</span>
    </div>
    <div class="dg-grow dg-box">
      <span class="dg-box__title">Detail</span>
      <span class="dg-box__note">One record in full, its actions, and the records related to it.</span>
    </div>
  </div>

## 1. The homepage, and the user group question first

Before you design a homepage, list the groups that log in. Clients and internal staff. Teachers, parents and students. Employees and the finance team. This decision comes before everything else, because it determines whether you build one homepage or several.

My rule of thumb: if more than about half the blocks on the page would differ between two groups, give each group its own homepage. Below that, one page with visibility conditions on a few blocks.

**One shared homepage** (Groups mostly overlap)

- A handful of blocks shown by condition
- One page to restyle when the brand changes
- Gets unreadable fast past a few conditions

**One homepage per group** (Groups want different things)

- Each page reads like it was designed for them
- No condition logic to trace
- Shared changes have to be made twice

_The 50% line is a habit, not a measurement. It's roughly where I've found a conditional page stops being readable to whoever maintains it next._

What belongs on it: the two to four actions this group takes most, and the thing they need to act on now. Not more. The app has a narrow scope, so the homepage should be narrow too.

An expense tracker makes it concrete. An employee logs in to submit a request, so the form is one click away, and below it their own requests still pending. The finance team logs in to approve, so they see the requests waiting on them. Not every request ever filed, not the denied ones from March. The list they have to act on.

Everything else can live in the navigation bar, and usually should.

## 2. Utility pages, which you should not spend time on

Login. Sign up, or a disabled sign up if it's an internal tool and people get invited. Forgot password and reset password. The 404. An onboarding flow if you want to force someone to complete their profile before they reach the app.

All boring. All required. None of them is where your app gets good.

This is the family I'd rather not build, and with Softr I don't: they ship configured, and the work is styling and wording. If you're building from scratch, budget for them anyway, because every one of them exists in every app and forgetting the 404 is how someone hits a dead end with no way back.

## 3. Entity pages, one per object

Once your database is right, these almost write themselves. One page per table that means something to a user. A CRM gets contacts, companies, deals, tasks. Log into HubSpot and that's exactly what the nav is.

The page lists records, and the format is a decision worth making per object:

- **A table** when the job is finding one row among many, and density helps.
- **A kanban board** for anything with a status people move through, like tasks or deals.
- **A calendar** when the date is the thing people navigate by.
- **A grid of cards** when a logo or a photo is how people recognise a record.

You can offer two, as tabs on the same page, when different people work differently. In my CRM the deals page has the pipeline as the default and a table view next to it.

The actions belong here too. Add a record. Export the list as CSV, which costs nothing and someone always asks for it. Import a CSV, if people arrive with batches.

**Not every table deserves a page**

In that CRM there's an interactions table, and no interactions page. An interaction only means something attached to a contact, so it lives on the contact's detail page and nowhere else. A page per table is the starting point, not the rule. Ask whether anyone would ever open a list of all of them.

Sometimes the entity page is the whole feature. A documents table with a name and a file, unrelated to anything else, can just be a list with edit and delete on each row. No detail page needed.

## 4. Detail pages, and what sits underneath them

Usually you do want to open a record. A table row has no space to work in, and a company has a description and a website and notes that belong somewhere.

A detail page has three parts.

The record itself, with the fields worth showing, which is more than the entity page shows. The actions on it: edit, delete, change status, assign to someone. Permissions go on these individually, so deleting a contact can be admin only while everyone can edit one.

Then the part I always add and the one that makes an app feel finished: the related records, listed below. Open a company and you see its contacts, its deals, its past interactions. Open a task and you see the project it belongs to.

**Navigation from an entity page to a record's detail page, and from there into a related record's own detail page, each opening in a side panel over the list.**

  <div class="dg-col">
    <div class="dg-box">
      <span class="dg-box__title">Contacts</span>
      <span class="dg-box__note">Entity page, the full list</span>
    </div>

    <span class="dg-arrow dg-arrow--down" aria-hidden="true"></span>

    <div class="dg-box">
      <span class="dg-box__title">One contact, in a side panel</span>
      <span class="dg-box__note">Fields, then edit and delete, then the related company and past interactions</span>
    </div>

    <span class="dg-arrow dg-arrow--down" aria-hidden="true"></span>

    <div class="dg-box dg-box--info">
      <span class="dg-box__title">That company, in a side panel</span>
      <span class="dg-box__note">Its own fields, its contacts, its deals</span>
    </div>
  </div>

Open these in a modal rather than as a full page, centered or sliding in from the side. The URL doesn't change, the list stays behind it, and going back is closing a panel instead of a page load. On a list someone is working through, that difference is most of how fast the app feels.

## The two extra pages worth planning for

**A dashboard.** Charts and counts. Sometimes it is the homepage, sometimes it's its own page when there's enough of it.

**A form on its own page.** This one is a maintenance argument. If four different places let someone create a company, and each has its own create form configured on it, then adding a field means editing four forms and forgetting one. Build the form once on its own page, and have every button open that page in a modal. One form to maintain.

## Structuring an ERP the same way

The four families hold up on bigger apps, they just get grouped. On an ERP I organised the navigation by department rather than by object: inventory, sales, finance. Behind each one, the same entity pages.

Two things I did differently there and would do again. Some pages consolidate two objects, so sales carries orders and customers together, because the people who work in sales work across both. And the homepage doesn't list all products, it lists products with fewer than 100 units in stock, under a heading saying these need attention. A list filtered to what requires action beats a complete list, on a homepage.

## Get the database right and the pages follow

1. **Scope the app**. What it lets people do
2. **List user groups**. Who logs in, and what each needs
3. **Design the tables**. One per real object, right fields
4. **Derive the pages**. One entity page per object, detail behind it

_Step three is where the time goes. The pages are close to mechanical once the objects are right, which is why a bad table structure shows up as a confusing app._

One table per real object, with fields that belong to it. A task has a description, a due date, an owner. A company has a name, a website, an industry. Get that wrong and no page layout saves you.

AI is genuinely good at this part. Describe the CRM you want and you'll get a reasonable first database out of it, which is how I start most projects now.

## Knowing the framework is what lets you leave it

Softr's AI builder produces apps shaped exactly like this. So do the others. Which raises a fair question: if the tool already knows the pattern, why learn it.

Because the generated version is a default, and defaults are the average of everyone's app rather than yours. The moments that make an app good are the departures: not building the interactions page, opening details in a side panel instead of a route, filtering the homepage list to what needs attention. An AI builder won't propose those, because nothing in your prompt told it your people work through a list all day.

I keep finding the same thing with agents generally, in Claude Code as much as in an app builder. They're fast at producing the standard shape, and what you bring is knowing which part of the standard shape is wrong for you. That only comes from having built the thing by hand enough times to have opinions about it.

So use the generator. Then open what it made and change the three things you'd have done differently.