Secure, Self-Destructing Message Sharing Service. Chingu Voyage Tier 3 (Fullstack) Submission
- Deployed App: https://flash-paper-zeta.vercel.app/
- Repository: https://github.com/Direwen/Flash-Paper
| Home | Dashboard |
|---|---|
![]() |
![]() |
| View (Locked) | View (Success) | View (Expired) |
|---|---|---|
![]() |
![]() |
![]() |
| Encryption Flow | About | Mobile |
|---|---|---|
![]() |
![]() |
![]() |
To test the Dashboard and Protected Routes, use this account:
- Email:
test@gmail.com - Password:
password
FlashPaper is a secure "Pastebin" alternative designed for sending sensitive data (passwords, API keys, config files) over insecure channels.
FlashPaper uses server-side encryption with AES-256-GCM to protect your data at rest. When you create a secret, the backend encrypts it before storing in the database. Combined with self-destruction policies, your sensitive data is protected from database breaches and automatically purged after use.
- 🔥 Self-Destruction: Snippets can be set to "burn" after 1 view or specific time limits.
- 🔒 Row-Level Locking: Uses PostgreSQL
FOR UPDATElocks to strictly enforce view limits, preventing race conditions even under high concurrency. - 🧹 The Janitor: A background Go routine that continuously monitors and scrubs expired records from the database.
- 📊 Dashboard: Authenticated users can track the status of their active secrets (Active vs. Burnt).
- 📱 Responsive UI: Built with Nuxt 3 and TailwindCSS, fully optimized for mobile and desktop.
The system uses PostgreSQL hosted on Neon. We strictly enforce referential integrity and use indices for the Janitor process.
erDiagram
USERS ||--o{ SNIPPETS : "owns"
USERS {
uuid id PK
string email UK
string password
timestamp created_at
timestamp updated_at
}
SNIPPETS {
uuid id PK
uuid user_id FK "Nullable"
string content "AES-256 Encrypted Blob"
string title
string language
int current_views
int max_views
timestamp expires_at "Indexed for Janitor"
timestamp created_at
}
The core complexity lies in the "Reveal & Burn" logic. To ensure a secret with MaxViews: 1 is viewed exactly once, we wrap the read operation in a transaction with a Row Lock.
- Language: Go (Golang) 1.23
- Framework: Gin Web Framework
- ORM: GORM
- Database: PostgreSQL (Neon Tech)
- Authentication: JWT (JSON Web Tokens)
- Deployment: Docker Container on Koyeb
- Framework: Nuxt 3 (Vue.js)
- Styling: TailwindCSS + MazUI
- State Management: Pinia
- Deployment: Vercel
Tier 3 requires CRUD, but FlashPaper implements CRD (Create, Read, Delete). The "Update" operation is intentionally omitted for security integrity. Once a secret is encrypted and armed, allowing modifications would break the chain of trust and potentially allow an attacker to swap the ciphertext.
All secrets are encrypted on the backend using AES-256-GCM before being stored in the database. The encryption key is managed server-side via environment variables. This protects data at rest—if the database is compromised, attackers only see encrypted blobs, not plaintext secrets.
The dashboard uses Nuxt's lazy: true and dedupe: 'defer' configuration. This ensures the UI renders immediately without blocking hydration, preventing "infinite loading" states on slower networks.
You can run the entire stack locally using Docker Compose.
- Docker & Docker Compose
- Node.js (for frontend development)
git clone https://github.com/Direwen/Flash-Paper.git
cd Flash-PaperBackend (flashpaper/.env):
# Server
PORT=8080
# Database (for local Docker setup)
DB_HOST=localhost
DB_USER=flashuser
DB_PASSWORD=flashpassword
DB_NAME=flashpaper_local
DB_PORT=5432
DB_SSLMODE=disable
# Or use a connection string for hosted DB (e.g., Neon)
DB_URL=postgresql://user:password@host/dbname?sslmode=require
# Security
JWT_SECRET=your-secret-key-here
ENCRYPTION_KEY=your-32-byte-encryption-key
# App Config
CLIENT_URL=http://localhost:3000
JANITOR_INTERVAL=10s
TOKEN_EXPIRATION=24hFrontend (client/.env):
NUXT_PUBLIC_API_BASE=http://localhost:8080This spins up a local Postgres instance and the Go API.
cd flashpaper
docker-compose -f docker-compose.local.yml up --buildThe API will be available at http://localhost:8080.
In a new terminal:
cd client
npm install
npm run devThe App will be available at http://localhost:3000.
This project is open source and available under the MIT License.
Built with ❤️ by Direwen







