catforest
← 返回笔记列表
方法与实践其他语言中文

From one colour variable to many management systems

On 2 June I made the first commit to yTemplate. It's a starter template for Next.js, and its README says it exists so new projects can skip setup and start writing features. Eight web projects in the matrix have started from it, among them yPulse, the component library yBlocks, a CRM template and yAgentKit, a kit for agent workspaces.

What I wanted from it is that every management system I build, whatever its domain, looks the same and behaves the same. That has to be built from the bottom up, one layer at a time.

At the bottom are the colour variables. One CSS file in the template owns colour, with 31 variables named by purpose: the primary colour, the card background, borders, five chart colours. Components use only those names and never a raw colour value. Greys are parameters too, one variable for hue and one for how strong the tint is, and the rules later gained a sentence saying that any new variable carrying a grey has to be written that way. Corner radii work the same way, a whole scale computed from one value.

The next layer is themes. The settings panel offers six ready-made accent colours, blue, green, purple, indigo, orange and red, or any hex value you type, which the template turns into nine variables. There are five neutral families and four radius steps, plus contrast, compact density and the navigation style. Those settings take effect in two places, once before the page is painted and once after it loads, and the two files have to say exactly the same thing; the theming document has a rule for that alone. yPulse opens in the orange theme. On top of that, every project in the matrix has a colour of its own: Tailwind's 17 colour families in one lap, then a lap one shade lighter, handed out by the project's position in the list. On every page of yPulse, a project is always the same colour.

Above that is the component library. Each project carries around fifty base components drawn from three sources, shadcn, Appica and Base UI. The rule is one source per slot, and switching a slot to another source replaces every use of it in the same change. On 16 September I put the input fields on one scale: small, medium and large are 28, 32 and 36 pixels, against Appica's own 32, 40 and 48, and selects, date fields and time fields all line up with it. The upstream for these components is yBlocks; on 1 September yTemplate took over yBlocks' whole component library.

Above the components are dense modules, and I practised on cards. On 10 July a card gallery opened in yBlocks; its first card was a replica of a dark usage card. The gallery now has 103 cards across seven domains, AI, finance, development, analytics and others. Each one records the design it was based on and what kind of card it is: 52 are replicas, 26 improve on the original, 5 carry it into a different context and 20 are original. On 12 July I wrote down a design language for cards, and two of its lines I still use all the time: consistency is the asset, and each card gets one signature element. There's a rule for lines too: solid lines only on the card's outer edge, and every division inside a card a faint dashed line.

Above the cards are pages. On 9 August I wrote the first page rule, for data tables. It records why it exists: before the kit, I had built the same kind of data page by hand ten times. The kit now has eleven parts, filters, sorting, pagination, view options, a strip of headline numbers at the top and an empty state among them. Rules followed for detail pages, boards, forms, workbenches and settings, and for things every page must respect, feedback, data fetching, icons and keyboard shortcuts. There are 18 in all now. A new page starts by deciding which kind it is, then reading that kind's rule and assembling it from the existing parts; building the frame by hand isn't allowed. A new shape of page only gets its own rule the second time it appears.

Above pages is one dataset seen many ways. On 21 August the Tasks app in yBlocks got all ten of its views in one day: overview, my work, list, board, table, timeline, calendar, workload, matrix and activity. They share one source of data; every change is recorded in a log that only grows, and each view works out its own picture from that log. Drag a card on the board and the same task moves in the table and the calendar, because the change was recorded in only one place.

The top layer goes from one system to many. On 10 September I started a CRM template from the CRM and calendar in yBlocks, with customers, a deal board, activities, a calendar, mail, reports and settings, carrying the same fifteen rules. yPulse is another system built this way: its changelog, project list, workflows, distribution ledger and works ledger all use the same data-table kit, projects and works open in the same side panel, and the distribution ledger has a board view as well. On 5 October yBlocks gained design notes for seven domains, billing, commerce, content, inventory, observability, people and support, which say these apps share one domain model across several operational views; customer IDs and stock numbers are shared, not copied. The management system in my day job follows the same rules.

With the layers stacked like this, moving to a new domain means writing only what belongs to that domain. Colour, themes, components, cards, page layouts and switching between views are already settled in the layers below.

A new web project today starts with those 31 colour variables, six accent colours and the full set of rules in its very first commit.