Skip to content

usalu/semio

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

semio
A free online playground to toy with semio without login. The documentation page to learn semio. The elements Storybook for shared javascript UI elements. Discord
The repository. Cite Affero General Public License v3.0 or later
The presentation of our latest research paper on LLMs with semio. The latest research paper on LLMs with semio. The presentation of our previous research paper on formalizing architecture.
Browser Grasshopper Windows macOS
Typescript Python C#

🧩 Design-Information-Modeling for Kit-of-Parts 🏘


You want to 🧩 the next 🏘🏛🏢🏭🏫🏨⛪🕌 with 🤖? But 📐🔢🗣👥🖱️️⌨️️ takes all your ⌚? Then try to 🧠 the 🧬 and let semio 💉🖥✒🖨🪄🚀

👋 Hello contributor

Note

Are you a user or new to semio? Then you might want to first check out our docs 📖

Glad to see you!

Let me walk you through 🚶

📑 Overview

  1. 🛍 Products
  2. 🦑 Repo
  3. 🧑💻 Development
  4. 💯 Brand
  5. ⚖️ License
  6. 🔒Security
  7. ✨ Contributors
  8. 📊 Stats

🛍 Products

Do you wonder how semio is interoperable? The reason is a shared specification 🪢

✏ sketchpad

sketchpad is a simple-to-use, accessible and browser-based user interface for semio🖱️️

It is the digital pencil for sketching plans and digital scalpel for building models in semio ✍

sketchpad demo

👥 studio

A studio is a synchronous collaboriation environment for teams to work together in semio 🤝

semio studio Demo

☁ cloud

Use any file-hosting platform as an asynchronous Common-Data-Environment 📁

Cloud Demo

🤖 assistant

The assistant helps you on every step in the design process with semio ✍

semio assistant Demo

A batteries-included Grasshopper plugin for semio ⚡

semio Grasshopper Demo

🦏 semio.3dm

A Grasshopper-based integration of Rhino and semio 🔀

🐝 semio.wasp

A Grasshopper-based integration of Wasp and semio 🔀

Wasp Demo

🦌 semio.monoceros

A Grasshopper-based integration of Monoceros and semio 🔀

Monoceros Demo

🐞 semio.ladybug

A Grasshopper-based integration of Ladybug and semio 🔀

🦑 Repo

This git repo has everything that exists in the open semio ecosystem 🤯

⚖️ Principles

Let's start with the rules of thumbs that this codebase was built with 🫰

💾 If something can be written in a single file, then it probably should ✅

I know, the urge to tidy up or separate things is big 🗃️️

But try to withstand it 🫥

Out of my experience, it makes development slower, not faster 🐌

A single file is easier for humans and computers to understand 💡

You will be surprised

  • by the awesome fill-in-the-middle suggestions of your copilot 🤖
  • by the hassle-free context selection for your ai agent 🖱️️
  • by the smooth refactor experience by just going top-to-bottom ⬇
  • by the beautiful diff for your next code review 🔍
  • by the clean git-history when you try to find a certain change 🔁
🙃 Write and read code upside down ✅

Whenever something is referenced it should be above in the source code ⬆

This means that all the building blocks (functions, classes, components, …) are first defined and then used below ⬇

If you have a cyclic depedency (really?!) then put the object with lower complexity first 🥇

This means that when you start with unknown code, it is probably best to start on the bottom and go upwards 🖱️️

Why? LLMs, reflection, … , work best left-to-write 🤖

But Fill-in-the-Middle training is for free!?

Yeah, if you consider only FiM for code, then yes 🆗

But we want it all!

And is really so hard to start reading a from the bottom?

📑 If a class, function, component, … is only used once, then don't create it ❌

Probably, you learned to group code by classes, functions, components, … even if those definitions are only used once 🥇

It hides the actual complexity and makes it harder to navigate the code 🔍

📺 Inline everything that bearly fits onto the screen ✅

Smaller code, less tokens and easier diffs 🔍

Your ai bill will be lower and the completions will resolve faster 🚀

If you are not sure what the code does, you can ask ai 💬

🗣 Don't use comments or if you must, only tag code at the end of the line ❌

Smaller code, less tokens and easier diffs 🔍

Your ai bill will be lower and the completions will resolve faster 🚀

If you are not sure what the code does, you can ask ai 💬

📑 Use regions to structure your code ✅

Because you are not using classes, functions, components, … and you are inlining everything, your code will become long 📃

To organize your code, you can use nested regions 📂

In general, our files follow this structure:

  1. Header
  2. TODOs
  3. Imports
  4. Constants
  5. CODE
📁 If a folder doesn't make your life dramatically easier, don't create it ❌

We all know this ./src/** folder that has made it into a lot of starters 🚀

Other than feeling cool about using hacky abbreviations, does it really help you to understand the bundle faster and work more efficient on it?

If your bundle contains hundreds of config file and other bundle folders at the root, maybe 🤔

But most likely not ❌

📦 Parts that belong together should be close in the source code ✅

The default code organization is to group kind of structurally similar parts together 📂

All models next to each other, all controllers next to each other, all errors next to each other, …

While this pattern supports structural refactoring, it makes plain extensions harder because you have to search through all the files 🔍

Most changes are plain extensions and not structural refactors 🔄

Further it has the advantage that every LLM-agent only has to predict one big block of code instead of plenty of small ones 🤖

That's why frameworks like React exist or vendoring such as with shadcn is more flexible than dependcenies such as with bootstrap

Cutting components vertically (a bit of logic with a bit of UI) instead of horizontally (all logic, all ui) requires more effort but enhances reusability 🔮

📄 If multiple people work longterm on the same part, then one file for each part should be created ✅

Trust me, it will make collaboration much easier 🔀

🔮 If you don't need an port because something is not likely to be extended soon, don't create it ❌

The main question is the port productive or not?

The pay-off of abstraction happens in the future 🛣

Every extension profits from a clean port 🚀

Most things are not extended 🪨

If you change your architecture, just design proper ports for something concrete not something potential and reactor it ✍

🤏 Repeating code is ok if it the repeated code is close in the source code ✅

We are past the time where we copy code for no reason 📃

Actually repeated code can improve the attribute of your copilots suggestion 🤯

The main question is how can your application grow?

If a change requires exponentially more duplication then you'll probably have to fix it 🛠️

If not, then you are probably good 👌

🏷️ Never use `type` for naming enums, ports, or types. Always use `kind` instead ✅

To avoid confusion with the native type concept in Semio, always use kind for naming enums, ports, or types that represent categories or classifications 🏷️

Examples: ArtifactTypeArtifactKind, WindowTypeWindowKind, etc. 🔄

🤨 Wait, no high-level advice and only plain numbers, files, folders or close line of codes?

In our understanding, policy-of-thumbs are most useful when they are concrete 🔨

Besides that we are sure you know about KISS (Keep-It-Simple-Stupid), DRY (Dont-Repeat-Yourself) vs WET (Write-Every-Thing-Twice)/RUG (Repeat-Until-Good), YAGNI (You-Aren't-Gonna-Need-It), SoC (Separation-of-Concerns), Avoid Premature Optimization, Law of Demeter, LCHC (Low-Coupling-High-Cohesion), SOLID (SR (Single Responsibility), OC (Open/Closed), LS (Liskov's Substitution), IS (Port Segregation), DI (Dependency Inversion)), …

But as always, the devil is in the details 😈

Even if 95% of the codebase follows those principles, there are good reasons for the other 5% ⚖️

🚩 Don't worry, you'll figure out the possibilities and make the right choice for the specific problems ✅

🏗️ Technologies

The monorepo organizes its code into distinct technologies, each serving a specific domain in the ecosystem:

The core design-information-modeling technology, containing the main schema, engines, and domain implementations.

Infrastructure and tooling for the monorepo, including CLI, vscode integrations, MCP servers, and generic utilities.

A research project introducing an AI-first design assistant, bridging the semantic graph with interactive UI.

Shared React UI components and layouts used across the browser-based applications within the monorepo.

🔀 Git

🦑 GitKraken

Note

It is free for open-source bundles like this one ❤

We use GitKraken Desktop as our git client 🖱️️

It is the only nice chronological graphical overview for all branches at the same time that we found 🔍

The devcontainer installs Linux GitKraken Desktop and bootstraps zero-touch local workspace config for the semio monorepo and its git submodules, so the default Semio workspace is ready after attach without manual repository grouping 🔀

🔍 ripgrep

The devcontainer installs ripgrep (rg) for zero-touch codebase searching 🔎

It is the fastest way to find anything in this monorepo ⚡

💬 Discord

Most git events are synchronized with our repo channel 💬

It is perfect to find the latest activities and the history 🔍

📢 Release

Every release contains a set of matching requirements, bundles, examples and docs 📦

The release notes follow this format:

SYMBOL TITLE

COMPONENT
- SYMBOL SUMMARY [CONTRIBUTOR]
…

Title symbols:

  • 🏗️️ Foundational work
  • 🛠️ Heavy work
  • 🪛 Minor work
  • 🐛 Major Bug fix

Description symbols:

  • 🌱 Started [not yet ready]
  • ➕ Added [ready]
  • ⬆ Updated
  • 🔄 Renamed
  • 🔁 Refactored
  • 🐛 Bug fix

Before every release the repo is archived 📦

🏷️ Tag

We have two different types of tags:

🌿 Branch

The main branch is compressed (squashed history) and acts as the canonical integration branch 🗜

If a release receives updates after main already progressed, create a parallel release/rYY.MM-V branch for that release and keep it compressed as well 🧵

Every contributor has their own FIRSTNAME general-purpose development branch 🛠️

In GitKraken you will quickly find the latest development branch 👀

Other branches are created for bundles, specific features or bug fixes 🐛

Usually one person works on one feature at a time and hence the -NAME suffix 📛

🗃️️ Commit

Commit messages follow this format:

MAIN-TASK-SYMBOL SUMMARY WORK-SYMBOL

The first symbol encodes the main task of the commit and the last symbol encodes the amount of work (🪛 < 🔨 < 🛠️ < 🏗️️) 🧰

📦 Commit as much as you like ✅

Are you worried about committing all those binary application files (.zip, .gh, .blend, .glb, .3dm, …) or the intermediate versions between your ai edits?

Well, normally you should be 💾

But as we archive and squash all commits on every release nothing is lost or polluted 💯

⌛ Push around once an hour ✅

Pushing regularly keeps you extra safe from losing your work 🛟

There are a few services (like Discord) that are automatically updating to what happens in the repo 🔄

To keep our inbox notifications low, we try to push not more than once an hour ⬆

🧑‍💻 Development

Different ecosystems need different tools 🧰

🐳 Devcontainer (Recommended)

The recommended way to develop is using the devcontainer which provides a consistent cross-platform environment 🖥️

Prerequisites:

Getting Started:

  1. Clone the repository
  2. Open in VS Code
  3. Click "Reopen in Container" when prompted (or run "Dev Containers: Reopen in Container" from command palette)
  4. Wait for container build and setup to complete

The devcontainer includes:

  • Node.js 24 LTS, Go 1.26, Python 3.14, .NET SDK 8.0/9.0/10.0, Rust 1.92
  • All required VS Code extensions
  • Pre-configured development environment
  • Port forwarding for all dev servers (3000, 4000, 4321, 5678, 6006, 2507)

🪟 Windows Setup

Native Windows development is zero-touch through the checked-in bootstrap script:

powershell -NoProfile -ExecutionPolicy Bypass -File script.ps1 setup

The script installs the same baseline toolchain the devcontainer provides on a fresh machine:

  • Git, Git LFS, GitHub CLI, ripgrep, jq, SQLite
  • Microsoft OpenJDK 21 and native Neo4j Desktop integration
  • Node.js 24 LTS + npm 11.7, Go 1.26, Python 3.14, uv, rustup, .NET SDK 8/9/10
  • GitKraken Desktop + CLI, F3D, VS Code + code
  • Gemini CLI, TypeScript LSP, Pyright
  • repo hooks, MCP client config, Python/Rust/Playwright setup, npm/uv dependencies, and the local repo VSIX

After the bootstrap completes, open a new terminal and use the same repo commands as in the devcontainer. The script also keeps PLAYWRIGHT_BROWSERS_PATH on the repo-local shared cache so Playwright downloads stay warm across runs.

Native Neo4j Desktop must own the local DBMS. Create a Neo4j Desktop Local Instance named semio, set the initial password to password, and start it. The repo setup then enables APOC on that DBMS, restarts it when needed, and configures/imports through Bolt without editing Desktop internals:

  • URL: bolt://127.0.0.1:7687
  • User: neo4j
  • Password: password
  • Browser: http://127.0.0.1:7474
  • Database: neo4j

Native macOS and Linux use the same root router:

bash ./script.sh setup

IDE startup runs bash ./script.sh start (Windows: .\script.ps1 start or .\start.windows.ps1), which checks the native Neo4j Desktop semio DBMS at bolt://localhost:7687, verifies APOC, and attempts to create the product graph databases semio, elements, coda, and reuse, plus any names listed in NEO4J_EXTRA_GRAPH_DATABASES (comma-separated, e.g. metabolism,mydb), when the DBMS edition supports multi-database administration. Neo4j Community Edition allows only one standard user graph per DBMS (often still named neo4j until you rename it). Those CREATE DATABASE calls do nothing useful on Community, so you will not see extra graphs in Desktop or Browser unless the edition supports them. Use Neo4j Enterprise (or another deployment that supports multiple standard databases) if you need isolated Bolt databases for each graph.

Where “databases” show up: In Neo4j Browser, open your DBMS at http://127.0.0.1:7474, sign in, then use the database dropdown (next to the query editor). Only editions that support multi-database list more than one user graph besides system. To confirm what the server supports, run SHOW DATABASES while connected (Community typically shows system and one user database).

Optional MCP graphs: The neo4j-metabolism server runs … mcp neo4j metabolism (Bolt database metabolism, same argv pattern as the four product servers). For any other extra Bolt name without adding another MCP entry, set NEO4J_EXTRA_GRAPH_DATABASE and use neo4j-extra (it runs … mcp neo4j with no argv segments so NEO4J_DATABASE comes from that env). bun run generate uses NEO4J_EXTRA_GRAPH_DATABASES (plural, comma list) to include extra graphs in the APOC export loop alongside the four product graphs.

If you use Enterprise and an extra graph is missing: Connect to the system database and run CREATE DATABASE <name> IF NOT EXISTS; then START DATABASE <name> WAIT; (use backticks around <name> if it contains - or other special characters), and refresh the database list.

🪄 AI

Most of our codebase is heavily optimized for AI agents 🤖

We pick tools based on billing model (request-based vs token-based), required context size, and whether a workflow needs MCP (e.g. Playwright) 🧰

🛠️ Uses-Cases

Here some strategic advice for different uses-cases 🗺

⚖️ Decision Making

Model will always tell you that your ideas, guesses, analysis, … are great 💯

This makes it really hard to use them for decision making because they tend to just reinforce your own bias 📢

Try to formulate everything as neutral, general and unbiased as possible 🕊

🔁 Refactoring

Most refactors are too big to be done in one go and models are usually steered that if they think the problem is too big then they try to automate it with scripting 🤖

This is usually not possible and then they fail ❌

After all from a provider perspective those tasks are dangerous and hard to scale and we understand why they want the model to avoid doing it 🔥

The next problem is that when they take the wrong approach then, due to large context, they hardely remember how the original state was 🤔

For this reason, we usually create a new file which we name with the suffix*.old and this way in the prompt we can refer to the original state 📄

🐛 Bug Fixes

Try to describe only how to the bug appears and not what you think caused it 😶

Experience what can be causes for bugs is increadibly valuable skill as a developer but the problem is that models are really biased the way you ask questions 🏋

Especially when your guess is wrong then the model might have found the mistake but because of your bias it tries to take a different approach to fix it 🔀

Secondly, if the model can't find the bug then it will often try to remove functionality, add try catch blocks, add logging and other things that fastly turn your codebase into a mess 💣

Therefore, it is often a good idea that after you found the bug, reset your branch and create a new ticket where you define exactly how to fix the bug 🪛

⌨️️ Tools

🌐 Web-Chat

For research, prompt preparation or single file-related operations (sorting, formatting, explaining, …) we use the free , Gemini or Groq, … in the browser to not waste precious tokens 🆓

The free quota is very quickly reached but resets regularly and hence we just use it for questioning or prompt preparation 💬

Good for larger experiments due to more generous free quota 🥼

💻 Editor

📚 Resources:

Copilot is our default for most tickets because request-based billing makes fast interaction cheap 💳

🖱️️ Cursor

📚 Resources:

We have the Pro plan 💳

We use Cursor as our main editor for typing code mostly with Tab

For tasks that require updated large docs that are too large to paste into the prompt, we use the agent 📚

But in general, we don't use the chat because it is way too expensive 💰

🌊 Windsurf

Used for token-heavy test-driven-development workflows with MCP (especially Playwright) 🥼

⌨️️ CLI

⌨️️ Claude Code

We have the Pro plan 💳

Used for small bugs and focused fixes with strong repo context 🧠

🧾 Codex

Used for simple tasks (small edits, small refactors, small doc updates) 🧩

The canonical root agent instructions live in AGENTS.md. Root aliases such as CLAUDE.md and GEMINI.md are recreated from that file when you run bun ./script.ts setup git (also invoked from npm run setup), using symlinks when the shell supports them and a hard-link fallback on restricted Windows shells.

Run npm run setup once after cloning for the full workspace bootstrap, or run bun ./script.ts setup git if you only need git symlink checkout, root alias files, and repo-managed hooks on Windows, macOS, and Linux. On Windows, true symlink creation may require Developer Mode or an elevated shell.

☁ Cloud

🦑 Jules

[!NOTE] Free plan includes 15 tasks per day, 3 concurrent tasks and powered by Gemini 2.5 Pro 🚀

Used on the phone when no IDE is available 📱

🔍 Agents

↕ Reorderer

Used to ensure consistent order of source code, docs, …

🔁 Formatter

Used to ensure consistent formatting of source code, docs, …

🤖 Models

The default model for agent work is the one native to the platform we use for the agent 🧠

🔄 CI/CD

📺 Channels:

All automation, CI runs, and agent workflows are controlled through the canonical root commands setup, start, dev, generate, lint, format, test, build, publish, and purge (see root package.json). Only dev is intended to stay live for watch mode, while the remaining commands exit so CI and agents can finish reliably. The root package.json uses Nx to orchestrate the command pipeline, and delegates bundle builds, tests, and publishing to Nx targets (bun nx run …). Git pre-commit is managed by pre-commit: run bun ./script.ts setup git once for symlinks and hooks, then use pre-commit run --all-files to run hooks on all files.

💯 Brand

✍ Concept

✅ Do

  • Visual is better than text 👀
  • Compact ➡ More information ➡ Faster to understand 🚀

❌ Dont

  • Rounded corners ⬜
  • Shadows 🌤
  • Multiple unicode directly after each other 🥇🥈🥉

🌈 Colors

Palette

Name Hex RGB HSL HSV (or HSB) CMYK Color
Primary #FF344F 255, 52, 79 352, 100, 60.2 352, 79.6, 100 0, 80, 69, 0 Folly
Secondary #00A69D 0, 166, 157 176.7, 100, 32.5 176.7, 100, 65.1 100, 0, 5, 35 Persian green
Tertiary #FA9500 250, 149, 0 34.8, 100, 49 35.76, 1, 0.49 0, 40, 100, 2 Princeton orange
Dark (= 0) #001117
Grey 100 (= 0.1 = 1/10) #06171C
Dark 8-9 (= 0.1̅ = 1/9) #07181D
Dark-Dark-Dark-Grey (= 0.125 = 1/8) #091A1F
Dark 6-7 (= 0.142857 = 1/7) #0C1C21
Dark-Dark-Grey (= 0.166667 = 1/6) #112025
Grey 200 (= 0.2 = 1/5) #18272A
Dark 7-9 (= 0.2̅ = 2/9) #1D2B2F
Dark Grey (= 0.25 = 1/4) #243235
Dark 5-7 (= 0.285714 = 2/7) #2E3C3D
Grey 300 (= 0.3 = 3/10) #334041
Dark-Dark-Grey (= 0.3̅ = 1/3) #3E494A
Dark-Grey-Grey-Grey (= 0.375 = 3/8) #4C5756
Grey 400 (= 0.4 = 2/5) #555F5D
Dark 4-7 (= 0.428571 = 3/7) #606966
Dark 5-9 (= 0.4̅ = 4/9) #666E6B
Grey (= 0.5 = 1/2) #7B827D
Light 5-9 (= 0.5̅ = 5/9) #91968F
Light 4-7 (= 0.571429 = 4/7) #979B94
Grey 600 (= 0.6 = 3/5) #A2A59D
Light-Grey-Grey-Grey (= 0.625 = 5/8) #ABADA4
Light-Grey-Grey (= 0.6̅ = 2/3) #B9BBB0
Grey 700 (= 0.7 = 7/10) #C4C4B9
Light 5-7 (= 0.714286 = 5/7) #C9C8BD
Light Grey (= 0.75 = 3/4) #D3D2C5
Light 7-9 (= 0.7̅ = 7/9) #DAD9CB
Grey 800 (= 0.8 = 4/5) #DFDDD0
Light-Light-Grey (= 0.8̅ = 5/6) #E6E4D5
Light 6-7 (= 0.857143 = 6/7) #EBE8D9
Light-Light-Light-Grey (= 0.875 = 7/8) #EEEADB
Light 8-9 (= 0.8̅ = 8/9) #F0ECDD
Grey 900 (= 0.9 = 9/10) #F1EDDE
Light (= 1) #F7F3E3

🥇 Primary

Use the primary color for the most important elements of your design 🏆

We use it e.g. for:

  • Highlighting interactive elements 🖱️️
  • Background for important elements 🟥

🥈 Secondary

🥉 Tertiary

⚫ Dark

⚪ Light

🩶 Gray

Are you curious how a 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 and 11 colored gradient can come together for an invertible theme in a semantically meaningfull way? Well, here is how you achieve it with 33 colors 🤯

Grayscale

📄 Typography

Note

Try to place notes either in the beginning or the end of a section ↕ A starting note should contain something important but not crucial to give the brain the right context 🧠 The starting sentence of a note needs no symbol because every note type starts with a symbol 🥇

  • Be consistent with your language ♻
  • When things are analogical use the same sentence structure for it 🔄
  • One symbol after every sentance 💯
  • One symbol at a time 🥇
  • ➡️ No symbols ↔️ between blocks ⬅️
  • A symbol is preferably an emoji or otherwise unicode ⚖️
  • 📝 One symbol to summarize a title
  • 💡 One symbol to summarize a title description and one to think about in the end 🤔
  • . are forbidden ⛔
  • All components in semio (sketchpad,studio, …) start with a small letter 🔡
  • Did you know that is just one character?

Tip

In the end of a section you can give the curious reader a summarizing question to think about the consequences and a link to more resources 🤔

👀 Visual elements

  • Sharp corners 📐
  • Borders □
  • Basic geometric shapes ⚪

⚖️ License

The files in this repository are licensed under the GNU Affero General Public License unless otherwise described. Most libraries, modules, extensions, objects or code herein are explicitly licensed. This is indicated in the root of the containing folder under a different license file, or in the configuration files of a bundle or in the respective file's header.

As a reference, different type of components have usually different licenses:

If you have any questions, please don't hesitate to get in touch with us over email 📧

🔒 Security

If you have any security vulnerabilities or concerns, please contact us over email and don't open an issue, discussion or write into our public discord server 🥷

Ueli Saluz
Ueli Saluz
🟨 🟪 🐍 🦗
⚙️️ 🤖 🎛
📚 🛍 💯
🦏 🐝 🦌 🐞
🫀 👋 🚀
KinanSarak
KinanSarak

📚 👋 🦗
EinMysterium
Christian Hödtke

🦗
AdrianoCelentano
AdrianoCelentano

🟨
ellumpine
ellumpine

🦗 🐞
kaatzjo
kaatzjo

⚙️️
pizzadizza
pizzadizza

🤖

📊 Stats

We use Goatcounter for gaining insights about our docs 📈

views

Pixel