Discover how to launch a thriving subscription box service with Lovable. Our expert guide reveals essential steps and strategies to fuel your business growth.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Project Setup in Lovable
Create a new Lovable project using the Lovable dashboard. In your project file viewer, create three new files: one for the HTML markup (index.html), one for the CSS styling (subscription.css), and one for the JavaScript functionality (subscription.js).
index.html
in the root folder. Paste the following code into it:
Subscription Box Service
Subscribe to Our Box!
subscription.css
in the same project folder and insert the following styles:
/_ subscription.css _/
#subscription-container {
width: 300px;
margin: 0 auto;
text-align: center;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
#subscription-form input {
width: 100%;
padding: 8px;
margin: 10px 0;
box-sizing: border-box;
}
#subscription-form button {
padding: 10px 20px;
background-color: #007BFF;
color: #fff;
border: none;
cursor: pointer;
border-radius: 4px;
}
subscription.js
in the project root and insert the following code to handle the form submission:
/_ subscription.js _/
document.getElementById('subscription-form').addEventListener('submit', function(e) {
e.preventDefault();
var email = document.getElementById('email').value;
// Update the message div to inform the user
document.getElementById('message').innerText = 'Processing your subscription...';
// Use Lovable's built-in API call to process the subscription
lovable.post('/api/subscribe', { email: email }, function(response) {
if (response.success) {
document.getElementById('message').innerText = 'Subscription successful!';
} else {
document.getElementById('message').innerText = 'An error occurred. Please try again.';
}
});
});
Configuring Dependencies Without a Terminal
Since Lovable does not have a terminal for installing dependencies, you must declare dependencies within a configuration file. Create a file named lovable_config.json
in the root folder and include the following code. This informs Lovable which packages to use:
{
"dependencies": {
"lovable-api": "latest",
"express": "latest"
}
}
Creating Serverless Function for Subscription Processing
Lovable supports serverless functions to handle API requests. Create a new folder named functions
in your project. Inside this folder, create a file named subscribe.js
and add the following code. This simulates backend processing for subscription requests:
/_ File: functions/subscribe.js _/
module.exports = function(request, response) {
// Extract the email submitted in the request body
const { email } = request.body;
// Implement your subscription logic here, such as saving the email to a database
// For the purpose of this demo, we simply return a success response
response.json({ success: true, message: 'Subscription processed successfully.' });
};
Mapping the API Endpoint to Your Serverless Function
To connect your frontend API call with the serverless function, create a mapping file named lovable_routes.json
in the project root. Insert the following code:
{
"/api/subscribe": "functions/subscribe.js"
}
/api/subscribe
directly to your subscribe.js
function.
Testing Your Subscription Box Service
Making Further Adjustments
subscription.css
.functions/subscribe.js
.lovable\_config.json
file accordingly.
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.post('/api/subscribe', async (req, res) => {
try {
const { userId, subscriptionPlan, boxItems } = req.body;
if (!userId || !subscriptionPlan || !Array.isArray(boxItems)) {
return res.status(400).json({ error: 'Invalid payload' });
}
const subscription = {
userId,
subscriptionPlan,
boxItems: boxItems.map(item => ({
productId: item.productId,
quantity: item.quantity || 1,
customizations: item.customizations || {}
})),
createdAt: new Date(),
status: 'active'
};
// Simulated DB insertion; replace with actual DB logic
console.log('New subscription created:', subscription);
res.status(201).json({ message: 'Subscription successfully created', subscription });
} catch (err) {
res.status(500).json({ error: 'Internal server error' });
}
});
app.listen(3000, () => console.log('API server running on port 3000'));
const express = require('express');
const axios = require('axios');
const bodyParser = require('body-parser');
const crypto = require('crypto');
const app = express();
app.use(bodyParser.json());
app.post('/api/webhooks/lovable', async (req, res) => {
try {
const signature = req.headers['x-lovable-signature'];
const payload = JSON.stringify(req.body);
const secret = process.env.LOVABLE_WEBHOOK_SECRET;
const computedSignature = crypto.createHmac('sha256', secret).update(payload).digest('hex');
if (signature !== computedSignature) {
return res.status(401).json({ error: 'Invalid signature.' });
}
const eventType = req.body.type;
if (eventType === 'subscription.shipped') {
const shippingData = {
subscriptionId: req.body.data.subscriptionId,
trackingNumber: req.body.data.trackingNumber,
shippedAt: req.body.data.shippedAt
};
const shippingResponse = await axios.post(
'https://api.shippingpartner.com/notify',
shippingData,
{ headers: { 'Authorization': `Bearer ${process.env.SHIPPING_API_TOKEN}` } }
);
console.log('Shipping partner notified:', shippingResponse.data);
}
res.status(200).json({ received: true });
} catch (error) {
console.error('Webhook processing error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
app.listen(3000, () => console.log('Webhook listener running on port 3000'));
const { Router } = require('express');
const fetch = require('node-fetch');
const router = Router();
router.post('/api/subscription/cancel', async (req, res) => {
const { subscriptionId, userToken } = req.body;
if (!subscriptionId || !userToken) {
return res.status(400).json({ error: 'Missing subscriptionId or userToken' });
}
try {
const lovableResponse = await fetch('https://api.lovable.com/subscriptions/cancel', {
method: 'POST',
headers: {
'Authorization': `Bearer ${userToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ id: subscriptionId })
});
if (!lovableResponse.ok) {
const errorBody = await lovableResponse.text();
return res.status(502).json({ error: 'Failed to cancel subscription in Lovable', details: errorBody });
}
await updateLocalSubscriptionStatus(subscriptionId, 'cancelled');
res.status(200).json({ message: 'Subscription cancelled successfully.' });
} catch (err) {
res.status(500).json({ error: 'Internal server error', details: err.message });
}
});
async function updateLocalSubscriptionStatus(subscriptionId, status) {
// Placeholder for actual database update logic.
return new Promise((resolve) => setTimeout(resolve, 100));
}
module.exports = router;
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Introduction to Subscription Box Services
Prerequisites and Planning
Designing Your Subscription Model
Leveraging AI Code Generators
import openai
def generate_code(prompt):
response = openai.Completion.create(
engine="davinci-codex",
prompt=prompt,
max_tokens=150
)
return response.choices[0].text.strip()
generated_code = generate_code("Build a subscription management function")
print(generated_code)
Building the Core Platform
from flask import Flask, request, jsonify
app = Flask(name)
@app.route("/subscribe", methods=["POST"])
def subscribe():
data = request.get_json()
email = data.get("email")
# Add logic to process the subscription
return jsonify({"message": "Subscription successful for " + email}), 200
if name == "main":
app.run(debug=True)
Implementing Payment and Subscription Management
import stripe
stripe.api_key = "your_stripe_secret_key"
def create_subscription(customer_id, plan_id):
subscription = stripe.Subscription.create(
customer=customer_id,
items=[{"plan": plan_id}],
)
return subscription
Testing and Deployment
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.