-
-
Notifications
You must be signed in to change notification settings - Fork 5
feat: add Music licensing challenge example with Nextjs #120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.* | ||
.yarn/* | ||
!.yarn/patches | ||
!.yarn/plugins | ||
!.yarn/releases | ||
!.yarn/versions | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
.pnpm-debug.log* | ||
|
||
# env files (can opt-in for committing if needed) | ||
.env* | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/usr/bin/env sh | ||
. "$(dirname -- "$0")/_/husky.sh" | ||
|
||
pnpm run lint-staged |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/usr/bin/sh | ||
. "$(dirname "$0")/_/husky.sh" | ||
|
||
npm run type-check |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# Music Licensing Challenge Frontend | ||
|
||
|
||
## Features | ||
- Movie, scene, track, and song management UI | ||
- License status management for songs | ||
- Real-time updates for license status via GraphQL subscriptions | ||
- Authentication (login/register) | ||
- TypeScript, TailwindCSS, and Apollo Client integration | ||
- Linting and formatting with BiomeJs | ||
|
||
## Tech Stack | ||
- [Next.js 15 (App Router)](https://nextjs.org/) | ||
- [React 19](https://react.dev/) | ||
- [Apollo Client 3](https://www.apollographql.com/docs/react/) | ||
- [GraphQL](https://graphql.org/) | ||
- [TailwindCSS 4](https://tailwindcss.com/) | ||
- [TypeScript](https://www.typescriptlang.org/) | ||
- [Biome](https://biomejs.dev/) (linting/formatting) | ||
|
||
## Getting Started | ||
|
||
1. **Install dependencies:** | ||
```bash | ||
pnpm install | ||
# or | ||
npm install | ||
# or | ||
yarn install | ||
``` | ||
|
||
2. **Set up environment variables:** | ||
- Create a `.env.local` file with: | ||
```env | ||
NEXT_PUBLIC_GRAPHQL_URL=your-graphql-http-endpoint | ||
NEXT_PUBLIC_WS_URL=your-graphql-ws-endpoint | ||
``` | ||
|
||
3. **Run the development server:** | ||
```bash | ||
pnpm dev | ||
# or | ||
npm run dev | ||
# or | ||
yarn dev | ||
``` | ||
Open [http://localhost:3000](http://localhost:3000) in your browser. | ||
|
||
## Project Structure | ||
- `src/app/` — App Router pages, layouts, and routes (including movies, scenes, auth) | ||
- `src/components/` — UI components (SceneList, MovieCard, Navbar, etc.) | ||
- `src/lib/graphql/` — Apollo Client setup, queries, mutations, subscriptions | ||
- `src/hooks/` — Custom React hooks (e.g., `useSongWithLiveStatus`) | ||
- `src/types/` — TypeScript type definitions | ||
- `src/styles/` — Global and Tailwind styles | ||
|
||
## GraphQL Usage | ||
- **Apollo Client** is set up in `src/lib/graphql/client.ts` with HTTP and WebSocket links for queries/mutations and subscriptions. | ||
- **Queries:** | ||
- Example: `GET_SONG_BY_ID`, `GET_SCENES`, `GET_MOVIES` in `src/lib/graphql/queries/` | ||
- **Mutations:** | ||
- Example: `UPDATE_SONG_LICENSE_STATUS` in `src/lib/graphql/mutations/songs.ts` | ||
- **Subscriptions:** | ||
- Example: `LICENSE_STATUS_UPDATED` in `src/lib/graphql/subscriptions/license-status.ts` | ||
- **Custom Hooks:** | ||
- `useSongWithLiveStatus(song)` — Combines query and subscription for live song status | ||
|
||
## Linting & Formatting | ||
- Run `pnpm lint` or `pnpm format` to lint/format code with Biome. | ||
- Type-check with `pnpm type-check`. | ||
|
||
## TypeScript | ||
- Full TypeScript support with strict settings (`tsconfig.json`) | ||
- Types in `src/types/` | ||
|
||
## Styling | ||
- TailwindCSS is used for all styling. See `src/styles/globals.css`. | ||
|
||
## Contributing | ||
Pull requests are welcome! Please lint, format, and type-check your code before submitting. | ||
|
||
--- | ||
|
||
For more, see the source code and comments throughout the project. | ||
|
||
## Learn More | ||
|
||
To learn more about Next.js, take a look at the following resources: | ||
|
||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. | ||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
{ | ||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", | ||
"vcs": { | ||
"enabled": false, | ||
"clientKind": "git", | ||
"useIgnoreFile": false | ||
}, | ||
"files": { | ||
"ignoreUnknown": false, | ||
"ignore": [".next"], | ||
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx", "**/*.css"] | ||
}, | ||
"formatter": { | ||
"enabled": true, | ||
"indentStyle": "tab" | ||
}, | ||
"organizeImports": { | ||
"enabled": true | ||
}, | ||
"linter": { | ||
"enabled": true, | ||
"rules": { | ||
"recommended": true, | ||
"suspicious": { | ||
"noArrayIndexKey": "warn" | ||
}, | ||
"a11y": { | ||
"useAltText": "warn", | ||
"useValidAnchor": "warn", | ||
"noSvgWithoutTitle": "warn" | ||
}, | ||
"complexity": { | ||
"noExtraBooleanCast": "warn" | ||
}, | ||
"correctness": { | ||
"noUnusedVariables": "error", | ||
"noUnusedImports": "error" | ||
} | ||
} | ||
}, | ||
"javascript": { | ||
"formatter": { | ||
"arrowParentheses": "always", | ||
"bracketSameLine": false, | ||
"bracketSpacing": true, | ||
"semicolons": "always", | ||
"trailingCommas": "all", | ||
"jsxQuoteStyle": "double", | ||
"quoteProperties": "asNeeded", | ||
"lineWidth": 80, | ||
"indentWidth": 2 | ||
Comment on lines
+50
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure indentation width is consistent with formatter settings The indentation width is set to 2 spaces, but the formatter is configured to use tabs. This inconsistency can lead to formatting issues. "jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"lineWidth": 80,
- "indentWidth": 2
+ "indentStyle": "tab",
+ "indentWidth": 2 // Only applies when indentStyle is "space"
|
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
NEXT_PUBLIC_API_BASE_URL= | ||
NEXT_PUBLIC_AUTH_SECRET= | ||
NEXT_PUBLIC_USER_EXAMPLE= | ||
NEXT_PUBLIC_PASSWORD_EXAMPLE= | ||
NEXT_PUBLIC_WS_URL= | ||
NEXT_PUBLIC_GRAPHQL_URL= | ||
NEXTAUTH_URL= |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/// <reference types="next" /> | ||
/// <reference types="next/image-types/global" /> | ||
|
||
// NOTE: This file should not be edited | ||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,17 @@ | ||||||||||||||||||||||||||||||||||||
import type { NextConfig } from "next"; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
const nextConfig: NextConfig = { | ||||||||||||||||||||||||||||||||||||
images: { | ||||||||||||||||||||||||||||||||||||
remotePatterns: [ | ||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||
protocol: "https", | ||||||||||||||||||||||||||||||||||||
hostname: "**", | ||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||
Comment on lines
+4
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security concern with image remote patterns configuration The current configuration allows loading images from any HTTPS hostname, which is overly permissive and could pose security risks like content injection or tracking vulnerabilities. Consider restricting the remote patterns to only specific domains that you actually need: images: {
remotePatterns: [
{
protocol: "https",
- hostname: "**",
+ hostname: "trusted-image-domain.com",
},
+ // Add other specific domains as needed
],
}, If you need multiple domains, add them as separate entries with specific hostnames rather than using a wildcard. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||
eslint: { | ||||||||||||||||||||||||||||||||||||
ignoreDuringBuilds: true, | ||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
export default nextConfig; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"name": "music-licensing-challenge", | ||
"version": "0.1.0", | ||
"private": true, | ||
"scripts": { | ||
"dev": "next dev --turbopack", | ||
"build": "next build", | ||
"start": "next start", | ||
"lint": "biome lint --write", | ||
"lint:check": "biome lint --diagnostic-level=error", | ||
"format": "biome format --write", | ||
"format:check": "biome format", | ||
"prepare": "husky || true", | ||
"lint-staged": "lint-staged", | ||
"type-check": "tsc --noEmit" | ||
}, | ||
"dependencies": { | ||
"@apollo/client": "^3.13.8", | ||
"@apollo/client-integration-nextjs": "^0.12.2", | ||
"@headlessui/react": "^2.2.1", | ||
"@heroicons/react": "^2.2.0", | ||
"@tailwindcss/postcss": "^4.1.3", | ||
"clsx": "^2.1.1", | ||
"graphql-ws": "^6.0.4", | ||
"next": "15.2.5", | ||
"next-auth": "5.0.0-beta.25", | ||
"postcss": "^8.5.3", | ||
"react": "^19.0.0", | ||
"react-dom": "^19.0.0", | ||
"tailwindcss": "^4.1.3" | ||
}, | ||
"devDependencies": { | ||
"@biomejs/biome": "^1.9.4", | ||
"@types/node": "^20", | ||
"@types/react": "^19", | ||
"@types/react-dom": "^19", | ||
"husky": "^9.1.7", | ||
"lint-staged": "^15.5.0", | ||
"typescript": "^5" | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Expand ignore patterns to include more build and dependency directories
The current ignore patterns only exclude the
.next
directory, but other common directories should also be excluded.📝 Committable suggestion