Get in touch
Gabs

Design system.

The components this site is built from, each one live. Drag the lens sliders, or open the menu from its tile.

Wordmark

Gabs

Lens text

Selected work.

Motion

  • EntranceAnything arriving0.2, 0.7, 0.1, 1
  • CurtainThe menu and page changes0.7, 0, 0.2, 1

Homepage sliders

Engineering with a designer’s eye.

Adjust the headline's lens

Badge

Buttons

Inputs

Enter an email address I can reply to.

Colour

  • Navy 950#050C18
  • Navy 925#070D18
  • Navy 900#081428
  • Navy 850#0B1A31
  • Navy 800#102645
  • Navy 700#183559
  • Navy 600#24486F
  • Navy 500#2D567E
  • Navy 400#5A7FA8
  • Navy 300#8EA7C9
  • Navy 200#C3D2E8
  • Navy 100#E2E9F4
  • Navy 50#F2F5FA
  • Shirt#A9C1E6

Tabs

What's it about?

Navigation

Menu

Command menu

Opens from anywhere on the site

Theme switcher

Theme

Role card

2026 to nowNow

SharpHaw

Founder · Lisbon

My own studio, running websites, ads, content and automations for small businesses across Europe on software I built for it.

SharpOS commits since March 2026
2,700+
unit tests, written first
39,770

Stack list

Brand marks

Stack chips

  • TypeScript
  • Next.js
  • Convex
  • Electron
  • Expo
  • Tailwind CSS
  • MCP
  • Vitest
  • Playwright
  • Bun
  • Turborepo

Timeline

Release cards

v2.0.0

A native iOS app that enforces the same access rules as the web from shared code.

v3.0.0

53 independently versioned modules, and reads no longer wait on four serial auth lookups.

Syntax highlight

type Lens = { focus: number }

// Pull the subject sharp.
export function rackFocus(
  lens: Lens,
  depth = 0.4,
): Lens {
  const focus = lens.focus + depth
  return { ...lens, focus }
}

Listen player

Player size

Listen to this post· AI-narrated

0:00 / 8:41

Post card

Accordion

Are you looking for a full-time role or contract work?

Both. I'm open to full-time senior full-stack roles and to contract builds of a product or platform.

Before and after

Rebuild: the same pavilion, lawn and evening light, a centred three-line serif headline and the new Evergold wordmark.
Reference: a lawn-care page with a pavilion on a lawn in evening light, a centred three-line serif headline and a script wordmark splitting the menu.
ReferenceRebuild

Bar chart

SharpOS commits per week, with v1.0, v2.0 and v3.0 marked.
SharpOS commits per week, with v1.0, v2.0 and v3.0 marked.
Week ofCommits
23/03/202687
30/03/2026116
06/04/2026171
13/04/2026105
20/04/2026132
27/04/202689
04/05/202675
11/05/2026133
18/05/202684
25/05/202621
01/06/202654
08/06/202658
15/06/202633
22/06/2026194
29/06/202662
06/07/202687
13/07/202614
20/07/202647
27/07/202694
03/08/202665
10/08/202667
17/08/202699
24/08/2026132
31/08/2026358
07/09/202668
14/09/202641
21/09/202685
28/09/20261
05/10/20263

Film

Icon buttons

Theme toggle

Surfaces

Night

  1. 1Page#071427L 0.190 · C 0.04413.0#d0d9e66.5#869bb9
  2. 2Section#0b1a31L 0.220 · C 0.05013.1#d7e0ed6.5#8ba0be
  3. 3Card#0f223cL 0.250 · C 0.05612.9#dfe8f56.5#92a6c5
  4. 4Field#152946L 0.280 · C 0.06113.0#eaf2ff6.5#9aaecd
  5. 5Active#1a3051L 0.310 · C 0.06512.9#fafcff6.5#a3b8d6
  6. 6Dialog#21385bL 0.340 · C 0.06811.5#fafcff6.5#adc2e1
  7. 7Dialog field#274064L 0.370 · C 0.07010.2#fafcff6.5#b8ceed
  8. 8Top#2e486eL 0.400 · C 0.0729.0#fafcff6.5#c4dafa

Day

  1. 1Page#c9d2e0L 0.861 · C 0.02213.0#01091f6.5#2f4463
  2. 2Section#cfd8e5L 0.878 · C 0.02113.0#0412286.5#324767
  3. 3Card#d5dde9L 0.895 · C 0.01913.0#08182f6.5#354b6a
  4. 4Field#dbe3eeL 0.912 · C 0.01813.1#0d1d346.5#394e6e
  5. 5Active#e1e8f2L 0.929 · C 0.01613.0#1222396.5#3c5172
  6. 6Dialog#e7eef7L 0.946 · C 0.01513.0#16263e6.5#3f5575
  7. 7Dialog field#edf3fcL 0.963 · C 0.01313.0#1a2a426.5#425879
  8. 8Top#f5f9ffL 0.980 · C 0.00913.0#1d2e466.5#455b7c
  1. The body, where every surface starts
  2. Bands and quiet cards on the page
  3. Cards and tiles on the page
  4. Fields and chips in a card
  5. A selected tab, a focused field, a menu from a card
  6. Dialogs and sheets
  7. Fields in a dialog
  8. A menu from a dialog, the highest layer

Each level carries its own text, worked out for it: the number is set in its text and the role in its muted text. Text keeps 13:1 wherever the surface allows and never falls under 7:1; muted text keeps 6.5:1 on every level. Under each swatch: the surface in hex, its OKLCH lightness and chroma on hue 258, then each text colour with its contrast.

Night

Page1

Card3

Field5

Menu7

Day

Page1

Card3

Field5

Menu7

Typography

Newsreader · Display
Engineering with a designer’s eye.
Geist · Text
I build web products end to end, from the data model to the interface people touch.
Geist Mono · Code
rackFocus(shot, 0.4)
Display52–104px
Studio
Headline36–60px
Studio
Role32–56px
Studio
Subhead30–40px
Studio
Title28px
Studio
Text16px
Studio
Label13px
Studio

Heading one

A paragraph in Geist at 17px with loose leading, carrying bold, italic, bold italic, struck through, inline code and a link in the run of the text.

Heading two

Heading three

Heading four

Heading five
Heading six

A quote sets in the serif’s italic, its opening mark hung in the margin so the words keep the edge of the column.

  • An unordered list
  • Its second item
    • A nested item
  1. An ordered list
  2. Numbered in tabular figures
ElementFaceSize
Headings one and twoNewsreader30–40px
Heading threeNewsreader28px
Headings four to sixGeist20, 17, 15px
TextGeist17px
CodeGeist Mono15px

The Kanban board of a demo organization in SharpOS, with cards across Backlog, Ready, In Progress, Review and Done.

const lens = rackFocus(shot, 0.4)