diff --git a/learner-management-system/.gitignore b/learner-management-system/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/learner-management-system/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/learner-management-system/index.html b/learner-management-system/index.html
new file mode 100644
index 0000000..44a9335
--- /dev/null
+++ b/learner-management-system/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + TS
+
+
+
+
+
+
diff --git a/learner-management-system/package.json b/learner-management-system/package.json
new file mode 100644
index 0000000..1ec2d6d
--- /dev/null
+++ b/learner-management-system/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "learner-management-system",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "preview": "vite preview"
+ },
+ "devDependencies": {
+ "typescript": "~5.7.2",
+ "vite": "^6.2.0"
+ }
+}
diff --git a/learner-management-system/public/vite.svg b/learner-management-system/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/learner-management-system/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/learner-management-system/src/counter.ts b/learner-management-system/src/counter.ts
new file mode 100644
index 0000000..09e5afd
--- /dev/null
+++ b/learner-management-system/src/counter.ts
@@ -0,0 +1,9 @@
+export function setupCounter(element: HTMLButtonElement) {
+ let counter = 0
+ const setCounter = (count: number) => {
+ counter = count
+ element.innerHTML = `count is ${counter}`
+ }
+ element.addEventListener('click', () => setCounter(counter + 1))
+ setCounter(0)
+}
diff --git a/learner-management-system/src/main.ts b/learner-management-system/src/main.ts
new file mode 100644
index 0000000..6396b50
--- /dev/null
+++ b/learner-management-system/src/main.ts
@@ -0,0 +1,24 @@
+import './style.css'
+import typescriptLogo from './typescript.svg'
+import viteLogo from '/vite.svg'
+import { setupCounter } from './counter.ts'
+
+document.querySelector('#app')!.innerHTML = `
+
+
+
+
+
+
+
+
Vite + TypeScript
+
+
+
+
+ Click on the Vite and TypeScript logos to learn more
+
+
+`
+
+setupCounter(document.querySelector('#counter')!)
diff --git a/learner-management-system/src/style.css b/learner-management-system/src/style.css
new file mode 100644
index 0000000..3bcdbd0
--- /dev/null
+++ b/learner-management-system/src/style.css
@@ -0,0 +1,96 @@
+:root {
+ font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+#app {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.vanilla:hover {
+ filter: drop-shadow(0 0 2em #3178c6aa);
+}
+
+.card {
+ padding: 2em;
+}
+
+.read-the-docs {
+ color: #888;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/learner-management-system/src/typescript.svg b/learner-management-system/src/typescript.svg
new file mode 100644
index 0000000..d91c910
--- /dev/null
+++ b/learner-management-system/src/typescript.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/learner-management-system/src/vite-env.d.ts b/learner-management-system/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/learner-management-system/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/learner-management-system/tsconfig.json b/learner-management-system/tsconfig.json
new file mode 100644
index 0000000..a4883f2
--- /dev/null
+++ b/learner-management-system/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["src"]
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..5e0a3b3
--- /dev/null
+++ b/package.json
@@ -0,0 +1,6 @@
+{
+ "dependencies": {
+ "argon2-browser": "^1.18.0",
+ "bootstrap": "5.3"
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..91d1741
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,39 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ argon2-browser:
+ specifier: ^1.18.0
+ version: 1.18.0
+ bootstrap:
+ specifier: '5.3'
+ version: 5.3.5(@popperjs/core@2.11.8)
+
+packages:
+
+ '@popperjs/core@2.11.8':
+ resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
+
+ argon2-browser@1.18.0:
+ resolution: {integrity: sha512-ImVAGIItnFnvET1exhsQB7apRztcoC5TnlSqernMJDUjbc/DLq3UEYeXFrLPrlaIl8cVfwnXb6wX2KpFf2zxHw==}
+
+ bootstrap@5.3.5:
+ resolution: {integrity: sha512-ct1CHKtiobRimyGzmsSldEtM03E8fcEX4Tb3dGXz1V8faRwM50+vfHwTzOxB3IlKO7m+9vTH3s/3C6T2EAPeTA==}
+ peerDependencies:
+ '@popperjs/core': ^2.11.8
+
+snapshots:
+
+ '@popperjs/core@2.11.8': {}
+
+ argon2-browser@1.18.0: {}
+
+ bootstrap@5.3.5(@popperjs/core@2.11.8):
+ dependencies:
+ '@popperjs/core': 2.11.8