π― Project Overview
I successfully deployed a TypeScript-based Express.js API to Render.com as part of the HNG Stage 0 Backend task. The API provides profile information and integrates with an external Cat Facts API.
Tech Stack:
- Node.js with TypeScript
- Express.js
- dotenv for environment variables
- Custom middleware (CORS, error handling)
- Structured MVC architecture
Live Deployment: [Your Render URL here]
π Initial Project Structure
project/
βββ src/
β βββ app.ts # Express app configuration
β βββ index.ts # Module exports
β βββ server.ts # Server entry point
β βββ config/
β β βββ env.ts # Environment configuration
β βββ controllers/
β β βββ profileController.ts
β βββ middleware/
β β βββ cors.ts
β β βββ errorHandler.ts
β βββ routes/
β β βββ index.ts
β βββ services/
β β βββ catFactService.ts
β β βββ profileService.ts
β βββ types/
β β βββ index.ts
β βββ utils/
β βββ logger.ts
βββ package.json
βββ tsconfig.json
βββ .env.example
π§ Challenges Encountered & Solutions
Challenge 1: Module Not Found Error
Error:
Error: Cannot find module '/opt/render/project/src/index.js'
Root Cause:
Render was trying to run node index.js but my project was written in TypeScript (.ts files), not JavaScript (.js files). TypeScript needs to be compiled before execution.
Solution:
- Added build script to compile TypeScript:
{
"scripts": {
"build": "tsc",
"start": "node dist/server.js"
}
}
- Configured Render build command:
-
Build Command:
npm install && npm run build -
Start Command:
npm start
-
Build Command:
Key Learning: TypeScript projects require a compilation step before deployment. The tsc compiler transforms .ts files into .js files that Node.js can execute.
Challenge 2: Application Exiting Early
Error:
==> Running 'npm start'
==> Application exited early
Root Cause:
Two issues were causing silent failures:
- The start command pointed to
dist/index.js, but the actual server startup code was inserver.ts - The server wasn't binding to
0.0.0.0, which Render requires
Solution:
- Fixed the entry point mismatch:
// package.json - Changed from index.js to server.js
{
"scripts": {
"start": "node dist/server.js"
}
}
- Updated server binding for Render:
// src/server.ts
const HOST = '0.0.0.0'; // Critical for Render!
app.listen(config.port, HOST, () => {
logger.info(`Server is running on ${HOST}:${config.port}`);
});
Key Learning: Cloud platforms like Render require servers to bind to 0.0.0.0 (all network interfaces) rather than localhost or 127.0.0.1. This allows the platform's load balancer to route traffic to your application.
Challenge 3: TypeScript Type Error
Error:
Argument of type 'string | number' is not assignable to parameter of type 'number'
Root Cause:
process.env.PORT returns a string, but app.listen() expects a number for the port parameter.
Solution:
// src/config/env.ts - Before
export const config = {
port: process.env.PORT || 3000, // Could be string or number
};
// After - Ensures port is always a number
export const config = {
port: parseInt(process.env.PORT || '3000', 10),
};
Key Learning: Environment variables are always strings in Node.js. Type coercion is necessary when working with numeric values from process.env.
π οΈ Configuration Files
package.json
{
"name": "hng-backend-stage0",
"version": "1.0.0",
"scripts": {
"build": "tsc",
"start": "node dist/server.js",
"dev": "ts-node src/server.ts"
},
"dependencies": {
"express": "^4.18.2",
"dotenv": "^16.0.3"
},
"devDependencies": {
"typescript": "^5.0.0",
"@types/node": "^20.0.0",
"@types/express": "^4.17.17",
"ts-node": "^10.9.0"
}
}
tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
Render Settings
- Root Directory: (empty/default)
-
Build Command:
npm install && npm run build -
Start Command:
npm start -
Environment Variables:
-
USER_EMAIL: your.email@example.com -
USER_NAME: Your Full Name -
USER_STACK: Node.js/Express/TypeScript -
PORT: (auto-set by Render)
-
πΈ Deployment Process Screenshots
1. Initial Build Success
found 0 vulnerabilities
> hng-backend-stage0@1.0.0 build
> tsc
==> Build successful π
2. Successful Deployment
==> Running 'npm start'
> hng-backend-stage0@1.0.0 start
> node dist/server.js
PORT = 10000
Server is running on 0.0.0.0:10000
Profile endpoint: http://0.0.0.0:10000/me
3. API Response
{
"email": "your.email@example.com",
"current_datetime": "2025-10-18T14:30:00Z",
"github_url": "https://github.com/yourusername/repo",
"cat_fact": "Cats sleep 70% of their lives."
}
π‘ Key Lessons Learned
1. TypeScript Compilation Pipeline
TypeScript projects require a build step before deployment. Understanding the compilation process (.ts β .js) is crucial for production deployments.
2. Cloud Platform Requirements
Different hosting platforms have specific requirements:
-
Host binding: Must use
0.0.0.0instead oflocalhost -
Port configuration: Use
process.env.PORTprovided by the platform - Entry points: Start command must match your actual server file
3. Environment Variable Management
- Always validate and parse environment variables
- Use sensible defaults for development
- Document required variables in
.env.example - Set production values in the hosting platform's dashboard
4. Debugging Deployment Issues
Systematic approach to troubleshooting:
- Check build logs for compilation errors
- Verify file structure matches start command
- Ensure all dependencies are listed in
package.json - Add console logs to track startup process
- Implement error handlers for uncaught exceptions
5. Project Structure Best Practices
- Separate concerns (config, controllers, services, routes)
- Use TypeScript for type safety
- Implement proper error handling middleware
- Structure code for scalability
π What This Task Taught Me
Technical Skills
-
TypeScript Configuration: Understanding
tsconfig.jsonand compilation outputs - Express.js Architecture: Building scalable API structures with proper separation of concerns
- Cloud Deployment: Platform-specific requirements and configurations
- Environment Management: Proper handling of environment variables across environments
Problem-Solving Approach
- Read error messages carefully - They often contain the exact solution
- Understand the deployment pipeline - Build β Upload β Deploy β Run
- Test locally first - Ensure the build process works before deploying
- Use systematic debugging - Eliminate possibilities one by one
Professional Development
- Documentation: Writing clear, comprehensive documentation
- Version Control: Proper Git workflow for deployment
- Production Readiness: Considerations beyond "it works on my machine"
- Error Handling: Implementing robust error catching and logging
π Next Steps & Improvements
- Add Health Check Endpoint: For monitoring service status
- Implement Rate Limiting: Protect against API abuse
- Add Request Validation: Using libraries like Joi or Zod
- Set Up CI/CD: Automated testing and deployment pipeline
- Add Monitoring: Application performance monitoring (APM)
- Implement Caching: For external API responses
- Write Tests: Unit and integration tests for reliability
π Resources & References
- Render Documentation
- TypeScript Handbook
- Express.js Best Practices
- Node.js Production Best Practices
π Conclusion
This deployment task was an excellent learning experience that reinforced the importance of understanding the complete deployment pipeline. From TypeScript compilation to platform-specific configurations, each challenge provided valuable insights into production-ready application development.
The key takeaway: Success in deployment comes from understanding not just how to write code, but how that code transforms and executes in a production environment.
Project Repository: [GitHub Link]
Live API: [Render URL]
Author: [Your Name]
Date: October 18, 2025
HNG Internship: Stage 0 Backend Task
Top comments (1)
This is a brilliantly clear and actionable guide. The methodical approach to debugging is a lesson in itself. The initial project structure is also clean and sets a great precedent for scalability.