En este ejemplo práctico, desarrollaremos una aplicación web full-stack utilizando NestJS como framework backend en Node.js para crear una REST API. En el frontend, emplearemos Next.js para construir la interfaz de usuario. Además, este proyecto integrará tecnologías clave como TypeScript (tanto en el backend como en el frontend), Prisma (como ORM para bases de datos SQL) y ShadCN (para diseñar interfaces). También configuraremos el proyecto para su despliegue en producción, asegurando que esté optimizado y listo para un entorno real.

Creación de Backend

mkdir nestjs-nextjs-crud
nest new backend

Para este tutorial estaré trabajando con npm

Luego limpiaremos un poco el proyecto porque este trae archivos por defecto que empiezan con el nombre app así que vamos a eliminar los archivos: app.controller.ts, app.service.ts, app.controller.spec.ts y finalmnente actualiza el archivo app.module.ts así:

import { Module } from '@nestjs/common';

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

luego en prettier.rc tambien añadiremos lo siguiente, para evitar un tipico error de eslint en Nestjs:

{
  "singleQuote": true,
  "trailingComma": "all",
  "prettier/prettier": [
    "error",
    {
      "singleQuote": true,
      "parser": "flow"
    }
  ]
}

finalmnente en main.ts vamos a añadir un prefijo global para que todas las rutas empiecen con la ruta /api:

app.setGlobalPrefix('/api');

Creando un Resource de Productos

nest g resource products

Instalación de Prisma

npm i prisma
npx prisma init --datasource-provider sqlite

Luego en prisma/schema.prisma vamos a crear el siguiente esquema:

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

model Product {
  id          Int      @id @default(autoincrement())
  name        String
  description String?
  price       Float
  image       String?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}
npx prisma migrate dev --name init

Una vez creado el esquema vamos a crear un service de prisma con el comando:

nest g service prisma --no-spec

con el siguiente contenido:

import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    await this.$connect();
  }
}

En product.service.ts

Instalación de Swagger

Swagger

npm install --save @nestjs/swagger

Creación del Frontend

npx create-next-app@latest frontend --typescript --tailwind --eslint

npm i react-hook-form zod @hookform/resolvers