Skip to content
Snippets Groups Projects
3starblaze's avatar
3starblaze authored
Merge misc changes

See merge request !21
51c62517
History

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.

  1. Go to src/star_vibe_lab/localization.cljs
  2. Update localization-dictionary by adding the language key and corresponding translations. Use :en key as a reference for phrases that need to be translated.
  3. 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 at components/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.