npm create svelte@latest my-app
cd my-app
npm install
npm run dev
BOOTSTRAP
npm install bootstrap
src/routes/+layout.svelte
<script>
import "bootstrap/dist/css/bootstrap.min.css"
</script>
<slot />
MySQL2
npm install mysql2
bcryptjs
npm install bcryptjs
jwt
npm install jsonwebtoken
SweetAlert2
npm install sweetalert2
DATABASE
CREATE DATABASE svelte;
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
passcode VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL
);
Dummy data
INSERT INTO users (email, name, passcode, password)
VALUES
('user1@example.com', 'Alice Smith', 'passcode1', 'password1'),
('user2@example.com', 'Bob Johnson', 'passcode2', 'password2'),
('user3@example.com', 'Charlie Mat', 'passcode3', 'password3'),
('user4@example.com', 'Diana Peter', 'passcode4', 'password4'),
('user5@example.com', 'Evan Wright', 'passcode5', 'password5');
src\lib\server\db.js
import mysql from 'mysql2/promise';
export const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: '',
database: 'svelte',
});
src\lib\server\utils.js
export function validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
src\routes\register\+page.server.js
import bcrypt from 'bcryptjs';
import { pool } from '$lib/server/db';
import { validateEmail } from '$lib/server/utils';
export const actions = {
register: async ({ request }) => {
//FORM DATA
const formData = await request.formData();
const name = formData.get('name');
const email = formData.get('email');
const password = formData.get('password');
//console.log('Received data:', { name, email, password });
//VALIDATION 1
if (!name || !email || !password) {
return {
status: 400,
isError: true,
errorMsg: 'All fields are required',
name, email, password
};
}
//VALIDATION 2
if (!validateEmail(email)) {
return {
status: 400,
isError: true,
errorMsg: 'Invalid email address',
email, password
};
}
try {
//VALIDATION 3
const [emailCheck] = await pool.execute('SELECT * FROM users WHERE email = ?', [email]);
if (emailCheck.length > 0) {
return {
status: 400,
isError: true,
errorMsg: 'Email already exists',
name, email, password
};
}
//BCRYPT
const hashPassword = await bcrypt.hash(password, 12);
//ACTION
const [rows] = await pool.execute('INSERT INTO users (name, email, passcode, password) VALUES (?, ?, ?, ?)',
[name, email, password, hashPassword]
);
return {
status: 201,
isSuccess: true,
successMsg: 'User registered successfully. Please login',
userId: rows.insertId
};
} catch (error) {
console.error(error);
return {
status: 500,
isError: false,
errorMsg: 'Database error while registering user',
name, email, password
};
}
}
};
src\routes\register\+page.svelte
<script>
import { enhance } from '$app/forms';
let isLoading = false
export let form
</script>
<main class="bg-dark text-white" style="min-height:100vh">
<section class="container">
<h3 class="text-center py-5 text-info">User Registration</h3>
<div class="row justify-content-center">
<div class="col col-lg-4">
<form method="post" action="?/register"
use:enhance={()=>{
isLoading = true;
form.isError = false;
return async ({ update }) => {
await update();
isLoading = false;
};
}}>
<div class="mb-4">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control form-control-sm" id="name" name="name" value={form?.name??""}>
</div>
<div class="mb-4">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control form-control-sm" id="email" name="email" value={form?.email??""}>
</div>
<div class="mb-5">
<label for="password" class="form-label">Password</label>
<input type="text" class="form-control form-control-sm" id="password" name="password" value={form?.password??""}>
</div>
<a class="btn btn-secondary btn-sm" href="/">Back</a>
<button type="submit" class="btn btn-primary btn-sm">Register</button>
</form>
{#if isLoading}
<div class="d-flex justify-content-center mt-3">
<div class="spinner-border text-white" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
{/if}
{#if form?.isError}
<p class="text-warning text-center mt-3">{form?.errorMsg}</p>
{/if}
</div>
</div>
</section>
</main>
src\routes\login\+page.server.js
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { pool } from '$lib/server/db';
import { validateEmail } from '$lib/server/utils';
export const actions = {
login: async ({ cookies, request }) => {
//FORM DATA
const formData = await request.formData();
const email = formData.get('email');
const password = formData.get('password');
console.log('Received data:', { email, password });
//VALIDATION
if ( !email || !password) {
return {
status: 400,
isError: true,
errorMsg: 'All fields are required',
email, password
};
}
//VALIDATION
if (!validateEmail(email)) {
return {
status: 400,
isError: true,
errorMsg: 'Invalid email address',
email, password
};
}
try {
//FETCH USER
const [rows] = await pool.execute('SELECT * FROM users WHERE email = ?', [email]);
if (rows.length === 0) {
return {
status: 400,
isError: true,
errorMsg: 'Email not found. Please register !',
email, password
};
}
const user = rows[0];
const hashPassword = user.password;
//BCRYPT COMPARE
const isMatch = await bcrypt.compare(password, hashPassword);
if ( !isMatch ) {
return {
status: 400,
isError: true,
errorMsg: 'Incorrect password',
email, password
};
}
//CREATE JWT TOKEN
const token = jwt.sign(
{ userId: user.id, email: user.email },
'SECRET TOKEN', // Your secret key
{ expiresIn: '1h' } // Token expires in 1 hour
);
//SET SESSION COOKIE
cookies.set("authToken", token, {
httpOnly: true,
secure: true,
path: "/",
});
return {
status: 200,
isSuccess: true,
successMsg: 'Login successful',
};
} catch (error) {
console.error(error);
return {
status: 500,
isError: false,
errorMsg: 'Database error during user login',
email, password
};
}
}
};
src\routes\login\+page.svelte
<script>
import { enhance } from '$app/forms';
let isLoading = false
export let form
const handleEnhance = () => {
isLoading = true;
if(form) form.isError = false
return async ({ update }) => {
await update();
isLoading = false;
};
};
</script>
<main class="bg-dark text-white" style="min-height:100vh">
<section class="container">
<h3 class="text-center py-5 text-info">Login to account</h3>
<div class="row justify-content-center">
<div class="col col-lg-4">
<form method="post" action="?/login" use:enhance={handleEnhance}>
<div class="mb-4">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control form-control-sm text-white border-1 bg-dark" id="email" name="email" value={form?.email??""}>
</div>
<div class="mb-5">
<label for="password" class="form-label">Password</label>
<input type="text" class="form-control form-control-sm text-white border-1 bg-dark" id="password" name="password" value={form?.password??""}>
</div>
<a class="btn btn-secondary btn-sm" href="/">Back</a>
<button type="submit" class="btn btn-primary btn-sm">Login</button>
</form>
{#if isLoading}
<div class="d-flex justify-content-center mt-3">
<div class="spinner-border text-white" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
{/if}
{#if form?.isError}
<p class="text-warning text-center mt-3">{form?.errorMsg}</p>
{/if}
</div>
</div>
</section>
</main>
src\routes\login\+page.server.js
*Use onload to automatically redirect after success login
It also prevent a successful user to back to login
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { pool } from '$lib/server/db';
import { validateEmail } from '$lib/server/utils';
import { redirect } from '@sveltejs/kit';
export const actions = {
login: async ({ cookies, request }) => {}
};
export const load = async ({ cookies }) => {
const authToken = cookies.get('authToken');
if (authToken) {
throw redirect(302, '/dashboard');
}
// If the authToken is not present, allow the user to access the login page
return {};
};
src\routes\dashboard\+page.server.js
import { redirect } from '@sveltejs/kit';
export const load = async ({ cookies }) => {
const authToken = cookies.get('authToken');
if (!authToken) {
throw redirect(302, '/login');
}
// If the authToken is present, you can fetch user data or perform other actions
const email = cookies.get('email');
const name = cookies.get('name');
return { email, name };
};
src\routes\dashboard\+page.svelte
<script>
export let data = {}
console.log(data)
</script>
<main class="bg-dark" style="min-height:100vh">
<section class="container">
<h5 class="text-center pt-5 text-white">Welcome: {data?.name ?? ''}</h5>
<h6 class="text-center mb-4 text-white">{data?.email ?? ''}</h6>
<nav class="text-center mb-5 ">
<a class="text-info" href="/">Account</a>
<a class="text-info" href="/">Read</a>
<a class="text-info" href="/">Update</a>
<a class="text-info" href="/">Delete</a>
<a class="text-white text-opacity-75" href="/logout">Logout</a>
</nav>
</section>
</main>
src\routes\dashboard\+page.svelte
*Update
<a class="text-info" href="/dashboard/readUser">Read</a>
src\routes\dashboard\readUser\+page.server.js
import { redirect } from '@sveltejs/kit';
import { pool } from '$lib/server/db'
export const load = async ({ cookies }) => {
//VALIDATE COOKIES
const authToken = cookies.get('authToken');
if (!authToken) { throw redirect(302, '/login' )}
//ACTION
try {
const [rows] = await pool.execute('SELECT * FROM users');
if (!rows) {
return {
status: 500,
isError: true,
errorMsg: 'Connection errors while reading database',
};
}
return {
status: 200,
isSuccess: true,
successMsg: 'Read database successful',
data: rows,
};
} catch (error) {
//console.error(error);
return {
status: 500,
isError: true,
errorMsg: 'Database error while registering user',
};
}
};
src\routes\dashboard\readUser\+page.svelte
<script>
export let data;
//console.log(data)
let rows = data.data
</script>
<main class="bg-dark text-white" style="min-height:100vh">
<section class="container">
<div class="row justify-content-center">
<div class="col col-lg-8">
<h3 class="pt-5 mb-4 text-white">READ MySQL</h3>
<div class="d-flex justify-content-end me-2">
<a class="text-white" href="/dashboard">Back</a>
</div>
<table class="table table-sm table-secondary mt-1 table-hover">
<thead class="table-primary">
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
</tr>
</thead>
<tbody>
{#each rows as row, idx}
<tr>
<td>{idx+1}</td>
<td>{row.name}</td>
<td>{row.email}</td>
</tr>
{/each}
</tbody>
</table>
</div>
</div>
</section>
</main>
src\routes\logout\+page.server.js
import { redirect } from '@sveltejs/kit';
export const actions = {
exeLogout: async({cookies})=>{
//GET NAME
const name = cookies.get('name');
//DELETE COOKIES
cookies.delete("authToken", { path: "/" });
cookies.delete("email", { path: "/" });
cookies.delete("name", { path: "/" });
console.log("Cookies after deletion:", cookies.getAll());
return{ successMsg: 'GOODBYE '+name.toUpperCase() }
},
};
export function load({cookies}) {
const authToken = cookies.get('authToken');
if (!authToken) throw redirect(302, "/")
}
src\routes\dashboard\+page.svelte
*Logout example form dashboard
<script>
import { enhance } from '$app/forms';
import Swal from 'sweetalert2';
import { goto } from '$app/navigation';
export let data = {}
console.log(data)
const handleEnhance = () => {
return async ({ result, update }) => {
await update();
Swal.fire({
position: "center",
icon: "success",
html: `<b>${result.data.successMsg}</b>`,
showConfirmButton: false,
timer: 2000,
})
.then(() => {
goto('/login');
});
};
};
</script>
<main class="bg-dark" style="min-height:100vh">
<section class="container">
<h5 class="text-center pt-5 text-white">Welcome: {data?.name ?? ''}</h5>
<h6 class="text-center mb-4 text-white">{data?.email ?? ''}</h6>
<nav class="text-center mb-5 ">
<a class="text-info" href="/">Account</a>
<a class="text-info" href="/dashboard/readUser">Read</a>
<a class="text-info" href="/">Update</a>
<a class="text-info" href="/">Delete</a>
<button class="btn btn-link text-info text-opacity-75 mb-1" form="logoutForm">
Logout
</button>
</nav>
</section>
</main>
<!-- DUMMY LOGOUT FORM -->
<form id="logoutForm" method="POST" action='/logout?/exeLogout' use:enhance={handleEnhance}>
</form>
src\routes\dashboard\+page.svelte
<a class="text-info" href="/dashboard/updateUser">Update</a>
Go to Database Wizard
Create Database Users: svelte5
Click Password Generator: zg&L_aF9fOC(
Click Create User button
Check ALL PRIVILEGES
Click Next Step to completed
Go to Manage My Databases
Go to Add User To Database
Select User : mlrguitm_svelte5
Select Database : mlrguitm_svelte5
Click Add
Go to phpMyAdmin
Select database: mlrguitm_svelte5
Run
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
passcode VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL
);
Dummy data
INSERT INTO users (email, name, passcode, password)
VALUES
('user1@example.com', 'Alice Smith', 'passcode1', 'password1'),
('user2@example.com', 'Bob Johnson', 'passcode2', 'password2'),
('user3@example.com', 'Charlie Mat', 'passcode3', 'password3'),
('user4@example.com', 'Diana Peter', 'passcode4', 'password4'),
('user5@example.com', 'Evan Wright', 'passcode5', 'password5');