-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 793ff58
Showing
96 changed files
with
18,440 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"path": "cz-conventional-changelog" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
**/*.eslintrc.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// This configuration only applies to the package manager root. | ||
/** @type {import("eslint").Linter.Config} */ | ||
module.exports = { | ||
ignorePatterns: ["apps/**", "packages/**"], | ||
extends: ["@repo/eslint-config/library.js"], | ||
parser: "@typescript-eslint/parser", | ||
parserOptions: { | ||
project: true, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
name: build | ||
|
||
on: | ||
push: | ||
branches: ["*"] | ||
pull_request: | ||
branches: [main] | ||
workflow_dispatch: | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Setup node 20 | ||
uses: actions/setup-node@v4 | ||
with: | ||
cache: 'npm' | ||
node-version: 20.15.0 | ||
|
||
- name: npm ci | ||
run: npm ci | ||
|
||
- name: npm run build | ||
run: npm run build | ||
|
||
release: | ||
name: semantic-release | ||
runs-on: ubuntu-latest | ||
needs: [build] | ||
if: success() && github.ref == 'refs/heads/main' && github.event_name == 'push' | ||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Setup node 20 | ||
uses: actions/setup-node@v4 | ||
with: | ||
cache: 'npm' | ||
node-version: 20.15.0 | ||
|
||
- name: Install semantic-release | ||
run: npm i -g semantic-release | ||
|
||
- name: Release | ||
env: | ||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} | ||
run: npx semantic-release | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# Dependencies | ||
node_modules | ||
.pnp | ||
.pnp.js | ||
|
||
# Local env files | ||
.env | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
# Testing | ||
coverage | ||
|
||
# Turbo | ||
.turbo | ||
|
||
# Vercel | ||
.vercel | ||
|
||
# Build Outputs | ||
.next/ | ||
out/ | ||
build | ||
dist | ||
.eslintcache | ||
|
||
# Debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Misc | ||
.DS_Store | ||
*.pem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/usr/bin/env sh | ||
. "$(dirname "$0")/_/husky.sh" | ||
|
||
npx lint-staged |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/usr/bin/env sh | ||
. "$(dirname "$0")/_/husky.sh" | ||
|
||
exec < /dev/tty && npx cz --hook || true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
force=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
20.15.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"arrowParens": "always", | ||
"bracketSameLine": true, | ||
"bracketSpacing": true, | ||
"jsxSingleQuote": false, | ||
"singleQuote": false, | ||
"tabWidth": 4, | ||
"trailingComma": "es5", | ||
"useTabs": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
## Base | ||
FROM node:20-alpine3.19 AS base | ||
ARG AWS_ACCESS_KEY_ID | ||
ENV AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} | ||
ARG AWS_SECRET_ACCESS_KEY | ||
ENV AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} | ||
WORKDIR /app | ||
RUN apk add aws-cli | ||
|
||
# Download the sqlite db from s3 | ||
RUN aws s3 cp s3://arthistory-spotify-data/$(aws s3 ls s3://arthistory-spotify-data | sort | tail -n 1 | awk '{print $4}') _spotify-data.db | ||
|
||
## Builder | ||
FROM base AS builder | ||
RUN apk update | ||
RUN apk add --no-cache libc6-compat | ||
WORKDIR /app | ||
RUN npm install turbo@2 --global | ||
|
||
COPY . . | ||
|
||
# Generate a partial monorepo with a pruned lockfile for a target workspace. | ||
# Assuming "api" is the name entered in the project's package.json: { name: "api" } | ||
RUN npx turbo prune api --docker | ||
|
||
## Installer | ||
FROM base AS installer | ||
RUN apk update | ||
RUN apk add python3 make gcc g++ libc-dev | ||
WORKDIR /app | ||
|
||
COPY --from=builder /app/out/json/ . | ||
COPY --from=builder /app/out/package-lock.json ./package-lock.json | ||
RUN npm install | ||
|
||
# Build the project | ||
COPY --from=builder /app/out/full/ . | ||
RUN npx turbo run build --filter=api... | ||
|
||
## Runner | ||
FROM base AS runner | ||
WORKDIR /app | ||
|
||
RUN npm install pm2 --global | ||
|
||
# Don't run production as root | ||
RUN addgroup --system --gid 1001 nodejs | ||
RUN adduser --system --uid 1001 nodejs | ||
USER nodejs | ||
|
||
COPY --from=builder /app/process.yml ./process.yml | ||
COPY --from=builder /app/package.json ./package.json | ||
COPY --from=installer /app/apps/api/dist ./dist | ||
COPY --from=installer /app/apps/api/build ./build | ||
COPY --from=base /app/_spotify-data.db ./_spotify-data.db | ||
|
||
ARG PORT=3001 | ||
ENV PORT=${PORT} | ||
|
||
ARG CLIENT_ID | ||
ENV CLIENT_ID=${CLIENT_ID} | ||
|
||
ARG CLIENT_SECRET | ||
ENV CLIENT_SECRET=${CLIENT_SECRET} | ||
|
||
ARG DATABASE_PATH=/app/_spotify-data.db | ||
ENV DATABASE_PATH=${DATABASE_PATH} | ||
|
||
ARG POSTHOG_KEY | ||
ENV POSTHOG_KEY=${POSTHOG_KEY} | ||
|
||
ENV NODE_ENV=production | ||
|
||
CMD pm2 start process.yml && tail -f /dev/null | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<h1 align="center">arthistory</h1> | ||
|
||
<p align="center"> | ||
<a href="https://github.com/brandongregoryscott/arthistory/actions"> | ||
<img src="https://github.com/brandongregoryscott/arthistory/actions/workflows/build.yml/badge.svg"> | ||
</a> | ||
<a href="https://github.com/prettier/prettier"> | ||
<img alt="code style: prettier" src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square"/> | ||
</a> | ||
<a href="http://www.typescriptlang.org/"> | ||
<img alt="TypeScript" src="https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg"/> | ||
</a> | ||
<a href="http://commitizen.github.io/cz-cli/"> | ||
<img alt="Commitizen friendly" src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg"/> | ||
</a> | ||
</p> | ||
|
||
Web application for viewing historical Spotify artist data. | ||
|
||
## Quick Start | ||
|
||
The app can be accessed at [arthistory.brandonscott.me](https://arthistory.brandonscott.me). | ||
|
||
## About | ||
|
||
The Spotify API provides the current follower count and a popularity score for an artist, but does not provide any historical data. I always wanted to track how my favorite artists were growing over time, so maybe you'll find this app useful too. | ||
|
||
## How it works | ||
|
||
Artist data is synced and pushed everyday to the [spotify-data](https://github.com/brandongregoryscott/spotify-data) repo. To easily query the data over time, a SQLite database is built by iterating through the git history and pushed up to S3, which is pulled down and bundled with the API server. | ||
|
||
Not every artist on Spotify is tracked, but new artists can be requested through the web UI or by opening up a pull request to the [spotify-data](https://github.com/brandongregoryscott/spotify-data) repo. | ||
|
||
## Development | ||
|
||
### Database | ||
|
||
The API requires at least a partial SQLite database to query. See the [spotify-data](https://github.com/brandongregoryscott/spotify-data/tree/main?tab=readme-ov-file#building-a-sqlite-database) repo for instructions on how to build a SQLite database to use. | ||
|
||
### Spotify API keys | ||
|
||
The search endpoint in the API hits the Spotify API, so you'll need API keys to search for artists. See the [Spotify API](https://developer.spotify.com/documentation/web-api/tutorials/getting-started) documentation on signing up for developer access. | ||
|
||
### Setup | ||
|
||
```sh | ||
# Edit the environment file to add your Spotify API keys and path to the SQLite database file | ||
cp apps/api/.env.example apps/api/.env | ||
|
||
# The environment file for the web app probably doesn't need to be changed. | ||
cp apps/web/.env.example apps/web/.env | ||
|
||
# Install packages (ensure you are using Node v20+, run `nvm use` if you have `nvm` installed.) | ||
npm i | ||
|
||
# Run the development servers for the web app and API | ||
npm run dev | ||
|
||
# Now, open http://localhost:3000 in your browser to view the app. | ||
``` | ||
|
||
## Issues | ||
|
||
If you find a bug, feel free to [open up an issue](https://github.com/brandongregoryscott/arthistory/issues/new) and try to describe it in detail with reproduction steps if possible. | ||
|
||
If you would like to see a feature, and it isn't [already documented](https://github.com/brandongregoryscott/arthistory/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement), feel free to open up a new issue and describe the desired behavior. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
PORT=3001 | ||
CLIENT_ID=abc | ||
CLIENT_SECRET=xyz | ||
DATABASE_PATH=~/spotify-data/output/_spotify-data.db |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
module.exports = { | ||
root: true, | ||
extends: [ | ||
"@brandongregoryscott/eslint-config", | ||
"@brandongregoryscott/eslint-config/typescript", | ||
], | ||
parserOptions: { | ||
tsconfigRootDir: __dirname, | ||
project: "tsconfig.json", | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"dependencies": { | ||
"@repo/common": "*", | ||
"@spotify/web-api-ts-sdk": "1.2.0", | ||
"body-parser": "1.20.2", | ||
"cors": "2.8.5", | ||
"date-fns": "3.6.0", | ||
"dotenv": "16.3.1", | ||
"esbuild": "0.18.18", | ||
"express": "5.0.0-beta.3", | ||
"express-rate-limit": "6.8.1", | ||
"lodash": "4.17.21", | ||
"posthog-js": "1.144.2", | ||
"sqlite": "5.1.1", | ||
"sqlite3": "5.1.7" | ||
}, | ||
"devDependencies": { | ||
"@repo/eslint-config": "*", | ||
"@repo/typescript-config": "*", | ||
"@types/cors": "2.8.13", | ||
"@types/express": "4.17.17", | ||
"@types/lodash": "4.14.195", | ||
"@types/node": "20.4.2", | ||
"concurrently": "8.2.0", | ||
"nodemon": "3.0.1", | ||
"typescript": "5.5.3" | ||
}, | ||
"name": "api", | ||
"private": true, | ||
"scripts": { | ||
"build": "esbuild src/server.ts --bundle --platform=node --target=node20 --outfile=dist/server.js", | ||
"clean": "rm -rf dist", | ||
"dev": "concurrently --names esbuild,nodemon \"npm run build -- --watch\" \"nodemon -q dist/server.js\"", | ||
"start": "node dist/server.js", | ||
"postbuild": "rm -rf ../../build build && cd ../../node_modules/sqlite3 && npm run rebuild && cd - && cp -r ../../node_modules/sqlite3/build ../.. && cp -r ../../node_modules/sqlite3/build ." | ||
}, | ||
"version": "1.0.0" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import posthog from "posthog-js"; | ||
import { POSTHOG_KEY } from "./config"; | ||
import { DEFAULT_ARTIST_IDS } from "@repo/common"; | ||
|
||
posthog.init(POSTHOG_KEY); | ||
|
||
interface ArtistRequestedProperties { | ||
id: string; | ||
} | ||
|
||
const artistRequested = (properties: ArtistRequestedProperties): void => { | ||
posthog.capture("Artist Requested", properties); | ||
}; | ||
|
||
interface ArtistSelectedProperties { | ||
id: string; | ||
} | ||
|
||
const artistSelected = (properties: ArtistSelectedProperties): void => { | ||
const { id } = properties; | ||
if (DEFAULT_ARTIST_IDS.includes(id)) { | ||
return; | ||
} | ||
|
||
posthog.capture("Artist Selected", properties); | ||
}; | ||
|
||
interface SearchQueryEnteredProperties { | ||
query: string; | ||
totalCount: number; | ||
trackedCount: number; | ||
} | ||
|
||
const searchQueryEntered = (properties: SearchQueryEnteredProperties): void => { | ||
posthog.capture("Search Query Entered", properties); | ||
}; | ||
|
||
export { artistRequested, artistSelected, searchQueryEntered }; |
Oops, something went wrong.