User Library v1: Saving Tracks
Authors: @szainmehdi
Type: Feature
Overview
Build a system that allows users to save Tracks to their library on Nawhas.com.
Definitions
Term | Definition |
---|---|
Track | A nawha, stored in the tracks table |
Playlist | A collection of nawhas with a user-defined name. |
User | A logged in person on Nawhas.com |
Why are we making this change?
Currently, Nawhas.com is not very interactive. Users have no way to “favorite” nawhas, create playlists, and listen to playlists.
To enable more interactivity on the site, and entice users to sign up for an account, we’re building a feature that, to start, will start to allow users to “favorite” nawhas and save them to their library.
Requirements
- A user can sign up for an account on Nawhas.com
- A user can save a track anywhere in the application.
- A user can view saved tracks.
- A user can play all saved tracks.
- A user must be authenticated to save tracks.
- A user is prompted to sign up if attempting to save track.
Detailed Engineering Design
In the backend, we’ll create a new Accounts
module for all changes described below.
Events
Keeping event sourcing in mind, we only have the following events to consider for favoriting nawhas.
TrackSaved
- userId: UUID
- trackId: UUID
SavedTrackRemoved
- userId: UUID
- trackId: UUID
How we store these saved tracks in a database can change in the future. What’s most important is that we capture the right events, with clarity on the intent of the event.
API
A few new API endpoints will need to be added to allow managing saved tracks.
Get Saved Tracks
GET /me/tracks
Query Params:
- sort_by: string
- sort_dir: "asc"|"desc"
- per_page: int
- page: int
- include: Array<TrackIncludes>
-> 200 OK
{
data: Array<Track>
meta: {
pagination: PaginationMetadata
}
}
By default, this endpoint will sort by most recently saved tracks.
Database
We’ll process the events above and write records to the following table.
table: saves
========================
user_id: uuid (index)
saveable_type: [Track|Album|Reciter] (index)
saveable_id: uuid (index)
created_at: timestamp
updated_at: timestamp
Save Track
PUT /me/tracks
{
ids: Array<UUID>
}
-> 204 No Content
Remove Saved Track
DELETE /me/tracks
{
ids: Array<UUID>
}
-> 204 No Content
Frontend
- We’ll need to build a new
Api
class:nuxt/api/library.ts
that handles calling the endpoints described above. - A new page
nuxt/pages/library/LandingPage.vue
will be created and mapped to the/library
route. - A new page
nuxt/pages/library/HomePage.vue
will be created and mapped to the/library/home
route.- A new middleware that checks to see if the user is authenticated will need to be used to guard this page.
- If the user is not authenticated, we’ll redirect them to the
LibraryLandingPage
- If the user is not authenticated, we’ll redirect them to the
- This page will display a user’s saved tracks, limited to 6 tracks.
- The “View All” button will take the user to
/library/tracks
.
- A new middleware that checks to see if the user is authenticated will need to be used to guard this page.
- A new page
nuxt/pages/library/TracksPage.vue
will be created and mapped to the/library/tracks
page.- This page will show a list of tracks in a sortable, paginated table. Sorting and pagination will be handled server-side.
- All components that show a track will need to be updated to support saving the track.
- This action will need to prompt a user to log in if unauthenticated, and then, once authenticated, complete the requested action.
Deployment Strategy
TODO
Future Scope
Saving Albums
We’ll want to enable users to save albums in a fast-follow.
Playlists
We’ll eventually want to enable users to create and manage playlists. We can use the data from these events to automatically add saved tracks to an autogenerated playlist called “Favorites”.