SecureVault is a secure file-storage application built with product depth, not just UI polish. It combines encrypted-at-rest uploads, resumable large-file handling, controlled sharing, lifecycle management, and optional semantic search in a single Next.js workspace.
For external reviewers, the central point is simple: this is not a toy upload form. SecureVault already implements the harder product and systems features that make storage software credible.
Published documentation: https://mariadb-hackathon-my-2026.github.io/securevault/
For the full product screenshot gallery, see docs/product/ui-showcase.md.
The repository docs are now structured as a VitePress site in docs/ so they can publish cleanly to GitHub Pages through GitHub Actions.
- docs homepage:
docs/index.md - local setup guide:
docs/getting-started/local-development.md - architecture handbook:
docs/architecture/project-handbook.md - API reference:
docs/reference/api.md - benchmark workflows:
docs/testing/benchmarks.md
- Encrypted-at-rest file handling with a layered key model instead of plain object storage uploads.
- Resumable chunked uploads with queue controls, retry handling, and server-aware concurrency limits.
- File and folder sharing with public and restricted links, OTP verification, secure shared PDF image preview, download caps, and access logging.
- Operational lifecycle features including trash, restore, permanent delete, storage dashboards, and activity feeds.
- Optional semantic indexing for eligible PDFs and images, so AI search enhances the product instead of defining it.
- Real engineering surface area: documented architecture, Docker workflows, Vitest coverage, and a sizable Playwright suite.
| Area | Current capability |
|---|---|
| Authentication | Signup, login, secure session cookies, forgot-password OTP reset |
| File ingestion | Chunked uploads, resume flows, upload queue controls, encrypted storage in Cloudflare R2 |
| Workspace | File explorer, folders, search, preview, download, rename, move, bulk actions |
| Sharing | Public links, restricted links, email allowlists, OTP unlock, secure shared PDF image preview, download limits, access logs |
| Lifecycle | Trash, restore, permanent delete, cleanup flows, storage visibility, activity timeline |
| AI search | Optional semantic indexing and semantic search for supported PDFs and images |
SecureVault sits in a useful middle ground between a portfolio demo and a production-minded system design exercise.
- It is opinionated about security: encrypted at rest, scoped access, rate limiting, secure cookies, and hardened response headers.
- It is opinionated about product behavior: users can recover mistakes, share safely, audit access, and understand storage usage.
- It is opinionated about AI: semantic indexing is additive, gated, and non-blocking, so the storage product still works when AI is off.
Important scope note: SecureVault uses application-managed encryption at rest, not end-to-end encryption. Authorized server flows can decrypt files for preview, download, sharing, and indexing.
SecureVault is implemented as a Next.js App Router application backed by MariaDB, Redis, Cloudflare R2, and an optional embeddings provider.
MariaDBstores users, sessions, file metadata, sharing state, upload sessions, and indexing state.Cloudflare R2stores encrypted file chunks and related object assets.Redissupports rate limiting, upload-slot coordination, and optional queued indexing workflows.Geminior a fake local provider can power semantic indexing when enabled.
The real product experience lives in the authenticated dashboard under /files, /activity, /storage, /settings, and /trash.
This project does not use MariaDB as a passive record store. MariaDB is part of the product story.
- Relational ownership and lifecycle state live in one place: users, sessions, folders, files, shares, trash, quotas, activity, and indexing state.
- Security-sensitive flows such as OTP reset handling and share access governance depend on transactional database behavior and indexed lookups.
- Semantic search is still grounded in MariaDB through vector storage and cosine-distance ranking, so the AI layer stays integrated with the core storage product instead of living in a separate demo silo.
- The result is a more convincing hackathon system: MariaDB powers both the operational backbone and one of the differentiating features.
| Path | Purpose |
|---|---|
secure-vault/ |
Main Next.js application, API routes, schema, tests, Dockerfile |
docs/ |
VitePress-powered GitHub Pages docs source, organized by onboarding, architecture, operations, reference, testing, and product showcase |
resources/ |
Supporting references for security standards, external docs, and UI guidance |
tasks/ |
Phase-by-phase implementation breakdown |
implementation_plan.md |
Broader architecture and delivery blueprint |
The default local workflow runs the app on the host while MariaDB and Redis run through Docker Compose.
-
Install dependencies.
cd secure-vault npm install -
Create
secure-vault/.env.localfromsecure-vault/.env.example. -
Set the minimum required values.
DATABASE_HOST=127.0.0.1 DATABASE_PORT=3307 DATABASE_NAME=SecureVault DATABASE_USER=securevault DATABASE_PASSWORD=securevault MASTER_ENCRYPTION_KEY=<64-char hex key> R2_ACCOUNT_ID=<r2-account-id> R2_ACCESS_KEY_ID=<r2-access-key> R2_SECRET_ACCESS_KEY=<r2-secret> R2_BUCKET_NAME=<r2-bucket> NEXT_PUBLIC_APP_URL=http://127.0.0.1:3000 REDIS_URL=redis://127.0.0.1:6379 SEMANTIC_INDEXING_ENABLED=true SEMANTIC_INDEXING_EXECUTION_MODE=inline SEMANTIC_INDEXING_PROVIDER=google GEMINI_API_KEY=<gemini-api-key> GEMINI_EMBEDDING_MODEL=gemini-embedding-2-preview
Generate a master key with:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
-
Start MariaDB and Redis.
npm run dev:services
-
Apply the checked-in migrations.
npx drizzle-kit migrate -
Start the app.
npm run dev
- Real upload, preview, and download flows need valid
R2_*credentials. - For local runs without Redis-backed coordination, set
DISABLE_REDIS=true. - The documented local default keeps semantic indexing enabled with
SEMANTIC_INDEXING_EXECUTION_MODE=inline. - For local semantic indexing without an external Gemini key, use
SEMANTIC_INDEXING_PROVIDER=fake. - Shared PDF links can use the secure WebP preview flow when
SHARED_PDF_IMAGE_PREVIEW_ENABLED=true; on host-run Windows development, setSHARED_PDF_IMAGE_PREVIEW_RENDERER_PATHto yourpdftocairo.exepath if Poppler is not already onPATH. - If
RESEND_API_KEYis unset, OTP and email flows log locally instead of sending real email.
For the repo's canonical local setup flow, see docs/getting-started/local-development.md.
The repo-root compose.yaml supports two practical modes:
- dependency services only: MariaDB and Redis for normal local development
- full container stack:
webunder theappprofile, withworkeras an opt-in profile for queued semantic indexing
Use dependency services only:
cd secure-vault
npm run dev:servicesUse the full container stack:
docker compose --profile app up --buildThe app container installs poppler-utils, so pdftocairo is available for the secure shared PDF preview path when you run the full containerized stack.
Start the embeddings worker only when queued indexing is intentionally enabled:
docker compose --profile app --profile worker up --buildWarning
The worker path is only relevant when SEMANTIC_INDEXING_EXECUTION_MODE=queued, and inline execution is the more stable local path right now.
The current Docker build context also allows secure-vault/.env.local into the image path, so do not push or share locally built images that contain real secrets.
The container guide is in docs/operations/docker-compose.md.
From secure-vault/:
npm run lintnpm testnpm run test:e2enpm run test:e2e:managed
The automated coverage is meaningful across auth, uploads, sharing, trash, activity, storage search, and semantic indexing. CI currently runs lint plus Vitest, while Playwright remains a managed local suite.
See docs/testing/playwright.md for the detailed case matrix.
SecureVault also includes a benchmark package under secure-vault/benchmark/ with runnable scripts in secure-vault/scripts/benchmark/.
npm run benchmark:semanticmeasures semantic and hybrid retrieval latency after indexing is already complete.npm run benchmark:semantic:pipelinemeasures end-to-end semantic indexing and retrieval quality with the Google embedding provider.
The new benchmark guide explains prerequisites, commands, output files, and how to read the reports: docs/testing/benchmarks.md.
- Next.js 16 App Router
- React 19
- TypeScript
- Drizzle ORM
- MariaDB
- Redis
- Cloudflare R2
- Resend
- Optional Gemini-powered embeddings
- Vitest and Playwright
For a quick repository review, start here:
README.mddocs/product/ui-showcase.mddocs/architecture/project-handbook.mddocs/reference/api.mdsecure-vault/src/app/secure-vault/src/lib/secure-vault/tests/
SecureVault already has a real dashboard workflow, but a few implementation realities are worth knowing up front:
/is now a completed landing page that introduces the product and routes users into the live workspace.- Semantic indexing is feature-gated and environment-dependent by design.
- New signups are intentionally auto-verified right now as a hackathon shortcut; a fuller production flow would send verification email through Resend or a similar provider before enabling the account.
- The project is already strong enough for demos, technical review, and portfolio use, while still leaving obvious room for broader production hardening.
