Discover how to build a subscription system with v0. Follow our step-by-step guide for best practices in recurring billing and scalable solutions.

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
This guide explains how to build a basic subscription system using v0. The subscription system will allow users to subscribe, check their subscription status, and have their subscriptions managed. Because v0 does not have a terminal, all dependency management is handled by adding the appropriate configuration code directly.
v0 does not have a terminal, so installing dependencies is done by listing them in a configuration file. Create a file named dependencies.txt and add the following lines. This ensures that when the project runs, v0 installs these libraries automatically.
Flask==2.1.2
Werkzeug==2.1.2
Explanation: We are using Flask for web routing and Werkzeug for HTTP tools. Adjust the version numbers as needed.
This file contains the functions that manage user subscriptions. Create a file named subscription\_manager.py and insert the following code snippet.
from datetime import datetime, timedelta
// A simple in-memory store for subscriptions
subscriptions = {}
def addsubscription(userid, duration\_days):
"""Function to add a subscription for a user."""
enddate = datetime.now() + timedelta(days=durationdays)
subscriptions[userid] = enddate
return subscriptions[user\_id]
def issubscribed(userid):
"""Function to check if a user's subscription is still active."""
enddate = subscriptions.get(userid)
if end\_date is None:
return False
if datetime.now() > end\_date:
# Subscription expired
return False
return True
Explanation: The code creates functions to add subscriptions with a certain duration and to check if a user is subscribed. This uses a simple dictionary to store subscription end dates. In a production system, you would use a database.
Create a file named main.py. This file will use Flask to set up a basic web server with endpoints to subscribe a user and to check their subscription status. Insert the code snippet below into main.py.
from flask import Flask, request, jsonify
from subscriptionmanager import addsubscription, is\_subscribed
app = Flask(name)
// Endpoint to subscribe a user
@app.route("/subscribe", methods=["POST"])
def subscribe():
# Read user id and subscription duration from the request
data = request.get\_json()
userid = data.get("userid")
duration = data.get("duration", 30) # Default duration set to 30 days
if user\_id is None:
return jsonify({"error": "User ID is required"}), 400
# Add subscription for user
enddate = addsubscription(user\_id, duration)
return jsonify({"message": "Subscription added", "userid": userid, "expires": end\_date.isoformat()})
// Endpoint to check subscription status
@app.route("/status", methods=["GET"])
def status():
# Get the user id from query parameter
userid = request.args.get("userid")
if user\_id is None:
return jsonify({"error": "User ID is required"}), 400
subscribed = issubscribed(userid)
return jsonify({"userid": userid, "subscribed": subscribed})
// Entry point for the application. This is where the server starts.
if name == "main":
app.run(host="0.0.0.0", port=8080)
Explanation: Two endpoints are defined. The /subscribe endpoint accepts a POST request with a user ID and an optional subscription duration in days. The /status endpoint accepts a GET request that returns whether or not the user is currently subscribed.
If v0 requires any in-code dependency installation instructions, use a startup section in your main.py to verify dependencies. Although v0 automatically reads the dependencies.txt file, you can include this block at the top of your main.py to ensure that dependencies are recognized.
"""
The dependencies file (dependencies.txt) includes:
Flask==2.1.2
Werkzeug==2.1.2
These libraries are automatically installed by v0 when the project starts.
"""
Explanation: This text block reminds anyone reading the code that dependency management is handled via the file and by v0’s built-in installation process.
When you click the Run button on v0, the following actions occur:
dependencies.txt and installs Flask and Werkzeug.main.py starts and binds the server to host 0.0.0.0 on port 8080./subscribe and /status using v0’s built-in preview or by using an external tool such as a web browser or Postman.
To test the subscription system:
/subscribe with JSON data for user\_id and optionally duration./status with the user\_id as a query parameter.Example POST request JSON for subscribing a user:
{
"user\_id": "user123",
"duration": 60
}
Example GET request URL for checking subscription: /status?user\_id=user123.
This detailed guide showed how to build a basic subscription system with v0 by creating the necessary files, managing dependencies with a configuration file, and setting up web endpoints with Flask. With these steps, you have a foundational subscription system suitable for testing and further enhancement in a production environment.
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
const subscriptions = new Map();
function createSubscription(userId, plan, startDate) {
return {
id: Date.now().toString(),
userId,
plan,
startDate,
nextBillingDate: calculateNextBillingDate(startDate, plan),
status: 'active',
usage: {
apiCalls: 0,
limit: plan === 'premium' ? 1000 : 100
}
};
}
function calculateNextBillingDate(startDate, plan) {
const date = new Date(startDate);
date.setMonth(date.getMonth() + 1);
return date;
}
app.post('/api/subscription', (req, res) => {
const { userId, plan } = req.body;
if (!userId || !plan) {
return res.status(400).json({ error: 'Missing parameters: userId and plan are required.' });
}
const subscription = createSubscription(userId, plan, new Date());
subscriptions.set(subscription.id, subscription);
res.status(201).json(subscription);
});
app.get('/api/subscription/:id', (req, res) => {
const subscription = subscriptions.get(req.params.id);
if (!subscription) {
return res.status(404).json({ error: 'Subscription not found.' });
}
res.json(subscription);
});
app.post('/api/subscription/:id/usage', (req, res) => {
const subscription = subscriptions.get(req.params.id);
if (!subscription) {
return res.status(404).json({ error: 'Subscription not found.' });
}
const { apiCalls } = req.body;
if (typeof apiCalls !== 'number') {
return res.status(400).json({ error: 'apiCalls must be a number.' });
}
subscription.usage.apiCalls += apiCalls;
if (subscription.usage.apiCalls > subscription.usage.limit) {
subscription.status = 'limit\_exceeded';
}
res.json(subscription);
});
app.delete('/api/subscription/:id', (req, res) => {
const subscription = subscriptions.get(req.params.id);
if (!subscription) {
return res.status(404).json({ error: 'Subscription not found.' });
}
subscription.status = 'cancelled';
res.json(subscription);
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(Server running on port ${PORT}));
const express = require('express');
const bodyParser = require('body-parser');
const stripe = require('stripe')(process.env.STRIPESECRETKEY);
const app = express();
// Stripe requires the raw body to validate the webhook signature.
app.use('/webhook/stripe', bodyParser.raw({ type: 'application/json' }));
const subscriptionStore = new Map();
app.post('/webhook/stripe', (req, res) => {
const sig = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(
req.body,
sig,
process.env.STRIPEWEBHOOKSECRET
);
} catch (err) {
return res.status(400).send(Webhook Error: ${err.message});
}
const subscriptionData = event.data.object;
switch (event.type) {
case 'customer.subscription.created': {
const subscription = {
id: subscriptionData.id,
userId: subscriptionData.metadata.userId,
plan: subscriptionData.plan.id,
status: subscriptionData.status,
currentPeriodEnd: new Date(subscriptionData.currentperiodend \* 1000)
};
subscriptionStore.set(subscription.id, subscription);
break;
}
case 'customer.subscription.updated': {
if (subscriptionStore.has(subscriptionData.id)) {
const updatedSubscription = subscriptionStore.get(subscriptionData.id);
updatedSubscription.plan = subscriptionData.plan.id;
updatedSubscription.status = subscriptionData.status;
updatedSubscription.currentPeriodEnd = new Date(subscriptionData.currentperiodend \* 1000);
}
break;
}
case 'customer.subscription.deleted': {
subscriptionStore.delete(subscriptionData.id);
break;
}
default:
break;
}
res.json({ received: true });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(Stripe webhook listener running on port ${PORT}));
const Koa = require('koa');
const Router = require('@koa/router');
const bodyParser = require('koa-bodyparser');
const app = new Koa();
const router = new Router();
const subscriptions = new Map();
// Example subscription stored as:
// { id: '12345', userId: 'user1', plan: 'basic', planPrice: 20, billingCycleStart: '2023-10-01T00:00:00.000Z' }
function calculateProrationFee(currentPlanPrice, newPlanPrice, billingCycleStart, currentDate) {
const start = new Date(billingCycleStart);
const end = new Date(start);
end.setMonth(end.getMonth() + 1);
const cycleDuration = end - start;
const timeUsed = currentDate - start;
const remainingFraction = (cycleDuration - timeUsed) / cycleDuration;
return (newPlanPrice - currentPlanPrice) \* remainingFraction;
}
router.put('/api/subscription/:id/upgrade', async (ctx) => {
const subscription = subscriptions.get(ctx.params.id);
if (!subscription) {
ctx.status = 404;
ctx.body = { error: 'Subscription not found.' };
return;
}
const { newPlan, newPlanPrice } = ctx.request.body;
if (!newPlan || typeof newPlanPrice !== 'number') {
ctx.status = 400;
ctx.body = { error: 'Request must contain newPlan and newPlanPrice (number).' };
return;
}
const now = new Date();
const prorationFee = calculateProrationFee(
subscription.planPrice,
newPlanPrice,
subscription.billingCycleStart,
now
);
// Update subscription info with upgrade details and proration calculation.
subscription.plan = newPlan;
subscription.planPrice = newPlanPrice;
subscription.prorationFee = prorationFee;
subscriptions.set(subscription.id, subscription);
ctx.body = {
message: 'Subscription upgraded successfully.',
subscription
};
});
app.use(bodyParser());
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(4000, () => {
console.log('Koa server running on port 4000');
});

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
This guide explains how to build a basic subscription system (v0) in simple steps. A subscription system allows users to sign up, choose a subscription plan, process payments, and access content. The architecture usually includes modules for user management, subscription plan management, payment integration, and security controls.
def register\_user(email, password):
"""This function validates the user input and stores the user info in the database."""
// Check if both email and password are provided
if not email or not password:
return "Invalid input. Please provide both email and password"
// Place code here to store the user data securely in the database
return "User registered successfully"
result = register\_user("[email protected]", "strongpassword123")
print(result)
def subscribeuser(userid, planid, paymentdetails):
"""This function processes the subscription and integrates with a payment gateway."""
// Verify if the selected subscription plan is available
// Insert code here to process payment via the chosen payment gateway using payment\_details
// Update the user's subscription status in the database to indicate activation
return "Subscription activated successfully for user " + str(user\_id)
subscriptionstatus = subscribeuser(1, "basicplan", {"cardnumber": "1234567890123456", "expiry": "12/25"})
print(subscription\_status)
Following these steps and best practices will help you build a basic yet secure subscription system. This version (v0) serves as a foundation, which you can later enhance as your needs grow.
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Block quote
Ordered list
Unordered list
Bold text
Emphasis
Superscript
Subscript
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Block quote
Ordered list
Unordered list
Bold text
Emphasis
Superscript
Subscript
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Block quote
Ordered list
Unordered list
Bold text
Emphasis
Superscript
Subscript
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Block quote
Ordered list
Unordered list
Bold text
Emphasis
Superscript
Subscript

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Block quote
Ordered list
Unordered list
Bold text
Emphasis
Superscript
Subscript
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.