DEV Community

Fahd Adebayo
Fahd Adebayo

Posted on

Deploying a TypeScript Express API to Render: A Complete Journey

🎯 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
Enter fullscreen mode Exit fullscreen mode

🚧 Challenges Encountered & Solutions

Challenge 1: Module Not Found Error

Error:

Error: Cannot find module '/opt/render/project/src/index.js'
Enter fullscreen mode Exit fullscreen mode

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:

  1. Added build script to compile TypeScript:
{
  "scripts": {
    "build": "tsc",
    "start": "node dist/server.js"
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Configured Render build command:
    • Build Command: npm install && npm run build
    • Start Command: npm start

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
Enter fullscreen mode Exit fullscreen mode

Root Cause:
Two issues were causing silent failures:

  1. The start command pointed to dist/index.js, but the actual server startup code was in server.ts
  2. The server wasn't binding to 0.0.0.0, which Render requires

Solution:

  1. Fixed the entry point mismatch:
// package.json - Changed from index.js to server.js
{
  "scripts": {
    "start": "node dist/server.js"
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. 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}`);
});
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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),
};
Enter fullscreen mode Exit fullscreen mode

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"
  }
}
Enter fullscreen mode Exit fullscreen mode

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}
Enter fullscreen mode Exit fullscreen mode

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 πŸŽ‰
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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."
}
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ 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 of localhost
  • 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:

  1. Check build logs for compilation errors
  2. Verify file structure matches start command
  3. Ensure all dependencies are listed in package.json
  4. Add console logs to track startup process
  5. 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

  1. Read error messages carefully - They often contain the exact solution
  2. Understand the deployment pipeline - Build β†’ Upload β†’ Deploy β†’ Run
  3. Test locally first - Ensure the build process works before deploying
  4. 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

  1. Add Health Check Endpoint: For monitoring service status
  2. Implement Rate Limiting: Protect against API abuse
  3. Add Request Validation: Using libraries like Joi or Zod
  4. Set Up CI/CD: Automated testing and deployment pipeline
  5. Add Monitoring: Application performance monitoring (APM)
  6. Implement Caching: For external API responses
  7. Write Tests: Unit and integration tests for reliability

πŸ”— Resources & References


πŸ“ 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

HNGInternship #TypeScript #ExpressJS #NodeJS #BackendDevelopment #DevOps

Top comments (1)

Collapse
 
hashbyt profile image
Hashbyt

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.