Quick start
Let’s build a tiny Posts admin — one resource, one panel, done.
1. Define a resource
Section titled “1. Define a resource”from almasix.orbit import Resourcefrom almasix.orbit.forms import Form, TextInput, Textareafrom almasix.orbit.tables import Table, TextColumnfrom almasix.orbit.infolists import Infolist, TextEntry
from app.models.post import Post
class PostResource(Resource): model = Post navigation_label = "Posts" navigation_group = "Content" navigation_sort = 1 navigation_icon = "heroicon-o-pencil-square" permission_prefix = "posts" record_title_attribute = "title"
@classmethod def form(cls, form: Form) -> Form: return form.schema([ TextInput.make("title").required().max_length(200), TextInput.make("slug").required(), Textarea.make("body").rows(8), ])
@classmethod def table(cls, table: Table) -> Table: return table.columns([ TextColumn.make("title").searchable().sortable(), TextColumn.make("slug").searchable(), ])
@classmethod def infolist(cls, infolist: Infolist) -> Infolist: return infolist.schema([ TextEntry.make("title"), TextEntry.make("slug").copyable(), TextEntry.make("body").prose(), ])Orbit fills row / bulk / header actions for you when you leave those slots empty — view, edit, delete, delete selected, and create.
2. Register a panel
Section titled “2. Register a panel”from almasix.orbit import Panel, PanelRegistry
from app.orbit.post_resource import PostResource
def register_orbit(app) -> None: panel = ( Panel.make("admin") .path("orbit") .brand_name("Acme Admin") .primary("#f1511b") .resources([PostResource]) .login() ) app.make(PanelRegistry).register(panel)Call register_orbit(app) from a service provider’s boot() (or wherever you wire app services). The registry is a singleton bound by OrbitServiceProvider.
3. Render the shell
Section titled “3. Render the shell”When you need the HTML chrome — sidebar, brand, Orbit assets — ask the panel:
panel = app.make(PanelRegistry).get("admin")html = panel.render_shell("<p>Welcome.</p>", user=request.user)Navigation items come from resources and pages: label, icon, group, URL, sort.
4. Sanity-check with LiveResource
Section titled “4. Sanity-check with LiveResource”from almasix.orbit.testing import LiveResource
from app.orbit.post_resource import PostResource
def test_post_resource_shape(): live = LiveResource(PostResource) live.assert_form_has_field("title") live.assert_table_has_column("title") errors = live.fill_form({}) assert "title" in errorsYou wrote Python. The panel has a sidebar entry, a form, and a table. That’s the whole game.