📖 Project Story
💡 Inspiration
As a student leader at KIT, I've watched our EEE department society spend ₹15,000+ every semester renting projectors, speakers, and event supplies — while the Mechanical society, just two buildings away, has the exact same equipment gathering dust in its storage room.
Multiply this across 500+ student organizations at any major university, and you're looking at millions in duplicated spending with zero infrastructure to connect them.
The problem isn't scarcity — it's visibility. Every organization has resources. No organization knows what others have.
I built TrojanShare because the solution isn't another inventory spreadsheet — it's a shared resource discovery platform with a structured request and approval workflow.
But the implications go beyond individual student clubs. TrojanShare has the potential to become infrastructure that Student Government can adopt, maintain, and scale across an entire university.
📚 What I Learned
| Area | Key Learning |
|---|---|
| Database Design | Row Level Security (RLS) is more than database protection. RLS policies effectively become your application's permission model. |
| Authentication Flows | Two-step onboarding (authentication → organization setup) requires careful trigger design using Supabase auth.users, profiles, and organizations. |
| Static Generation | Next.js 14 static prerendering can fail when components call Supabase during build time. Environment configuration and middleware help ensure clean builds. |
| Product Scope | Club discovery is a common hackathon concept. Building organizational infrastructure around requests, approvals, and savings tracking creates stronger real-world adoption potential. |
| Demo-Driven Development | Building for a three-minute demonstration requires prioritization. Every feature should contribute to the product's narrative and demonstrate its value. |
🛠️ How I Built It
Architecture
Technology Stack: Next.js 14 App Router + Supabase + Vercel
┌──────────────────────────────┐
│ Vercel (Edge) │
│ │
│ Next.js 14 • React 18 │
│ TypeScript • Tailwind CSS │
└──────────────┬───────────────┘
│
HTTPS
│
▼
┌──────────────────────────────┐
│ Supabase Cloud │
│ │
│ ┌────────┐ ┌────────────┐ │
│ │ Auth │ │ PostgreSQL │ │
│ │ Email/ │ │ + RLS │ │
│ │ OAuth │ │ Policies │ │
│ └────────┘ └────────────┘ │
│ │
│ ┌────────────────────────┐ │
│ │ Realtime │ │
│ │ Notifications & Events │ │
│ └────────────────────────┘ │
└──────────────────────────────┘
Core Database Tables
| Table | Purpose |
|---|---|
organizations |
Stores student organizations and their details. |
profiles |
Links authenticated users to organizations with admin/member roles. |
resources |
Stores equipment, spaces, and other shareable resources. |
resource_requests |
Manages the booking lifecycle: pending → approved → picked up → returned. |
savings_log |
Tracks estimated financial savings from resource sharing. |
notifications |
Stores alerts for booking and resource status changes. |
Database Security
Row Level Security (RLS) policies enforce access permissions:
- Organization admins manage their organization's resources.
- Members can browse resources across organizations.
- Requesters can view their own requests.
- Resource owners can view incoming requests for their resources.
Key Application Components
| Route | Functionality |
|---|---|
/browse |
Resource discovery with search, category filters, and pagination. |
/resources/[id] |
Resource details, image gallery, and date selection. |
/dashboard |
Four dashboard sections: My Resources, Incoming Requests, Outgoing Requests, and Savings. |
/auth/signup |
Two-step onboarding: account creation followed by organization setup. |
⚙️ Challenges Faced
1. Row Level Security (RLS) Policy Complexity
Problem:
How can Organization A browse Organization B's available resources while ensuring that private requests remain accessible only to authorized users?
Solution:
Designed table-specific RLS policies based on organization membership and user roles.
Example PostgreSQL policies:
-- Allow users to browse available resources
CREATE POLICY "Available resources viewable"
ON resources
FOR SELECT
USING (is_available = true);
-- Allow organization members to view their own resources
CREATE POLICY "Org members view own"
ON resources
FOR SELECT
USING (
EXISTS (
SELECT 1 FROM profiles
WHERE id = auth.uid()
AND organization_id = resources.organization_id
)
);
-- Allow organization admins to manage resources
CREATE POLICY "Admins manage resources"
ON resources
FOR ALL
USING (
EXISTS (
SELECT 1 FROM profiles
WHERE id = auth.uid()
AND organization_id = resources.organization_id
AND role = 'admin'
)
);
2. Build-Time Supabase Client Errors
Problem:
The Next.js production build failed with a Supabase configuration error because environment variables were unavailable during static generation.
Solution:
Configured build-time environment variables and middleware to handle protected dashboard routes.
Example configuration:
NEXT_PUBLIC_SUPABASE_URL=https://dummy.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=dummy
These dummy values are intended only for controlled build-time configuration, not production deployment. Actual Supabase credentials must be configured in the deployment environment.
3. Two-Step Organization Onboarding
Problem:
A newly registered user needs to join or create an organization. However, the organization requires an administrator, and the user profile must reference that organization.
This creates a circular dependency during registration.
Solution:
Implemented a two-stage onboarding workflow:
- User signs up through Supabase Authentication.
- A
handle_new_user()database trigger creates an initial profile. - The user creates or joins an organization.
- The profile is updated with the corresponding
organization_idand role.
This separates authentication from organization setup.
4. Booking Conflict Prevention
Problem:
Two organizations could attempt to reserve the same projector for overlapping dates.
Solution:
Implemented booking conflict checks at the application layer and explored PostgreSQL exclusion constraints using date ranges.
Example PostgreSQL concept:
EXCLUDE USING gist (
resource_id WITH =,
daterange(start_date, end_date, '[]') WITH &&
)
This approach can prevent overlapping bookings at the database level when configured with the appropriate range types and constraints.
🚀 The Result
TrojanShare delivers a working resource-sharing platform designed to reduce duplicated spending and improve resource utilization across student organizations.
Key Platform Capabilities
- Resource Management: Organization admins can list and manage their resources.
- Cross-Organization Discovery: Members can browse resources across participating organizations.
- Booking Workflow: Requests move through approval, pickup, and return stages.
- Savings Tracking: Estimated financial savings are recorded for shared resources.
- Administrative Insights: Student Government can use utilization data to understand resource-sharing activity.
Development Highlights
| Metric | Achievement |
|---|---|
| Development Time | 48 hours |
| Frontend | Next.js 14 |
| Backend | Supabase |
| Database | PostgreSQL |
| Deployment | Vercel |
TrojanShare was developed as a rapid prototype with the goal of demonstrating how shared infrastructure can improve collaboration between student organizations.
Fight On. 🏁
Built With
- clsx
- css
- date-fns
- lucide
- next.js
- postgresql
- radix
- react
- supabase
- tailwind
- tailwind-merge
- typescript
- ui
- vercel
- zod