Sling Academy
Home/Node.js/How to Return Raw HTML in NestJS

How to Return Raw HTML in NestJS

Last updated: December 31, 2023

Getting Started

NestJS is a powerful Node.js framework for building efficient and scalable server-side applications. This tutorial guides you through the process of returning raw HTML from a NestJS endpoint, perfect for when you need to serve web pages or templates as part of your application.

To get started, ensure you have Node.js and NestJS CLI installed. Create a new NestJS project by running the following command:

nest new my-html-project

Navigate to your new project folder and open it in your preferred code editor.

Serving Static HTML

If you simply need to return raw HTML files without dynamic content, you can use the built-in static assets feature of NestJS, which is configured in the main.ts file like so:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { join } from 'path';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useStaticAssets(join(__dirname, '..', 'public'));
  await app.listen(3000);
}
bootstrap();

Place your HTML files in the public directory and access them directly through your browser.

Returning HTML from a Controller

To return HTML from a controller, use the @Res() decorator to access the response object directly. Here’s an example:

import { Controller, Get, Res } from '@nestjs/common';
import { Response } from 'express';

@Controller()
export class AppController {
  @Get()
  async getHtml(@Res() res: Response) {
    res.send('<!DOCTYPE html><html><body><h1>Hello World</h1></body></html>');
  }
}

This allows you to return custom HTML content directly within your controller actions.

Using Template Engines

NestJS makes integrating template engines like Pug, EJS, or Handlebars straightforward. For example, using EJS:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { RenderModule } from 'nest-next';

@Module({
  imports: [RenderModule],
  controllers: [AppController],
})
export class AppModule {}

In your controller, use the rendering feature provided by the module:

import { Controller, Get, Render } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Render('index')
  getHtml() {
    // index.ejs will be rendered with any provided data
  }
}

The index.ejs template file must be located in the views directory, and NestJS will render it as HTML.

Advanced: Custom Decorators for HTML Responses

For more control and cleaner code, create a custom decorator that returns HTML. The decorator can set the necessary HTTP header to indicate HTML content:

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const HtmlResponse = createParamDecorator(
  (data: unknown, ctx: ExecutionContext) => {
    const response = ctx.switchToHttp().getResponse();
    response.type('text/html');
    return response;
  },
);

Use the decorator in your controller like so:

import { Controller, Get } from '@nestjs/common';
import { HtmlResponse } from './html-response.decorator';

@Controller()
export class AppController {
  @Get()
  getHtml(@HtmlResponse() res) {
    return '<!DOCTYPE html><html><body><h1>Hello World</h1></body></html>';
  }
}

This approach ensures that your endpoints explicitly state their intention to return HTML content.

Adding Dynamic Content

In real-world scenarios, you’ll likely need to return HTML with dynamic content. This can be achieved within your template engine context:

Controller()
export class AppController {
  @Get()
  @Render('index')
  getHtml() {
    return { title: 'Dynamic Title' };
  }
}

In the example above, title can be used in the index.ejs template to dynamically insert content.

Security Considerations

When returning HTML, especially with dynamic content, it’s essential to consider security aspects. Always sanitize the dynamic data to prevent XSS attacks, and use secure coding practices to ensure that user-generated content doesn’t compromise your application.

Conclusion

Knowing how to return raw HTML is a powerful addition to your NestJS skill set, whether for creating simple APIs, full-fledged web apps, or generating email templates. With this tutorial, you should have a solid understanding of how to serve static files, return HTML content from controllers, use template engines, and inject dynamic content into your HTML responses with NestJS.

Next Article: Fixing NestJS Error: Cannot Find Module When Running Tests

Previous Article: How to Extract and Parse Headers in NestJS

Series: Nest.js Tutorials: From Basics to Advanced

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates