Skip to content

AnEntrypoint/design

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

114 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

247420

The 247420 / AnEntrypoint design system, packaged as a single-file ESM SDK.

friendly rounded sans body, monospace only on real code, tonal surfaces over borders, indicator rails for color-coded separation, generous negative space, terminal-flavoured rhythm.

we fart in its general direction. ◰

install (the only step)

You have two choices. Both are one line.

npm (when you already have a bundler):

npm install anentrypoint-design

unpkg (when you don't, and you don't want one):

<link rel="stylesheet" href="https://unpkg.com/anentrypoint-design@latest/dist/247420.css">
<script type="importmap">
  { "imports": { "anentrypoint-design": "https://unpkg.com/anentrypoint-design@latest/dist/247420.js" } }
</script>

Add the scope class on a wrapping element and you are done:

<html class="ds-247420" data-theme="light">
  <body><div id="app"></div></body>
</html>

use it (3-line app)

import { mount, components as C } from 'anentrypoint-design';

mount(document.getElementById('app'), () => C.AppShell({
  topbar: C.Topbar({ brand: '247420', leaf: 'gm', items: [['works','#/works']] }),
  main:   C.HomeView({ /* hero, features, examples — see ./site/content/pages/home.yaml */ }),
  status: C.Status({ left: ['main'], right: ['live'] })
}));

mount automatically adds .ds-247420 to your root.

use it from a buildless flatspace project

A canonical example lives at c:\dev\flatspace-demo. It has no package.json. It has a flatspace.config.mjs, YAML pages under config/, and a src/theme.mjs that turns each page into HTML at build-time. CI runs npx --yes flatspace@latest build and deploys dist/.

To plug 247420 into that shape, do exactly three things:

1. Reference the SDK from <head> in src/theme.mjs

export default function render({ site, page }) {
  return `<!doctype html>
<html lang="en" class="ds-247420" data-theme="light">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>${page.title}${site.title}</title>
  <link rel="stylesheet" href="https://unpkg.com/anentrypoint-design@latest/dist/247420.css">
  <script type="importmap">
    { "imports": { "anentrypoint-design": "https://unpkg.com/anentrypoint-design@latest/dist/247420.js" } }
  </script>
</head>
<body>
  <div id="app"></div>
  <script type="module">
    import { mount, components as C } from 'anentrypoint-design';
    const data = ${JSON.stringify({ site, page })};
    mount(document.getElementById('app'), () => C.AppShell({
      topbar: C.Topbar({ brand: data.site.title, items: data.site.nav }),
      crumb:  C.Crumb({ leaf: data.page.title }),
      main:   data.page.template === 'home' ? C.HomeView(data.page) : C.Section(data.page),
      status: C.Status({ left: ['main'], right: ['live'] }),
    }));
  </script>
</body>
</html>`;
}

2. Author pages in YAML

# config/pages/home.yaml
id: home
title: home
template: home
hero:
  heading: tigers
  subheading: large striped cats
  body: a flatspace site, styled by 247420.
  badges: [ { label: encyclopedic }, { label: lowercase }, { label: 100% YAML } ]
features:
  heading: why tigers
  items:
    - { name: stripes, desc: structurally redundant, semiotically loud. }
    - { name: silence, desc: we like ambush as a design pattern. }
examples:
  heading: pages
  items:
    - { name: about,   href: ./about.html,   cta: open }
    - { name: species, href: ./species.html, cta: open }

3. CI workflow (.github/workflows/build.yml)

name: Deploy
on: { push: { branches: [main] }, workflow_dispatch: }
permissions: { contents: read, pages: write, id-token: write }
concurrency: { group: pages, cancel-in-progress: false }
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npx --yes flatspace@latest build
      - uses: actions/configure-pages@v5
      - uses: actions/upload-pages-artifact@v3
        with: { path: ./dist }
  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment: { name: github-pages, url: ${{ steps.deployment.outputs.page_url }} }
    steps:
      - id: deployment
        uses: actions/deploy-pages@v4

That is the whole integration. No package.json, no install, no bundler, no copy step. Push a YAML change to main, GH Actions builds, GH Pages serves.

components

Primitives: Brand, Chip, Btn, Glyph, Heading, Lede, Dot, Rail. Chrome: Topbar, Crumb, Side, Status, AppShell. Surfaces: Panel, Row, RowLink, Section, Install, Receipt, Changelog. Pages: Hero, WorksList, WritingList, Manifesto, HomeView, ProjectView. Chat: Chat, ChatMessage, ChatComposer, AICat, AICatPortrait. Helpers: renderInline, fmtBytes. Files: FileIcon, FileRow, FileGrid, FileToolbar, DropZone, UploadProgress, EmptyState, BreadcrumbPath, FileViewer (+ ConfirmDialog / PromptDialog / FilePreviewMedia / FilePreviewCode / FilePreviewText). Helpers: fileGlyph, fmtFileSize.

All factories are pure: props in, WebJSX tree out. Component source is split per group under src/components/<shell|content|chat>.js; src/components.js is a re-export barrel. The 200-line cap applies per module.

chat / markdown / code-highlight

Chat({ messages, onSend }) renders the bubble timeline; ChatComposer({ onSend }) is the input row. Block markdown inside messages is sanitized through renderMarkdown (marked@15 + DOMPurify@3, lazy-loaded from jsDelivr ESM on first call) and code blocks are highlighted by Prism (lazy-loaded core + per-language scripts via ensurePrism / highlightAllUnder). Direct innerHTML from chat content is forbidden — DOMPurify is the only XSS gate.

import { components as C } from 'anentrypoint-design';

C.Chat({
  messages: [
    { role: 'user', text: 'hello' },
    { role: 'assistant', text: '```js\nconsole.log(1)\n```' }
  ],
  onSend: text => /* push to your store, re-render */ null
});

<ds-chat> web component

src/index.js auto-registers <ds-chat> in any browser context. Set el.messages = [...] (or pass JSON via the messages attribute) and listen for the bubbling, composed send event:

<ds-chat id="c"></ds-chat>
<script type="module">
  import 'https://unpkg.com/anentrypoint-design@latest/dist/247420.js';
  const el = document.getElementById('c');
  el.messages = [{ role: 'assistant', text: 'gm.' }];
  el.addEventListener('send', e => console.log(e.detail.text));
</script>

ui-kit bootstrap

mountKit({ root, view, screen }) is the single entry point every kit uses — it installs styles, scopes the root, runs the WebJSX render loop, and registers the kit on the window.__debug registry. Do not roll your own motion / applyDiff / CDN loop in a kit's app.js.

import { mountKit } from 'anentrypoint-design';
mountKit({ root: document.getElementById('app'), view: () => myView(), screen: 'aicat' });

DeckStage

import { registerDeckStage } from 'anentrypoint-design';
await registerDeckStage();
// <deck-stage width="1920" height="1080">…<section>…</section></deck-stage>

tokens (override anywhere)

The system runs entirely on CSS custom properties under .ds-247420. To rebrand a single surface, declare overrides at any level:

<div class="ds-247420" style="
  --panel-accent: #6FA9FF;
  --panel-select: #DCE8FF;
  --green: #6FA9FF;
">
  …same components, sky-blue accent…
</div>

The full token list lives in colors_and_type.css. The voice rules and the storytelling pass live in SKILL.md.

why scope-prefixed

Every selector in the bundle is namespaced under .ds-247420 via PostCSS. The bundle ships Nunito + Archivo + JetBrains Mono + the design tokens without colliding with whatever the host app already runs. Add the class to a root element to opt in.

CSS only (no JS)

<link rel="stylesheet" href="https://unpkg.com/anentrypoint-design@latest/dist/247420.css">
<div class="ds-247420"></div>

You get the tokens, primitives, and utility classes. You write the markup.

publishing

Every push to main runs .github/workflows/publish.yml:

  1. Resolves max(local, remote) version, bumps patch.
  2. Builds with scripts/build.mjs (esbuild + postcss-prefix-selector).
  3. Publishes to npm with NPM_TOKEN.
  4. Commits the bump back to main and pushes a vX.Y.Z tag.

Skip publish for any commit by including [skip publish] in the message; release commits use that automatically to prevent loops.

links

About

247420-design-system

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors