Erick · product & design engineer

REAL PROJECT · DESIGN SYSTEM, ACCESSIBILITY AND CODE

The bio link was rented. The audience was ours — and the data, nobody’s.

the final page · desktop and mobile

Canaltech distributed eight destinations through a Linktree. It worked as an index and failed as a product: no brand, no states, no consent and not a single click event coming back home. I rebuilt it as an owned page — design system, accessibility, telemetry and a single HTML file the team publishes with no build.

About the numbers.

The page is finished and tested, not published. Everything measured here is about the build — tokens, components, states, test coverage and weight. There’s no traffic or conversion data, and section 06 says so instead of estimating.

CLIENT

Canaltech

owned link hub

ROLE

Design system

and design engineer

DELIVERABLES

Design system · UI

Single HTML · accessibility

MADE WITH

Claude Code ⇄ Figma via MCP

HTML, CSS and JS · Playwright

PERIOD

2026 · solo

3rd generation of the page

01 · THE PROBLEM

The page existed. Owning it didn’t.

The bio sends the audience to a Linktree: good as an index, incapable as a product. Eight destinations with the same weight, and the click stayed outside.

3

generations of the same page; the first two rented

8

destinations competing at the same visual weight

0

click events in the house’s own analytics

0

control over consent, brand and states

02 · BEFORE AND AFTER

The change wasn’t about layout. It was about ownership.

The same goal — from the bio to eight destinations — down both paths. What shows up in the middle is everything the rented page couldn’t do from the inside.

before · the two generations on Linktree

BEFORE

A list hosted by a third party, eight destinations with the same weight and the brand reduced to a round avatar. No campaign banner, no focus state, no keyboard path. Consent and click data stayed with the platform, and any change depended on another company’s dashboard.

None of those last four can be solved from inside the tool. That’s the cost of renting.

after · the owned page

AFTER

A Canaltech page, with a brand field at the top and real hierarchy: campaign banner, CTA, sections and eight destinations with different weights. Clicks, newsletter and consent become events in the house’s analytics.

It’s one file. It goes up on Canaltech’s domain with no build, responds to hover, press, focus and keyboard, and degrades on its own if an asset is missing.

03 · CONSTRAINTS

The rules that existed before the first pixel.

It wasn’t a blank-canvas project. What could be done was already bounded by who publishes, where they publish and how much it costs to maintain after I leave.

Publishing

The dev team publishes, it doesn’t build. No build, no bundler, no dependencies: it arrives as a finished file.

Hosting

No application server. It has to work as a static file anywhere Canaltech already uses.

Performance

Traffic comes from the bio, on mobile, often on a poor connection. No third-party requests — fonts included.

Privacy

Consent is a requirement, not decoration. The page measures clicks, so it asks first and stores the answer.

Resilience

If an asset is missing from the deploy, the row can’t break. Every icon and image has a plan B in the HTML itself.

Campaign

The event banner comes and goes without touching the layout, because the vote has an end date.

04 · PRODUCT DECISIONS

Four decisions the static frame didn’t answer.

Figma delivers the page standing still. Product happens in what it doesn’t draw: what the button does with no destination, what the page does if the file disappears.

the four decisions, on screen

01

States became rules. Eleven rules derived from the tokens themselves — hover, press, focus, invalid, accepted and the toggle on.

02

The consent panel was built from scratch. Figma only had the button; I built the modal dialog, the focus trap, ESC and the scroll lock.

03

With no destination, the button declares itself disabled. It loses the href, becomes aria-disabled and stops responding, instead of becoming a dead anchor.

04

The hero grain shipped as code. Reproduced in CSS with feTurbulence — no file and no third-party request.

05 · SYSTEM AND DELIVERY

Ten components, 35 variants, and no hover left to invent.

The system isn’t a pretty palette: it’s the contract that lets the next person get the state right without asking. A variable in Figma is a custom property in CSS.

16

color tokens, with the same name in Figma and CSS

11

state rules specified, not improvised

10

component sets · 35 variants

176

automated assertions in Playwright

One file. Zero dependencies. Zero build.

The team gets a 55 KB index.html and an assets folder. It opens in the browser, goes up on any static host, has nothing to install — because whoever publishes isn’t whoever builds. The font comes from the repository itself: no request goes out to a third party. Every <img> has an onerror that swaps it for the inline sprite and keeps the row standing.

The system goes back to Figma.

The frame was read through MCP — nodes, variables, typography, grid and assets, nothing described from memory. What came out of the code went back as two 16:9 boards in this same file. In a one-way flow, Figma dies at handoff and becomes an image that goes stale at the first tweak; closing the loop, the file’s system and the HTML’s are the same.

Board 01 · Foundations
Board 02 · Components

06 · MEASUREMENT AND HONESTY

The page started answering questions nobody could ask before.

Three events go from the page into Canaltech’s own analytics. It isn’t a vanity dashboard: it’s knowing which destination pays for the next story.

ct:link

id · href · label

Which destination the audience actually uses, by position in the list and by live campaign.

ct:newsletter

email

How much of the audience coming from social becomes an owned base, with no middleman.

ct:cookies-consentimento

choice · audience · advertising · date

What share of the base accepts measurement — and what can honestly be attributed.

the page in both densities

What isn’t here.

No traffic, click or conversion numbers — the page is finished and tested, not published. Once it goes live, the three events above start feeding exactly these columns, and then the case gets a results section that today would be a guess. Two things were consciously left open: without production data, the hierarchy of the eight destinations is a hypothesis, to be revisited in the first month; and there was no test with a real screen reader — only checks of focus, labels, keyboard order and contrast.

07 · MORE

Other projects

Available for work

I design, I write the code, and I tell you what didn’t work.

Thirteen years in design, five of them at Canaltech across design systems, marketing and sales. If you have a surface that needs to ship finished and measured, not just specified, get in touch.

© 2026 Erick Teixeira

oerickteixeira@gmail.com · São Paulo

Erick · product & design engineer

REAL PROJECT · DESIGN SYSTEM, ACCESSIBILITY AND CODE

The bio link was rented. The audience was ours — and the data, nobody’s.

the final page · desktop and mobile

Canaltech distributed eight destinations through a Linktree. It worked as an index and failed as a product: no brand, no states, no consent and not a single click event coming back home. I rebuilt it as an owned page — design system, accessibility, telemetry and a single HTML file the team publishes with no build.

About the numbers.

The page is finished and tested, not published. Everything measured here is about the build — tokens, components, states, test coverage and weight. There’s no traffic or conversion data, and section 06 says so instead of estimating.

CLIENT

Canaltech

owned link hub

ROLE

Design system

and design engineer

DELIVERABLES

Design system · UI

Single HTML · accessibility

MADE WITH

Claude Code ⇄ Figma via MCP

HTML, CSS and JS · Playwright

PERIOD

2026 · solo

3rd generation of the page

01 · THE PROBLEM

The page existed. Owning it didn’t.

The bio sends the audience to a Linktree: good as an index, incapable as a product. Eight destinations with the same weight, and the click stayed outside.

3

generations of the same page; the first two rented

8

destinations competing at the same visual weight

0

click events in the house’s own analytics

0

control over consent, brand and states

02 · BEFORE AND AFTER

The change wasn’t about layout. It was about ownership.

The same goal — from the bio to eight destinations — down both paths. What shows up in the middle is everything the rented page couldn’t do from the inside.

before · the two generations on Linktree

BEFORE

A list hosted by a third party, eight destinations with the same weight and the brand reduced to a round avatar. No campaign banner, no focus state, no keyboard path. Consent and click data stayed with the platform, and any change depended on another company’s dashboard.

None of those last four can be solved from inside the tool. That’s the cost of renting.

after · the owned page

AFTER

A Canaltech page, with a brand field at the top and real hierarchy: campaign banner, CTA, sections and eight destinations with different weights. Clicks, newsletter and consent become events in the house’s analytics.

It’s one file. It goes up on Canaltech’s domain with no build, responds to hover, press, focus and keyboard, and degrades on its own if an asset is missing.

03 · CONSTRAINTS

The rules that existed before the first pixel.

It wasn’t a blank-canvas project. What could be done was already bounded by who publishes, where they publish and how much it costs to maintain after I leave.

Publishing

The dev team publishes, it doesn’t build. No build, no bundler, no dependencies: it arrives as a finished file.

Hosting

No application server. It has to work as a static file anywhere Canaltech already uses.

Performance

Traffic comes from the bio, on mobile, often on a poor connection. No third-party requests — fonts included.

Privacy

Consent is a requirement, not decoration. The page measures clicks, so it asks first and stores the answer.

Resilience

If an asset is missing from the deploy, the row can’t break. Every icon and image has a plan B in the HTML itself.

Campaign

The event banner comes and goes without touching the layout, because the vote has an end date.

04 · PRODUCT DECISIONS

Four decisions the static frame didn’t answer.

Figma delivers the page standing still. Product happens in what it doesn’t draw: what the button does with no destination, what the page does if the file disappears.

the four decisions, on screen

01

States became rules. Eleven rules derived from the tokens themselves — hover, press, focus, invalid, accepted and the toggle on.

02

The consent panel was built from scratch. Figma only had the button; I built the modal dialog, the focus trap, ESC and the scroll lock.

03

With no destination, the button declares itself disabled. It loses the href, becomes aria-disabled and stops responding, instead of becoming a dead anchor.

04

The hero grain shipped as code. Reproduced in CSS with feTurbulence — no file and no third-party request.

05 · SYSTEM AND DELIVERY

Ten components, 35 variants, and no hover left to invent.

The system isn’t a pretty palette: it’s the contract that lets the next person get the state right without asking. A variable in Figma is a custom property in CSS.

16

color tokens, with the same name in Figma and CSS

11

state rules specified, not improvised

10

component sets · 35 variants

176

automated assertions in Playwright

One file. Zero dependencies. Zero build.

The team gets a 55 KB index.html and an assets folder. It opens in the browser, goes up on any static host, has nothing to install — because whoever publishes isn’t whoever builds. The font comes from the repository itself: no request goes out to a third party. Every <img> has an onerror that swaps it for the inline sprite and keeps the row standing.

The system goes back to Figma.

The frame was read through MCP — nodes, variables, typography, grid and assets, nothing described from memory. What came out of the code went back as two 16:9 boards in this same file. In a one-way flow, Figma dies at handoff and becomes an image that goes stale at the first tweak; closing the loop, the file’s system and the HTML’s are the same.

Board 01 · Foundations
Board 02 · Components

06 · MEASUREMENT AND HONESTY

The page started answering questions nobody could ask before.

Three events go from the page into Canaltech’s own analytics. It isn’t a vanity dashboard: it’s knowing which destination pays for the next story.

ct:link

id · href · label

Which destination the audience actually uses, by position in the list and by live campaign.

ct:newsletter

email

How much of the audience coming from social becomes an owned base, with no middleman.

ct:cookies-consentimento

choice · audience · advertising · date

What share of the base accepts measurement — and what can honestly be attributed.

the page in both densities

What isn’t here.

No traffic, click or conversion numbers — the page is finished and tested, not published. Once it goes live, the three events above start feeding exactly these columns, and then the case gets a results section that today would be a guess. Two things were consciously left open: without production data, the hierarchy of the eight destinations is a hypothesis, to be revisited in the first month; and there was no test with a real screen reader — only checks of focus, labels, keyboard order and contrast.

07 · MORE

Other projects

Available for work

I design, I write the code, and I tell you what didn’t work.

Thirteen years in design, five of them at Canaltech across design systems, marketing and sales. If you have a surface that needs to ship finished and measured, not just specified, get in touch.

© 2026 Erick Teixeira

oerickteixeira@gmail.com · São Paulo

Email copied