Skip to content

Commit 23ec7dc

Browse files
committed
feat: integrate footer component into dashboard, login, and onboarding pages, and update README documentation
1 parent db8d95b commit 23ec7dc

File tree

7 files changed

+181
-53
lines changed

7 files changed

+181
-53
lines changed

README.md

Lines changed: 158 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,37 @@
1-
# ElysiaJS Backup Plugin
1+
# @riligar/elysia-backup
22

3-
Elysia plugin for R2/S3 backup with a built-in UI dashboard. Uses native Bun S3 client for optimal performance.
3+
[![Open Source](https://img.shields.io/badge/Open%20Source-RiLiGar-blue)](https://riligar.click/)
4+
[![npm version](https://img.shields.io/npm/v/@riligar/elysia-backup.svg)](https://www.npmjs.com/package/@riligar/elysia-backup)
5+
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
46

5-
## Features
7+
> **An open source project by [RiLiGar](https://riligar.click/)**
68
7-
- 📁 Backup local directories to R2/S3
8-
- 🔄 Scheduled backups with cron expressions
9-
- 🖥️ Built-in UI dashboard
10-
- ⬇️ One-click restore
11-
- 🗑️ Delete remote backups
12-
- ⚙️ Runtime configuration
9+
A powerful Elysia plugin for R2/S3 backup with a beautiful built-in UI dashboard. Designed for Bun runtime with native S3 client for optimal performance.
1310

14-
## Installation
11+
## ✨ Features
12+
13+
- 📁 **Smart Backup** — Backup local directories to R2/S3 with file filtering
14+
- 🔄 **Scheduled Backups** — Cron-based automatic backups
15+
- 🖥️ **Beautiful Dashboard** — Modern UI with real-time status
16+
- 🔐 **Secure Authentication** — Session-based auth with 2FA/TOTP support
17+
- 🧭 **Guided Onboarding** — Multi-step setup wizard for first-time configuration
18+
- ⬇️ **One-Click Restore** — Easily restore files from backup
19+
- 🗑️ **Backup Management** — Delete old backups from the UI
20+
- ⚙️ **Runtime Configuration** — Update settings without restarting
21+
22+
## 📦 Installation
1523

1624
```bash
1725
bun add @riligar/elysia-backup
1826
```
1927

20-
## Usage
28+
### Peer Dependencies
29+
30+
```bash
31+
bun add elysia @elysiajs/html
32+
```
33+
34+
## 🚀 Quick Start
2135

2236
```javascript
2337
import { Elysia } from 'elysia'
@@ -26,60 +40,158 @@ import { r2Backup } from '@riligar/elysia-backup'
2640
const app = new Elysia()
2741
.use(
2842
r2Backup({
29-
bucket: process.env.R2_BUCKET,
30-
accessKeyId: process.env.R2_ACCESS_KEY_ID,
31-
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
32-
endpoint: process.env.R2_ENDPOINT,
3343
sourceDir: './data',
34-
prefix: 'backups/',
35-
extensions: ['.db', '.sqlite'],
36-
cronSchedule: '0 0 * * *', // Daily at midnight
37-
cronEnabled: true,
44+
configPath: './config.json',
3845
})
3946
)
4047
.listen(3000)
4148

42-
console.log('Server running at http://localhost:3000')
43-
console.log('Backup UI at http://localhost:3000/backup')
49+
console.log('🦊 Server running at http://localhost:3000')
50+
console.log('📦 Backup UI at http://localhost:3000/backup')
4451
```
4552

46-
## Configuration
53+
On first run, you'll be guided through an onboarding wizard to configure:
54+
55+
- Storage credentials (R2/S3)
56+
- Backup schedule
57+
- Admin authentication
58+
59+
## ⚙️ Configuration
60+
61+
### Plugin Options
4762

48-
| Option | Type | Required | Description |
49-
| ----------------- | -------- | -------- | ------------------------------------------------------ |
50-
| `bucket` | string || R2/S3 bucket name |
51-
| `accessKeyId` | string || R2/S3 Access Key ID |
52-
| `secretAccessKey` | string || R2/S3 Secret Access Key |
53-
| `endpoint` | string || R2/S3 Endpoint URL |
54-
| `sourceDir` | string || Local directory to backup |
55-
| `prefix` | string || Prefix for S3 keys (e.g., 'backups/') |
56-
| `extensions` | string[] || File extensions to include |
57-
| `cronSchedule` | string || Cron expression for scheduled backups |
58-
| `cronEnabled` | boolean || Enable/disable scheduled backups |
59-
| `configPath` | string || Path to save runtime config (default: './config.json') |
63+
| Option | Type | Required | Description |
64+
| ------------ | ------ | -------- | ------------------------------------------------------ |
65+
| `sourceDir` | string || Local directory to backup |
66+
| `configPath` | string || Path to save runtime config (default: `./config.json`) |
6067

61-
## API Endpoints
68+
### Runtime Configuration (via UI or config.json)
69+
70+
| Option | Type | Description |
71+
| ----------------- | -------- | ---------------------------------------------- |
72+
| `bucket` | string | R2/S3 bucket name |
73+
| `accessKeyId` | string | R2/S3 Access Key ID |
74+
| `secretAccessKey` | string | R2/S3 Secret Access Key |
75+
| `endpoint` | string | R2/S3 Endpoint URL |
76+
| `prefix` | string | Prefix for S3 keys (e.g., `backups/`) |
77+
| `extensions` | string[] | File extensions to include (empty = all files) |
78+
| `cronSchedule` | string | Cron expression for scheduled backups |
79+
| `cronEnabled` | boolean | Enable/disable scheduled backups |
80+
| `auth.username` | string | Admin username |
81+
| `auth.password` | string | Admin password |
82+
| `auth.totpSecret` | string | TOTP secret for 2FA (optional) |
83+
84+
## 🔌 API Endpoints
6285

6386
The plugin adds the following routes under `/backup`:
6487

65-
| Method | Path | Description |
66-
| ------ | --------------------- | --------------------- |
67-
| GET | `/backup` | UI Dashboard |
68-
| POST | `/backup/api/run` | Trigger manual backup |
69-
| GET | `/backup/api/files` | List remote files |
70-
| POST | `/backup/api/restore` | Restore a file |
71-
| POST | `/backup/api/delete` | Delete a remote file |
72-
| POST | `/backup/api/config` | Update configuration |
88+
### Pages
89+
90+
| Method | Path | Description |
91+
| ------ | -------------------- | ----------------------- |
92+
| GET | `/backup` | Dashboard UI |
93+
| GET | `/backup/login` | Login page |
94+
| GET | `/backup/onboarding` | First-time setup wizard |
95+
96+
### Authentication
97+
98+
| Method | Path | Description |
99+
| ------ | --------------------- | ----------------- |
100+
| POST | `/backup/auth/login` | Authenticate user |
101+
| POST | `/backup/auth/logout` | End session |
102+
103+
### Backup Operations
104+
105+
| Method | Path | Description |
106+
| ------ | --------------------- | --------------------------- |
107+
| POST | `/backup/api/run` | Trigger manual backup |
108+
| GET | `/backup/api/files` | List remote backup files |
109+
| POST | `/backup/api/restore` | Restore a specific file |
110+
| POST | `/backup/api/delete` | Delete a remote backup file |
111+
| POST | `/backup/api/config` | Update configuration |
112+
113+
### Two-Factor Authentication (TOTP)
114+
115+
| Method | Path | Description |
116+
| ------ | --------------------------- | ----------------------------- |
117+
| GET | `/backup/api/totp/status` | Check 2FA status |
118+
| POST | `/backup/api/totp/generate` | Generate new TOTP secret & QR |
119+
| POST | `/backup/api/totp/verify` | Verify and enable 2FA |
120+
| POST | `/backup/api/totp/disable` | Disable 2FA |
73121

74-
## Environment Variables Example
122+
## 🔐 Security Features
123+
124+
### Session-Based Authentication
125+
126+
- Secure session tokens with configurable expiration
127+
- HTTP-only cookies for session management
128+
- Automatic session cleanup
129+
130+
### Two-Factor Authentication (TOTP)
131+
132+
- Compatible with any authenticator app (Google Authenticator, Authy, etc.)
133+
- QR code for easy setup
134+
- Backup codes support
135+
136+
## 📂 Project Structure
137+
138+
```
139+
src/
140+
├── index.js # Main plugin entry
141+
├── assets/ # Static assets (favicon, logo)
142+
├── views/
143+
│ ├── LoginPage.js # Login page
144+
│ ├── DashboardPage.js # Main dashboard
145+
│ ├── OnboardingPage.js # Setup wizard
146+
│ ├── components/ # UI components
147+
│ │ ├── ActionArea.js
148+
│ │ ├── FilesTab.js
149+
│ │ ├── Footer.js
150+
│ │ ├── Head.js
151+
│ │ ├── Header.js
152+
│ │ ├── LoginCard.js
153+
│ │ ├── OnboardingCard.js
154+
│ │ ├── SecuritySection.js
155+
│ │ ├── SettingsTab.js
156+
│ │ └── StatusCards.js
157+
│ └── scripts/ # Client-side JavaScript
158+
│ ├── backupApp.js
159+
│ ├── loginApp.js
160+
│ └── onboardingApp.js
161+
```
162+
163+
## 🌍 Environment Variables Example
75164

76165
```env
166+
# Optional - for initial configuration
77167
R2_BUCKET=your-bucket-name
78168
R2_ACCESS_KEY_ID=your-access-key
79169
R2_SECRET_ACCESS_KEY=your-secret-key
80170
R2_ENDPOINT=https://your-account.r2.cloudflarestorage.com
81171
```
82172

83-
## License
173+
> **Note:** All configuration can be set via the onboarding wizard. Environment variables are optional.
174+
175+
## 📸 Screenshots
176+
177+
The dashboard provides:
178+
179+
- **Status Overview** — Cron status, next run time, bucket info
180+
- **Quick Actions** — Manual backup trigger with real-time feedback
181+
- **Files Browser** — View, restore, and delete backup files
182+
- **Settings** — Update storage and backup configuration
183+
- **Security** — Enable/disable 2FA
184+
185+
## 🤝 Contributing
186+
187+
Contributions are welcome! See our [GitHub repository](https://github.com/riligar-solutions/elysia-backup) for more information.
188+
189+
## 📄 License
190+
191+
MIT © [RiLiGar](https://riligar.click/)
192+
193+
---
84194

85-
MIT
195+
<p align="center">
196+
Made with ❤️ by <a href="https://riligar.click/">RiLiGar</a>
197+
</p>

src/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ export const r2Backup = initialConfig => app => {
191191
backupJob = new CronJob(
192192
config.cronSchedule,
193193
async () => {
194-
console.log('Running scheduled backup...')
195194
try {
196195
const now = new Date()
197196
const timestamp =

src/services/backup.service.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ export const createBackupService = getConfig => {
4747
}
4848
const key = config.prefix ? join(config.prefix, finalPath) : finalPath
4949

50-
console.log(`Uploading ${key}...`)
5150
await s3.write(key, fileContent)
5251
}
5352

src/views/DashboardPage.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { ActionArea } from './components/ActionArea.js'
1111
import { FilesTab } from './components/FilesTab.js'
1212
import { SettingsTab } from './components/SettingsTab.js'
1313
import { SecuritySection } from './components/SecuritySection.js'
14+
import { Footer } from './components/Footer.js'
1415
import { backupAppScript } from './scripts/backupApp.js'
1516

1617
export const DashboardPage = ({ config, jobStatus, hasAuth }) => `
@@ -48,6 +49,9 @@ export const DashboardPage = ({ config, jobStatus, hasAuth }) => `
4849
${SettingsTab()}
4950
${SecuritySection()}
5051
</div>
52+
53+
<!-- Footer -->
54+
${Footer()}
5155
</div>
5256
5357
${backupAppScript({ config, jobStatus })}

src/views/LoginPage.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
import { Head } from './components/Head.js'
88
import { LoginCard } from './components/LoginCard.js'
9+
import { Footer } from './components/Footer.js'
910
import { loginAppScript } from './scripts/loginApp.js'
1011

1112
export const LoginPage = ({ totpEnabled = false }) => `
@@ -14,8 +15,14 @@ export const LoginPage = ({ totpEnabled = false }) => `
1415
<head>
1516
${Head({ title: 'Login - Backup Manager' })}
1617
</head>
17-
<body class="bg-gray-50 min-h-screen flex items-center justify-center p-6 antialiased">
18-
${LoginCard({ totpEnabled })}
18+
<body class="bg-gray-50 min-h-screen flex flex-col items-center justify-center p-6 antialiased">
19+
<div class="flex-1 flex items-center justify-center w-full">
20+
${LoginCard({ totpEnabled })}
21+
</div>
22+
23+
<div class="w-full max-w-md">
24+
${Footer()}
25+
</div>
1926
2027
${loginAppScript({ totpEnabled })}
2128
</body>

src/views/OnboardingPage.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
import { Head } from './components/Head.js'
77
import { OnboardingCard } from './components/OnboardingCard.js'
8+
import { Footer } from './components/Footer.js'
89
import { onboardingAppScript } from './scripts/onboardingApp.js'
910

1011
export const OnboardingPage = ({ sourceDir }) => `
@@ -13,8 +14,14 @@ export const OnboardingPage = ({ sourceDir }) => `
1314
<head>
1415
${Head({ title: 'Setup - Backup Manager' })}
1516
</head>
16-
<body class="bg-gray-50 min-h-screen flex items-center justify-center p-6 antialiased">
17-
${OnboardingCard({ sourceDir })}
17+
<body class="bg-gray-50 min-h-screen flex flex-col items-center justify-center p-6 antialiased">
18+
<div class="flex-1 flex items-center justify-center w-full">
19+
${OnboardingCard({ sourceDir })}
20+
</div>
21+
22+
<div class="w-full max-w-2xl">
23+
${Footer()}
24+
</div>
1825
1926
${onboardingAppScript({ sourceDir })}
2027
</body>

src/views/components/Footer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* @returns {string} HTML string
55
*/
66
export const Footer = () => `
7-
<footer class="mt-12 pt-8 border-t border-gray-200 text-center">
7+
<footer class="pt-4 text-center">
88
<p class="text-sm text-gray-500">
99
Open source project by
1010
<a href="https://riligar.click/" target="_blank" rel="noopener noreferrer"

0 commit comments

Comments
 (0)