π― 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.0
instead oflocalhost
-
Port configuration: Use
process.env.PORT
provided 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.json
and 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.