Skip to content

samymih/Cloud

Repository files navigation

BFI Cloud

A collaborative cloud platform built for my class at high school, centralizing course documents, shared resources, and academic tools in one place.

Built and maintained by Samy M. — live at bfi-cloud.samymihoubi.fr


What it does

BFI Cloud lets the whole class upload, browse, and access files organized in folders, with an integrated agenda for tracking assignments, and a built-in PDF reader. Authentication is handled via Clerk, and file write operations are gated behind organization-level permissions — only authorized users can upload or delete content.


Tech stack

Layer Technology
Framework Next.js 14 (App Router)
Language TypeScript
Styling Tailwind CSS
Auth & Permissions Clerk (org-level permissions)
File Storage Backblaze B2 (older version with Vercel Blob, but too limited)
Database PostgreSQL via Prisma
Deployment Vercel (custom domain)

Features

File management

  • Upload files via click or drag & drop
  • Browse files organized in virtual folders (built on top of B2's flat key structure)
  • Download via generated links
  • Delete files (with confirmation modal)
  • Create new folders
  • Integrated PDF viewer for in-browser reading

Access control

  • Public browsing: anyone can view and download files without signing in
  • Write operations (upload, delete, create folder) require authentication
  • Fine-grained control via Clerk organization permissions (org:files:write), not just roles — users without the permission see disabled UI elements

Agenda

  • Displays upcoming class assignments stored in PostgreSQL
  • Fetched server-side via Prisma with raw SQL queries
  • Groups assignments by date with relative labels ("Tomorrow", "In 3 days", etc.)

Architecture notes

File storage (Backblaze B2)

Files are stored in a flat B2 bucket. Folder structure is simulated client-side by parsing file name prefixes (e.g. maths/chapter3/notes.pdf). The API route handles:

  1. B2 authentication (Basic auth → token)
  2. Upload URL retrieval
  3. SHA-1 checksum computation before upload
  4. File deletion by fileId + fileName
POST /api/file?filename=...  → upload to B2
DELETE /api/file             → delete from B2 by fileId

Auth flow

Clerk middleware marks most routes as public. Write operations go through authenticatedFetch, which attaches a short-lived Bearer token to each request. Server-side, clerkClient.authenticateRequest() validates the token before any B2 operation is performed.

UI components use Clerk's <Protect> with the org:files:write permission to conditionally render upload/delete/folder controls.

Database

Prisma with a PostgreSQL adapter (@prisma/adapter-pg) manages the agenda. The assignment table stores subject (enum), date, and optional description. Subjects include: Maths, Physics, Literature, History & Geography, Spanish, French, SVT, and others.


Running locally

# 1. Copy environment variables
cp .env.example .env
# Fill in: POSTGRES_PRISMA_URL, B2_KEY_ID, B2_APPLICATION_KEY,
#          B2_BUCKET_ID, B2_BUCKET_NAME, CLERK_SECRET_KEY, NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY

# 2. Install dependencies
npm install

# 3. Push DB schema and generate Prisma client
npx prisma db push
npx prisma generate

# 4. Start dev server
npm run dev

App runs at http://localhost:3000


Project structure

src/
├── app/
│   ├── api/file/route.ts     # B2 upload & delete endpoints
│   ├── files/page.tsx        # File browser (server component)
│   ├── files/read/page.tsx   # PDF viewer page
│   └── agenda/page.tsx       # Assignment agenda
├── components/
│   ├── upload-button.tsx     # Drag & drop uploader
│   ├── delete-button.tsx     # Delete with confirm modal
│   ├── newFolder-button.tsx  # Folder creation
│   ├── download-button.tsx   # Link generator
│   ├── DocViewer.tsx         # PDF viewer (react-pdf-viewer)
│   ├── Navbar.tsx            # Responsive nav with Clerk auth
│   └── Agenda/agenda.tsx     # Assignment table component
└── lib/
    ├── prisma.ts             # Prisma client singleton
    └── utils.ts              # Date formatting helpers

Design decisions

Why Backblaze B2 over Vercel Blob or S3? Cost — B2 is significantly cheaper for storage and egress at small scale, and the API is S3-compatible enough to migrate later if needed.

Why virtual folders? B2 uses a flat key-value structure. Rather than maintaining a separate folder metadata layer in the database, folder hierarchy is derived from file name prefixes at render time. This keeps the system simple and stateless.

Why Clerk permissions over simple role checks? Clerk's organization permission system (org:files:write) allows fine-grained access control without hardcoding role names in the UI. Any user in the organization can be granted or revoked write access independently of their role.


Related

About

Collaborative cloud platform deployed on Vercel, built for my class. Features file upload/download with Backblaze B2, virtual folder navigation, org-level write permissions via Clerk, a PostgreSQL agenda for tracking assignments, and an integrated PDF viewer. Used daily by real students.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors