DevShowcase is a full-stack developer media platform that enables developers to showcase their software projects through high-quality demo videos. Instead of relying solely on GitHub repositories or screenshots, developers can create dedicated project pages containing descriptions, technology stacks, source code links, and shareable video demonstrations that recruiters, hiring managers, and other developers can view directly in their browser.
The motivation behind DevShowcase comes from a common problem faced by developers during interviews and portfolio reviews. Many projects are difficult to evaluate by simply looking at the source code. Recruiters rarely have the time to clone repositories, configure environments, and run applications locally. A short, well-recorded demonstration video often communicates the project's functionality, user experience, and technical implementation much more effectively.
To provide a reliable upload experience for large media files, DevShowcase implements a custom chunked upload pipeline. Videos are divided into smaller chunks, allowing uploads to resume after network interruptions instead of restarting from the beginning. This significantly improves the experience for developers uploading large project demonstrations.
The backend is designed around a scalable service-oriented architecture. Rather than coupling media storage directly with the main API, DevShowcase separates responsibilities into dedicated components:
- API Coordinator – Handles authentication, project management, upload orchestration, and metadata.
- Storage Services – Independent storage service instances responsible for receiving and managing uploaded media chunks.
- Metadata Service – Maintains upload sessions, chunk information, and project data using PostgreSQL.
- Background Worker – Processes uploaded videos asynchronously to generate thumbnails and media metadata without blocking user requests.
- Redis & BullMQ – Power the background job queue for asynchronous media processing.
Although the portfolio deployment runs multiple storage-service instances on a single virtual machine to minimize infrastructure costs, the architecture is intentionally designed for horizontal scalability. Since storage services communicate independently over HTTP, they can later be deployed across multiple virtual machines without requiring changes to the application logic. This separation of concerns keeps the upload pipeline modular and allows the platform to evolve as traffic grows.
The project also implements HTTP Range-based video streaming, allowing users to watch uploaded demonstrations efficiently without downloading the entire video. Combined with asynchronous processing, resumable uploads, and dedicated storage services, DevShowcase demonstrates how modern media platforms handle large-file ingestion and delivery while maintaining a responsive user experience.
Rather than being a distributed storage system, DevShowcase is a real-world product that applies distributed systems principles where they provide practical value. The project focuses on solving a genuine developer problem while showcasing scalable backend architecture, asynchronous processing, media streaming, and large-file upload techniques commonly used in modern production systems.
- User registration and login with JWT-based authentication
- Create portfolio projects with title, description, tech stack, GitHub URL, and live URL
- Upload large demo videos in chunks
- Distribute uploaded chunks across multiple storage nodes
- Resume interrupted uploads by checking which chunks already exist
- Merge stored chunks into a final video on the main backend
- Queue thumbnail generation with BullMQ and Redis
- Serve uploaded videos and generated thumbnails
The repository is split into three apps:
frontend- React + Vite UIbackend- Main API, Prisma models, upload coordination, and thumbnail job queuestorage-node- Lightweight chunk storage service used by multiple nodes
High-level upload flow:
- The frontend initializes an upload session from the backend.
- The file is split into 5 MB chunks in the browser.
- The backend forwards each chunk to one of the storage nodes.
- Chunk placement is tracked in PostgreSQL through Prisma.
- When all chunks arrive, the backend downloads and merges them into a final video.
- A BullMQ worker generates a thumbnail for the uploaded video.
- Frontend: React 19, Vite, Tailwind CSS, React Router, Axios
- Backend: Node.js, Express, Prisma, PostgreSQL, JWT, BullMQ, Redis, Multer
- Media processing: FFmpeg via
fluent-ffmpegand@ffmpeg-installer/ffmpeg - Infrastructure: Docker Compose, Redis, multi-node storage services
devShowcase/
|-- frontend/
|-- backend/
| |-- prisma/
| `-- src/
|-- storage-node/
`-- docker-compose.yml
Make sure these are installed before running the project:
- Node.js 18+
- npm
- PostgreSQL
- Redis
- Docker Desktop and Docker Compose for containerized runs
The backend expects a .env file inside backend/.
Example backend/.env:
PORT=5000
DATABASE_URL=postgresql://postgres:password@localhost:5432/devshowcase
JWT_SECRET=your_jwt_secret_here
REDIS_URL=redis://localhost:6379
NODE_A_URL=http://localhost:5001
NODE_B_URL=http://localhost:5002
NODE_C_URL=http://localhost:5003The storage node can run without a .env file because Docker Compose already injects:
PORTNODE_IDSTORAGE_PATH
cd frontend && npm install
cd ../backend && npm install
cd ../storage-node && npm installAdd backend/.env using the example above.
From backend/:
npx prisma generate
npx prisma migrate devIf Redis is installed locally:
redis-serverOr run it with Docker:
docker run -p 6379:6379 redis:7-alpineOpen three terminals from storage-node/ and run:
npm run devThe current code expects three storage services reachable at:
http://localhost:5001http://localhost:5002http://localhost:5003
If you run them manually, set different values for PORT, NODE_ID, and STORAGE_PATH in each terminal session.
Example:
PORT=5001 NODE_ID=node-a STORAGE_PATH=./data/node-a npm run dev
PORT=5002 NODE_ID=node-b STORAGE_PATH=./data/node-b npm run dev
PORT=5003 NODE_ID=node-c STORAGE_PATH=./data/node-c npm run devFrom backend/:
npm run devFrom backend/ in another terminal:
node src/workers/thumbnail.worker.jsFrom frontend/:
npm run devThe frontend currently calls the backend directly at http://localhost:5000.
The repository includes a docker-compose.yml that starts:
main-apiredisthumbnail-workernode-anode-bnode-c
Run:
docker compose up --buildImportant note:
- The current Compose file does not define a PostgreSQL service.
- You still need a running PostgreSQL instance and a valid
backend/.envfile.
POST /api/auth/registerPOST /api/auth/loginGET /api/projectsPOST /api/projectsPOST /api/upload/initPOST /api/upload/chunkPOST /api/upload/completeGET /api/upload/status/:uploadIdGET /api/videos/stream/:videoId
- Register or log in.
- Create a project.
- Go to the upload page.
- Select the target project.
- Upload a demo video in chunks.
- Let the backend merge the file and queue thumbnail generation.
- The frontend uses hardcoded backend URLs pointing to
http://localhost:5000. - Docker Compose does not currently provision PostgreSQL.
- There are no automated tests configured yet.
- Local manual storage-node startup on Windows may require setting env vars differently than the inline Unix-style examples above.
npm run dev
npm run build
npm run preview
npm run lintnpm run dev
npm startnpm run dev
npm start- Add PostgreSQL to
docker-compose.yml - Move frontend API URLs to environment variables
- Add upload retry/backoff and better failure reporting
- Add automated tests for upload, merge, and auth flows
- Add deployment documentation