NBA Feed
Your teams' news and games, with scores hidden until you reveal them.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A full-stack workout logging application with cloud storage (Supabase/Postgres) and optional native mobile builds (Capacitor).
• Frontend: React 18 + TypeScript + Vite
• Backend: Node.js + Express + TypeScript
• Database: PostgreSQL via Supabase
• Auth: Supabase Auth (JWT verified server-side on all API routes)
• Native: Capacitor (iOS/Android) with local SQLite for offline use
• Node.js 18 or later
• npm 9 or later
• A Supabase project (free tier works fine)
This installs dependencies for both the client and server workspaces via npm workspaces.README 전문 보기 ↗A full-stack workout logging application with cloud storage (Supabase/Postgres) and optional native mobile builds (Capacitor).
git clone https://github.com/your-username/workout-logger.git
cd workout-logger
npm install
This installs dependencies for both the client and server workspaces via npm workspaces.
Copy the root env example and fill in your Supabase credentials:
cp .env.example .env
Edit .env:
DATABASE_URL=postgresql://postgres:[password]@db.[project-ref].supabase.co:5432/postgres
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key
PORT=3001
CLIENT_ORIGIN=http://localhost:5173
Copy the client env example:
cp client/.env.example client/.env
Edit client/.env:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key
VITE_API_URL=http://localhost:3001
Apply the schema to your Supabase Postgres database:
cd server && npm run migrate
This runs all SQL files in server/src/db/migrations/ in order, tracking applied migrations in a schema_migrations table.
Start both the backend and frontend together:
npm run dev
Or run them separately:
npm run server # Express API on http://localhost:3001
npm run client # Vite dev server on http://localhost:5173
In your Supabase dashboard: Authentication > Providers > Email — ensure it is enabled. For local development you may want to disable email confirmation under Authentication > Settings.
RLS policies are defined in supabase/migrations/. Run these in the Supabase SQL Editor if you want RLS enforced at the database level (optional — the Express API enforces user scoping via JWT on every query).
workout-logger/
├── package.json # Workspace root — runs both client and server
├── .env.example # Server environment variables template
│
├── server/
│ ├── package.json
│ ├── tsconfig.json
│ └── src/
│ ├── index.ts # Express app entry point + global error handler
│ ├── db/
│ │ ├── postgres.ts # Pool init and connection
│ │ ├── migrate.ts # Migration runner (npm run migrate)
│ │ └── migrations/
│ │ ├── 001_initial_schema.sql
│ │ ├── 002_seed_exercises.sql
│ │ ├── 003_templates.sql
│ │ └── 004_workout_exercise_metadata.sql
│ ├── middleware/
│ │ ├── auth.ts # JWT verification via Supabase, attaches req.userId
│ │ └── asyncHandler.ts # Wraps async handlers, forwards errors to Express
│ └── routes/
│ ├── workouts.ts # CRUD for workouts, workout_exercises, and metadata
│ ├── exercises.ts # CRUD for exercises
│ ├── sets.ts # CRUD for sets
│ └── templates.ts # Workout templates (save, apply, delete)
│
├── client/
│ ├── package.json
│ ├── capacitor.config.ts # Capacitor native build config
│ ├── tsconfig.json
│ ├── vite.config.ts
│ ├── index.html
│ ├── .env.example
│ └── src/
│ ├── main.tsx
│ ├── App.tsx # Router, auth state, UnitsProvider
│ ├── index.css # Global dark theme styles
│ ├── lib/
│ │ ├── api.ts # API layer — Supabase direct (web) or SQLite (native)
│ │ ├── auth.ts # Supabase auth helpers
│ │ ├── supabase.ts # Supabase client instance
│ │ ├── sqlite.ts # Capacitor SQLite init (native only)
│ │ ├── migrations.ts # Native SQLite migration runner
│ │ ├── sync.ts # Supabase sync helpers (native only)
│ │ └── audio.ts # Web Audio API tone generator for tempo timer
│ ├── hooks/
│ │ ├── useTempoTimer.ts # Tempo phase cycling and countdown logic
│ │ ├── useDialog.ts # Promise-based in-app confirm/prompt dialogs
│ │ └── useNetwork.ts # Online/offline detection
│ ├── contexts/
│ │ └── UnitsContext.tsx # Metric/imperial preference (localStorage)
│ ├── components/
│ │ ├── Nav.tsx # Top navigation bar
│ │ ├── Dialog.tsx # In-app modal (replaces window.confirm/prompt)
│ │ ├── ExercisePicker.tsx
│ │ ├── TemplatePicker.tsx
│ │ ├── SetRow.tsx # Inline editable set row
│ │ └── OfflineBanner.tsx
│ └── pages/
│ ├── Login.tsx
│ ├── Dashboard.tsx # Overview, recent workouts, stats
│ ├── WorkoutHistory.tsx # Full workout list
│ ├── NewWorkout.tsx # Create a new workout session
│ ├── WorkoutDetail.tsx # Log exercises, sets, and tempo timer
│ ├── ExerciseLibrary.tsx # Browse and create custom exercises
│ ├── Templates.tsx # Workout templates
│ ├── Charts.tsx # Historical progress charts
│ └── Settings.tsx # Metric/imperial toggle
│
└── supabase/
└── migrations/ # Postgres schema + RLS policies (for Supabase SQL Editor)
All endpoints (except /api/health) require a Authorization: Bearer <token> header. Requests are scoped to the authenticated user — no user can access another user's data.
| Method | Path | Description |
|---|---|---|
| GET | /api/health | Health check |
| GET | /api/workouts | List workouts for the authenticated user |
| GET | /api/workouts/:id | Get workout with exercises and sets |
| POST | /api/workouts | Create a new workout |
| PUT | /api/workouts/:id | Update a workout |
| DELETE | /api/workouts/:id | Delete a workout |
| POST | /api/workouts/:id/exercises | Add an exercise to a workout |
| DELETE | /api/workouts/exercises/:weId | Remove an exercise from a workout |
| PATCH | /api/workouts/exercises/:weId/metadata | Update exercise metadata (e.g. tempo) |
| GET | /api/exercises | List global + user's custom exercises |
| POST | /api/exercises | Create a custom exercise |
| PUT | /api/exercises/:id | Update a custom exercise |
| DELETE | /api/exercises/:id | Delete a custom exercise |
| GET | /api/sets?workout_exercise_id= | List sets for a workout exercise |
| POST | /api/sets | Log a new set |
| PUT | /api/sets/:id | Update a set |
| DELETE | /api/sets/:id | Delete a set |
| GET | /api/templates | List workout templates |
| POST | /api/templates/from-workout/:workoutId | Save a workout as a template |
| POST | /api/templates/:id/apply | Create a workout from a template |
| DELETE | /api/templates/:id |
cd client
npm run build
npx cap sync
npx cap open ios # or android
On native, the app uses a local SQLite database instead of the Express API. Migrations run automatically on first launch.
npm run build
This compiles the server TypeScript to server/dist/ and builds the client to client/dist/.
To run the compiled server:
cd server && node dist/index.js
| Delete a template |