Global Texture - Noise Background
Global Texture - Noise Background
    uxproof on two phones: the empty chat, and a chat that lists the uploaded reports and generates a deck
    uxproof on two phones: the empty chat, and a chat that lists the uploaded reports and generates a deck
Produced by
PAISAK4U
Role
UX/UI design, design system and frontend engineering
Scope
Site structure and contact flows, a design system in Figma, and an Astro and React build with automated tests
Year
2024—2026
Tools
AstroReact 19TypeScriptTailwind CSSGSAPWebGLZustandPlaywrightaxe-coreNetlifyFigma

Context

My own site is the first thing people judge my work by.

PAISAK4U is the name I work under as an independent consultant, mostly on interfaces for AI products and UX-led frontend work. The site is where product teams decide whether to get in touch. It has to show how I work and turn a first message into something I can plan from.

I used two typefaces: Schibsted Grotesk for headlines and IBM Plex Mono for labels and body text. Hierarchy comes from size and opacity, and nothing on the site is set in bold. The palette is black and white, and colour only appears for errors.

Both themes come from the same set of CSS custom properties. A small inline script reads the stored choice before the page paints, so someone who picked light never sees a flash of dark when they come back.

The site moves a lot. A short loader plays on the first visit of a session, and after that a curtain closes and opens between pages. Sections reveal as they scroll in, the services sit in a pinned deck that turns as you scroll, and a WebGL ripple runs over the wordmark and the photos under the pointer.

The site uses Google Analytics to count visits and see which pages get read. Consent Mode defaults are set in the head before anything else runs, and the Google tag is only added once a visitor accepts. If they decline or never answer, no request goes to Google at all.

The notice waits for the first click, tap, scroll or key press instead of covering the page on arrival, and Escape dismisses it for the rest of the visit. Both answers are tested: declining keeps Google entirely unloaded, and accepting loads the tag.

The PAISAK4U home page on two phones, one in the dark theme and one in the light, beside the desktop layout in the dark theme, all on a concrete wall
The last section of the PAISAK4U home page in the dark theme, on a screen against a concrete wall: the portrait with its chat bubble, the headline “Let’s discuss your project” and three experience figures
The Recommendations section of the PAISAK4U home page in the dark theme, on a screen against a concrete wall: the quote “Turning complex requirements into simple, intuitive user experiences.” beside the full LinkedIn recommendation from Serkan Altay, AI architect and lead for GenAI platforms at DSB
The analytics notice over the PAISAK4U home page in the dark theme, on a tablet and a phone against a concrete wall: what the data is used for, that nothing loads until a choice is made, and the choice between “I understand” and “No thanks”

Design system

One set of tokens for Figma and the code.

The design system lives in Figma as variables, and each variable carries its CSS name as code syntax, so inspecting a colour shows var(--color-bg) instead of a hex value. Colour has dark and light modes. A responsive collection has mobile, tablet and desktop modes, and the type sizes carry the same clamp() values as the code.

Every primitive has a spec beside it: the tokens it uses, how it behaves, what it does for screen readers and the file it lives in. The arrow, for example, is the only icon on the site. It’s sized in em so it matches the text around it, it’s always hidden from screen readers, and its meaning comes from the words next to it.

Contrast is measured in both themes. Dimmed mono text is 9.76:1 on dark and 8.45:1 on light, and the faintest text is 6.86:1 and 5.33:1.

The PAISAK4U design system in Figma on a laptop: the pages from Documentation to Accessibility down the side, with the Color and Typography foundations open
Figma, the Design tokens page: primitive, semantic and component tokens, the six collections, the colour tokens in dark and light with their CSS code syntax, the responsive sizes for mobile, tablet and desktop, spacing, shape and emphasis, the text styles and the naming rules
Figma, the Accessibility page: the WCAG 2.2 AA target, the contrast of each text colour in dark and light against what it needs, the focus ring on a bracket action, a choice card, the skip link and a rail item, the keyboard, screen reader and form behaviour with how each is built, and reduced motion, no-JS and target size
Figma, the Responsive page: the breakpoints, how each component changes below and above its breakpoint, and the rules for viewport units, the fixed bars, line breaks and Figma’s Responsive modes

Contact

One question at a time.

The contact page asks visitors to choose first: a short route to book a 30-minute intro call, or a longer one to send a project brief. The call takes five questions. The brief takes thirteen, and they’re the questions I’d ask in a first discovery session, such as who we’re designing for, what alternatives those users have today and what value the experience should create.

Each question is its own step. Focus moves to the new question going forwards or back, and to the review heading at the end. An error shows on the step that caused it, is announced, and is tied to its field, so a screen reader reads it with the question. From the review screen any answer can be edited, and the flow jumps straight back to it.

Small details got the same attention. Enter moves a short answer on but adds a new line in a longer one, and on phones the controls stay clear of the fixed bottom bar.

Without JavaScript, both routes render as complete ordinary forms and still submit. Tests check that every answer reaches the POST Netlify receives, and that every field is registered in the static HTML Netlify reads at build time.

Figma, the Forms components: the choice card for picking a route in its default, hover and focus states, the stepper progress from step 1 to 5, the question field single-line and multi-line when empty, filled, focused and with an error, the plain field used without JavaScript, and a review row, each with its properties, tokens, accessibility notes and the code it maps to
Step 7 of 14 of the project brief, “Who are we designing for?”, on two screens against a concrete wall, dark above and light below: the hint beside the question and the answer typed in below it
Step 12 of 14 of the project brief, “What do you like — and why?”, on two screens against a concrete wall, dark above and light below: the hint beside the question, and Linear, Monzo and GOV.UK given as the answer
The last step of the project brief, “Review your answers, then send”, on two screens against a concrete wall, dark above and light below: step 14 of 14, the answers so far with an Edit link beside each, and “OK, submit answers”
Three phones in the dark theme against a concrete wall, each on a step of the project brief: 8 of 14, “What alternatives do your users have today?”, 12 of 14, “What do you like — and why?”, and 13 of 14, “What should I know before we start?”
Three phones in the dark theme against a concrete wall, each on a step of the project brief: 7 of 14, “Who are we designing for?”, 9 of 14, “What value should the experience create?”, and the last step, “Review your answers, then send”

Testing

97 tests, with and without JavaScript.

The site has 97 Playwright tests. axe checks all eight routes against WCAG 2.1 A and AA, plus the home page in both themes and the contact and request forms while they’re being filled in. Other tests check that no page scrolls sideways on a phone, tablet or desktop, that every internal link and anchor resolves, and that each route has one h1 and its own canonical URL, title and social card.

A few cover things that break quietly. The skip link has to be the first tab stop, the theme has to apply before any script runs on reload, and a browser that blocks storage mustn’t break the page. TypeScript runs in strict mode, astro check runs in every build, and ESLint includes the jsx-a11y rules.

On the version live in October 2026, all 97 pass.

The Playwright report for the full suite, on a screen against a concrete wall: 97 passed, none failed, flaky or skipped, in 42 seconds, opening on the access-request and contact tests
Playwright’s trace viewer on a screen against a concrete wall, on the test “focus follows the stepper forwards, backwards and into review”: its last check, that focus lands on the heading “Review your answers, then send”, highlighted in the page snapshot beside the list of steps