- Used technologies and libraries
- Tools
- Project structure
- Components documentation
- Local environment setup
- Lints and fixes files
- S3 Policy
- API
- Contribution Guidelines
- License
- Vue.js - main framework
- Nuxt.js - SSR framework for Vue
- WaveSurfer.js - library for drawing spectrum and dealing with audio
- Tailwind CSS - CSS framework
├── assets
├───── css - global styles and Tailwind configuration
├───── icons - SVG icons used in app
├── atoms
├── molecules
├── layouts - Nuxt 2 layouts used in application
├── organisms
├── pages
├── static - static resources
├ nuxt.config.js - SSR configuration file
├ tailwind.config.js - Tailwind CSS extension and configuration file
All the components are reusable and based on Atomic Design.
All available icons should be added to /icons/index.ts file with specific name. If we try to render an icon that name is not included in this file, the icon will not be rendered.
<atom-icon name="stems" />- Inputs:
-
name- the name of icon that should be rendered
<molecule-icon-button :disabled="isPreviousDisabled" icon="previous" @click="onPreviousButtonClick" />- Inputs:
-
icon- the name of icon that should be rendered
-
disabled- indicates if button should be disabled or not
-
small- indicates if button should be displayed in small mode
- Outputs:
-
click- emitted after clicking on button
<molecule-menu
:is-playing="isPlaying"
:is-previous-disabled="isPreviousDisabled"
:is-next-disabled="isNextDisabled"
:is-shuffle="isShuffleMode"
:hook="hook"
@previous="previousTrack()"
@next="nextTrack()"
@toggle-shuffle="onToggleShuffle"
@add-hook="addHook"
/>- Inputs:
-
is-playing- indicates if player is in playing mode
-
is-previous-disabled- indicates if previous button should be disabled or not
-
is-next-disabled- indicates if next button should be disabled or not
-
is-shuffle- indicates if shuffle button should be active or not
-
hook- indicates if hook button should be displayed in small mode
- Outputs:
-
previous- emitted after clicking on previous button
-
next- emitted after clicking on next button
-
toggle-shuffle- emitted after clicking on button for shuffling playlist
-
add-hook- emitted after clicking on button for adding hook
<molecule-radio-button :checked="isRadioButtonChecked" @click="selectStem" />- Inputs:
-
checked- indicates if button should be marked as checked or not
- Outputs:
-
click- emitted after clicking on radio button
MoleculeStemsButton.vue - component used for displaying stems button responsible for showing stems box
<molecule-stems-button disabled="false" stems-title="Stems" @click="toggleStemsVisibility" />- Inputs:
-
stems-title- placeholder for button title
-
disabled- indicates if button should be disabled or not
- Outputs:
-
click- emitted after clicking on radio button
<molecule-track-info :band-name="bandName" :track-name="trackName" />- Inputs:
-
band-name- placeholder for the name of the track band
-
track-name- placeholder for the name of the track
MoleculeTrackProgress.vue - component used for displaying the progress and duration of the current track
<molecule-track-progress
v-if="waveSurfer"
:progress="() => waveSurfer.getCurrentTime()"
:duration="() => waveSurfer.getDuration()"
:is-loading="isLoading"
/>- Inputs:
-
progress- input for method for getting the current track time
-
duration- input for method for getting the current track duration
-
is-playing- indicates if the current track is in play mode
<molecule-volume-control v-if="waveSurfer" :value="currentVolume" @volume-change="onVolumeChange" />- Inputs:
-
value- placeholder for the current value of volume
- Outputs:
-
volume-change- emitted after changing the volume
<organism-audio-controls
:is-playing="isPlaying"
:is-previous-disabled="isPreviousDisabled"
:is-next-disabled="isNextDisabled"
:is-shuffle="isShuffleMode"
@toggle-play="togglePlay"
@previous="previousTrack()"
@next="nextTrack()"
@toggle-shuffle="onToggleShuffle"
/>- Inputs:
-
is-playing- indicates if player is in playing mode
-
is-previous-disabled- indicates if previous button should be disabled or not
-
is-next-disabled- indicates if next button should be disabled or not
-
is-shuffle- indicates if shuffle button should be active or not
- Outputs:
-
previous- emitted after clicking on previous button
-
next- emitted after clicking on next button
-
toggle-shuffle- emitted after clicking on the button for shuffling playlist
-
toggle-play- emitted after clicking on the play/pause button
<organism-stems-controls
v-if="areStemsVisible"
:stems="stems"
:progress="() => waveSurfer.getCurrentTime()"
:max-width="stemsContainerMaxWidth"
:volume="currentVolume"
@select-stem="onSelectStem"
@stem-time-update="onStemTimeUpdate"
/>- Inputs:
-
stems- list of stems (each object should containnameandiconproperty)
-
progress- input for method for getting the current track time
-
max-width- indicates the maximum width of the spectrum container
-
volume- the current value of volume
- Outputs:
-
select-stem- emitted after stem selection. Contains 2 objects: the selected stem and the stem WaveSurfer
-
stem-time-update- emitted continuously if stem is playing. Notify the main WaveSurfer object to update its progress
<organism-hook-controls
v-if="hook"
:is-playing-loop="isPlayingLoopHook"
@share="shareHook()"
@download="downloadHook()"
@play-loop="playLoopHook()"
@remove="removeHook()"
/>- Inputs:
-
is-playing-loop- indicates if the loop mode is active
- Outputs:
-
share- emitted after clickingsharebutton
-
download- emitted after clickingdownloadbutton
-
play-loop- emitted after clicking button for turning on/off loop mode
-
remove- emitted after clickingremovebutton
Inside it contains all listed above components. It is responsible for generating spectrum and grouping all the functionalities of the audio player
<organism-audio-player
v-if="currentTrack && currentTrack.mainFile"
:track-details="currentTrack.mainFile"
:is-previous-disabled="isStartOfTrackList"
:is-next-disabled="isEndOfTrackList"
:band-name="currentTrack.music_store_author ? currentTrack.music_store_author.legal_name : null"
:track-name="currentTrack.title"
:stems="currentTrack.stems"
@toggle-shuffle="onShuffle($event)"
@share-hook="onShareHook"
@download-hook="onDownloadHook"
@previous="onPreviousTrack"
@next="onNextTrack"
@wave-surfer-init="onWaveSurferInit"
/>- Inputs:
-
track-details- object that contains information about the track URL and the spectrum data
-
is-previous-disabled- indicates if previous button should be disabled or not
-
is-next-disabled- indicates if next button should be disabled or not
-
is-shuffle- indicates if shuffle button should be active or not
-
band-name- placeholder for the name of the track band
-
track-name- placeholder for the name of the track
-
stems- list of stems (each object should containnameandiconproperty)
- Outputs:
-
share-hook- emitted after clickingsharebutton in the hook menu
-
download-hook- emitted after clickingdownloadbutton in the hook menu
-
wave-surfer-init- emitted after initializing of the new WaveSurfer object. It is done after playing new track
-
previous- emitted after clicking on previous button
-
next- emitted after clicking on next button
-
toggle-shuffle- emitted after clicking on the button for shuffling playlist
-
Install NVM (Node Version Manager):
- For Mac or Ubuntu: NVM Installation
- For Windows: NVM for Windows
-
Install Node.js:
- Run the command
nvm install 22.9.0and thennvm use 22.9.0.
- Run the command
-
Install Yarn:
- Follow the instructions on Yarn Installation.
-
Install project dependencies:
- Run
yarn installto installnode_modules.
- Run
-
Run the project:
- Use
yarn devto start the application with hot reload onhttp://localhost:3000.
- Use
- Run command
yarn lintto check for linting issues and apply fixes.
Go to the folder api and run:
poetry installThen run:
poetry run uvicorn main:app --reload --host 0.0.0.0 --port 7070Track examples will be available at http://localhost:7070/api/tracks.
We welcome contributions! Please follow these steps:
- Fork the repository.
- Create a new branch for your feature or bug fix.
- Make your changes and commit them.
- Push your branch and create a pull request.
This project is licensed under the MIT License - see the LICENSE file for details.