Thank you for your interest in actively participating in the project's development! Please read the Contributor Covenant Code of Conduct and the Contributor License Agreement first.
The project is written in ClojureScript - a compiler for Clojure that targets JavaScript, and is based on re-frame - a framework for building Modern Web Apps in ClojureScript. You should probably take a look at their exceptional documentation first.
We try to follow the Clojure Style Guide as much as possible.
An additional resource about how to name Clojure functions by Stuart Sierra.
In addition to the idiomatic names, we use the following conventions
e -> event el, els -> element, elements attr, attrs -> attribute, attributes prop, props -> property, properties w, h -> width, height t -> time h, m, s, ms -> hours, minutes, seconds, milliseconds
We also use the following namespace aliases
v -> views e -> events h -> handlers s -> subs fx -> effects
If the namespace belongs to a dedicated module, we use module.v
.
Main structure
src\ ├── renderer\ <--- Renderer Process ├── electron\ <--- Main Process & Preload script ├── lang\ <--- Translation files └── worker\ <--- Web Workers
We are trying to split our code under renderer into relatively independent modules, following re-frame's app structure suggestions with some minor additions.
module\ ├── core.cljs <--- entry point ├── db.cljs <--- schema, validation ├── views.cljs <--- reagent views ├── events.cljs <--- event handlers ├── subs.cljs <--- subscription handlers ├── handlers.cljs <--- helper functions for db transformations ├── effects.cljs <--- effect handlers ├── hierarchy.cljs <--- multimethods and hierarchies ├── styles.css <--- styles └── README.md <--- documentation
Avoid chaining events to create new ones. Always prefer composing pure functions that directly transform the db. That is the whole purpose of handlers
namespace.
Use interceptors sparingly. Although they look (and probably are) ingenious, it is hard to write and reason with them. Doing things explicitly, is usually easier to grasp and maintain.
Always use auto-qualified keywords (e.g. ::copy
) for subscriptions, events and effects. You can use as-alias
to require those namespaces without evaluating the registrations multiple times.
We use malli to describe the shape of our app db and selectively validate incoming data (e.g. file loading). We also use this spec to generate default values. You can optionally enable full db validation on dev mode (see renderer.dev
namespace).
Flat arrow function schemas are used selectively on critical namespaces, like renderer.utils.bounds
. Runtime instrumentation can also be enabled on dev environment.
Ctrl+Shift+I Toggle devtools
Ctrl+Shift+X Toggle 10x
Ctrl+R Reload app