Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# API Documentation

The API can be accessed at `https://d1e7htx1c4j3w0.cloudfront.net/api`.

## Endpoints

### POST /auth/token

Exchanges an authorization code for access and refresh tokens.

**Headers:**
- `Content-Type: application/x-www-form-urlencoded`

**Body Parameters:**
- `code` (required): Authorization code from Spotify OAuth flow

**Returns:**
```json
{
"access_token": "string",
"refresh_token": "string",
"expires_in": number
}
```

Also sets `access_token` and `refresh_token` cookies.

### GET /me

Retrieves the current user's Spotify profile information.

**Headers:**
- `Authorization: Bearer <access_token>` (or access_token cookie)

**Returns:**
```json
{
"id": "string",
"username": "string"
}
```

### GET /artist-name

Fetches the name of an artist by their Spotify ID.

**Headers:**
- `Authorization: Bearer <access_token>` (or access_token cookie)

**Query Parameters:**
- `artistId` (required): Spotify artist ID

**Returns:**
```json
{
"artistName": "string"
}
```

### GET /artists-albums

Retrieves all albums for a given artist, including albums, singles, compilations, and appearances.

**Headers:**
- `Authorization: Bearer <access_token>` (or access_token cookie)

**Query Parameters:**
- `artistId` (required): Spotify artist ID

**Returns:**
```json
{
"artistsAlbums": [
{
"id": "string",
"name": "string"
}
]
}
```

### GET /artists-tracks

Fetches all tracks by a given artist.

**Headers:**
- `Authorization: Bearer <access_token>` (or access_token cookie)

**Query Parameters:**
- `artistId` (required): Spotify artist ID

**Returns:**
```json
{
"artistsTracks": [
{
"id": "string",
"name": "string"
}
]
}
```

### GET /create-playlist

Initiates asynchronous creation of a playlist containing all tracks by the specified artist. The playlist will be created in the user's Spotify account.

**Headers:**
- `Authorization: Bearer <access_token>` (or access_token cookie)

**Query Parameters:**
- `artistId` (required): Spotify artist ID

**Returns:**
```json
{
"message": "Playlist creation accepted"
}
```

Note: This endpoint returns immediately while playlist creation continues asynchronously.
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,72 @@
# all-tracks

all-tracks generates a complete playlist of every track by any Spotify
artist—no hunting for user-made playlists required.

## Demo

https://github.com/user-attachments/assets/623dcf1d-d8a1-46ed-9d7f-eb16c18ca77c

Users visit the site [here](https://d1e7htx1c4j3w0.cloudfront.net/). Once
authorised, they enter an artist's Spotify URL and click 'Create Playlist'.
After a short delay, a playlist with all the artist's tracks is created in the
user's Spotify account.

Unfortunately Spotify does not allow apps developed by individuals to leave
'development mode' (see
[here](https://developer.spotify.com/documentation/web-api/concepts/quota-modes)
for more details). This means to use the app your account must be allow-listed,
so please contact me if you wish to use the app!

## Installation of dependencies

Clone repo and run `yarn`.

## Tests

Run `yarn test` to run the Jest tests. However, only the small tests will work
as the medium and large tests require secrets on your machine. Contact me to
obtain them.

Run `yarn test:cypress` to run the Cypress tests. Secrets are not required for
these tests. Run `yarn cypress:open` to open cypress. The tests can also be run
from here.

## API endpoints

The API can be accessed at `https://d1e7htx1c4j3w0.cloudfront.net/api`.
See [API.md](API.md) for detailed endpoint documentation.

## Architecture

### Back-end architecture

![Back-end Architecture](docs/back-end-architecture.png)

The back-end consists of an API Gateway, a Lambda to serve the gateway and a
downstream Lambda to create playlists. The Lambda to create playlists is invoked
asynchronously by the API Lambda. Playlist creation is handled in this way
because creation can take a long time for artists that have a lot of tracks.

### Front-end architecture

<img src="docs/front-end-architecture.png" width="50%" height="50%">

The front-end is simple HTML and JavaScript. It is served from an S3 bucket
behind a CloudFront Distribution. Authorization is handled through Spotify's
OAuth 2.0 flow. Once authenticated, the browser can make requests to the API.

## Technical decisions and process

- All infrastructure is managed by Terraform.
- TDD is used throughout development.
- CI/CD is handled by GitHub actions.
- No external libraries are mocked out. A wrapper is created around functions
that use external libraries. Small tests are used to test the functions that
use the wrapper, and medium or large tests are used to test the wrapper
itself. For example, a wrapper is used to make requests to Spotify. Functions
that use this wrapper have small tests that mock the wrapper out. The wrapper
itself is tested with medium tests that make actual calls to the Spotify API.
- As this is a POC the front end is kept purposely simple. Ideally a framework
would be used to allow easier development and testing.
- Cypress is used to test E2E to closely simulate user interactions.
Binary file added docs/all-tracks-demo.mp4
Binary file not shown.
Binary file added docs/back-end-architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/front-end-architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.