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
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