Backend server for the College Freelancers Portfolio Platform, built with Node.js, Express, and TypeScript. Uses Google Sheets as the database and Google Drive for file storage.
- Node.js (v18 or higher)
- A Google Cloud project with Sheets and Drive APIs enabled
- Service account credentials JSON file
-
Install dependencies:
npm install
-
Set up Google Cloud (see detailed instructions below)
-
Configure environment variables:
cp .env.example .env
Edit
.envand fill in your configuration. -
Add service account credentials:
- Download your service account key JSON from Google Cloud Console
- Open the JSON file and copy its entire content
- In your
.envfile, paste the JSON as a single line inGOOGLE_SERVICE_ACCOUNT_KEY - Example:
GOOGLE_SERVICE_ACCOUNT_KEY={"type":"service_account","project_id":"...","private_key":"..."}
-
Run the development server:
npm run dev
The server will start on http://localhost:5000
- Go to Google Cloud Console
- Click "Select a project" → "New Project"
- Name it (e.g., "Freelancers Platform") and click "Create"
- In the Cloud Console, go to "APIs & Services" → "Library"
- Search for and enable:
- Google Sheets API
- Google Drive API
- Go to "APIs & Services" → "Credentials"
- Click "Create Credentials" → "Service Account"
- Fill in the details:
- Name:
freelancers-backend - Description: "Backend service for freelancers platform"
- Name:
- Click "Create and Continue"
- Skip the optional steps and click "Done"
- Click on the service account you just created
- Go to the "Keys" tab
- Click "Add Key" → "Create new key"
- Choose "JSON" format
- Download the file and save it as
service-account-key.jsonin the Backend directory
- Create a new Google Sheet
- Copy the Sheet ID from the URL:
https://docs.google.com/spreadsheets/d/SHEET_ID_HERE/edit - Share the sheet with your service account email:
- Click "Share" in the top right
- Paste the service account email (found in the JSON file as
client_email) - Give it "Editor" permissions
- Create a new folder in Google Drive for file uploads
- Copy the folder ID from the URL:
https://drive.google.com/drive/folders/FOLDER_ID_HERE - Share the folder with your service account email (Editor permissions)
Edit your .env file:
GOOGLE_SHEETS_ID=your-sheet-id-from-step-5
GOOGLE_DRIVE_FOLDER_ID=your-folder-id-from-step-6Backend/
├── src/
│ ├── config/
│ │ └── google.ts # Google API configuration
│ ├── controllers/
│ │ ├── auth.controller.ts # Authentication logic
│ │ ├── user.controller.ts # User management
│ │ ├── admin.controller.ts # Admin operations
│ │ └── upload.controller.ts # File uploads
│ ├── middleware/
│ │ └── auth.middleware.ts # JWT authentication
│ ├── routes/
│ │ ├── auth.routes.ts # Auth endpoints
│ │ ├── user.routes.ts # User endpoints
│ │ ├── admin.routes.ts # Admin endpoints
│ │ └── upload.routes.ts # Upload endpoints
│ ├── services/
│ │ ├── sheets.service.ts # Google Sheets CRUD
│ │ └── drive.service.ts # Google Drive operations
│ ├── utils/
│ │ ├── jwt.ts # JWT utilities
│ │ └── password.ts # Password hashing
│ └── server.ts # Express server
├── .env.example # Environment template
├── .gitignore
├── package.json
└── tsconfig.json
POST /api/auth/signup- Register new userPOST /api/auth/login- Login userPOST /api/auth/logout- Logout userGET /api/auth/me- Get current user (requires auth)
GET /api/users- Get all approved usersGET /api/users/:id- Get user by IDPUT /api/users/:id- Update user profile (requires auth)POST /api/users/:id/complete-onboarding- Complete onboarding (requires auth)
GET /api/admin/pending-users- Get pending applications (requires admin)POST /api/admin/approve/:id- Approve user (requires admin)POST /api/admin/reject/:id- Reject user (requires admin)
POST /api/upload/profile-image- Upload profile image (requires auth)POST /api/upload/banner-image- Upload banner image (requires auth)POST /api/upload/project-image- Upload project image (requires auth)
| Column | Type | Description |
|---|---|---|
| id | string | Unique user ID (UUID) |
| name | string | User's full name |
| string | User's email | |
| password_hash | string | Bcrypt hashed password |
| role | string | 'user' or 'admin' |
| status | string | 'incomplete', 'pending', 'approved', 'rejected' |
| tagline | string | Professional tagline |
| bio | string | User biography |
| tech_stack | string | Comma-separated tech skills |
| profile_image_url | string | Google Drive URL |
| banner_image_url | string | Google Drive URL |
| availability | string | 'Available', 'Busy', 'Open' |
| rate | string | Hourly rate |
| experience | string | Years of experience |
| github | string | GitHub URL |
| string | LinkedIn URL | |
| portfolio | string | Portfolio URL |
| created_at | string | ISO timestamp |
| updated_at | string | ISO timestamp |
| Column | Type | Description |
|---|---|---|
| id | string | Unique project ID (UUID) |
| user_id | string | Owner's user ID |
| title | string | Project title |
| link | string | Project URL |
| description | string | Project description |
| image_url | string | Google Drive URL |
| created_at | string | ISO timestamp |
The API uses JWT (JSON Web Tokens) for authentication:
- User signs up or logs in
- Server returns a JWT token
- Client stores token (localStorage)
- Client sends token in
Authorization: Bearer <token>header - Server verifies token for protected routes
# Install dependencies
npm install
# Run development server with auto-reload
npm run dev
# Build for production
npm run build
# Run production server
npm start- Never commit
service-account-key.jsonor.envfiles - Use strong JWT secrets in production
- Implement rate limiting for production
- Use HTTPS in production
- Validate and sanitize all user inputs
- Ensure
service-account-key.jsonexists in the Backend directory - Check that
GOOGLE_SHEETS_IDis set in.env - Verify the sheet is shared with the service account email
- Make sure the Google Sheet is shared with the service account email
- Check that the service account has "Editor" permissions
- Verify the APIs are enabled in Google Cloud Console
- Ensure
GOOGLE_DRIVE_FOLDER_IDis set in.env - Verify the Drive folder is shared with the service account
- Check file size limits (default: 5MB)
MIT