Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c839554
docs(app): Impeccable product record for OpenBot
samjulien Oct 29, 2026
7078dd5
feat(app): design tokens, Atkinson type and dark palette for the defa…
samjulien Oct 29, 2026
ff036a4
feat(app): derive a Bot's orb palette from its seed
samjulien Oct 29, 2026
5a23902
feat(app): BotOrb, a Bot's orb in its own palette
samjulien Oct 29, 2026
378e206
feat(app): Bots appear as their orb in the default skin
samjulien Oct 29, 2026
10eab47
feat(app): flat sidebar with Waiting for you and compact times
samjulien Oct 29, 2026
a5fedca
feat(app): home subheader and examples from your own Bots
samjulien Oct 29, 2026
402ffec
feat(app): conversation intro and centered reading column
samjulien Oct 29, 2026
87c17d3
feat(app): stronger rows and empty states; one meaning for orange in …
samjulien Oct 29, 2026
a429ff4
fix(app): show the highlighted row in dark-mode menus
samjulien Oct 30, 2026
848c141
fix(app): keep the conversation intro's role to two lines
samjulien Oct 30, 2026
b1b8ed1
fix(app): keep the skin tests and the composer hook passing
samjulien Oct 30, 2026
7621aa4
Use Tailwind's slate greys instead of neutral
guidovizoso Oct 30, 2026
aeb0e2e
Put each page in an inset panel: darker frame, light panel, white cards
guidovizoso Oct 30, 2026
cf0ccfa
Set the sidebar's conversation text on the type scale
guidovizoso Oct 30, 2026
6028a21
Lighten page and section headings
guidovizoso Oct 30, 2026
a8dc69f
Show an app's logo or initial instead of the same plug on every row
guidovizoso Oct 30, 2026
731d7e0
Home: drop the product-name label above the greeting
guidovizoso Oct 30, 2026
25b503f
Home: show Explore Bots as compact cards in a grid
guidovizoso Oct 30, 2026
d412533
Bot page: describe the Bot, not the page
guidovizoso Oct 30, 2026
7125aac
Bot page: fold an idle Activity section into For you
guidovizoso Oct 30, 2026
82d502b
Connections: fit each tile's line, and drop the one that repeats its …
guidovizoso Oct 30, 2026
7058c0a
Browse Composio: show placeholder rows while the directory loads, and…
guidovizoso Oct 30, 2026
22dfead
Put CopilotKit's dot matrix behind empty states, swappable by token
guidovizoso Oct 30, 2026
a2f02be
Show the Bots bolt, not a robot, in empty states about Bots
guidovizoso Oct 30, 2026
12a20dd
Note the default look's changes in the changelog
guidovizoso Oct 30, 2026
7d6be3a
Merge Guido's inset panel (#912) into the design uplift
samjulien Oct 30, 2026
37fccbf
style(app): the uplift's palette on Guido's three surfaces
samjulien Oct 30, 2026
77acce8
refactor(app): back to stock shadcn where the uplift restyled it
samjulien Oct 30, 2026
b1989b2
feat(app): the conversation orb's halo is the empty-state pattern
samjulien Oct 30, 2026
549494a
Revert "Bot page: fold an idle Activity section into For you"
samjulien Oct 30, 2026
b3486d8
Revert "Bot page: describe the Bot, not the page"
samjulien Oct 30, 2026
df22f75
Revert "Lighten page and section headings"
samjulien Oct 30, 2026
cb86238
style(app): bring back the uplift's look on Guido's inset layout
samjulien Oct 30, 2026
33dfc3f
refactor(app): the default look's edges, lift and orange as theme tokens
samjulien Oct 30, 2026
21b1a5d
fix(app): skins keep their own look
samjulien Oct 30, 2026
0de53e5
fix(app): keep the message scroller's data-slot
samjulien Oct 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ Newest first. `Unreleased` is what is on `main` and not yet tagged.
`COMPUTER_MEMORY_HIGH_PERCENT=0` and `COMPUTER_TAB_IDLE_MS=0` (Helm: `computers.memoryHighPercent`
and `computers.tabIdleMs`) keep the old behaviour.

### The default look: an inset page, slate greys and quieter headings

Each page now sits in a panel inset from the window, on a darker frame shared with the sidebar,
with white cards on a light grey page; admin and settings scroll inside it like the rest of the
app. The greys are Tailwind's slate rather than neutral, and page and section headings are lighter.
Rows show an app's logo or initial instead of the same plug; Home shows Bots as compact cards; a
Bot's page leads with its own one-liner; Connections tiles no longer cut their text off; and the
Composio directory shows its rows loading. Empty states carry a faint dot pattern whose file,
colour and strength are theme tokens (`--empty-pattern*` in `theme.css`), so a deployment can
replace it or turn it off. Skins are unchanged.

### A computer closes browsers nobody is using when its memory runs high

A computer runs one browser for each Bot that is browsing, and the only limits were a count and half
Expand Down
59 changes: 59 additions & 0 deletions app/PRODUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Product

<!-- impeccable:product-schema 1 -->

## Platform

web

## Users

Two audiences use the same app.

- **Company employee (daily end user).** Usually not technical. Asks Bots to do jobs: read an expense claim, turn a meeting note into follow-ups, research a topic. Expects the ease of ChatGPT, Claude or Grok.
- **IT owner (buyer and administrator).** Chooses and deploys OpenBot. Adds Bots, grants tools and connections, answers approvals, and reads the audit log. Needs trust and control.

## Product Purpose

OpenBot is an AI assistant that a company runs on its own infrastructure and can change completely. Any agent that speaks AG-UI arrives as a coworker. Success: employees use it as their everyday assistant, and the IT owner is confident about what each Bot can do.

## Positioning

Bots are coworkers, and you own them. Each Bot has a computer of its own (a real browser with its own logins, files and only the tools you grant). It runs on your infrastructure, with your PostgreSQL and your model choice. A hosted chatbot cannot truthfully say either.

## Operating Context

- The web app in `app/` is the main surface. A Tauri desktop app and a mobile client use the same frame.
- Main areas: chat with a chosen Bot, the Bot's own computer and browser, Bots, skills, routines, connections, memory, approvals, audit, admin and settings.
- OpenBot is a template. Companies clone the repository and rename it through `brand.yaml`.
- A person can pick a skin per account: the default `openbot` skin, OpenDuet, OpenDots or OpenMuse.

## Capabilities and Constraints

- Light and dark mode must both ship finished.
- The skin system stays. This redesign replaces the default `openbot` skin. The other skins stay as alternates.
- Desktop and mobile must both work at native quality.
- Dense admin screens (audit log, approvals, tables, settings) must stay easy to scan.
- Stack: React 19, Vite, Tailwind 4, shadcn and Base UI components, Tabler icons, Motion.

## Brand Commitments

- The new look is opinionated. When a company renames OpenBot, it swaps the name and logo. The visual world stays.
- The design must move away from the generic shadcn look (gray neutrals, Inter, default components).
- The user named Grok and Muse as references for simplicity, polish and elegance. The result must be unique, not a copy of either.
- Binding brand input (pinned 2026-10-28): take the pixelation and color schemes of copilotkit.ai. Pixelation means square-pixel dither fields. The colors are periwinkle `#7480F1` to mint `#23D5A2`, sky `#8DC1F1` to violet `#686FDF`, lilac `#BEC2FF`, pale lavender `#EDEDF5` and deep plum `#35295F`. The rest of that website is not a reference.
- Direction rounds 1 and 2 were rejected as generic. The user likes bold directions, except extreme ones such as a hand-drawn newsprint catalog.

## Evidence on Hand

- Real product copy in `README.md` and `docs/`.
- Real Bots: General Assistant, Knowledge, Risk Analyst, and ten catalog Bots in `examples/fintech/catalog/`.
- No customer logos, testimonials or usage numbers. Do not invent them.

## Product Principles

1. A Bot is a colleague, not a chat widget. It has a name, a computer and a record of its work.
2. Ownership feels calm and solid. Nothing in the interface suggests a hosted service.
3. The conversation leads. Chrome that does not help the current job stays out of the way.
4. Control is visible but quiet. Approvals and audit are part of the product, not an alarm system.
5. Every detail is finished. Rough spacing, type and motion break trust.
2 changes: 2 additions & 0 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"@base-ui/react": "^1.6.0",
"@better-auth/sso": "^1.7.1",
"@copilotkit/react-core": "1.83.0",
"@fontsource-variable/atkinson-hyperlegible-mono": "^5.3.0",
"@fontsource-variable/atkinson-hyperlegible-next": "^5.3.0",
"@fontsource-variable/inter": "^5.3.0",
"@openbot/shared": "workspace:*",
"@shadcn/react": "^0.3.0",
Expand Down
136 changes: 136 additions & 0 deletions app/src/assets/patterns/dot-matrix.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 5 additions & 4 deletions app/src/components/admin/admin-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import {
IconArrowLeft,
IconBuildingBank,
IconBulb,
IconChecks,
IconCode,
IconDeviceDesktop,
IconFileText,
IconKey,
IconLayoutGrid,
IconListDetails,
IconPuzzle,
IconShieldCheck,
IconSlash,
IconUsers,
} from "@tabler/icons-react";
import { Link, type LinkOptions } from "@tanstack/react-router";
Expand Down Expand Up @@ -79,12 +80,12 @@ const GROUPS: {
},
{
title: "Skills",
icon: IconFileText,
icon: IconSlash,
linkOptions: { to: "/admin/skills" },
},
{
title: "Automatic learning",
icon: IconFileText,
icon: IconBulb,
linkOptions: { to: "/admin/learning" },
},
{
Expand Down Expand Up @@ -130,7 +131,7 @@ export function AdminSidebar({
...props
}: React.ComponentProps<typeof Sidebar>) {
return (
<Sidebar {...props}>
<Sidebar variant="inset" {...props}>
{/*
* Pinned to the same height as the app sidebar's header. Left to itself this one is 60px
* against the app's 45px — `p-2` around a `size="lg"` button rather than a fixed height — so
Expand Down
11 changes: 11 additions & 0 deletions app/src/components/agents/abstract-avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import Avatar from "boring-avatars";
import { BotOrb } from "@/components/agents/bot-orb";
import { DEFAULT_SKIN, useSkinId } from "@/skins/store";

/**
* A Bot's avatar. OpenBot's own look draws the Bot as its orb; a skin keeps the face it was
* designed with.
*/
export function AbstractAvatar({
name,
seed,
Expand All @@ -9,6 +15,11 @@ export function AbstractAvatar({
seed: string;
size?: number;
}) {
const skin = useSkinId();
if (skin === DEFAULT_SKIN) {
return <BotOrb name={name} seed={seed} size={size} />;
}

return (
<span
role="img"
Expand Down
22 changes: 11 additions & 11 deletions app/src/components/agents/agent-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ export function AgentCard({
appearance = "compact",
}: {
agent: AgentProfile;
appearance?: "compact" | "tile";
appearance?: "compact" | "row";
}) {
if (appearance === "tile") {
if (appearance === "row") {
return (
<div className="flex h-[180px] w-[144px] flex-col overflow-hidden rounded-2xl border border-border bg-card p-3 transition-colors hover:border-ring dark:border-transparent">
/*
* The avatar beside the name rather than above it: a tall card left most of its height empty
* between the two, and a row reads the name and what the Bot is for in one glance.
*/
<div className="flex h-16 min-w-0 items-center gap-3 rounded-xl border border-card-border bg-card px-3 shadow-card transition-[border-color,box-shadow] hover:border-ring hover:shadow-card-hover">
<div aria-hidden="true" className="flex shrink-0">
<AbstractAvatar name={agent.name} seed={agent.avatarSeed} size={36} />
<AbstractAvatar name={agent.name} seed={agent.avatarSeed} size={32} />
</div>
{/* Bottom-aligned, where the text sat on the earlier artwork card; the avatar holds the top. */}
<div className="mt-auto flex min-w-0 flex-col gap-2">
<span
className="line-clamp-1 break-words text-sm font-medium leading-5"
title={agent.name}
>
<div className="flex min-w-0 flex-col gap-0.5">
<span className="truncate text-sm font-medium" title={agent.name}>
{agent.name}
</span>
<span className="line-clamp-3 break-words text-xs leading-4 text-muted-foreground">
<span className="truncate text-xs text-muted-foreground">
{agent.roleDescription}
</span>
</div>
Expand Down
Loading
Loading