grain
Built into everything. Dependent on nothing.
Deploy like infrastructure. Adopt like a framework. Copy a folder, serve a page — no internet required, no ongoing dependency on anything outside the folder you already copied.
full version (modern devices)
<link rel="stylesheet" href="grain.css">
<script src="grain.js"></script>
lite version (old devices / low-power)
<link rel="stylesheet" href="grain-lite.css">
<script src="grain-lite.js"></script>
colors
typography
Courier Prime — mono
self-hosted · OFL license
Lora — serif body
self-hosted · OFL license
override colors
:root {
--gr-accent: #your-color;
--gr-bg: #your-bg;
}
Heading One
Heading Two
Heading Three
Heading Four
Body copy set in Lora serif. The tension between monospace structure and humanist type is intentional — it reads like a document that knows what it is.
Paragraphs breathe at 1.85 line-height. Italic text holds its own. Bold is spare.
small label · uppercase mono
accent label
Muted text for secondary content.
Default — solid border, copper corners.
Dashed subtle frame.
Accent border frame.
Terminal chrome. Pairs naturally with .gr-frame.
badges
chips (hover)
status
-
01.
School Intranet PortalStudent resources, timetables, announcements
-
02.
NGO Field DashboardData collection and reporting for field workers
-
03.
Community Health ToolPatient records on a local mesh network
Grain is built for places where bootstrap fails — not because it can't load, but because it assumes a connection that doesn't exist.
<link rel="stylesheet" href="grain.css">
Copy the folder to your server. Open index.html. That's it. Works on Apache, Nginx, Python's http.server, or directly from a USB drive.
| name | role | status |
|---|---|---|
| Aisha Mohammed | teacher | active |
| James Okonkwo | admin | active |
| Priya Sharma | student | pending |
default
ink
blue
slow
fast
default — auto-fit min 22ch
narrow — min 14ch
wide — min 32ch, gap-lg
wide column a
Content with breathing room. Wide columns suit long-form reading contexts.
wide column b
Resize the window to watch both columns collapse into one below ~32ch.
gr-grid--3 with spanning
alignment — gr-grid--middle
quick reference
.gr-grid auto-fit min 22ch
.gr-grid .gr-grid--narrow auto-fit min 14ch
.gr-grid .gr-grid--wide auto-fit min 32ch
.gr-grid .gr-grid--2/3/4 fixed columns
.gr-span-2/3/full item spanning
.gr-grid--gap-none/sm/md/lg/xl
___ _ ___ ___ _____ / __|| | | _ \ __|_ _| | (__ | |_| / _| | | \___||___|_|_\___| |_|
Use .gr-ascii with .gr-ascii--accent or .gr-ascii--mid.
Pair with typewriter via data-grain-type (full version only).
Add data-grain-type="your text" to any element. Full version only.
default — auto-fit, min 22ch
gr-grid--narrow — min 16ch (more columns)
gr-grid--wide — min 32ch (fewer, wider columns)
gr-grid--2 · gr-grid--3 — explicit counts
gr-span-full — spanning
real-world — cards in a grid