How to Return Raw HTML in NestJS

Updated: December 31, 2023 By: Guest Contributor Post a comment

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.