Skip to content

usalu/semio

Repository files navigation

👀 Are you curious how we develop semio? Then you might want to check out our Discord server 👥

semio
Cite AGPLv3 License Discord
Browser Grasshopper Windows macOS
Typescript Python C#
🧩 Design-Information-Modeling for Kit-of-Parts Architecture 🏘️


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

👋 Hello contributor

Note

Are you a user of semio? Then you probably want to visit our docs 👀

Glad to see you!

Let me walk you through 🚶

📑 Overview

  1. 🛍️ Products
  2. 📄 Specs
  3. 🦑 Repo
  4. ♻️ Ecosystems
  5. 📦 Components
  6. 🏘️ Examples
  7. 💯 Brand
  8. ✨ Contributors

🛍️ Products

Do you wonder how semio is interopable? The reason are shared specification, ecosystems and components 🪢

✏️ sketchpad

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

sketchpad demo

👀 studio

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

☁️ 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 🔀

📄 Specs

📦 Kit

A kit is a collection of types and designs 📦

A kit is either static (a special .zip file) or dynamic (bound to a runtime) 📦

A static kit contains a reserved .semio folder that contains a kit.db sqlite file 💾

The SQL-schema of kit.db is found in ./sqlite/schema.sql 📄

For Inter-Process-Communication (IPC) the JSON-schema in ./jsonschema/kit.json is used 📄

🏙️ Design

A design is an undirected graph of pieces (nodes) and connections (edges) 📐

A flat design has no connections and all pieces are fixed

The pieces are placed hierarchically (breadth-first) for every cluster 🌿

Additional connections which where not used in the placement can be used to validate the computed planes 🛂

🔗 Connection

A connection is a 3D-Link between two pieces with the translation parameters gap (offset in y-direction), shift (offset in x-direction) and raise (offset in z-direction), and the rotation parameters rotation (rotation around y-axis), turn (rotation around z-axis) and tilt (rotation around x-axis) 🪢

The translation is applied first, then the rotation 🥈

The two pieces are called connected and connecting but there is no difference between them 🔄

The direction of a connection goes from the lower hierarchy to the higher hierarchy of the pieces ➡️

⭕ Piece

A piece is an instance of either a type or a design 📐

A piece is either fixed (with a plane) or linked (with a connection) 📐

A group of connected pieces is called a cluster 🌿

The hierachy of a piece is the length of the shortest path to the next fixed piece 👣

💾 Representation

A representation is a tagged url to a resource with an optional description 📄

No tags means the default representation 🔑

The similarity of representations is determined by the jaccard index of their tags 🔄

📏 Quality

A quality is metadata with a name, an optional value, an optional unit and an optional definition (url or text) 🔤

The name is kebab-cased and with .-separated string similar to toml keys 🔑

No value is equivalent to the boolean true where the name is the category of the quality 🔑

The unit is a unit identifier 🔢

  • mm for millimeter, cm for centimeter, dm for decimeter, m for meter, km for kilometer
  • for square meter, for cubic meter, m⁴ for quartic meter
  • ° for degree, rad for radian
  • N for newton, kN for kilonewton, MN for meganewton
  • °C for degree Celsius, °F for degree Fahrenheit
  • W for watt, kW for kilowatt, MW for megawatt, GW for gigawatt
  • Wh for watt-hour, kWh for kilowatt-hour, MWh for megawatt-hour, GWh for gigawatt-hour
  • J for joule, kJ for kilojoule, kcal for kilocalorie
  • kWh/m²a for kilowatt-hour per square meter per year
  • m/s for meter per second, m²/s for square meter per second, m³/s for cubic meter per second
  • Pa for pascal, kPa for kilopascal, MPa for megapascal

🏷️ Tag

A tag is a kebab-cased name 🔤

◳ Plane

A plane is a location (origin) and orientation (x-axis, y-axis and derived z-axis) in 3D space ✈️

The coordinate system is left-handed where the thumb points up into the direction of the z-axis, the index-finger forwards into the direction of the y-axis and the middle-finger points to the right into the direction of the x-axis 👈

🔗 Url

A url is either relative (to the root of the .zip file) or remote (http, https, ftp, …) string🌐

A relative url is a /-normalized path to a file in the .zip file and is not prefixed with with ., ./, /, …

🦑 Repo

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

⚖️ Principles

Let's start with the rule 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 🔁
📁 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 project faster and work more efficient on it?

If your project contains hundreds of config file and other project 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 interface because something is not likely to be extended soon, don't create it ❌

The main question is the interface productive or not?

The pay-off of abstraction happens in the future 🛣️

Every extension profits from a clean interface 🚀

Most things are not extended 🪨

If you change your architecture, just design proper interfaces 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 quality 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 👌

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

In our understanding, rule-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), YAGNI (You-Aren't-Gonna-Need-It), SoC (Separation-of-Concerns), Avoid Premature Optimization, Law of Demeter, LCHC (Low-Coupling-High-Cohesion), SOLID (Single Responsibility (SR), Open/Closed (OC), Liskov's Substitution (LS), Interface Segregation (IS), Dependency Inversion (DI)), …

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 ✅

🧑‍💻 Development

Different components need different tools 🧰

For a complete setup you need:

If you do not have Python installed, I recommend to install it over the Microsoft Store 🏪

Afterwards you can install poetry with this Powershell command:

(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | python -

In the console you will see a warning that the poetry.exe is not installed in the requested location 📁 Actual Location Then copy the actual path ...\AppData\Local\Packages\PythonSoftwareFoundation...\Roaming\pypoetry\venv\Scripts and add it to your environmental path variable ➕

Then you can build.ps1 in the Powershell and add your full path LOCAL_PATH\dotnet\Semio.Grasshopper\Debug\net48 to your GrasshopperDeveloperSettings ⚙️

If you have never executed local Powershell before then you have to first Set-ExecutionPolicy ⚠️ If you don't care just run:

Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine

🪄 AI

Most of our codebase is heavily optimized for AI agents 🤖

🖱️ Cursor

We use Cursor as general editor mostly with Tab ➡️

For brain-heavy tasks we prepare good tickets and use Gemini 2.5 Pro

We parllely work on two tasks that are unrelated to each other in order switch between them during waiting times ⌛

✈️ Copilot

For monkey-tasks we use the free Copilot with GPT-4.1 🚀

🔀 Git

📢 Release

Every release contains a set of matching specs, components, 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 and then all branches are merged and squashed into a single commit 📦

🏷️ Tag

We have two different types of tags:

🌿 Branch

The main branch is the default archive branch 🔒

The dev branch is the default general-purpose development branch 🛠️

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

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

🗃️ Commit

📦 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 ⬆️

♻️ Ecosystems

You might have noticed that the individual components can be closely related such as sketchpad, Grasshopper and engine but they are in totally different folders 📂

The reason for this is that the repo is not disected according content but according technology stack ✂️

This is less intuitive but more tool-friendly and everything that is easier for our tools is less pain to develop 🧑‍💻

🔗 Useful links:

🟪 .NET

🔗 Useful links:

A .NET core for semio 🥜

Warning

Rhino still runs on .NET 7.0 7️⃣ Be careful to not update packages to a higher version, that might break the compatibility 🚨

🐍 Python

🔗 Useful links:

Currently only engine but in the future it might grow and then the .venv will be centralized, …

📦 Components

A component is a piece of software which is packaged independently 🏝️

🔗 Useful links:

The core which is shared in the semio JavaScript ecosystem 🥜

🔗 Useful links:
An electron-based desktop app primarly working for with local kits 💾
🔗 Useful links:

Mostly a Large Language Model-based assistant 🧰

🔗 Useful links:

A playground for sketchpad 🎮

🔗 Useful links:

The core which is shared in the semio .NET ecosystem 🥜

🔗 Useful links:

A full-blown Grasshopper Plugin that has (almost) everything 💯

🪢 Scriptstyle

Analogous to our principles for text-based code, we follow a similar logic for script-based code 🔄

💻 Optimize your definitions for rectangular space ✅

Every inch of wasted screen space, means a loss of productivity because you need longer for navigation 🖱️

It is harder to understand something far away compared to something close 🔍

I know, the triangular layout where you place the next component always vertically in the middle of the inputs looks cleaner due to the better wire display 🧹

But you waste a lot of space for nothing 💸

📛 Don't name things unless it is the output of a group or cluster ❌

We know that there are only two hard things in Computer Science: Cache invalidation and naming things 🥈

Visual programming languages solve the naming problem by using wires to overcome the neeed of names ⬆️

That is a big gain in productivity because you can focus on the logic instead of the names 🚀

Wait, but how I am supposed to understand what is happening in the code if I don't use names?

Most things in Grasshopper are visual and the green Only draw preview of selected components button on the top left is your best friend 🔍

📦 If you don't absolutely need a cluster, don't create it ❌

Clusters are a good way to make code reusable and hide complexity 🥸

But hiding complexity means a slower development speed because you have to navigate through more files 🐌

Did you know that Grasshopper behaves different inside a cluster when outside?

E.g. when you feed an empty branch into a cluster the input inside it its magically pruned and when you leave it is there again which makes debugging much harder 🐛

I don't have to tell you about open definition tabs, updating nested clusters, recompute, performance, … right?

🤏 Minimize the amount of external parameters and take as much decisions as possible ✅

Designing means making decisions 🪨

Fewer parameters makes your design more parameteric and not less 🤯

The price for a synergizing system is the loss of flexibility 🤷‍♂️

If you don't know the parameters in the first place, you shouldn't create the Grasshopper script in the first place 🥈

Grasshopper is an amazing tool if you know the system that you want to create but is terrible for prototyping because of its lack of abstraction ⬇️

🔗 Useful links:

A hidden fat-client which exposes shared functionality to other desktop uis 🤝

It takes care of:

  • CRUDs (Create-Read-Update-Delete) for local kits 💾
  • Client-Server communication ↔️

It offers two APIs to other clients:

  • A simple REST OpenAPI 🥇
  • A complex GraphQL Relay API 🥈

If you go to http://127.0.0.1:2412/api/docs/ you find the Swagger UI:

GraphQL Query

Still a prototype ✏️

If you go to http://127.0.0.1:2412/graphql/ you find the GraphiQL UI:

GraphQL Query

🏷️ Badges

Each badge is created with shields.io with style flat-square and semio colors.

  1. Copy the *.shields file of an existing badge 📄
  2. Open and download the *.svg file ⬇️

📄 Fonts

  1. Search font on fontsource.org 🔍
  2. Hit Download and extract zip file 📂
  3. Use kebaberized font name as folder name and remove everything else (such as version numbers) ➖
  4. Merge all types in one folder (ttf, webfonts, …) - they won't collide due to different extensions 🗃️
  5. Remove all parts that repeat everywher (such as common name prefix, single weighted fonts, …) 💯

👁️ Icons

  1. Open favicongenerator.net 🔍
  2. Select Circle as Background Shape ⏺️
  3. Select Anta as Font Family 📃
  4. Enter the Code that you find in the dictionary
  5. Adjust the Font Size to the largest so that the space to the side is the same as the thickness of the stroke 🖊️
  6. Toggle Enable SVG on 🔳
  7. Hit Generate Favicon and download the zip file to assets/icons/temp/NAME.zip where NAME is the lowercase name and verb of the icon 📂
  8. Repeat the process for all icons 🔁
  9. Run build icons in the debugger of vscode 🔨

🏘️ Examples

💯 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

🥇 Primary

🥈 Secondary

🥉 Tertiary

⚫ Dark

⚪ Light

🩶 Grey

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 🥇
  • 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 ⚪
Ueli Saluz
Ueli Saluz
🟨 🟪 🐍 🦗
✏️ ⚙️ 🤖 🎛️
📚 🛍️ 💯
🦏 🐝 🦌 🐞
🫀 👋 🚀
KinanSarak
KinanSarak

📚 👋 🦗
EinMysterium
Christian Hödtke

🦗
drymuzzle
drymuzzle

🦗 🐞
kaatzjo
kaatzjo

⚙️
pizzadizza
pizzadizza

🤖

📊 Stats

views