Angular Desarrollo web Git Herramientas Utiles javascript PHP Repositorios Typescript

Cómo Integrar Giscus en Angular 21: Sistema de Comentarios con GitHub Discussions

giscus

🚀 ¿Quieres añadir comentarios a tu blog sin pagar hosting, sin bases de datos y con una experiencia perfecta
para desarrolladores
? En esta guía te muestro cómo integré Giscus en mi blog Hackeruna usando Angular 21.

💡 Giscus convierte GitHub Discussions en un sistema de comentarios. Tus lectores comentan con
su cuenta de GitHub, todo se sincroniza automáticamente, y tú moderas desde GitHub. ¡Gratis!

🎯 ¿Por Qué Giscus?

Característica Giscus Disqus Comentarios WP
💰 Precio Gratis Freemium Gratis
🔒 Privacidad Sin tracking Ads y tracking Variable
👨‍💻 Markdown Completo + código Limitado No
🌙 Tema oscuro Automático Manual Manual
📊 Base de datos GitHub (gratis) Disqus servers Tu DB
🎯 Ideal para Blogs técnicos Blogs generales WordPress

📋 Requisitos Previos

  • ✅ Repositorio público en GitHub
  • ✅ GitHub Discussions habilitado en tu repo
  • ✅ Proyecto Angular 17+ (usaremos standalone components)
  • ✅ Conocimientos básicos de TypeScript

🔧 Paso 1: Configurar GitHub Discussions

  1. Ve a tu repositorio en GitHub
  2. Click en SettingsFeatures
  3. Activa Discussions
  4. Crea una categoría llamada General o Comentarios

Mi repositorio: github.com/juanitourquiza/ng-hackeruna

🔧 Paso 2: Obtener Configuración de Giscus

  1. Visita giscus.app
  2. Ingresa tu repositorio: usuario/repositorio
  3. Selecciona la categoría de discussions
  4. Elige el mapping: pathname (recomendado para blogs)
  5. Copia los valores generados

Los valores que necesitas son:

data-repo="tu-usuario/tu-repo"
data-repo-id="R_xxxxx"
data-category="General"
data-category-id="DIC_xxxxx"

🚀 Paso 3: Crear el Componente en Angular

Primero, creamos la estructura del componente:

mkdir -p src/app/shared/components/giscus-comments

giscus-comments.component.ts

Este es el corazón de la integración. Nótese cómo manejamos SSR correctamente:

import { 
  Component, 
  OnInit, 
  OnDestroy, 
  PLATFORM_ID, 
  inject, 
  ChangeDetectionStrategy 
} from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
@Component({
  selector: 'app-giscus-comments',
  standalone: true,
  imports: [],
  templateUrl: './giscus-comments.component.html',
  styleUrls: ['./giscus-comments.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class GiscusCommentsComponent implements OnInit, OnDestroy {
  private platformId = inject(PLATFORM_ID);
  ngOnInit(): void {
    // ⚡ Solo cargar en browser, NO durante SSR
    if (isPlatformBrowser(this.platformId)) {
      this.loadGiscus();
    }
  }
  ngOnDestroy(): void {
    // 🧹 Limpiar al destruir el componente
    if (isPlatformBrowser(this.platformId)) {
      const giscusScript = document.querySelector(
        'script[src="https://giscus.app/client.js"]'
      );
      if (giscusScript) giscusScript.remove();
      const giscusFrame = document.querySelector('.giscus');
      if (giscusFrame) giscusFrame.remove();
    }
  }
  private loadGiscus(): void {
    const script = document.createElement('script');
    script.src = 'https://giscus.app/client.js';
    
    // 🔧 Tu configuración de giscus.app
    script.setAttribute('data-repo', 'juanitourquiza/ng-hackeruna');
    script.setAttribute('data-repo-id', 'R_kgDOQTQzSQ');
    script.setAttribute('data-category', 'General');
    script.setAttribute('data-category-id', 'DIC_kwDOQTQzSc4C0LRM');
    script.setAttribute('data-mapping', 'pathname');
    script.setAttribute('data-strict', '0');
    script.setAttribute('data-reactions-enabled', '1');
    script.setAttribute('data-emit-metadata', '0');
    script.setAttribute('data-input-position', 'bottom');
    script.setAttribute('data-theme', 'preferred_color_scheme');
    script.setAttribute('data-lang', 'es');
    script.setAttribute('crossorigin', 'anonymous');
    script.async = true;
    // 📍 Insertar en el contenedor
    const container = document.getElementById('giscus-container');
    if (container) {
      container.appendChild(script);
    }
  }
}

giscus-comments.component.html

<div class="giscus-wrapper">
  <div id="giscus-container"></div>
</div>

giscus-comments.component.scss

:host {
  display: block;
}
.giscus-wrapper {
  margin-top: 2rem;
  
  ::ng-deep .giscus {
    width: 100%;
  }
  
  ::ng-deep .giscus-frame {
    border: none;
    width: 100%;
  }
}

🔧 Paso 4: Integrar en la Página de Post

Ahora usamos el componente en nuestra página de detalle de post. Usamos @defer para lazy loading:

<!-- post-detail.component.html -->
<!-- ... contenido del post ... -->
<!-- Sección de Comentarios -->
<div class="mt-12 pt-8 not-prose" 
     style="border-top: 1px solid var(--border-color);">
  
  <h2 class="text-2xl font-bold mb-6" 
      style="color: var(--text-primary);">
    💬 Comentarios
  </h2>
  
  <p class="text-sm mb-6" 
     style="color: var(--text-secondary);">
    Comparte tus ideas, preguntas o sugerencias. 
    Los comentarios se gestionan a través de GitHub Discussions.
  </p>
  
  <!-- ⚡ Lazy loading con @defer -->
  @defer (on viewport; prefetch on idle) {
    <app-giscus-comments></app-giscus-comments>
  } @placeholder {
    <div class="h-32 bg-gray-200 dark:bg-gray-700 
                animate-pulse rounded"></div>
  }
  
</div>

No olvides importar el componente en tu post-detail.component.ts:

import { GiscusCommentsComponent } from '../../shared/components/giscus-comments/giscus-comments.component';
@Component({
  // ...
  imports: [
    // ... otros imports
    GiscusCommentsComponent
  ],
})

🔒 Paso 5: Configurar Content Security Policy (CSP)

⚠️ Este paso es CRUCIAL. Sin él, el navegador bloqueará el script de giscus.

En tu index.html, agrega https://giscus.app a las directivas CSP:

<meta http-equiv="Content-Security-Policy" content="
  default-src 'self';
  script-src 'self' 'unsafe-inline' 'unsafe-eval' https://giscus.app;
  style-src 'self' 'unsafe-inline' https://giscus.app;
  connect-src 'self' https://giscus.app;
  frame-src 'self' https://giscus.app;
">

✅ Resultado Final

Así se ve el sistema de comentarios funcionando en Hackeruna:

  • 🌙 Tema automático: Se adapta a light/dark mode
  • 👨‍💻 Markdown completo: Los lectores pueden escribir código
  • 🔔 Notificaciones: Te llegan a GitHub cuando alguien comenta
  • 🛡️ Moderación: Edita o elimina desde GitHub Discussions
  • 📱 Responsive: Funciona perfecto en móviles

🎨 Personalización Adicional

Cambiar el Tema

// Temas disponibles:
'preferred_color_scheme'  // Automático según sistema
'light'                   // Siempre claro
'dark'                    // Siempre oscuro
'dark_dimmed'             // Oscuro atenuado
'dark_high_contrast'      // Oscuro alto contraste
'dark_protanopia'         // Accesible
'light_high_contrast'     // Claro alto contraste
'light_protanopia'        // Accesible
'transparent_dark'        // Transparente oscuro
'noborder_light'          // Sin borde claro

Cambiar el Idioma

script.setAttribute('data-lang', 'es');  // Español
script.setAttribute('data-lang', 'en');  // Inglés
script.setAttribute('data-lang', 'pt');  // Portugués
// Ver más: https://giscus.app

🔗 Repositorio Completo

Todo el código está disponible en mi repositorio:

👉 github.com/juanitourquiza/ng-hackeruna

Archivos relevantes:

  • src/app/shared/components/giscus-comments/ – Componente completo
  • src/app/features/post/post-detail.component.html – Integración
  • src/index.html – Configuración CSP

💡 Tips y Mejores Prácticas

  1. Usa @defer: El widget solo carga cuando el usuario hace scroll hasta él
  2. Limpia en ngOnDestroy: Evita memory leaks al navegar entre posts
  3. SSR compatible: Usa isPlatformBrowser para evitar errores en server
  4. OnPush: El componente no necesita change detection reactiva
  5. Mapping por pathname: Cada URL = una discusión única

🤔 Preguntas Frecuentes

¿Funciona sin JavaScript?

No, giscus requiere JavaScript para cargar el widget. Considera mostrar un link a GitHub Discussions como fallback.

¿Puedo usarlo en repos privados?

No, el repositorio debe ser público para que giscus funcione.

¿Afecta el SEO?

Los comentarios se cargan dinámicamente, así que Google no los indexa directamente. Pero las discusiones en GitHub sí
son indexables.

¿Es seguro?

Sí. Giscus usa OAuth de GitHub y no almacena credenciales. Todo el código es open source.

📚 Recursos Adicionales


¿Te fue útil esta guía? ¡Déjame un comentario usando giscus! 👇

Si tienes dudas, también puedes abrir un Discussion en GitHub o contactarme en LinkedIn.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *