A platform for kendama instructors to share tutorial videos and for students to learn. Teach Niche enables instructors to monetize their expertise by selling bundled lesson packages with secure video content.
- Content Management: Create lessons and upload tutorial videos
- Monetization: Set prices for lesson packages (including free options)
- Stripe Connect: Receive payments directly to your Stripe account
- Dashboard: Track earnings, purchases, and lesson analytics
- Security: Content protected with secure access controls
- Discover Content: Browse lessons from expert kendama instructors
- Purchase Content: Buy complete lesson packages with secure checkout
- Personal Library: Access purchased content anytime in your library
- Secure Payments: Pay securely through Stripe
- Framework: Next.js 15 App Router
- Authentication: Supabase Auth
- Database: Supabase PostgreSQL
- Storage: Supabase Storage with RLS policies
- Payments: Stripe Connect + Webhooks
- UI: Tailwind CSS + shadcn/ui components
- Node.js 18+ and pnpm
- Supabase account and CLI
- Stripe account (with Connect capability)
- Stripe CLI for webhook testing
The project uses separate environments for development and production:
- Create a development environment by copying the example file:
pnpm setup:env
# Or manually: cp .env.development.example .env.development- Fill in your development environment values in
.env.development:
# Supabase Development Environment
NEXT_PUBLIC_SUPABASE_URL=your_dev_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_dev_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_dev_service_role_key
# Stripe Test Environment (Always use TEST MODE keys)
STRIPE_SECRET_KEY=sk_test_your_test_key
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_your_test_key
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret
# Other settings
NEXT_PUBLIC_SITE_URL=http://localhost:3000
See docs/environment-setup-guide.md for complete environment setup details.
- Clone the repository:
git clone https://github.com/jayminwest/TeachNicheV0.git
cd TeachNicheV0- Install dependencies:
pnpm install- Set up Stripe webhook forwarding in a separate terminal:
pnpm setup:stripe
# Or manually: stripe listen --forward-to localhost:3000/api/webhooks/stripe- Run the development server:
pnpm dev- Open http://localhost:3000 in your browser.
Detailed setup instructions are available in ai_docs/supabase_schema_setup.md. The main steps include:
- Run the migrations in the
supabase/migrationsdirectory - Set up secure storage buckets for videos with proper RLS policies
- Configure authentication providers and email templates
Use the admin setup page at /admin/setup to configure storage and RLS policies.
Detailed setup instructions are available in ai_docs/stripe_test_setup.md and docs/stripe-setup-guide.md. Key steps:
- Create a Stripe account and enable Connect
- Configure webhooks for payment events and account updates
- Use the test script at
scripts/setup-stripe-dev.shfor local webhook testing
- RLS policies for secure video access
- Server-side authentication and verification for purchases
- Secure video storage and delivery
- Video bucket security upgrade (see
supabase/migrations/20250426000000_fix_video_bucket_security.sql)
pnpm dev: Run development server with development environmentpnpm dev:prod: Run development server with production environmentpnpm build: Build production versionpnpm build:dev: Build with development environmentpnpm start: Start production serverpnpm lint: Run ESLintpnpm typecheck: Run TypeScript type checkerpnpm setup:stripe: Start Stripe webhook forwardingpnpm setup:env: Create development environment file from template
This project uses TypeScript for type safety, with database types generated from Supabase. Due to the Next.js 15 and Supabase integration, there are a few important notes about type handling:
-
Awaiting Supabase Client: In Next.js 15, the Supabase client from
createServerClient()returns a Promise that must be awaited before use:const supabase = await createServerClient()
-
Database Types: When working with database operations, use type assertions with the proper Database types:
.update({ field1: value1, field2: value2, } as Database["public"]["Tables"]["table_name"]["Update"])
-
Type Guards: When working with Supabase query results, use type guards to handle potential
nullor error return values:const { data, error } = await supabase.from("table").select("*") if (error || !data) { // Handle error return } // Now TypeScript knows data is not null const item = data[0]
-
Error Handling: For routes that use Supabase, always handle potential errors and provide appropriate HTTP status responses.
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Commit your changes:
git commit -m 'Add my feature' - Push to the branch:
git push origin feature/my-feature - Open a pull request