Skip to content

The admin panel that became a second job — and what to map before screen one

6/7/2026Backend Development•Next Boilerplate•9 min read

title: The admin panel that became a second job — and what to map before screen one slug: business-automation-admin-panel-trap pillar: Business Automation angle: mistake audience: SME owners, ops leads, manual-process buyers status: draft

The admin panel that became a second job — and what to map before screen one

Why "add an admin panel" is never a feature and always a project — and the mapping exercise that surfaces the real scope before a single screen is designed.

The request arrives in a familiar form: "We need a way to manage things from the backend." Sometimes it is more specific: manage users, manage orders, manage settings. Sometimes it is vaguer: "just an internal tool." In almost every case, the person making the request has one mental model — a table with rows and buttons — and has not yet mapped what "manage" actually means across the entire application.

The admin panel trap is not that the feature is technically complex. It is that the scope is invisible until you start building, and by then it has already expanded in three directions you did not see coming.

The mistake

The mistake is estimating an admin panel as a set of screens rather than a set of domains. The developer hears "admin panel" and thinks: user list, a detail view, an edit form. Two weeks of work. The client hears "admin panel" and sees: everything they currently do manually in a spreadsheet, several things they want to track that nobody tracks yet, and a settings section that lets them change things they currently ask the developer to change.

The trigger is usually a scope document that says something like "admin dashboard for managing users and content" and nothing more. What that document should say — and what a proper discovery process would surface — is a complete list of entities, actions per entity, roles that perform those actions, and the audit trail that records them.

Here is what "users and content" actually means in a TypeScript API that follows domain-driven module organisation. The modules/ directory reads as a scope audit:

modules/
├── auth/              # login methods, session config, JWT secrets
├── auth_impersonation/ # admin can act as another user
├── auth_saml/         # enterprise SSO support
├── auth_sso/          # OAuth provider management
├── coupon/            # discount codes, redemption limits
├── notification_inapp/ # in-app notifications management
├── notification_mail/  # email templates, delivery settings
├── notification_push/  # push notification credentials
├── notification_sms/   # SMS provider config
├── payment/           # payment records, provider config
├── setting/           # global app configuration
├── storage/           # file storage provider, folders
├── tenant/            # tenant creation, status
├── tenant_branding/   # per-tenant logos, colours, favicons
├── tenant_domain/     # custom domain management
├── tenant_export/     # data export requests
├── tenant_invitation/ # invitation emails, acceptance
├── tenant_member/     # role assignment, member removal
├── tenant_setting/    # per-tenant configuration
├── tenant_subscription/ # plan management, upgrades
├── tenant_usage/      # usage tracking, limits
├── user/              # user accounts
├── user_preferences/  # notification and UI preferences
├── user_profile/      # display name, avatar
├── user_security/     # passkeys, 2FA, session list
├── user_social_account/ # connected OAuth accounts
├── webhook/           # outbound webhook configuration
└── audit_log/         # who did what, when

That is forty-plus modules. An admin panel for an application of this scope is not two weeks of work — it is a project large enough to warrant its own discovery phase.

Why it looks fine on day one

Day one, "admin panel" is three tables: users, settings, perhaps a content list. The developer builds them. The UI looks like what the client imagined. Then the first review session happens.

"Can we also see which users are on which plan?" — tenant_subscription.
"Can we pause a subscription without cancelling it?" — tenant_subscription state management.
"Can we see who invited whom?" — tenant_invitation.
"Can we see the audit log for a specific user?" — audit_log, filtered.
"Can we manage the notification templates?" — notification_mail.
"Can we give some admins read-only access?" — role-based access control across every module.

Each request is reasonable on its own. Taken together, they represent a complete admin application that was not scoped in the original estimate. The mistake was that the estimate covered three tables and the requirements covered forty modules.

The auth configuration alone covers thirty-plus setting keys:

// modules/auth/auth.setting.keys.ts
export const AuthSettingKeySchema = z.enum([
  'allowRegistration', 'emailVerificationRequired', 'sessionDuration', 'maxLoginAttempts',
  'ssoAllowedProviders',
  'jwtAccessTokenSecret', 'jwtAccessTokenExpiresIn', 'jwtRefreshTokenSecret', 'jwtRefreshTokenExpiresIn',
  'oauthGoogle', 'oauthGitHub', 'oauthMicrosoft', 'oauthLinkedIn',
  'oauthApple', 'oauthTwitter', 'oauthMeta', 'oauthAutodesk',
  'googleClientId', 'googleClientSecret',
  'githubClientId', 'githubClientSecret',
  // ... additional provider keys
]);

Managing auth settings from an admin panel means building a form that handles all of these keys correctly — with the right input types, the right validation, and the right display logic that hides Google OAuth keys when Google OAuth is disabled. That is not a single form. That is a configuration management sub-application.

The cost

The cost is not the developer's time, though that is significant. The cost is schedule compression. When the admin panel scope expands mid-build, the developer has three options: deliver the original scope and tell the client the rest is out of scope, work evenings to cover the expanded scope within the original timeline, or renegotiate the contract.

The first option usually triggers a client satisfaction problem. The second triggers a personal burnout problem. The third requires a contract renegotiation at the worst possible moment — when the client sees the gap between what they expected and what they are getting.

The storage module shows the kind of configuration complexity that gets discovered mid-project:

// modules/storage/storage.enums.ts
export const StorageProviderTypeSchema = z.enum([
  'aws-s3', 's3', 'cloudflare-r2', 'digitalocean-spaces', 'minio'
])

export const StorageFolderSchema = z.enum([
  'general', 'categories', 'users', 'posts', 'projects', 'comments',
  'images', 'videos', 'audios', 'files', 'content',
  'branding/logos', 'branding/favicon', 'branding/wallpapers',
])

"Can we manage storage settings?" Yes. But storage settings include the provider choice, the region, the bucket name, the credentials, and the folder structure. That is not a settings page. That is a storage configuration module.

The fix

The fix is a domain map before discovery ends. The developer's job before writing a single line of admin panel code is to produce a table that looks like this:

Domain Entities Actions Roles Audit?
Users User, Profile List, View, Edit, Deactivate, Impersonate Super-admin, Support Yes
Tenants Tenant, Member List, View, Create, Suspend Super-admin Yes
Subscriptions Plan, Subscription View, Upgrade, Cancel, Pause Super-admin, Finance Yes
Auth settings JWT config, OAuth providers View, Edit Super-admin only Yes
Storage Provider config, Folders View, Edit Super-admin only No

Once this table exists, the scope of the admin panel is visible as a number: X entities, Y actions, Z roles, and N audit-logged operations. That number becomes the estimate's foundation. The client can prioritise — "start with users and tenants, skip auth settings for now" — and the developer can give a confident number for each increment.

The module structure in a well-organised codebase is the fastest input for this table. Every entry in modules/ is a potential row. Every service method is a potential action. Walking the directory listing and asking "does the admin need to see or change this?" takes thirty minutes and produces a scope document that takes three weeks to recover from if skipped.

Trade-off you are accepting with the fix

The domain map exercise adds time to the discovery phase. A client who wants to start building immediately will push back. The response: every hour spent on the domain map saves two to three hours of scope renegotiation later. The mapping is not overhead; it is the fastest path to a signed change order or a realistic original estimate.

The other trade-off: a complete domain map might reveal that the admin panel is actually a significant portion of the total project scope — sometimes larger than the end-user-facing application. That is an uncomfortable conversation to have, but it is better to have it at the estimate stage than at the delivery stage.

Trade-off

Investing in scope discovery before building saves time at the cost of delaying the start of visible progress. For clients who measure progress by screens built, early discovery can feel like slow movement. The developer's job is to make the hidden scope visible — usually by showing the domain map — before the client makes a budget commitment based on an incomplete picture.

Business impact

Admin panels are where operational efficiency is either created or destroyed. A well-scoped admin panel gives operations teams the controls they need without requiring developer involvement for routine configuration changes. A poorly scoped one creates a support burden — operations asks for changes the panel does not support, and the developer implements them as one-off requests indefinitely.

The configuration management that the setting keys pattern represents — storing application configuration in the database, changeable at runtime — is only useful if there is an admin interface to expose it. An application with thirty-plus auth configuration keys that can only be changed by editing environment variables and redeploying is not using that capability. The admin panel's business purpose is to put those controls in the hands of the people who should have them.

What to do next

Before estimating your next admin panel request: take the application's module list and spend thirty minutes writing one row per domain in the table format above. Count the total number of distinct admin actions. If the count is above twenty, the admin panel is a significant sub-project that needs its own estimate. If the count is above fifty, it warrants its own discovery phase.

The question to ask the client before the estimate goes out: "When you imagine the admin panel, what is the one action you do most often today in a spreadsheet or by emailing the developer?" That answer tells you what Phase 1 actually is.

Related Articles

Same Category

Comments (0)

Newsletter

Stay updated! Get all the latest and greatest posts delivered straight to your inbox