Fullstack developer, Umain
2023 - Now
Umain is a digital consulting firm who works with a range of brands, everything from mcDonalds, Scania and biamp. Umain offers both web and digital services
Clients: Scania, Poc Sports
Senior Software Engineer
charles.krook@gmail.com · charleskrook.com · linkedin.com/in/charleskrook · github.com/ckrook · instagram.com/charleskrook
Work
Fullstack engineer at Umain. My work spans e-commerce platforms, design systems, and content-driven sites, where the engineering exists to serve the design.
Place
Stockholm, Sweden. Grew up just outside it, spent a few years moving between cities, and came back in 2019.
Off-hours
Outdoors whenever I can. Mostly on the road bike and swiming.
Experience
2023 - Now
Umain is a digital consulting firm who works with a range of brands, everything from mcDonalds, Scania and biamp. Umain offers both web and digital services
Clients: Scania, Poc Sports
2023 - 2023
Grebban is a retail e-commerce firm who create extraordinary e-commerce experiences and digital flagship stores for brands globally.
Clients: Grandpa, Byon, Norstedts, Hestra Gloves
2022 - 2023
I worked at Sopra Steria, a big tech and consulting company helping businesses with digital solutions and transformation.
Clients: Radiohjälpen
2016 - 2019
Freelance developer during a longer period of my life. developing sites for clients and businesses.
Selected work
2023-2024
Led frontend for a new e-commerce platform, from architecture to UI for a fast, modern customer experience.
Centra, Tailwind, Nextjs, Sanity, Klaviyo, Adyen, Gladly, Playwright
Oct 2024 – 2026
Scania's multibrand design system, powering Scania products across the organization suporting mulit frameworks.
Stenciljs, npm, aws
2025-2026
An interactive museum platform with 3D installations synced across touchscreens and wall displays in real time.
Technologies
Nextjs, Stenciljs, Tailwind, React, Centra, Sanity, Hygraph, Gladly, Klaviyo, Adyen, Playwright, npm, aws
An interactive museum platform with 3D installations synced across touchscreens and wall displays in real time.
4 installations · 2 languages · 1920px → 6835px+ displays · runs unattended, all day
One experience, many screens, real time. A visitor touches the table; the wall reacts, and they can't drift apart.
Content changes often, in two languages, edited by curators not engineers. Installations run unattended all day and must recover on their own when a visitor walks off or a screen idles.
Globe: interactive 3D globe (R3F) with multiple themes plus a story mode that plays a film on the wall while the table drives it.
Timeline: auto slideshow of Scania's history with openable milestones; a separate build for rooms past 6835px.
Quiz: scored multiple choice with live feedback.
Remote: a phone that lets staff drive playback and reset any installation from the floor.
Table and wall never talk directly. They share a few realm variables over a WebSocket (PIXILAB Blocks). One screen publishes, the rest react.
Hardest piece: story-mode video. Lockstep playback meant time-stamped play/pause/seek commands, position/duration reporting, and handling players that aren't ready or films that have ended.
To build it without a museum on my desk, I made a localStorage fallback so two browser tabs behave like the real table and wall.
Everything visitors see comes from Sanity: pages, globe content, quiz questions, Swedish translations, no code required. Next.js fetches and caches it.
Around it: an idle reset timer, a broadcast refresh trigger, an access whitelist, per-installation Plausible analytics, and layouts from 1920px to ultrawide.
Next.js 14 (App Router) · Three.js / R3F · GSAP + Lottie · Redux Toolkit · Tailwind + Styled Components · Sanity.
The rule that kept it sane: local state → Redux. Shared-across-displays state → realm variables only. Always one home for every piece of state.
Write the realm-variable contract down sooner. Once a remote and several installations depend on the same variables, the names and defaults are an API, so treat them like one.
Photography and video by Ludwig Mattsson.