Contributing¶
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.
Style Guide¶
We try to follow the Clojure Style Guide as much as possible. You are also advised to read 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
App structure¶
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
Re-frame recommendations¶
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. Most functions under handlers take the db as their first argument,
so they can be easily composed using the thread-first macro ->.
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.
Spec¶
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. Full db validation is enabled on dev mode.
Function schemas
are selectively applied to pure and critical namespaces, such as utils and
handlers. By default, function schemas are instrumented only during tests to
avoid performance overhead. However, runtime instrumentation can also be enabled
in the development environment (see dev.cljs).
Useful development shortcuts¶
Ctrl+Shift+I -> Toggle devtools
Ctrl+Shift+X -> Toggle 10x
Ctrl+R -> Reload app
AI and LLM policy¶
Contributors should ensure that their work does not violate any copyright laws. This also applies to AI generated code. Check the tool’s terms of use, to ensure you are not using copyrighted sources. You are advised to use models trained on content with compatible licensing.
Using AI to review changes to catch minor errors or fix typos before submitting a PR is allowed, and does not require notice.
Changes assisted by AI tools should be marked by adding an "Assisted-by: MODELS"
label at the end of the pull requests. MODELS should be replaced by a
comma-separated list of the utilized models. You should always review any AI
generated changes, and make sure that they don't introduce any bugs, or reduce
the quality of the code.
Contributions that are fully generated by AI tools will be rejected.
Translations under src/lang are mostly generated using LLMs, and are exempted
from the previous rule. Using AI to update or add new languages without further
modifications is accepted, but human intervention may required to make sure that
the changes don't break existing functionality, or do not reduce the quality of
existing translations. We are looking into ways to fully automate this process.
Pull requests fully generated by AI tools should be marked by adding a "Generated-by: MODELS" label at the end of the pull requests.