DropX is a modern, full-stack cloud storage solution built with the latest web technologies. Effortlessly upload, organize, and manage your images and files with a beautiful UI, robust authentication, and lightning-fast performance.
- π Secure Authentication β Powered by Clerk for seamless, branded user management.
- π Folders & File Management β Organize files in folders, star important files, and manage trash.
- βοΈ ImageKit Integration β Fast, optimized image uploads and delivery with advanced processing.
- ποΈ PDF & Image Support β Restrict uploads to images and PDFs for safety and performance.
- ποΈ Trash & Restore β Soft-delete files with a 30-day recovery window.
- β Starred Files β Mark important files for quick access.
- πΌοΈ Instant Previews β View images directly in the app.
- π§βπΌ User Profile β View and manage your account, including email verification status.
- β‘ Real-time UI β Instant feedback and updates with toasts and smooth transitions.
- π‘οΈ Role-based Access β Secure file access and folder management per user.
- π Dark Mode β Beautiful, accessible design in both light and dark themes.
- Next.js β Latest app router, server components, and security middleware.
- React β Modern, performant UI.
- Clerk β Authentication and user management.
- ImageKit β Image storage, optimization, and delivery.
- Neon PostgreSQL β Serverless, scalable Postgres database.
- Drizzle ORM β Type-safe, modern ORM for schema and migrations.
- Zod β Schema validation for forms and API.
- HeroUI β Custom UI components for a polished look.
- Lucide Icons β Crisp, modern icons.
- Tailwind CSS β Utility-first styling.
- date-fns β Date formatting and manipulation.
Create your DropX account: Clean, modern sign-up form with validation and custom branding.
Password strength indicator: Encourages users to set a secure password for their account.
Verify your email: Secure your account with a simple email verification step.
Access your cloud: Elegant sign-in form with error handling and Clerk authentication.
Welcome to DropX: Discover features and sign up or sign in to get started.
Personalized dashboard access: See your files and quick actions after signing in.
landing view: Responsive design showcasing DropXβs capabilities.
Your cloud workspace: Manage, upload, and organize files and folders with ease.
Upload files instantly: Drag-and-drop or browse to upload images and PDFs.
Organize your files: Create new folders to keep your cloud storage tidy.
Folder added: Instantly see your new folder in the file list.
Upload to folders: Add files directly inside any folder for better organization.
Star important files: Mark files as favorites for quick access.
View starred files: Easily find and manage your favorite files.
Soft delete: Move files to trash with a single clickβrestore anytime within 30 days.
Manage trashed files: View and restore or permanently delete files in trash.
Undo delete: Restore files from trash back to your main storage.
Permanent removal: Confirm before deleting files forever for extra safety.
Cleaned up: See your updated file list after permanent deletion.
Bulk delete: Empty your trash to permanently remove all deleted files at once.
Trash emptied: Your storage is now free of deleted files.
Profile overview: View your account info, email status, and role badges.
Sign out securely: End your session and protect your cloud data.
-
Clone the repo:
git clone https://github.com/Aashay30/DropX.git cd DropX
-
Install dependencies:
npm install npm run dev
-
Set up environment variables:
Copy .env.example to .env.local and fill in your keys for Clerk, ImageKit, and NeonDB.
-
Run the development server:
npm run dev
-
Open http://localhost:3000 to view the app.
Building DropX was a rewarding experience that also presented several technical and design challenges. Below are some of the key problems encountered and how they were addressed:
Integrating Clerk for authentication and user management required careful configuration to ensure secure, seamless onboarding. Handling edge cases like email verification status, role-based access control, and protecting sensitive routes added complexity.
Solution: Leveraged Clerk middleware and client APIs to build conditional UI elements, enforce email verification, and manage roles (admin, user) across server and client components.
Designing an intuitive and scalable folder-file hierarchy was tricky, especially when enabling CRUD operations with relational constraints using PostgreSQL.
Solution: Structured the database with clear parent-child relationships using foreign keys and recursive queries, and used Drizzle ORM for type-safe and consistent access.
Handling large image uploads while ensuring optimal delivery and display across devices was a significant hurdle.
Solution: Integrated ImageKit's client SDK and transformed images on the fly using URL-based parameters for compression, resizing, and caching.
Implementing a reliable trash system with 30-day recovery required managing soft-deletes at both database and UI layers, along with time-based expiration handling.
Solution: Added
deletedAt
timestamps and conditional filters in queries, along with periodic UI feedback and restore options.
Ensuring consistent theme behavior across client-rendered and server-rendered pages involved syncing dark/light mode preferences via Tailwind and hydration-safe logic.
Solution: Used
next-themes
for persistent theme control, along with Tailwindβsdark:
variants and responsive component design.
Since Clerk heavily relies on client context, combining it with Next.js server components introduced challenges, especially around authentication and conditional rendering.
Solution: Used Clerkβs server-side helpers (
auth()
andgetAuth()
) in server components and API routes while keeping sensitive logic server-only.
Configuring deployment with Vercel while managing secrets for Clerk, ImageKit, and NeonDB securely and correctly across environments (dev, staging, prod) required extra care.
Solution: Set up
.env.local
files, environment variable checks, and used Vercelβs environment management to keep secrets safe and consistent.
Working with a newer ORM like Drizzle introduced learning curve around schema generation, migrations, and advanced SQL operations.
Solution: Invested time in understanding Drizzleβs approach to declarative schema definitions and built reusable migration patterns.
These challenges helped improve the architecture, developer experience, and robustness of the final product. Each issue brought deeper understanding of modern full-stack development with Next.js App Router, Clerk, Tailwind, and PostgreSQL.
Building DropX involved tackling several complex, real-world issues β each of which sharpened my ability to think critically, debug effectively, and make informed engineering decisions. These challenges reflect the kind of scenarios often brought up in technical interviews, system design rounds, and behavioral assessments.
Challenge: Configuring Clerk for auth was non-trivial β managing email verification, server-client auth state sync, and conditional access based on user roles (admin/user).
What I Did:
- Implemented Clerk middleware and client-side guards to enforce route protection and UI-level visibility.
- Used Clerkβs server-side helpers to ensure secure SSR in Next.js App Router.
- Interview Relevance: Demonstrates deep understanding of auth flows, RBAC, and managing auth across client-server boundaries β frequently asked in system design and backend interviews.
Challenge: Designing a scalable, recursive folder/file structure with PostgreSQL and handling constraints like unique names, parent-child relationships, and cascading deletes.
What I Did:
- Created a normalized schema with self-referencing foreign keys and implemented soft delete logic.
- Used Drizzle ORM for type-safe schema migrations and recursive queries to render nested views.
- Interview Relevance: Showcases database schema design, data modeling for tree structures, and ORM proficiency β ideal for backend or database-heavy roles.
Challenge: Uploading large files without slowing down the UI, and delivering optimized previews across device types.
What I Did:
- Integrated ImageKit SDK for real-time compression, transformation, and delivery via URL params.
- Optimized upload performance with feedback loaders and lazy loading.
- Interview Relevance: Highlights experience with media optimization, CDN usage, and performance tuning β useful in frontend performance or infra rounds.
Challenge: Implementing a user-friendly trash system with time-bound recovery (30 days) and permanent deletion.
What I Did:
- Added a
deletedAt
timestamp for soft deletes and filtered views accordingly. - Built periodic purge logic and restore capabilities in UI with user confirmations.
- Interview Relevance: Demonstrates handling of lifecycle management, temporal logic, and non-trivial state transitions β great for product-focused or system design questions.
Challenge: Maintaining light/dark theme consistency across SSR and CSR without hydration mismatch.
What I Did:
- Used
next-themes
for persistence and Tailwindβsdark:
variants to keep styling declarative and scalable. - Ensured hydration safety by conditionally rendering after mount.
- Interview Relevance: Good talking point for frontend interviews where SSR/CSR synchronization, UX consistency, and accessibility are discussed.
Challenge: Integrating Clerk (which relies on client context) with Next.js Server Components β especially in protected server-rendered routes.
What I Did:
- Used Clerk's
auth()
andgetAuth()
in server actions and loaders to maintain secure server-side rendering. - Handled client-only logic carefully to avoid SSR-related crashes.
- Interview Relevance: Shows fluency with Next.js App Router internals, server/client boundaries, and third-party SDK integration β common in frontend/full-stack interviews.
Challenge: Managing secrets and environment-specific settings across dev, staging, and production in Vercel.
What I Did:
- Created
.env.local
configs, used Vercelβs environment manager, and sanitized client-server variable usage. - Ensured no secrets leaked during build or runtime.
- Interview Relevance: Highlights deployment readiness, CI/CD awareness, and secure config management β useful in DevOps/backend discussions.
Challenge: Drizzle was a newer ORM with limited documentation β initially confusing for advanced schema definitions, relations, and raw SQL fallbacks.
What I Did:
- Studied the codebase and community examples to learn migration patterns.
- Built reusable schema components for consistent database interactions.
- Interview Relevance: Demonstrates adaptability, rapid learning of new tools, and confidence in SQL + ORM concepts β often explored in backend interviews.
β Each of these challenges helped me become a more thoughtful, product-oriented developer. They reflect not only technical ability but also decision-making, debugging, and the ability to ship robust features β qualities that are critical in real-world engineering roles and interviews.
Building DropX was not just about implementing a cloud storage solution β it was a deep dive into modern full-stack development practices and architecture. Below are the major insights and learnings gained throughout the journey:
Gained hands-on experience with the latest Next.js App Router features like server components, dynamic routing, layout nesting, and middleware β helping build a scalable and modular architecture.
Learned to integrate Clerk for secure and branded authentication, along with role-based access control and email verification β making user management both robust and user-friendly.
Understood the importance of relational database design using Neon PostgreSQL, especially when modeling hierarchical data (folders/files) and implementing soft-delete logic.
Implemented end-to-end data safety using Zod for schema validation, ensuring consistent client-server communication and preventing malformed data entries.
Used Tailwind CSS and HeroUI to build a clean, responsive, and theme-aware UI, reinforcing the importance of design systems and utility-first styling in production apps.
Faced and solved real-world challenges like:
- Soft delete with trash and restore logic
- Optimized image delivery via ImageKit
- Handling file operations and role-guarded access
- Managing edge cases like hydration mismatches and auth context in server components
Learned how to configure Vercel deployment, manage secrets across environments, and ensure that build processes remain stable, efficient, and secure.
Practiced clean folder structuring, reusable hooks, and modular components to make the codebase easier to scale and maintain.
Used visual feedback (toasts, loaders) and real-time state updates to improve the user experience β highlighting the impact of micro-interactions on usability.
Working on DropX helped me apply and deepen practical skills across the full stack. These takeaways not only enhanced my technical foundation but also strengthened my system design and problem-solving mindset β making me better prepared for real-world engineering roles and interviews.
- Gained hands-on experience using Next.js App Router with server/client components, middleware, and layouts to design scalable applications.
- Learned to split concerns between frontend, backend, and API layers β a critical aspect discussed in system design interviews.
- Integrated Clerk to build branded, secure auth with email verification and role-based access.
- Valuable for demonstrating understanding of authentication flows, session management, and RBAC in interviews.
- Designed normalized schemas for hierarchical file/folder structures with soft-deletion (Trash).
- Practiced writing migrations, relations, and handling edge cases like cascading deletes or renames β highly relevant for backend or database-focused roles.
- Used Zod to enforce schema validation on both client and server.
- Helped in understanding API contract integrity, which is often tested in API design or backend interviews.
- Integrated ImageKit for instant image delivery and used toasts/loaders for real-time UI.
- Reinforced the importance of perceived performance and user feedback, useful in front-end interviews.
- Built reusable, accessible components with Tailwind CSS and HeroUI.
- Focused on writing clean, maintainable UI logic β a good talking point in frontend design rounds.
- Tackled practical scenarios like:
- Soft delete with recovery window
- File type restrictions (images/PDFs only)
- Fallbacks for failed uploads or network issues
- Demonstrates experience beyond CRUD apps β important when asked about challenges you've solved in interviews.
- Managed secrets, environments, and production builds using Vercel.
- Ready to talk about deployment pipelines, build failures, and production readiness in DevOps or backend rounds.
- Followed principles like separation of concerns, reusable hooks, and modular layouts.
- Improved ability to discuss code maintainability, readability, and scalability β a frequent topic in behavioral or code review interviews.
- Focused on:
- What makes a good user experience?
- Where can the app fail and how should it recover?
- What if 10,000 users sign up tomorrow?
- These are questions hiring managers love to see you think about β showing ownership mindset and product thinking.
β Overall, DropX gave me a strong foundation in designing and building real-world, scalable web applications. The problems tackled and solutions built are not just technical exercises β they reflect the depth of thought, planning, and system design expected in real-world engineering roles.
- Situation: We needed secure authentication and role-based access in DropX.
- Task: Implement Clerk to manage auth and restrict access based on roles.
- Action: Integrated Clerkβs client/server APIs, added email verification, and set up role guards using middleware and conditional UI.
- Result: Delivered a secure auth system with seamless onboarding and reliable role-based UI rendering, improving the appβs access control.
- Situation: Users needed to organize files into nested folders.
- Task: Design a database schema supporting recursive folder structures.
- Action: Created a self-referencing table using Drizzle ORM, handled cascading soft-deletes, and optimized retrieval using recursive queries.
- Result: Achieved a robust and scalable file system, which handled edge cases like rename, restore, and deletion efficiently.
- Situation: Large image uploads slowed down the UI and load times.
- Task: Ensure fast, responsive image loading across devices.
- Action: Integrated ImageKit for on-the-fly image transformations and added responsive previews with loading states.
- Result: Enhanced perceived performance and user experience significantly, with minimal latency on uploads or previews.
- Situation: Users wanted the ability to recover deleted files.
- Task: Implement a trash system with a 30-day recovery window.
- Action: Used a
deletedAt
field to soft-delete, built restore logic in UI, and filtered queries based on time-based conditions. - Result: Enabled non-destructive deletes, which improved user trust and flexibility in file management.
- Situation: The app required dark mode with SSR support.
- Task: Implement a theme toggle without causing hydration issues.
- Action: Used
next-themes
for persistent theme handling and ensured hydration safety with client-only guards. - Result: Delivered a consistent light/dark theme UX across all pages, including server-rendered routes.
- Situation: Clerkβs client-centric nature conflicted with Server Components in Next.js.
- Task: Securely manage auth across both client and server layers.
- Action: Utilized Clerkβs
auth()
/getAuth()
on server routes, and carefully separated logic between server-only and client-only contexts. - Result: Maintained secure access control without breaking SSR functionality or leaking sensitive data.
- Situation: Needed to deploy securely with different environments (dev/prod).
- Task: Configure secrets and environment variables across environments.
- Action: Used
.env
files and Vercelβs environment manager to safely isolate variables, including Clerk and DB credentials. - Result: Enabled seamless CI/CD workflows and ensured no secrets were leaked during deployment.
- Situation: Drizzle ORM was relatively new with limited documentation.
- Task: Set up relational schemas and migrations quickly.
- Action: Explored community resources, built modular schema components, and wrote migration scripts.
- Result: Successfully handled complex schema relationships and became proficient in Drizzle β a skill transferable to other ORM tools.
This project was a significant milestone in sharpening my skills across front-end, back-end, DevOps, and product thinking β and laid a strong foundation for building robust, scalable web applications in production environments.