A Full-Stack subscription system built with React, Express, Stripe, and SQLite. Features an application for subscription plans with secure payment processing.
https://www.loom.com/share/3bb83283fdf44b5b8140d384b13284c5?sid=a9ab6439-6977-4b5f-b4aa-da7a0732bceb
- Modern React Frontend with TypeScript and Tailwind CSS
- Express.js Backend with Stripe integration
- Secure Payment Processing via Stripe Checkout
- Real-time Webhook Processing for subscription events
- SQLite Database for subscription tracking
- Beautiful UI with responsive design and shadcn/ui components
- Complete Subscription Flow from signup to payment confirmation
Before running this application, ensure you have:
- Node.js (v18 or higher)
- npm or yarn
- SQLite installed (or use the in-project DB file)
- Stripe Account (for payment processing)
- ngrok (for webhook testing in development)
Note: While the initial prototype was built using MySQL, SQLite has been used in the current implementation due to its lightweight nature and similar querying style to MySQL.
git clone <your-repo-url>
cd subscription-system
npm installCopy the example environment file and configure your secrets:
cp .env.example .envEdit .env with your actual values (see Environment Variables section below).
On first run, SQLite will auto-create the database file (subscription.db) and tables if not present.
- Create a Stripe account at stripe.com
- Get your test API keys from the Stripe Dashboard
- Create product and price objects for your subscription plans
- Set up a webhook endpoint (see Webhook Setup section)
npm run devThe application will be available at http://localhost:8080
Configure these variables in your .env file:
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key_here
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here
STRIPE_BASIC_PRICE_ID=price_your_basic_plan_price_id
STRIPE_PRO_PRICE_ID=price_your_pro_plan_price_id
STRIPE_ENTERPRISE_PRICE_ID=price_your_enterprise_plan_price_idFRONTEND_URL=http://localhost:8080The application uses a simple SQLite schema:
CREATE TABLE subscriptions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE NOT NULL,
stripe_customer_id TEXT,
plan_name TEXT CHECK(plan_name IN ('Basic', 'Pro', 'Enterprise')) NOT NULL,
subscription_id TEXT,
subscription_status TEXT CHECK(subscription_status IN ('active', 'canceled', 'incomplete', 'incomplete_expired', 'past_due', 'trialing', 'unpaid')) DEFAULT 'incomplete',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);Timestamps are automatically updated using triggers in SQLite.
In your Stripe Dashboard:
- Go to Products β Add Product
- Create three products: "Basic", "Pro", "Enterprise"
- For each product, create a recurring price
- Copy the
price_xxxIDs to your.envfile
-
Go to Developers β Webhooks β Add endpoint
-
Endpoint URL:
https://your-domain.com/api/webhook(use ngrok for local development) -
Select these events:
checkout.session.completedinvoice.paidcustomer.subscription.updatedcustomer.subscription.deleted
-
Copy the webhook signing secret to your
.envfile
# Install ngrok
npm install -g ngrok
# Expose your local server
ngrok http 8080
# Use the ngrok HTTPS URL for your Stripe webhook endpoint
# Example: https://abc123.ngrok.io/api/webhookPOST /api/create-checkout-sessionβ Create Stripe checkout sessionGET /api/subscription-status/:emailβ Get subscription detailsPOST /api/webhookβ Handle Stripe webhooks
GET /api/pingβ Server health check
/β Main subscription page with pricing plans/successβ Payment success confirmation/dashboardβ Subscription status checker
Run tests with:
npm testBuild for production:
npm run build
npm start- Never commit real API keys to version control
- Use Stripe's test mode during development
- Validate webhook signatures for security
- Implement proper error handling and logging
- Use HTTPS in production
- User visits homepage β Sees pricing plans
- User selects plan β Enters email and chooses plan
- User clicks Subscribe β Redirected to Stripe Checkout
- User completes payment β Redirected to success page
- Webhook processes event β Updates database with subscription status
- User can check status β Via dashboard page with email lookup