JamSpot is a local concert discovery application that recommends live music events based on a user's location, date range, music preferences, mood, and favorite artists.
Find your next live show.
Finding concerts is easy when you already know exactly who you want to see. JamSpot is designed for the other situation: when you want to go to a show but need help discovering what is happening nearby.
Users provide preferences such as:
- Location
- Date range
- Music genre
- Mood
- Favorite artists
JamSpot uses those preferences to find and rank relevant local concerts.
The MVP will use Supabase for preference storage and the Ticketmaster Discovery API for concert data.
| Technology | Purpose |
|---|---|
| Next.js | Web application framework |
| React | User interface |
| TypeScript | Application language |
| Tailwind CSS | Styling |
| Supabase | Backend platform |
| PostgreSQL | Database |
| Ticketmaster Discovery API | Concert and event data |
| Vercel | Hosting and deployment (web) |
| Expo / React Native | Mobile application (iOS/Android), in progress |
| npm workspaces | Monorepo tooling |
Possible future integrations:
- Claude API for natural-language preference input
- Last.fm API for artist and music recommendations
- Google authentication
JamSpot is an npm-workspaces monorepo:
apps/web— the Next.js web app described throughout this README.apps/mobile— the Expo/React Native app for iOS and Android (managed workflow, in progress).packages/shared— TypeScript types shared betweenapps/webandapps/mobilefor the normalized API response shapes.
Run npm install once from the repo root to install every workspace's dependencies. Root-level
convenience scripts delegate to the relevant workspace, e.g. npm run dev:web, npm run dev:mobile, npm run build:web, npm run test:web, npm run test:e2e, npm run lint. Each
app's own scripts still work unchanged when run with that app as the working directory (e.g. cd apps/web && npm run dev).
Current foundation work:
- GitHub repository created
- Local project connected to GitHub
- Next.js application initialized
- Node.js 24 development environment configured
- Supabase project created
- Supabase JavaScript client installed
- Local environment variables configured
- Next.js-to-Supabase database connection tested
- Vercel deployment completed
- User preferences schema finalized
- Preferences page implemented
- Ticketmaster API integrated
- Recommendation logic implemented
- Concert recommendation UI implemented
- UI unit tests and coverage reporting added
- MVP testing completed
- Repo converted to an npm-workspaces monorepo (apps/web, apps/mobile, packages/shared)
- Expo mobile app scaffolded (managed workflow)
- Mobile app UI implemented
- Mobile CI / EAS Build pipeline set up
JamSpot's MVP has two primary pages.
Route:
/
The Home page will be the first page users see.
It will:
- Load saved preferences
- Fetch matching concerts
- Rank concert recommendations
- Display concert cards
- Show the currently active preferences
- Handle loading states
- Handle empty results
- Handle API and database errors
Route:
/preferences
Users will enter:
- Location
- Genre
- Mood
- Favorite artist or artists
- Start date
- End date
Required MVP fields:
- Location
- Genre
- Start date
- End date
Before running JamSpot locally, install:
- Git
- NVM
- Node.js 24
- npm
Check whether NVM is installed:
nvm --versionInstall Node.js 24:
nvm install 24Use Node.js 24:
nvm use 24Confirm the active version:
node --versionThe output should begin with:
v24.
Create a file named:
.nvmrc
with:
24
Team members can then switch to the correct Node.js version with:
nvm useIf Node.js 24 has not been installed yet:
nvm install
nvm usegit clone <REPOSITORY_URL>Enter the project directory:
cd jamspotnvm usenpm installCreate:
apps/web/.env.local
Add:
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=Add the values from the JamSpot Supabase project.
The project currently only requires these two environment variables.
Future integrations may add:
TICKETMASTER_API_KEY=
ANTHROPIC_API_KEY=
LASTFM_API_KEY=These variables are not required until the corresponding integrations are implemented.
Run:
git check-ignore apps/web/.env.localExpected output:
apps/web/.env.local
Also check:
git statusapps/web/.env.local should not appear as an untracked or staged file.
Never commit real API credentials or environment files containing credentials.
From the repo root:
npm run dev:webOr from apps/web:
npm run devOpen:
http://localhost:3000
JamSpot currently connects to Supabase using:
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=The application uses the Supabase JavaScript client:
npm install @supabase/supabase-jsA simple client configuration can be created in:
lib/supabase.ts
Example:
import { createClient } from "@supabase/supabase-js";
const supabaseUrl =
process.env.NEXT_PUBLIC_SUPABASE_URL;
const supabasePublishableKey =
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY;
if (!supabaseUrl) {
throw new Error("Missing NEXT_PUBLIC_SUPABASE_URL");
}
if (!supabasePublishableKey) {
throw new Error(
"Missing NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY"
);
}
export const supabase = createClient(
supabaseUrl,
supabasePublishableKey
);During initial setup, JamSpot uses a temporary connection-test page:
/test-db
Start the application:
npm run devThen visit:
http://localhost:3000/test-db
The current connection flow is:
Next.js
↓
Environment Variables
↓
Supabase JavaScript Client
↓
Supabase Data API
↓
PostgreSQL
The temporary connection-test route and database table should be removed after the real preferences database flow is implemented and verified.
JamSpot currently uses three separate environments.
Environment variables are stored in:
.env.local
Current variables:
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=GitHub Actions runs UI tests with coverage before either deployment workflow can continue. The repository requires these Actions secrets for Vercel deployment:
VERCEL_TOKEN
VERCEL_ORG_ID
VERCEL_PROJECT_ID
VERCEL_PROJECT_ID_K7PZ
VERCEL_PROJECT_ID targets the subprod project. VERCEL_PROJECT_ID_K7PZ targets the production-preview project. Application runtime variables remain in Vercel rather than GitHub.
The following variables must be configured in the Vercel project:
NEXT_PUBLIC_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
Recommended environments:
Production
Preview
Development
The current configuration should be:
Local
└── .env.local
GitHub
└── Source code only
Vercel
├── NEXT_PUBLIC_SUPABASE_URL
└── NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
Before opening a pull request, run the same UI quality gate used by GitHub Actions:
nvm use
npm ci
npm run coverageOpen pull requests against:
main → subprod deployment
prod → production-preview deployment
Each deployment job depends on the UI unit tests job. A failed test or coverage threshold prevents the Vercel build, deployment, and alias steps from running. Do not commit .env.local.
In the Vercel dashboard:
Add New
→ Project
→ Import jamspot
For a standard project with package.json at the repository root:
Framework Preset: Next.js
Root Directory: ./
Leave the detected Next.js build settings at their defaults unless the project structure changes.
In the Vercel JamSpot project:
Settings
→ Environment Variables
Add:
NEXT_PUBLIC_SUPABASE_URL
and:
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
Use the values from the JamSpot Supabase project.
Assign them to:
Production
Preview
Development
Deploy the project.
After deployment, test:
/
and, while the connection-test route still exists:
/test-db
Verify that:
- The application loads
- Supabase queries work
- No environment variable errors occur
- No private credentials are displayed
Do not develop features directly on main.
Start from an updated main branch:
git checkout main
git pull origin mainCreate a feature branch:
git checkout -b feature/preferences-formMake changes, then review them:
git statusCommit:
git add .
git commit -m "Add preferences form"Push:
git push -u origin feature/preferences-formThen open a pull request into:
main
Recommended branch prefixes:
feature/
fix/
refactor/
test/
docs/
Examples:
feature/preferences-form
feature/ticketmaster-search
feature/concert-cards
fix/date-range-validation
fix/supabase-query-error
refactor/recommendation-ranking
docs/update-readme
With Vercel connected to GitHub, the intended workflow is:
Feature Branch
↓
Push to GitHub
↓
Vercel Preview Deployment
↓
Pull Request Review
↓
Merge to main
↓
Production Deployment
The MVP is expected to use a user_preferences table.
Proposed fields:
| Field | Purpose |
|---|---|
id |
Unique preference record |
location |
User-specified concert location |
genre |
Preferred music genre |
mood |
Optional mood preference |
favorite_artists |
One or more favorite artists |
start_date |
Beginning of concert search range |
end_date |
End of concert search range |
created_at |
Preference creation timestamp |
The exact schema and access strategy should be finalized before preference data is exposed through the application.
Because location and music preferences are user-related data, the preferences table should not use an unrestricted public-read policy.
The MVP will begin with deterministic recommendation logic rather than AI.
Possible ranking priorities:
- Favorite artist match
- Genre match
- Mood-to-genre match
- Location match
- Event date
Example mood mapping:
Chill
→ Indie, R&B, Acoustic
Energetic
→ EDM, Pop, Hip-Hop
Sad
→ Alternative, Indie
Party
→ EDM, Rap, Pop
The ranking logic should be implemented as a separate testable function rather than directly inside a page component.
Example future location:
lib/recommendations/rank-concerts.ts
JamSpot will use the Ticketmaster Discovery API to find concert events.
The application will eventually search using data such as:
- Location
- Start date
- End date
- Genre
- Artist keyword
- Music classification
The Ticketmaster API response should be normalized before being passed to UI components.
A possible internal concert type:
type Concert = {
id: string;
name: string;
venue: string;
city: string;
date: string;
time?: string;
imageUrl?: string;
ticketUrl: string;
genre?: string;
};The UI should depend on JamSpot's normalized concert model rather than directly depending on the full Ticketmaster response structure.
JamSpot can gradually move toward a structure similar to:
jamspot/
├── app/
│ ├── api/
│ │ └── concerts/
│ │ └── route.ts
│ │
│ ├── preferences/
│ │ └── page.tsx
│ │
│ ├── test-db/
│ │ └── page.tsx
│ │
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
│
├── components/
│ ├── concert-card.tsx
│ ├── concert-grid.tsx
│ └── preference-form.tsx
│
├── lib/
│ ├── supabase.ts
│ │
│ ├── ticketmaster/
│ │ ├── normalize-event.ts
│ │ └── search-events.ts
│ │
│ └── recommendations/
│ ├── mood-map.ts
│ └── rank-concerts.ts
│
├── types/
│ ├── concert.ts
│ └── preferences.ts
│
├── public/
├── .env.local
├── .gitignore
├── .nvmrc
├── package.json
└── README.md
Add folders when the corresponding functionality is implemented rather than creating unused abstractions in advance.
- Create GitHub repository
- Initialize Next.js application
- Configure Node.js development environment
- Create Supabase project
- Install Supabase client
- Configure local environment variables
- Verify Supabase connectivity
- Deploy to Vercel
- Finalize database schema
- Create Preferences page
- Add location input
- Add genre input
- Add mood input
- Add favorite artist input
- Add date-range inputs
- Add validation
- Save preferences to Supabase
- Fetch saved preferences
- Add database error handling
- Obtain Ticketmaster API credentials
- Research API search parameters
- Build server-side concert search function
- Search by location
- Search by date range
- Apply genre or music classification filters
- Normalize API data
- Add API error handling
- Create Home page layout
- Fetch saved preferences
- Fetch matching concerts
- Implement genre matching
- Implement favorite artist matching
- Add mood-to-genre mapping
- Rank recommendations
- Create concert card component
- Add loading state
- Add empty state
- Add error state
- Add navigation
- Improve styling
- Test responsive layouts
- Test preference form submission
- Test multiple cities and genres
- Test invalid date ranges
- Test no-results scenarios
- Test Supabase failures
- Test Ticketmaster failures
- Remove temporary database test route
- Remove debug logging
- Perform final MVP cleanup
JamSpot includes UI unit tests built on Node.js's test runner and React server rendering. The tests cover concert formatting and filtering, the home page's UI state handlers, concert cards, modal states, streaming-service links, and artist-data error handling.
Run the UI unit tests:
npm testThe explicit UI-only command is also available as npm run test:ui.
Run the tests with enforced coverage thresholds and generate readable reports:
npm run coverageThe explicit command is also available as npm run test:ui:coverage.
Coverage must remain at or above 70% for lines, branches, and functions. Reports are written to:
coverage/ui-unit.txt
coverage/ui-unit.html
Pull requests to main and prod run this coverage command before deployment. GitHub Actions uploads the generated coverage/ directory as an artifact retained for 14 days. The deployment job has needs: test, so it cannot run unless the test job succeeds.
To prevent merging around the workflow, configure a GitHub ruleset or branch protection rule for both main and prod and require the UI unit tests status check. The workflow gate blocks deployment; the repository rule blocks the merge itself.
Run the browser end-to-end suite separately:
npm run test:e2ePlanned concert search tests:
Dallas, TX + Rap
New York, NY + Pop
Austin, TX + Country
Chicago, IL + EDM
Input and failure cases should include:
- Empty location
- Missing genre
- Missing start date
- Missing end date
- End date before start date
- Narrow date range
- Location with no events
- Supabase query failure
- Ticketmaster API failure
Check:
node --versionSwitch to the project version:
nvm useIf necessary:
nvm install 24
nvm use 24Then reinstall dependencies if required:
rm -rf node_modules
npm installConfirm .env.local exists in the web app directory:
jamspot/apps/web/.env.local
Then restart the development server:
npm run dev:webCheck:
NEXT_PUBLIC_SUPABASE_URLis correctNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEYis correct- Both values belong to the same Supabase project
- The requested table exists
- The table is in the expected schema
- Required database permissions exist
- The required RLS policy exists
- The correct Node.js version is active
macOS or Linux (from apps/web):
rm -rf .next
npm run devPowerShell (from apps/web):
Remove-Item -Recurse -Force .next
npm run dev- Never commit
.env.local. - Never commit database passwords or private API keys.
- Keep future Ticketmaster and AI API credentials server-side.
- Do not prefix server-only credentials with
NEXT_PUBLIC_. - Use Row Level Security for user-associated data.
- Do not create unrestricted public access to private preference records.
- Check
git statusbefore committing configuration changes. - Remove temporary test routes once they are no longer needed.
After the MVP is stable, possible additions include:
- User accounts
- Google authentication
- User profiles
- Natural-language concert searches
- Claude-powered preference parsing
- Last.fm artist similarity recommendations
- Pagination
- Saved concerts
- Concert reviews
- Personalized recommendation history
- Native mobile application
A project license has not yet been selected.