<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 𝝝̷𝝟̷𝝙̷ 𝝗̷𝝘̷𝝞̷𝝝̷𝝥̷𝝛̷</title>
    <description>The latest articles on DEV Community by 𝝝̷𝝟̷𝝙̷ 𝝗̷𝝘̷𝝞̷𝝝̷𝝥̷𝝛̷ (@okabrionz).</description>
    <link>https://dev.to/okabrionz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F46729%2F33c8e989-beb3-453b-aad4-22e3c3bdc5c3.jpeg</url>
      <title>DEV Community: 𝝝̷𝝟̷𝝙̷ 𝝗̷𝝘̷𝝞̷𝝝̷𝝥̷𝝛̷</title>
      <link>https://dev.to/okabrionz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/okabrionz"/>
    <language>en</language>
    <item>
      <title>Universal OKLCH Color System Blueprint: One-Base-Color Design Tokens</title>
      <dc:creator>𝝝̷𝝟̷𝝙̷ 𝝗̷𝝘̷𝝞̷𝝝̷𝝥̷𝝛̷</dc:creator>
      <pubDate>Wed, 08 Jul 2026 20:55:35 +0000</pubDate>
      <link>https://dev.to/okabrionz/universal-oklch-color-system-blueprint-one-base-color-design-tokens-3639</link>
      <guid>https://dev.to/okabrionz/universal-oklch-color-system-blueprint-one-base-color-design-tokens-3639</guid>
      <description>&lt;h2&gt;
  
  
  OKLCH Color Systems: One Base Color, Entire Token System
&lt;/h2&gt;

&lt;p&gt;When you hand over a color system to your team, the worst-case scenario is this: your designers pick a brand red, the developers build a palette around it using HSL—and six months later, the mid-tone reds are unreadable over your backgrounds because the lightness formula broke in a way neither of you saw coming.&lt;/p&gt;

&lt;p&gt;This article walks through why that happens, how OKLCH fixes it, and introduces &lt;strong&gt;CHROMA/1&lt;/strong&gt;—a framework and tool I've built to generate entire design systems from a single base color, guaranteed perceptually uniform, with light/dark modes, WCAG validation, and components ready to copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The HSL Problem
&lt;/h2&gt;

&lt;p&gt;HSL looks intuitive at first: hue (0–360°), saturation (0–100%), lightness (0–100%). You'd think that if you pick L=50 for two colors, they'd look equally bright, right?&lt;/p&gt;

&lt;p&gt;Wrong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;hsl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt; &lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%)&lt;/span&gt;   &lt;span class="c"&gt;/* red — actually looks bright */&lt;/span&gt;
&lt;span class="nt"&gt;hsl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;240&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt; &lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%)&lt;/span&gt; &lt;span class="c"&gt;/* blue — looks much darker */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the &lt;strong&gt;lightness perception gap&lt;/strong&gt;. HSL measures lightness mathematically, but human eyes don't perceive it linearly. Yellow and blue at the same L value appear wildly different in actual brightness. This is fine for one-off colors, but the moment you try to scale a palette—say, generating a 50–950 scale for red and blue using the same L curve—the blue steps look wrong because the perceptual jumps are uneven.&lt;/p&gt;

&lt;p&gt;Web designers have patched this with tweaks: nudge the saturation down, shift the lightness up, add special cases per hue. It works, but it's brittle and doesn't scale across brands.&lt;/p&gt;

&lt;h2&gt;
  
  
  OKLCH: Perceptual Linearity
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;OKLCH&lt;/strong&gt; is an entirely different approach: it's based on &lt;strong&gt;OKLab&lt;/strong&gt;, a color space engineered for perceptual uniformity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;oklch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;L&lt;/span&gt; &lt;span class="nt"&gt;C&lt;/span&gt; &lt;span class="nt"&gt;H&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;L&lt;/strong&gt; (lightness): 0–1, perceptually linear. A step from L=0.3 to L=0.4 looks the same brightness jump as 0.6 to 0.7, across any hue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C&lt;/strong&gt; (chroma): how saturated the color is (roughly 0–0.4 for sRGB).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;H&lt;/strong&gt; (hue): 0–360°.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the magic: because L is perceptually uniform, a simple 11-step scale (50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950) works for &lt;em&gt;every&lt;/em&gt; color. Red, blue, yellow—same L values mean same perceived brightness.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Red base #990000 */&lt;/span&gt;
&lt;span class="nt"&gt;--color-red-50&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="nt"&gt;oklch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;971&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;013&lt;/span&gt; &lt;span class="err"&gt;28&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;--color-red-500&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;oklch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;637&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;237&lt;/span&gt; &lt;span class="err"&gt;28&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;--color-red-950&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;oklch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;250&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;090&lt;/span&gt; &lt;span class="err"&gt;28&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c"&gt;/* Blue — same L curve, different hue */&lt;/span&gt;
&lt;span class="nt"&gt;--color-blue-50&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="nt"&gt;oklch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;971&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;013&lt;/span&gt; &lt;span class="err"&gt;259&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;--color-blue-500&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;oklch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;637&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;215&lt;/span&gt; &lt;span class="err"&gt;259&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;--color-blue-950&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;oklch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;250&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;070&lt;/span&gt; &lt;span class="err"&gt;259&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c"&gt;/* Both 50 look equally light. Both 500 look equally bright. */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  One Base Color → Entire System
&lt;/h2&gt;

&lt;p&gt;Here's the insight: if L and C curves are predictable and reusable, you only need &lt;strong&gt;one input&lt;/strong&gt;—the brand color—and everything else derives mathematically.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Method
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Convert input hex to OKLCH&lt;/strong&gt;: &lt;code&gt;#990000&lt;/code&gt; → &lt;code&gt;oklch(0.429 0.176 29.23)&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Find anchor step&lt;/strong&gt;: Look at the L value (0.429). That's perceptually between step 700–800, so place your brand color at step 800 (the anchor). Don't force it to 500.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generate scale&lt;/strong&gt;: Apply the standard L and chroma curves:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.637&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="nx"&gt;C_peak&lt;/span&gt;
   &lt;span class="nx"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.577&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="nx"&gt;C_peak&lt;/span&gt;
   &lt;span class="nx"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;700&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.505&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.87&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="nx"&gt;C_peak&lt;/span&gt;
   &lt;span class="nx"&gt;Step&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.429&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.72&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="nc"&gt;C_peak &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;←&lt;/span&gt; &lt;span class="nx"&gt;your&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="nx"&gt;sits&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Derive accent&lt;/strong&gt; (for CTAs): Rotate hue +180° (complementary), keep L/C structure. Isolated accent = Von Restorff effect = higher click-through.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Derive neutral&lt;/strong&gt;: Same hue, ultra-low chroma (0.004–0.012) for gray that feels warm/cool depending on brand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build semantic tokens&lt;/strong&gt;: error, warning, success, info get fixed hues (29°, 90°, 145°, 259°) but share the L/C boosts from the system—so they feel like family.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dark mode&lt;/strong&gt;: Not an inversion. Background L≈0.14 (not &lt;code&gt;#000&lt;/code&gt;), text L≈0.94 (not &lt;code&gt;#fff&lt;/code&gt;), accent chroma down 15–30%. Elevate surfaces via lightness, not shadow.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of that—with full WCAG 2.2 validation—from one hex input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical: CHROMA/1 Studio
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;CHROMA/1&lt;/strong&gt; to make this repeatable and visual. It's a single HTML file (works offline, no build step).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input&lt;/strong&gt;: one color picker.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Interactive scale preview (click any swatch to copy OKLCH value).&lt;/li&gt;
&lt;li&gt;Token diffs: light vs. dark side-by-side, with contrast badges.&lt;/li&gt;
&lt;li&gt;WCAG audit: 6 checks (text, muted text, CTA, each mode).&lt;/li&gt;
&lt;li&gt;6 real components (navbar, hero, pricing, form, stats, alerts) rendered live with tokens.&lt;/li&gt;
&lt;li&gt;Copy-ready code for each component.&lt;/li&gt;
&lt;li&gt;Export: &lt;code&gt;tokens.css&lt;/code&gt; (Tailwind v4), &lt;code&gt;vars-only.css&lt;/code&gt; (vanilla), &lt;code&gt;tokens.json&lt;/code&gt; (W3C DTCG).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real-World Use
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Download tokens.css from CHROMA/1 --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"tokens.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Tailwind v4 picks up @theme automatically --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-brand-600 text-white"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click me&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Or use CSS variables --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background: var(--cta); color: var(--on-cta)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click me&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Toggle light/dark mode on the page to stress-test both token sets in real time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters for Teams
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Consistency across brand&lt;/strong&gt;: One system per brand. Swap the base color, everything else scales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No guesswork on contrast&lt;/strong&gt;: OKLCH's perceptual linearity means a rule (L ≥ 0.4 gap = WCAG AA) actually holds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dark mode doesn't break&lt;/strong&gt;: Because you're not inverting—you're re-computing with the same formulas, just different L ranges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CRO built-in&lt;/strong&gt;: Token architecture enforces 60-30-10 (neutral/structure/accent), preventing rainbow syndrome. CTA = only accent element on the page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility-first&lt;/strong&gt;: WCAG checks run live; you see failures before shipping.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Catch: Browser Support
&lt;/h2&gt;

&lt;p&gt;OKLCH as a CSS keyword:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chrome 111+ ✅&lt;/li&gt;
&lt;li&gt;Safari 15.4+ ✅&lt;/li&gt;
&lt;li&gt;Firefox 113+ ✅&lt;/li&gt;
&lt;li&gt;Edge 111+ ✅&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For older browsers, pre-compute hex values and export &lt;code&gt;vars-only.css&lt;/code&gt;. The math doesn't change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Numbers: What Changed Since HSL
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Material Design 3&lt;/strong&gt; (Google) switched to &lt;strong&gt;HCT&lt;/strong&gt; (a similar approach). Build times for their docs: no dramatic speedup, but consistency improved measurably.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tailwind CSS v4&lt;/strong&gt; moved the entire default palette to OKLCH. From their blog:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We've upgraded the entire default color palette from RGB to OKLCH, taking advantage of the wider gamut to make colors more vivid where we were previously limited by sRGB."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Teams at Shopify, Figma, Apple (via Adaptive Colors), and Stripe all use perceptually uniform spaces. The pattern is clear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Download &lt;code&gt;chroma1-oklch-studio.html&lt;/code&gt; (standalone, no build needed).&lt;/li&gt;
&lt;li&gt;Enter your brand color.&lt;/li&gt;
&lt;li&gt;Export tokens.&lt;/li&gt;
&lt;li&gt;Drop &lt;code&gt;tokens.css&lt;/code&gt; into your next Tailwind project.&lt;/li&gt;
&lt;li&gt;Swap the base color for a different brand—entire system re-derives, no manual tweaks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For documentation and Astro 7 scaffold, see the full build at &lt;code&gt;/docs&lt;/code&gt; (included in the studio).&lt;/p&gt;

&lt;h2&gt;
  
  
  Going Deeper
&lt;/h2&gt;

&lt;p&gt;If you want to understand the math:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OKLab&lt;/strong&gt;: Björn Ottosson's breakdown of &lt;a href="https://bottosson.github.io/posts/oklab/" rel="noopener noreferrer"&gt;OKLab color space&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;W3C DTCG&lt;/strong&gt;: Design Tokens Community Group's spec (reached Candidate Recommendation October 2025).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WCAG 2.2 vs. APCA&lt;/strong&gt;: WCAG is the legal standard (4.5:1 text); APCA is more accurate for dark mode but still draft.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  One More Thing: AI Integration
&lt;/h2&gt;

&lt;p&gt;The studio includes AI asistants (via OpenRouter, model &lt;code&gt;nvidia/nemotron-3-super-120b-a12b:free&lt;/code&gt; free tier) that can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Suggest a brand color from a product description.&lt;/li&gt;
&lt;li&gt;Audit your palette for CRO + accessibility gaps.&lt;/li&gt;
&lt;li&gt;Name and narrate your palette for design docs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No Claude API key needed—you bring your own OpenRouter key (free tier available).&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;CHROMA/1&lt;/strong&gt; is open and MIT-licensed. The tool is a single HTML file with zero dependencies (not even Tailwind); the math is vanilla JavaScript. Astro 7 starter kit included.&lt;/p&gt;

&lt;p&gt;If you build a color system using OKLCH, or improve on this framework, I'd love to hear about it—drop a comment or reach out.&lt;/p&gt;

&lt;p&gt;One color. Entire system. Perceptually sound. No regrets.&lt;/p&gt;

</description>
      <category>css</category>
      <category>ui</category>
      <category>ux</category>
      <category>web</category>
    </item>
    <item>
      <title>What is AMP PWA Offline Generated Page?</title>
      <dc:creator>𝝝̷𝝟̷𝝙̷ 𝝗̷𝝘̷𝝞̷𝝝̷𝝥̷𝝛̷</dc:creator>
      <pubDate>Mon, 24 Feb 2020 16:15:55 +0000</pubDate>
      <link>https://dev.to/okabrionz/what-is-amp-pwa-offline-generated-page-34h0</link>
      <guid>https://dev.to/okabrionz/what-is-amp-pwa-offline-generated-page-34h0</guid>
      <description>&lt;p&gt;If you've learned about Progressive Web Apps,&lt;br&gt;
you might know that the core of it&lt;br&gt;
is a technology called service worker, a client-side proxy&lt;br&gt;
that sits between your server and web app&lt;br&gt;
to provide things like faster loads&lt;br&gt;
and offline functionality.&lt;/p&gt;

&lt;p&gt;But what if you built the most amazing Progressive Web App,&lt;br&gt;
and nobody discovers it?&lt;br&gt;
The problem with service workers is&lt;br&gt;
that they won't make your first &lt;a href="https://www.okabrionz.com/jasa-mempercepat-website/" rel="noopener noreferrer"&gt;page load fast&lt;/a&gt;.&lt;br&gt;
On a cold start, your service worker&lt;br&gt;
will only activate on the second page load.&lt;/p&gt;

&lt;p&gt;Even though the service worker API&lt;br&gt;
allows you to cache away all of your site's assets&lt;br&gt;
for an almost instant subsequent load,&lt;br&gt;
like when meeting someone new, it's&lt;br&gt;
the first impression that counts.&lt;br&gt;
If the first load takes more than three seconds,&lt;br&gt;
our latest DoubleClick study shows that more than 53%&lt;br&gt;
of all users will drop off.&lt;br&gt;
Don't feel too bad though.&lt;br&gt;
The overall landscape of today's web looks a lot grimmer.&lt;/p&gt;

&lt;p&gt;The average mobile page loads in about 19 seconds,&lt;br&gt;
with 77% of it taking longer than 10,&lt;br&gt;
doing 214 survey requests, 50% of which are ad-related.&lt;br&gt;
Yeah.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndq8gffjhjpzcv14zllh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndq8gffjhjpzcv14zllh.png" alt="AMP PWA The Perfect Combination" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take a moment to wipe away your tears.&lt;br&gt;
Turns out we found a solution for the first page load.&lt;br&gt;
And surprise, surprise, we call it AMP.&lt;br&gt;
AMP, short for Accelerated Mobile Pages,&lt;br&gt;
is an ecosystem consisting of web components library that&lt;br&gt;
allows you to declaratively write&lt;br&gt;
HTML we call AMP HTML, because it's&lt;br&gt;
both a superset and a subset.&lt;br&gt;
And AMP caches,&lt;br&gt;
basically CDN's, or more technically correct,&lt;br&gt;
reverse proxies that accelerate the delivery.&lt;/p&gt;

&lt;p&gt;Now, if you've already read about the individual advantages&lt;br&gt;
and disadvantages of Progressive Web Apps versus AMP,&lt;br&gt;
you have surely struggled with this question before.&lt;/p&gt;

&lt;p&gt;AMP or Progressive Web App?&lt;br&gt;
Instant delivery and optimized delivery, or the latest&lt;br&gt;
advanced platform features and super flexible application&lt;br&gt;
code?&lt;/p&gt;

&lt;p&gt;In the end, what matters is the user journey.&lt;br&gt;
The first hop to your site should feel almost instant.&lt;br&gt;
And the browsing experience should get more and more&lt;br&gt;
engaging afterwards.&lt;/p&gt;

&lt;p&gt;AMP and Progressive Web App are both critical components&lt;br&gt;
to make this happen AMP pages for the first navigation,&lt;br&gt;
and your Progressive Web App for the onward journey.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd33wubrfki0l68.cloudfront.net%2F8feecf6d280b12fd68e0aa8933e998423b08a5e4%2F84a6d%2Fimg%2Fposts%2Fpwa.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd33wubrfki0l68.cloudfront.net%2F8feecf6d280b12fd68e0aa8933e998423b08a5e4%2F84a6d%2Fimg%2Fposts%2Fpwa.svg" alt="AMP PWA The Perfect Combination" width="1139" height="654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two ways of combining the two-steps I personally&lt;br&gt;
call AMP up and AMP down.&lt;br&gt;
Now, AMP up is the background bootstrapping&lt;br&gt;
of your Progressive Web App shell.&lt;/p&gt;

&lt;p&gt;While the user is enjoying your AMP page.&lt;br&gt;
And then number two, AMP down, describes&lt;br&gt;
reusing AMP pages as a data source for your Progressive Web&lt;br&gt;
App.&lt;/p&gt;

&lt;p&gt;So the basics with AMP up are that the first click&lt;br&gt;
will be an AMP page, usually served from the AMP cache.&lt;br&gt;
But any links on that page will navigate&lt;br&gt;
to your Progressive Web App&lt;br&gt;
Now normally, that second click would still&lt;br&gt;
be considerably slower than the instant-feeling, preloaded,&lt;br&gt;
first click to your AMP page.&lt;/p&gt;

&lt;p&gt;But there's a powerful component baked into AMP--&lt;br&gt;
the tag.&lt;br&gt;
It allows you to install your service worker&lt;br&gt;
for your origin--&lt;br&gt;
yes, even when your AMP page is served from the AMP cache.&lt;/p&gt;

&lt;p&gt;That means while the user is reading the article,&lt;br&gt;
the service worker can warm up and precache&lt;br&gt;
the entire Progressive Web App app&lt;br&gt;
shell and some initial data.&lt;/p&gt;

&lt;p&gt;When the user now clicks on any link on the page,&lt;br&gt;
or call to action at the bottom, your Progressive Web App&lt;br&gt;
shows up instantly.&lt;/p&gt;

&lt;p&gt;Start fast, stay fast.&lt;br&gt;
This is what I call AMP up.&lt;br&gt;
But now you're in the Progressive Web App,&lt;br&gt;
and chances are most of you are using&lt;br&gt;
some Ajax-driven navigation that fetches content via JSON.&lt;/p&gt;

&lt;p&gt;Now, you can certainly do that, but now&lt;br&gt;
you have these crazy infrastructure&lt;br&gt;
needs for two completely different content backends.&lt;br&gt;
One generating AMP pages, and one offering a JSON-based API&lt;br&gt;
for your Progressive Web App.&lt;/p&gt;

&lt;p&gt;The AMP team has asked themselves&lt;br&gt;
the logical next question-- what if we could dramatically&lt;br&gt;
simplify backend complexity by ditching the additional JSON&lt;br&gt;
API and instead reusing AMP as a data format for our Progressive&lt;br&gt;
Web App?&lt;/p&gt;

&lt;p&gt;We started with a proof of concept many months ago&lt;br&gt;
and iterated on it for a while, rewriting many parts of AMP&lt;br&gt;
to make it a reality.&lt;/p&gt;

&lt;p&gt;So how do we do it?&lt;br&gt;
The process looks like this.&lt;br&gt;
The Progressive Web App hijacks navigation clicks,&lt;br&gt;
then does an Ajax request to fetch the requested AMP page.&lt;br&gt;
Third, puts the content into a new Shadow Root.&lt;br&gt;
And fourth, tells the main AMP library, hey,&lt;br&gt;
I have a new document for you.&lt;/p&gt;

&lt;p&gt;Check it out.&lt;br&gt;
Which, in other terms, means calls&lt;br&gt;
attachShadow Doc on the runtime.&lt;br&gt;
And then you have things like Shadows Slots&lt;br&gt;
and advanced CSS classes to insert advanced widgets&lt;br&gt;
and functionality into your AMP pages&lt;br&gt;
from the Progressive Web App.&lt;/p&gt;

&lt;p&gt;Now of course, you can do that last step manually&lt;br&gt;
by regexing the source of the AMP page,&lt;br&gt;
but the key is that the above is easy for everyone.&lt;/p&gt;

&lt;p&gt;OK, finally, time for an even more advanced pattern I&lt;br&gt;
call AMP Konami Code, because it's up, down, left,&lt;br&gt;
right-- all the things.&lt;/p&gt;

&lt;p&gt;So we have a pretty good experience now,&lt;br&gt;
but if you are in the Progressive Web App,&lt;br&gt;
copy a link, and share it on Twitter,&lt;br&gt;
that link will open the Progressive Web App directly.&lt;/p&gt;

&lt;p&gt;And for a new user who doesn't have a warmed up service worker&lt;br&gt;
cache, it won't feel instant.&lt;br&gt;
That, too, is a problem we can solve in the final step&lt;br&gt;
of our development journey.&lt;/p&gt;

&lt;p&gt;Instead of creating a separate URL space for the Progressive&lt;br&gt;
Web App-- for instance, pwa.yourdomain.com/article--&lt;br&gt;
like we did before, we reuse existing AMP URLs&lt;br&gt;
to load the Progressive Web App on the site's origin.&lt;/p&gt;

&lt;p&gt;All we need to do for this is to listen for navigation requests&lt;br&gt;
in the service worker.&lt;br&gt;
Then, instead of serving a cached AMP page,&lt;br&gt;
we serve the cached PWA shell, which&lt;br&gt;
then does an XHR to fetch the requested AMP doc.&lt;br&gt;
This means that in just one request,&lt;br&gt;
your Progressive Web App would show up along&lt;br&gt;
with the requested content.&lt;/p&gt;

&lt;p&gt;Best of all, we now progressively&lt;br&gt;
enhance our AMP pages with our Progressive Web App.&lt;br&gt;
And showing that no matter what, your users&lt;br&gt;
will get a super fast experience.&lt;br&gt;
For browsers that do not support service worker,&lt;br&gt;
they'll simply see AMP pages.&lt;/p&gt;

&lt;p&gt;So now, one additional thing we build&lt;br&gt;
is called fallback URL rewriting.&lt;br&gt;
And this means that even for browsers&lt;br&gt;
that do not support AMP caches, we're giving to you the ability&lt;br&gt;
to rewrite links to another URL space that&lt;br&gt;
is a fallback URL for your Progressive Web App.&lt;/p&gt;

&lt;p&gt;And there you got it.&lt;br&gt;
We've successfully combined AMP with a Progressive Web App.&lt;br&gt;
Now the user always gets it fast experience, no matter what.&lt;br&gt;
Your site is progressively enhanced.&lt;br&gt;
You have less backend complexity because you have just one data&lt;br&gt;
source, and profit from the built-in performance of AMP&lt;br&gt;
everywhere, even in your Progressive Web App.&lt;/p&gt;

&lt;p&gt;Before I leave you, keep in mind this is just one pattern&lt;br&gt;
to build sites, and it won't work for everyone.&lt;br&gt;
You probably shouldn't build the next Air Horn or Gmail with it,&lt;br&gt;
but focus on sites that have lots of leaf nodes--&lt;br&gt;
individual sites with static content.&lt;/p&gt;

&lt;p&gt;By all means, find out if the pattern&lt;br&gt;
is the right one for you, and feel&lt;br&gt;
free to get in touch to discuss.&lt;br&gt;
Check out our React-based demo and learn more about AMP&lt;br&gt;
and Progressive Web Apps individually on &lt;a href="https://amp.dev" rel="noopener noreferrer"&gt;amp.dev&lt;/a&gt;&lt;br&gt;
and &lt;a href="https://developers.google.com/web" rel="noopener noreferrer"&gt;developers.google.com/web&lt;/a&gt;.&lt;br&gt;
I can't wait to see what you will build.&lt;/p&gt;

</description>
      <category>amp</category>
      <category>pwa</category>
    </item>
    <item>
      <title>Manfaat Dan Pentingnya Website Perusahaan Company Profile</title>
      <dc:creator>𝝝̷𝝟̷𝝙̷ 𝝗̷𝝘̷𝝞̷𝝝̷𝝥̷𝝛̷</dc:creator>
      <pubDate>Sun, 07 Jul 2019 10:12:34 +0000</pubDate>
      <link>https://dev.to/okabrionz/manfaat-dan-pentingnya-website-perusahaan-company-profile-m5e</link>
      <guid>https://dev.to/okabrionz/manfaat-dan-pentingnya-website-perusahaan-company-profile-m5e</guid>
      <description>&lt;p&gt;Manfaat dan Pentingnya Website Company Profile Untuk Perusahaan Anda Perkembangan internet yang semakin pesat telah menyadarkan banyak orang akan pentingnya sebuah layanan yang mudah. Dengan hal itu, tak kita tidak akan kesulitan lagi dalam mencari sebuah informasi. Kini sebuah perusahaan sudah selayaknya memiliki sebuah website yang menjadi ruang untuk calon klien mengetahui tentang perusahaan itu. Dalam website tersebut bisa mencantumkan berbagai hal yang berkaitan dengan perusahaan Anda. Ada banyak manfaat yang bisa didapatkan sebuah perusaan jika mereka memiliki website yang biasa disebut company profile.&lt;/p&gt;

</description>
      <category>companyprofile</category>
    </item>
    <item>
      <title>Cara Halaman Pertama Pada Hasil Pencarian Google</title>
      <dc:creator>𝝝̷𝝟̷𝝙̷ 𝝗̷𝝘̷𝝞̷𝝝̷𝝥̷𝝛̷</dc:creator>
      <pubDate>Mon, 14 Jan 2019 00:41:51 +0000</pubDate>
      <link>https://dev.to/okabrionz/cara-halaman-pertama-pada-hasil-pencarian-google-2ef2</link>
      <guid>https://dev.to/okabrionz/cara-halaman-pertama-pada-hasil-pencarian-google-2ef2</guid>
      <description>&lt;p&gt;Coba search site:blogspot.com di Google. Ketika saya mencobanya beberapa waktu lalu, keluar hasil 321.000.000. Artinya ada 321.000.000 halaman web pada blogspot.com yang terindeks oleh Google. Tentu urusan ranking soal lain. Tapi terindeks saja sudah sudah satu langkah positif. Beberapa diantara halaman-halaman tersebut memiliki ranking yang bagus. Meskipun pada blogspot.com, bukan pada website kita sendiri, memiliki halaman page dengan ranking bagus membawa banyak manfaat. Lalu bagaimana caranya mendapatkan ranking yang tinggi dengan blogspot.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>google</category>
    </item>
  </channel>
</rss>
