1. Overview
The current AARIVON website is a static HTML site. While this works well for displaying information, adding dynamic features requires a database. This guide outlines the database architecture needed to power dynamic features such as:
- Student Login System - Secure authentication for enrolled students
- Course Management - Dynamic course listings, enrollment, and updates
- Testimonials - Store and manage student testimonials in a database
- Application Forms - Collect and manage course applications
- Contact Submissions - Store and track contact form submissions
Goal: Transition from a static HTML website to a dynamic, database-driven web application while maintaining the existing design and user experience.
2. Recommended Tech Stack
Based on AARIVON's needs as an educational platform, we recommend the following database technologies:
1 PostgreSQL (Primary Recommendation)
PostgreSQL is a powerful, open-source relational database. It is reliable, well-documented, and ideal for structured data like student records, courses, and applications.
- Pros: ACID compliance, complex queries, excellent performance, free
- Cons: Requires setup and maintenance on a server
- Best for: Full control over your database infrastructure
2 Supabase (Recommended for Startups)
Supabase is a managed PostgreSQL service that includes authentication, real-time updates, and an auto-generated REST API. This is our top recommendation for AARIVON.
- Pros: Free tier available, instant REST API, built-in auth, easy to set up
- Cons: Less control than self-hosted PostgreSQL
- Best for: Fast development, low maintenance, startups
- Free tier includes: 500MB database, unlimited API requests, up to 50,000 monthly active users
3 MongoDB (Alternative)
MongoDB is a document-based NoSQL database. It offers flexibility for unstructured data but is less ideal for relational data like course enrollments.
- Pros: Flexible schema, easy to get started
- Cons: Less suited for relational data, eventual consistency
- Best for: Projects with rapidly changing data structures
Our Recommendation: Start with Supabase. It gives you PostgreSQL power with zero maintenance overhead, built-in authentication, and an instant API.
3. Database Schema
The following tables define the core data structure for the AARIVON platform. Run these SQL statements in your Supabase SQL Editor or PostgreSQL console.
Users Table
Stores student and admin accounts with authentication details.
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(50) DEFAULT 'student',
name VARCHAR(255) NOT NULL,
phone VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_role ON users(role);
Courses Table
Stores all available courses with their details and pricing.
CREATE TABLE courses (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
slug VARCHAR(255) UNIQUE NOT NULL,
description TEXT,
duration VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
category VARCHAR(100),
featured BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO courses (title, slug, description, duration, price, category, featured)
VALUES
('Full Stack Data Science', 'full-stack-data-science',
'Complete data science program from basics to advanced',
'20 Weeks', 29999.00, 'Data Science', TRUE),
('Cloud Computing with AWS', 'cloud-computing-aws',
'Master AWS cloud services and infrastructure',
'16 Weeks', 24999.00, 'Cloud', FALSE);
Testimonials Table
Stores student testimonials and success stories.
CREATE TABLE testimonials (
id SERIAL PRIMARY KEY,
student_name VARCHAR(255) NOT NULL,
role VARCHAR(255),
company VARCHAR(255),
salary VARCHAR(50),
quote TEXT NOT NULL,
avatar_initials VARCHAR(5) DEFAULT 'AA',
active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO testimonials (student_name, role, company, salary, quote, avatar_initials)
VALUES
('Rahul Sharma', 'Data Analyst', 'Infosys', '8.5 LPA',
'AARIVON completely transformed my career. The hands-on training helped me land my dream job.',
'RS');
Team Members Table
Stores team member profiles displayed on the About page.
CREATE TABLE team_members (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
role VARCHAR(255) NOT NULL,
bio TEXT,
initials VARCHAR(5) DEFAULT 'AA',
active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO team_members (name, role, bio, initials)
VALUES
('Aarushi Mehta', 'Lead Data Science Instructor',
'Former senior data scientist at Google with 10+ years of industry experience.',
'AM');
Applications Table
Stores student applications for courses.
CREATE TABLE applications (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
phone VARCHAR(20),
course_interest VARCHAR(255),
message TEXT,
status VARCHAR(50) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Contacts Table
Stores contact form submissions from the website.
CREATE TABLE contacts (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
phone VARCHAR(20),
message TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Complete Schema (Run All at Once)
You can copy and run all tables together in the Supabase SQL Editor:
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(50) DEFAULT 'student',
name VARCHAR(255) NOT NULL,
phone VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS courses (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
slug VARCHAR(255) UNIQUE NOT NULL,
description TEXT,
duration VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
category VARCHAR(100),
featured BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS testimonials (
id SERIAL PRIMARY KEY,
student_name VARCHAR(255) NOT NULL,
role VARCHAR(255),
company VARCHAR(255),
salary VARCHAR(50),
quote TEXT NOT NULL,
avatar_initials VARCHAR(5) DEFAULT 'AA',
active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS team_members (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
role VARCHAR(255) NOT NULL,
bio TEXT,
initials VARCHAR(5) DEFAULT 'AA',
active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS applications (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
phone VARCHAR(20),
course_interest VARCHAR(255),
message TEXT,
status VARCHAR(50) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS contacts (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
phone VARCHAR(20),
message TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
4. Connecting to Frontend
There are two recommended approaches for connecting the frontend to the database:
Option A: Node.js/Express REST API
Create a backend server that handles API requests from the frontend.
const express = require('express');
const { createClient } = require('@supabase/supabase-js');
const app = express();
app.use(express.json());
const supabase = createClient(
'https://your-project.supabase.co',
'your-anon-key'
);
app.get('/api/courses', async (req, res) => {
const { data, error } = await supabase
.from('courses')
.select('*')
.eq('active', true);
if (error) return res.status(500).json({ error: error.message });
res.json(data);
});
app.post('/api/contact', async (req, res) => {
const { name, email, phone, message } = req.body;
const { data, error } = await supabase
.from('contacts')
.insert([{ name, email, phone, message }]);
if (error) return res.status(500).json({ error: error.message });
res.json({ success: true, message: 'Message sent successfully' });
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Option B: Next.js API Routes
If you are using Next.js for the frontend, you can create API routes directly within the framework.
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_ANON_KEY
);
export default async function handler(req, res) {
if (req.method === 'GET') {
const { data, error } = await supabase
.from('courses')
.select('*');
if (error) return res.status(500).json({ error: error.message });
return res.status(200).json(data);
}
res.status(405).json({ message: 'Method not allowed' });
}
5. Step-by-Step Setup
Follow these steps to set up your database and connect it to the AARIVON website:
1 Create a Supabase Account
- Go to https://supabase.com
- Click "Start your project" and sign up with your email or GitHub account
- Verify your email address
2 Create a New Project
- Click "New Project" in your Supabase dashboard
- Choose your organization (default is fine)
- Enter a project name:
AARIVON
- Set a secure database password (save this somewhere safe)
- Choose the region closest to your users (e.g., Mumbai for India)
- Click "Create new project" and wait 1-2 minutes
3 Run the Schema SQL
- In your project dashboard, click the "SQL Editor" tab on the left
- Click "New query"
- Copy the complete schema SQL from Section 3 above
- Paste it into the SQL Editor
- Click "Run" to execute all the CREATE TABLE statements
- Verify all tables were created by checking the "Table Editor" tab
4 Get Your API Keys
- Click the "Settings" icon (gear) in the left sidebar
- Go to "API" in the settings menu
- Copy the following values:
- Project URL (e.g.,
https://xxxxx.supabase.co)
- Anon/public key (starts with
eyJ...)
- Service role key (keep this secret - only for server-side use)
- Store these in a secure location - you will need them for the frontend connection
5 Connect from the Frontend
Install the Supabase JavaScript client in your project:
npm install @supabase/supabase-js
Then create a configuration file:
import { createClient } from '@supabase/supabase-js';
const SUPABASE_URL = 'https://your-project-url.supabase.co';
const SUPABASE_ANON_KEY = 'your-anon-key-here';
export const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
6. Sample API Calls
Here are practical examples of fetching and sending data from the frontend using JavaScript's fetch API:
Fetch All Courses
async function getCourses() {
const response = await fetch('https://your-project.supabase.co/rest/v1/courses?select=*&active=eq.true', {
method: 'GET',
headers: {
'apikey': 'your-anon-key',
'Authorization': 'Bearer your-anon-key'
}
});
const courses = await response.json();
console.log(courses);
return courses;
}
getCourses().then(courses => {
courses.forEach(course => {
console.log(`${course.title} - Rs ${course.price}`);
});
});
Submit a Contact Form
async function submitContact(formData) {
const response = await fetch('https://your-project.supabase.co/rest/v1/contacts', {
method: 'POST',
headers: {
'apikey': 'your-anon-key',
'Authorization': 'Bearer your-anon-key',
'Content-Type': 'application/json',
'Prefer': 'return=minimal'
},
body: JSON.stringify({
name: formData.name,
email: formData.email,
phone: formData.phone,
message: formData.message
})
});
if (response.ok) {
console.log('Contact form submitted successfully!');
return true;
} else {
console.error('Failed to submit contact form');
return false;
}
}
const formData = {
name: 'John Doe',
email: 'john@example.com',
phone: '+91 98765 43210',
message: 'I am interested in the Data Science course. Please contact me.'
};
submitContact(formData);
Submit a Course Application
async function submitApplication(applicationData) {
const response = await fetch(
'https://your-project.supabase.co/rest/v1/applications',
{
method: 'POST',
headers: {
'apikey': 'your-anon-key',
'Authorization': 'Bearer your-anon-key',
'Content-Type': 'application/json'
},
body: JSON.stringify(applicationData)
}
);
return response.ok;
}
submitApplication({
name: 'Priya Patel',
email: 'priya@example.com',
phone: '+91 99887 76655',
course_interest: 'Full Stack Data Science',
message: 'I want to enroll in the upcoming batch.'
});
Fetch Testimonials
async function getTestimonials() {
const response = await fetch(
'https://your-project.supabase.co/rest/v1/testimonials?select=*&active=eq.true&order=created_at.desc',
{
headers: {
'apikey': 'your-anon-key',
'Authorization': 'Bearer your-anon-key'
}
}
);
return await response.json();
}
7. Migration Path
Transitioning from a static HTML site to a dynamic, database-driven application should be done in phases to minimize risk:
1 Phase 1: Forms (Week 1-2)
- Set up Supabase project and database schema
- Connect the contact form to store submissions in the
contacts table
- Connect the application form to store submissions in the
applications table
- Add a simple admin page to view submissions
2 Phase 2: Authentication (Week 3-4)
- Implement Supabase Auth for student login/signup
- Create protected routes for student dashboard
- Add role-based access (student vs. admin)
- Update login page to use real authentication
3 Phase 3: Content Management (Week 5-6)
- Move courses data from HTML to the
courses table
- Move testimonials from HTML to the
testimonials table
- Move team members from HTML to the
team_members table
- Update frontend to fetch data dynamically from the database
- Create an admin dashboard to manage content
4 Phase 4: Learning Management System (Week 7-8)
- Add course enrollment functionality
- Create student dashboard with enrolled courses
- Add progress tracking
- Implement course content delivery (videos, assignments)
- Add certificate generation
8. Security Notes
Security is critical when working with databases and user data. Follow these guidelines:
1 Never Expose API Keys
The Supabase anon key is safe to use in frontend code. However, the service role key has admin privileges and should never be exposed in client-side code.
- Use environment variables for API keys
- Add
.env to your .gitignore file
- Never commit API keys to version control
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
2 Use Row Level Security (RLS)
Supabase provides Row Level Security (RLS) to control access at the database level. Enable RLS on all tables:
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE courses ENABLE ROW LEVEL SECURITY;
ALTER TABLE testimonials ENABLE ROW LEVEL SECURITY;
ALTER TABLE applications ENABLE ROW LEVEL SECURITY;
ALTER TABLE contacts ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Allow public read access"
ON courses FOR SELECT
USING (true);
CREATE POLICY "Users see own applications"
ON applications FOR SELECT
USING (auth.uid() = user_id);
3 Validate All Inputs
Always validate user input before sending it to the database. Never trust data from the client:
function validateContactForm(data) {
const errors = [];
if (!data.name || data.name.trim().length < 2) {
errors.push('Name must be at least 2 characters');
}
if (!data.email || !data.email.includes('@')) {
errors.push('Valid email is required');
}
if (!data.message || data.message.trim().length < 10) {
errors.push('Message must be at least 10 characters');
}
return errors.length === 0 ? null : errors;
}
4 Use HTTPS
Always serve your website over HTTPS, especially when handling login credentials and personal data:
- Supabase provides HTTPS by default for all API calls
- Ensure your frontend hosting also uses HTTPS
- Never send sensitive data over unencrypted HTTP connections
5 Additional Security Checklist
- Enable two-factor authentication (2FA) on your Supabase account
- Regularly rotate API keys (especially service role keys)
- Monitor database usage and set up alerts for unusual activity
- Keep Supabase client libraries updated to the latest version
- Use prepared statements or ORM to prevent SQL injection
- Rate-limit API endpoints to prevent abuse
- Log all admin actions for audit purposes
Remember: Security is not a one-time setup. Regularly review your security settings and stay updated on best practices.
This guide is maintained by the AARIVON Technical Team. Last updated: June 2026.