MyGo 云音乐
用 Go 与 MyGo 写成的第三方网易云音乐桌面客户端。原生界面,没有 WebView;边下边播,无损与 Hi-Res,逐字歌词与「律动」,刘海播放器。
Translation pending
The definitive Sturgill Simpson | Johnny Blue Skies & The Dark Clouds concert setlist archive
Translation pending
MediaJavaScript · PythonGitHub @dlevyOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
A full-stack web application for browsing and tracking Sturgill Simpson & Johnny Blue Skies concert setlists. Live at skysets.org.
Inspired by Crowesbase.com. Initial setlist data imported from setlist.fm.Read the full README ↗A full-stack web application for browsing and tracking Sturgill Simpson & Johnny Blue Skies concert setlists. Live at skysets.org.
Inspired by Crowesbase.com. Initial setlist data imported from setlist.fm.
profiles.role = 'editor')profiles.role = 'admin')| Layer | Technology |
|---|---|
| Frontend | React 19 + Vite (via rolldown-vite), Tailwind CSS, Porsche Design System v4 |
| Backend | Node.js + Express 5 (serverless on Vercel via api/[...path].js) |
| Database | Supabase (PostgreSQL) with Row Level Security |
| Auth | Supabase Auth (email/password) |
| Image processing | sharp — re-encodes uploads (lossless WebP for graphics, mozjpeg for photos) and generates gallery thumbnails |
| Maps | Leaflet / react-leaflet (attended-shows map) |
| Charts | Recharts (stats dashboard) |
| Deployment | Vercel (static frontend + one serverless API function) |
BlueskiesBase/
├── client/ # React frontend
│ └── src/
│ ├── components/
│ │ ├── SetlistEditor.jsx # Admin setlist builder
│ │ ├── SetlistPreview.jsx
│ │ ├── SetlistSubmissionSection.jsx
│ │ ├── NotesSection.jsx # Per-show community notes
│ │ ├── PhotosSection.jsx # Photo uploads per show
│ │ ├── PostersSection.jsx # Poster uploads per show (regular + foil)
│ │ ├── Avatar.jsx # Shared avatar-or-initials rendering
│ │ ├── BadgesPanel.jsx
│ │ ├── MainNavTabs.jsx # Top nav (horizontally scrollable on mobile)
│ │ ├── SongStatsWidget.jsx / TourStatsWidget.jsx / UserStatsWidget.jsx
│ │ ├── MostRecentShowWidget.jsx / UpcomingShowsWidget.jsx
│ │ ├── ShowMapShare.jsx # Shareable attended-shows map
│ │ ├── InstagramFollowBanner.jsx
│ │ ├── SEO.jsx / ErrorBoundary.jsx / ProtectedRoute.jsx
│ │ └── admin/
│ │ └── InstagramPostGraphic.jsx # Canvas-rendered Instagram post image
│ ├── contexts/
│ │ └── AuthContext.jsx # Supabase auth state, role/isAdmin/isEditorOrAdmin
│ ├── pages/
│ │ ├── SearchPage.jsx / HomePage.jsx # Main search + homepage
│ │ ├── ShowDetailPage.jsx # Individual show + setlist
│ │ ├── StatsPage.jsx / TourStatsPage.jsx
│ │ ├── PostersPage.jsx / PhotosPage.jsx
│ │ ├── LinksPage.jsx # Public links directory
│ │ ├── MembersPage.jsx # Member directory (login required)
│ │ ├── ProfilePage.jsx / EditProfilePage.jsx
│ │ ├── MemberLoginPage.jsx / SignupPage.jsx / ResetPasswordPage.jsx
│ │ └── admin/
│ │ ├── AdminLayout.jsx / AdminDashboard.jsx / AdminUsers.jsx
│ │ ├── ShowsList.jsx / ShowForm.jsx
│ │ ├── SongsList.jsx / SongForm.jsx
│ │ ├── AlbumsList.jsx / AlbumForm.jsx
│ │ ├── LinksList.jsx / LinkForm.jsx
│ │ ├── ToursList.jsx / TourEditPage.jsx
│ │ └── InstagramPostPage.jsx
│ └── services/
│ ├── api.js # Express API client
│ └── supabase.js # Supabase browser client
├── server/
│ ├── routes/
│ │ ├── shows.js / songs.js / venues.js / albums.js / bands.js
│ │ ├── search.js
│ │ ├── links.js # Links + link_categories
│ │ ├── notes.js / photos.js / posters.js
│ │ ├── setlist-submissions.js
│ │ ├── users.js # Profile, attendance, stats, directory
│ │ ├── admin.js # User management, roles, tour-style
│ │ └── sitemap.js
│ ├── middleware/
│ │ └── requireRole.js # requireAdmin / requireEditorOrAdmin
│ ├── utils/
│ │ ├── attendance.js / debuts.js / funStats.js / songStats.js
│ │ └── imageProcessing.js # sharp-based optimize + thumbnail helpers
│ └── config/
│ └── supabase.js # Supabase service-role client
├── api/
│ └── [...path].js # Vercel serverless entry point — mirrors app.js's route mounts
├── database/
│ ├── schema.sql # Original base schema + RLS policies
│ ├── seed_sample_data.sql
│ └── migrations/ # A couple of early one-off migrations
├── scripts/
│ ├── migrations/ # The actively-maintained migration history — run manually
│ │ └── *.sql # in the Supabase SQL Editor, in filename order
│ ├── backfill_thumbnails.js # One-off: generate thumbnails for existing posters/photos
│ ├── optimize_existing_images.js # One-off: re-compress existing full-size images
│ └── *.js / *.py # Assorted setlist.fm import/repair/verification scripts
├── app.js # Express server (local dev)
├── vercel.json
└── package.json
Clone the repo and install dependencies
git clone https://github.com/dlevy/BlueskiesBase.git
cd BlueskiesBase
npm install
cd client && npm install && cd ..
Configure environment variables
Copy .env.example to .env and fill in your credentials:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_KEY=your_service_role_key
Then create client/.env.local:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your_anon_key
Set up the database
In the Supabase SQL Editor, run in order:
database/schema.sql — base tables + RLS policiesdatabase/seed_sample_data.sql — optional sample datadatabase/migrations/, then everything in scripts/migrations/, in filename/date order — this is the real, actively-maintained migration history and is not optional; several features (editor roles, thumbnails, links, etc.) depend on columns/tables added here.Run the dev server
npm run dev:all
This starts both the Express API (localhost:3000) and the Vite dev server (localhost:5173) concurrently.
Note: The backend uses plain
node app.jswith no hot reload. Restart the server after any changes toserver/orapp.js.
All endpoints are prefixed /api/. Auth column: Public (no token), Auth (any signed-in user), Editor+ (requireEditorOrAdmin), Admin (requireAdmin).
/api/shows| Method | Path | Auth | Description |
|---|---|---|---|
| GET | / | Public | All shows (paginated, filterable by date range) |
| GET | /lookup | Public | Resolve a show ID from its URL slug parts |
| GET | /:id | Public | Single show with full setlist |
| GET | /:id/adjacent | Public | Previous/next show by date |
| GET | /:id/tour-rarity | Public | Per-song play-count rarity for the show's tour |
| GET | /:id/debuts | Public | Live/tour debut song IDs for this show |
| GET | /:id/attendees | Public | Members who marked this show attended (usernames only) |
| POST | /debuts-batch | Public | Debuts for many shows at once |
| POST | / | Editor+ | Create a show |
| PUT | /:id | Editor+ | Update a show |
| PATCH | /:id/tour | Editor+ | Reassign a show's tour only |
| PUT | /:id/setlist | Editor+ | Replace a show's entire setlist |
| POST | /:id/setlist/song | Editor+ | Add one song to a setlist |
| DELETE | /:showId/setlist/:setlistId | Editor+ | Remove one setlist row |
| DELETE | /:id | Admin | Delete a show and all dependent rows |
Standard CRUD under /api/songs, /api/albums, /api/venues, /api/bands — reads are public, create/update are Editor+, delete is Admin (venues/bands have no delete route). Albums additionally expose /api/albums/:id/songs for managing track order.
/api/links| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /categories | Public | List categories in display order |
| POST / PUT / DELETE | /categories, /categories/:id | Editor+ / Admin (delete) | Manage categories |
| GET | / | Public | All links, each with its category and optional associated member embedded |
| POST / PUT / DELETE | /, /:id | Editor+ / Admin (delete) | Manage links |
/api/search| Method | Path | Description |
|---|---|---|
| GET | /shows | Filter shows by year/month/day/venue/city/state/song/source/hasNotes/hasPhotos/hasPoster |
| GET | /songs | Filter songs by title/original |
/api/users| Method | Path | Auth | Description |
|---|---|---|---|
| GET/POST/DELETE | /attended-shows, /attended-shows/:showId | Auth | Manage the caller's attended shows |
| GET | /stats | Auth | Caller's personal stats |
| GET | /directory | Auth | Every member's public-safe fields (never email) |
| GET | /profile/:username | Public | A member's public profile |
| PUT | /profile | Auth | Update the caller's own opt-in profile fields |
| POST | /avatar | Auth | Upload/replace the caller's avatar |
| GET | /community-stats | Public | Site-wide member/photo/poster counts + top contributors |
/api/photos, /api/postersPublic reads (including /api/posters/collection and /api/posters/wants sub-resources for a member's own poster collection/wishlist, auth required); upload/update/delete require auth and ownership (or editor/admin to moderate). Uploads are auto-optimized and get a generated thumbnail.
/api/notes, /api/setlist-submissionsPublic reads, auth required to create/delete your own; submissions additionally support an admin/editor "merge into official setlist" action.
/api/admin (all Admin-only)| Method | Path | Description |
|---|---|---|
| GET | /users | List all users with role and confirmation status |
| POST | /users/:userId/resend-confirmation | Resend the activation email |
| POST | /users/:userId/send-password-reset | Trigger a password-reset email |
| PUT | /users/:userId/role | Assign member / editor / admin |
| DELETE | /users/:userId | Delete a user account |
| GET/PUT | /tour-style/:tourName | Instagram post style preset per tour (Editor+) |
| PUT | /tours/:tourName/rename | Rename a tour across every show in it |
| Table | Purpose |
|---|---|
profiles | Extends Supabase auth users — role (member/editor/admin), legacy is_admin, avatar/bio/location, social links, favorite show/venue, attendance-privacy toggle |
venues | Concert venues with city/state |
shows | Individual concerts — tour name, source types, opener (opened_for_id → bands), poster artist credit, links (JSONB) |
songs | Song catalog — is_original, cover attribution, writer credit |
albums / album_songs | Album catalog and its song ↔ album junction (track order) |
setlist_songs | Songs performed per show — set number, position, segue (jams_into), performance type (full/tease/partial) |
bands | Support acts |
link_categories / links | Admin-managed categories and external links for the public Links page; a link may optionally reference a profiles member |
user_shows | Shows a member attended |
user_notes | Per-show text notes |
user_photos | Photo uploads per show (full image + generated thumbnail) |
user_posters | Poster uploads per show, regular + foil variant (full image + generated thumbnail) |
user_poster_collection / user_poster_wants | A member's owned posters and wishlist |
setlist_submissions | Community-submitted setlists for shows missing an official one |
All tables have Row Level Security enabled as a defensive baseline, but the Express backend connects with the Supabase service-role key and bypasses RLS — the real authorization boundary is the requireAdmin/requireEditorOrAdmin Express middleware (server/middleware/requireRole.js), applied per-route.
The app is deployed on Vercel. The frontend is a static Vite build; the backend runs as a single serverless function (api/[...path].js) that mounts all the same Express routes as local app.js.
Important:
app.js(local dev) andapi/[...path].js(Vercel) each mount routes independently — adding a new route file to one and forgetting the other means it works locally but 404s in production. Always update both.
SUPABASE_URL
SUPABASE_SERVICE_KEY
VITE_SUPABASE_URL # build-time, prefixed VITE_
VITE_SUPABASE_ANON_KEY # build-time, prefixed VITE_
See DEPLOYMENT_GUIDE.md for the full Vercel setup walkthrough.
Pull requests are welcome. A few things to know before diving in:
app.js and api/[...path].js.exec_sql RPC. Every schema change is a plain .sql file added to scripts/migrations/ and run by hand in the Supabase SQL Editor — nothing applies it automatically.style={{ color: 'var(--p-color-contrast-low)' }} inline styles instead of color="contrast-low" prop — the prop value is invalid in this version.node app.js. Restart the server after any backend changes or your edits won't take effect.supabase.auth.getSession() for initial auth state — use onAuthStateChange only (see AuthContext.jsx for the pattern).cacheControl on upload does not change what Cache-Control header the public object endpoint actually serves (confirmed by direct testing) — don't rely on it for egress savings. Image size (via server/utils/imageProcessing.js) is what actually reduces egress.NOTIFY pgrst, 'reload schema'; if PostgREST doesn't pick up the change immediately.ISC