Admin UI

Every Sluurp server has a dashboard at /_/, like Django's admin: made from your schema, with nothing to write. Each collection gets a table to browse, filter and edit, and the server gets the screens to run it.

For your data

  • A table per collection, with a filter box (paid = true && total > 100), sorting, column choice and pages.
  • A form per record that fits each field: a date picker for dates, a searchable picker for relations, an image preview and upload for files.
  • History and undo: every change with who and why, any version brought back, deleted records in a recycle bin.
  • Explore and pivot tables, charts and formulas over a collection, without exporting it.
  • Rules for who may read and write, written next to the collection.

For the server

Logs, an SQL console, backups, scheduled jobs, rate limits, mail, sign-in providers, payments, forms, feeds, translations and storage, each a screen. Drag the Platform rows into your own order, or move one with Alt and an arrow key.

Components

The Components screen is the kit’s workshop, like Storybook. Each component is drawn alone on a canvas, at a phone’s width, a tablet’s or the full width, in light or dark. You can change its arguments in Controls and copy the code for what’s on show from Code. Docs is a page per component: what it’s for, a table of its arguments, and every story drawn under it.

Stories are Storybook’s own Component Story Format (CSF 3), so a story file moves between the two unchanged. A file named *.stories.tsx next to a component is found by its name, with no config:

client/kit/button.stories.tsx
import { Button } from "./button.js";

export default {
  title: "Actions/Button",
  component: Button,
  args: { children: "Save changes", disabled: false },
  argTypes: { variant: { control: "select", options: ["default", "outline", "destructive"] } },
};

export const Primary = {};
export const Destructive = { args: { variant: "destructive", children: "Delete" } };

With no render, a story is component(args). A kit component takes one object of props, as a story’s args are. Controls are inferred from each arg’s value; argTypes is only needed for a choice. A play({ canvasElement, args }) function runs once the story is drawn.

One addition of Sluurp’s own, which Storybook ignores: argTypes: { collection: { control: "collection" } } picks a collection of the open project, and its rows reach render(args, { loaded: { rows } }). A select, a table or a list is then drawn from real data, with this project’s words and lengths rather than three made-up ones. Every story is drawn in a test.

Compared with Django admin

What Sluurp has that Django admin does not:

  • Live updates: a record someone else changes changes on your screen.
  • History, restore and a recycle bin for every collection, built in.
  • An SQL console, backups, logs, jobs and rate limits in the same place.
  • Nothing to register or configure: a collection is in the admin as soon as it exists.
  • Translations edited live, with several people at once.

What Django admin has that Sluurp does not yet:

  • Customising a model’s admin in code: which columns show, how the form is grouped, read-only fields per screen.
  • Your own bulk actions, written in code, on the ticked rows.
  • Editing related records inside the parent’s form (inlines).
  • A date drill-down (years, then months, then days) above a list.

The admin UI is built with the same UI kit your app can use.