@tc-libs/seo-generator
v3.9.0
Published
Modulo NestJS per generare metadati SEO (title e description) in piu lingue tramite OpenAI, usando un prompt template letto da storage S3.
Downloads
166
Readme
@tc-libs/seo-generator
Modulo NestJS per generare metadati SEO (title e description) in piu lingue tramite OpenAI, usando un prompt template letto da storage S3.
Funzionalita
- Integrazione con OpenAI Chat Completions
- Generazione metadata multilingua
- Prompt template caricato da S3 con cache in memoria (TTL 30 minuti)
- Tracciamento costo totale e breakdown per lingua
- Controller admin pronto all'uso per endpoint di generazione
Installazione
Dipendenze principali usate dal modulo:
- @nestjs/common
- openai
- @tc-libs/storage
- @tc-libs/database
- @tc-libs/authentication
- @tc-libs/response
Configurazione modulo
register
import { Module } from '@nestjs/common';
import { StorageAwsS3Module } from '@tc-libs/storage';
import { SeoGeneratorModule } from '@tc-libs/seo-generator';
@Module({
imports: [
StorageAwsS3Module.register({
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
region: process.env.AWS_REGION!,
bucket: process.env.AWS_S3_BUCKET!,
}),
SeoGeneratorModule.register(
{
apiKey: process.env.OPENAI_API_KEY!,
models: {
mini: {
code: 'gpt-4.1-mini',
price: {
input: 0.15,
cachedInput: 0.075,
output: 0.6,
},
},
},
prompt: {
fileName: 'seo-generator.prompt.txt',
folder: 'prompts',
},
},
true,
),
],
})
export class AppModule {}registerAsync
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { SeoGeneratorModule } from '@tc-libs/seo-generator';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
SeoGeneratorModule.registerAsync(
{
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
apiKey: config.getOrThrow<string>('OPENAI_API_KEY'),
models: {
mini: {
code: config.get<string>('SEO_OPENAI_MODEL') ?? 'gpt-4.1-mini',
price: {
input: Number(config.get<string>('SEO_PRICE_INPUT') ?? '0.15'),
cachedInput: Number(
config.get<string>('SEO_PRICE_CACHED_INPUT') ?? '0.075',
),
output: Number(config.get<string>('SEO_PRICE_OUTPUT') ?? '0.6'),
},
},
},
prompt: {
fileName: config.getOrThrow<string>('SEO_PROMPT_FILE_NAME'),
folder: config.getOrThrow<string>('SEO_PROMPT_FOLDER'),
},
}),
},
true,
),
],
})
export class AppModule {}Uso service
import { Injectable } from '@nestjs/common';
import { SeoGeneratorService } from '@tc-libs/seo-generator';
@Injectable()
export class ProductSeoFacade {
constructor(private readonly seoGenerator: SeoGeneratorService) {}
async generateForProduct(productName: string, description: string) {
return this.seoGenerator.generateSeoMetadata(productName, description, [
'it',
'en',
]);
}
}Risposta del service:
type SeoGeneratorResult = {
seo: {
title: Record<string, string>;
description: Record<string, string>;
};
cost: number;
breakdown: Array<{
language: string;
inputTokens: number;
cachedInputTokens: number;
outputTokens: number;
cost: number;
}>;
};Endpoint admin
Il pacchetto esporta anche SeoGeneratorAdminController con route:
POST /v1/seo-generator/generate
Payload:
{
"entity": "Nome prodotto",
"context": "Descrizione completa del prodotto",
"languages": ["it", "en"]
}Validazioni DTO:
entity: stringa obbligatoriacontext: stringa obbligatorialanguages: array obbligatorio di stringhe
Prompt template
Il template viene letto da S3 (prompt.fileName, prompt.folder) e mantenuto in cache per 30 minuti.
Il contenuto del prompt deve forzare un output JSON con struttura:
{
"title": "...",
"description": "..."
}Export disponibili
SeoGeneratorModuleSeoGeneratorServiceSeoGeneratorAdminControllerSeoGeneratorGenerateAdminDtoSeoGeneratorSerialization- Tipi opzioni modulo (
SeoGeneratorModuleOptions, tokenSEO_GENERATOR_CONFIG_OPTIONS)
