Skip to content
ChatfuelSDK

Internal company panel

Your team gets one panel with the conversations, the contacts, the deals and the booking calendar in it, on a server you chose and in a codebase you can open. You pick the screens when it is generated, so nobody on your staff has to learn their way around a page you never wanted.

The screens your staff open all day

One React app, one left-hand rail, and a page behind each item on it. Every module is a directory under src/modules and a chunk fetched on the first visit, so an app carrying ten of them loads the one page somebody came for.

Inbox

The chat list beside the message thread. A link can open a conversation that is not even in the list, or start one with a person another screen just found.

Contacts

A list, the field catalog behind it, and an audience view. Saved views for the questions your team asks twice, and an undo for the edit that was wrong.

Deals

A board, a table and a forecast over one filter model, so the same slice of the pipeline reads three ways. Only the view on screen is mounted.

Bookings

Calendar, appointments, staff, services, settings and insights — six sections, one address, one live channel shared between them. Only the section on screen is mounted.

Publishing

A calendar of what is going out, a queue where a failure is read, a library of what is already on the account, and a composer over all three. The schedule runs on your own Postgres, because the API it talks to publishes immediately and stores no post.

Copilot

An assistant for the person operating the app, not for the customer. A bridge lets it read the screen somebody is on and move them to another one.

What you did not pick is not in the app

The directories of unselected modules are deleted from disk, the registry is regenerated with only what you chose, and the menu table in the app’s own source is filtered to match — down to the icon imports the filtered file no longer uses. A group that empties out stops rendering, and a single remaining module gets no menu at all.

Nobody on your staff holds the token

The proxy injects it server-side and forwards neither the caller’s own Authorization header nor their cookies; outgoing headers are built from scratch. Request bodies, variables, emails and tokens are never logged, and the browser is never handed the credential the app runs on.

The operator’s door is not on the menu

The admin panel is routed like any other page and listed in the rail like no other page: never, before or after unlocking. Its password is sixteen characters at minimum — shorter and every admin route answers 500, unset and the routes are not mounted at all — and the SQL behind it is granted to the service role and nobody else, so no browser can call it.

The code is yours, MIT

The design system, the typed API client and the proxy are copied into the project as source rather than installed as packages, so the app owns every line it runs. Changing how a table looks or what a screen fetches is an edit in your own repository, not a request to somebody else’s release schedule.

From the command to the team using it

Four moves, and the third and fourth are the ones an internal deployment actually argues about: where it lives, and who gets in.

  1. 01

    Pick the screens

    One command, then a checklist of the modules that are ready. Anything a pick depends on comes along and is named on screen; recommendations are offered rather than quietly added; everything else is removed from the tree before the app is written.

  2. 02

    The app is generated, and it runs

    A Vite and React project with your modules under src/modules, the design system and the API client vendored as source under src/vendor, the proxy in vendor/, and a .env holding the token. The wizard offers to start the dev server and open it in a browser.

  3. 03

    Put it where your team can reach it

    A plain node server serving the build, a Dockerfile that ships in the app, or one command onto Vercel. It mounts under a path on a domain you already have — VITE_BASE_PATH at build, BASE_PATH at runtime, and the startup line prints the state so a mismatch is visible immediately.

  4. 04

    Decide who gets in

    Without the auth module the proxy runs open, byte for byte as it did before there was one: whoever can reach the URL uses the panel. With it, colleagues arrive by invite into one workspace, a member opens only the bots granted to them, owners and admins see all of them, and the database re-decides that on every call rather than trusting the app.

Where it runs

The same proxy source in all four, and the same app: a build for the browser and a server that keeps the token. What changes is the machine and where the environment is read from.

NameWhat it isWhat it needsThe environment
npm run devThe dev server on port 5173, with the proxy inside it. The wizard offers to start this one for you and open the browser on it.A machine with NodeA .env beside the app
npm startBuild, then a plain node server that serves the built client and proxies HTTP and WebSocket traffic. A box on your own network, on port 3000 unless you say otherwise.A server you keep.env loaded on start, real variables winning
DockerThe two-stage Dockerfile that ships in the app: build the client, then run the server as a non-root user.A container hostBuild args for the client, --env-file for the rest
VercelOne command in the app — check the CLI, link the project, push the environment, deploy, then ask the deployment whether it came up configured.A Vercel accountPushed by the deploy script, production and preview

FAQs

Not with a switch in the app — there is none, and a project that has sign-ups turned off is read as a misconfiguration rather than a setting. Two ways to a staff-only panel. Leave the auth module out: there is no sign-up and no sign-in, the proxy runs open, and keeping people away from the URL becomes your network’s job rather than the app’s. Or keep auth and turn sign-up off in your own Supabase project, which is where that switch lives; the wizard leaves it on when it configures one, so it is a change you make afterwards.

One command, and your team has its own panel

Pick the screens, run it where you want it, and open the source when the workflow is not quite yours yet.

npx @chatfuel/wizard