habitat /ˈhæbɪtæt/ · noun

The natural home or environment of an organism — the specific conditions of light, temperature, and surroundings it has adapted to live in.

A screen that lives where you live

Every other interface assumes a fixed environment: a bright office, a calibrated monitor, a room that doesn't exist. habitat.css senses the light and color actually around you and lets the page adapt to that habitat instead — paper-toned in low light, camouflaged into the room's own palette, always contrast-safe. Try it above: Off, Eink, Camo — Camo will ask to use your camera, entirely on-device, and you can stop or forget it anytime.

npm install habitat.css
pnpm add habitat.css
yarn add habitat.css
bun add habitat.css
import { HabitatSensor } from "npm:habitat.css";
import "npm:habitat.css/habitat.css" with { type: "css" };
<link rel="stylesheet" href="https://unpkg.com/habitat.css/dist/habitat.css">
<script src="https://unpkg.com/habitat.css/dist/habitat.global.js"></script>
<script>const sensor = new Habitat.HabitatSensor();</script>
import { HabitatSensor } from "https://esm.sh/habitat.css";
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/habitat.css/dist/habitat.css">
<script src="https://cdn.jsdelivr.net/npm/habitat.css/dist/habitat.global.js"></script>

Two ways to inhabit the room

Both modes are driven by the same sensor, and both are built to be contrast-safe by construction, not by accident.

Eink mode

A sepia–saturate–brightness–contrast filter over a warm paper palette that tracks measured room brightness — pale paper in daylight, a darker warm tone as the room dims. No animation, no glow, like an e-reader with a gentle frontlight.

Camo mode

Every fifteen seconds, one tiny camera frame is blurred at capture, quantized into eight dominant colors, and recast as a semantic palette — background, text, accent — that the page wears. The room's most present color becomes the background; its most saturated voice becomes the accent.

Contrast-guaranteed

Every derived palette is walked until it clears your chosen WCAG target — AA (4.5:1), AAA (7:1), or High (10:1) — before it's ever applied. Camouflage never comes at the cost of reading your own page.

Privacy by construction

One 64×48 frame exists at a time, blurred as it's drawn, analyzed, then erased. Only a brightness number and a few hex colors ever persist — on-device, nowhere else.

Plays with shadcn/ui

habitat-shadcn.css maps habitat's semantic tokens onto shadcn/ui's full theming variable contract — --background, --primary, --card, --sidebar, --chart-1--radius, and the rest. Load it after habitat.css and every shadcn/ui component re-themes automatically under eink and camo modes, no component code changes — the same lightweight model shadcn's own Typeset ships with.

<link rel="stylesheet" href="habitat.css">
<link rel="stylesheet" href="habitat-shadcn.css">

This isn't a screenshot — it's live. Toggle Off / Eink / Camo in the header above and watch these ordinary shadcn-style components re-theme, styled with nothing but the standard --primary / --card / --border token set from habitat-shadcn.css.

Room sensor

Active

Reading ambient brightness and room color every 15 seconds.

Camera permission needed. Camo mode reads room color from your camera, on-device only.
Default Secondary Outline Error