StarVibeLab
What's this?
StarVibeLab is a front-end web-application that lets people explore music theory unintrusively. The application provides a virtual "piano" and information sidebar that feeds the curiosity of the user. Additionally, it gives reactive feedback, making the exploration more joyful and rapid.
For instance, the user strikes a few keys, discovers a pleasing sound and realizes they have hit a chord, which is displayed by the application. The curiosity leads the way as the user peeks in the information sidebar to get to know this chord a little better. The curiosity then morphs into intrigue, as the user wants to see more of it and is researching the external resources that are provided by the application.
Usage
Try it out in our website or build it yourself.
Development
Launching the app locally
To develop, you need Java and NodeJS. The initial setup is done by running these commands.
npm install
npm run tailwind
npm run watch
npm run watch
launches a local webserver at localhost:8080
and hosts the application. The application has fast hot-reloading -- your changes are visible immediately, without the need of reloading the site.
Note: when using new tailwindcss style classes, the changes may not get updated. To fix this, run npm run tailwindcss
again.
Deployment
Once you have tried using the app locally, run npx shadow-cljs release main
. public/
folder will contain everything you need to host the application.
Development tools
To debug re-frame, there is re-frame-10x
which is enabled in development. To disable it, comment out day8.re-frame-10x.preload
in [:builds :main :devtools :preloads]
in shadow-cljs.edn
.
To check malli schemas in re-frame database, there's spec-interceptor (star-vibe-lab.re-frame
). Spec checking is costly in time, which is why it's disabled in deployment. To disable it temporarily, you can do (set! goog.DEBUG false)
in the main code.
Tip: .gitlab-ci.yml
contains instructions to test and deploy in CI. These commands can be useful to understand how to develop locally.
Tip: You can host your application on LAN by changing [:dev-http 8080 :host]
in shadow-cljs.edn
to your local IP address. On linux this can be found by command hostname -I
. This gives several addresses; just pick the first one and you will be good to go. This is really handy because you can test and debug the application on an actual touch device. Sure, browsers have tools for responsive design tools which is sufficient for most cases but testing on actual device is indispensable. For example you can't do multi-touch on a normal computer. Not to mention that using the the app on a phone is a vastly different experience than using it on a computer, even if the the screen sizes are set identical. Overall, it's a useful tool to have to ensure the quality of mobile user experience.
Localization
StarVibeLab makes it easy to add support for new languages.
- Go to
src/star_vibe_lab/localization.cljs
- Update
localization-dictionary
by adding the language key and corresponding translations. Use:en
key as a reference for phrases that need to be translated. - You are done!
Technical
Overview of the project
The application is written in ClojureScript and most notable modules include reagent, re-frame and tailwindcss.
src/star_vibe_lab
is the most important folder, which stores the code of the application. The entry point is core.cljs
function init
. When code is hot-reloaded, reload!
is fired.
Brief description of top-level files and directories:
-
components
- Reagent components, the visual side of the application -
audio.cljs
- Handle synth settings and sound -
core.cljs
- The entry point of the application -
info.cljs
- Analyze and provide chord data. -
localization.cljs
- Translation -
macros.clj
- Macros -
re_frame.cljs
- Set up re-frame -
re_frame_util.cljs
- Miscellaneous utilities that depend on re-frame -
util.cljs
- Miscellaneous utilities -
virtual-keyboard.cljs
- Virtual keyboard logic. Note: the visual representation is located atcomponents/piano.cljs
Development guide
In case you wish to develop this application further, you need to know how it flows. The application has appearance and it has data.
The entry point of the appearance is star-vibe-lab.components.core/root-component
. To have your component show up on the screen, it (or its ancestors) have to be included there. The main driving force is reagent
. Additionally, tailwindcss
and inline styles are used to apply CSS, phosphor-react
is used for icons and antd
is used for components.
Data is managed by re-frame
in re-frame.cljs
. It is integral to know re-frame
to be able to understand the data flow. Once you know re-frame
, there are additional constructs in StarVibeLab that you must be aware of.
star-vibe-lab.re-frame-util/re-frame-provider-schema
describes maps that are consumed by star-vibe-lab.re-frame
. This way you can make isolated maps of state that are namespaced and easy to use. The slice is stored in the root with key ::map
(aka :YOUR-NAMESPACE/map
). If you want to use re-frame store, you need to make a re-frame-provider-schema
-compliant map (usually called re-frame-provider
) and include it in star-vibe-lab.re-frame/providers
.
The concept of re-frame-provider was made for these reasons:
- To avoid name collisions and weird subscription names. Instead of
:info-chord
,::star-vibe-lab.info/chord
is used. It may not seem a big difference now but having namespaces distinguished is handy for recognizing where the subscription comes from and also is easier to process via code. - To make subscription registration as easy as possible. By using provider map, we can automatize the process of inserting state sub-map, check it via schema and reload
::init!
function on initialization and hot-reloading.
Before re-frame-provider was a thing, all re-frame subscriptions were clumped together in one namespace and they did not have namespaced keyword. This was hard to manage because subscriptions were not sorted and everything was interwoven. Hopefully that gives more appreciation for why re-frame-providers exist.
Now that you know the application flow, you can write your additions with ease. In short, manage your data with your own re-frame-provider
and make components in components
folder.