OpportunitiesEntities
Docs
    Ring Platform

    Futuro descentralizado que se construye a sí mismo

    Iniciar sesión
    Entities
    Opportunities
    Store
    Docs
    Conceptos de la plataforma
    RING EconomíaSonoratek LLCImpacto globalIA encuentra Web3
    Empezar
    Inicio rápidoCalculadoraHoja de ruta
    Privacidad|Contacto
    v1.104.26|Sonoratek LLC

    Documentation

    Conceptos, valor y escenarios típicos de clon — menos código.

    Primeros pasos
    Requisitos previos
    Instalación
    Validación del primer éxito
    Próximos pasos
    Funcionalidades
    Blogs de miembros
    Personalización
    Ringization playbook
    Despliegue
    Despliegue autoalojado
    Arquitectura
    Arquitectura de News Kingdom
    Desarrollo
    OSS frente a enterprise

    Entrada rápida (CTOs · auditores · agentes)

    Bienvenida — misión y audiencias
    Referencia rápida
    Primeros pasos
    Arquitectura y Auth.js
    Modos de backend y bases de datos (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Lecturas de seguridad y cumplimiento
    ringdom.org — base LegioX
    Código fuente — licencia MIT (GitHub)

    Documentation

    Conceptos, valor y escenarios típicos de clon — menos código.

    Primeros pasos
    Requisitos previos
    Instalación
    Validación del primer éxito
    Próximos pasos
    Funcionalidades
    Blogs de miembros
    Personalización
    Ringization playbook
    Despliegue
    Despliegue autoalojado
    Arquitectura
    Arquitectura de News Kingdom
    Desarrollo
    OSS frente a enterprise

    Entrada rápida (CTOs · auditores · agentes)

    Bienvenida — misión y audiencias
    Referencia rápida
    Primeros pasos
    Arquitectura y Auth.js
    Modos de backend y bases de datos (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Lecturas de seguridad y cumplimiento
    ringdom.org — base LegioX
    Código fuente — licencia MIT (GitHub)

    Documentation

    Conceptos, valor y escenarios típicos de clon — menos código.

    Primeros pasos
    Requisitos previos
    Instalación
    Validación del primer éxito
    Próximos pasos
    Funcionalidades
    Blogs de miembros
    Personalización
    Ringization playbook
    Despliegue
    Despliegue autoalojado
    Arquitectura
    Arquitectura de News Kingdom
    Desarrollo
    OSS frente a enterprise

    Entrada rápida (CTOs · auditores · agentes)

    Bienvenida — misión y audiencias
    Referencia rápida
    Primeros pasos
    Arquitectura y Auth.js
    Modos de backend y bases de datos (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Lecturas de seguridad y cumplimiento
    ringdom.org — base LegioX
    Código fuente — licencia MIT (GitHub)
    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    Blogs de miembros

    Cambio de URL: los artículos de los miembros ahora viven en /{username}/{slug}, junto al perfil del miembro en /{username}. El patrón anterior /blog/{username}/{slug} ya no existe y no hay ninguna ruta /blog. Usa las pestañas Fundador / Desarrollador de la barra lateral para filtrar esta página.

    Los blogs de miembros convierten el módulo de noticias de tu clon en un espacio de publicación para cada miembro. Los artículos se guardan en la misma tabla news que las noticias oficiales, se etiquetan con el identificador del autor y se sirven en la URL propia del autor. Si un autor quiere llegar al feed principal, solicita la promoción y el artículo entra en el pipeline de News Kingdom.

    La documentación anterior decíaComportamiento actual
    /blog/{username} y /blog/{username}/{slug}/{username} (perfil) y /{username}/{slug} (artículo)
    La membresía de pago desbloquea el blogPara escribir se necesita el rol member o superior. Una mejora de membresía de pago otorga member
    El perfil muestra un enlace al blog y una insignia de TelegramNo está en la página de perfil actual. Los autores comparten su enlace desde /my-news
    Sin membresía, la ruta del blog devuelve 404Un artículo devuelve 404 cuando no está publicado, el identificador o el slug no coinciden, o el idioma es distinto

    Por qué importa para tu clon

    • Los miembros se convierten en editores. Cada miembro de pago obtiene un espacio personal con una URL limpia y fácil de compartir bajo tu dominio.
    • Una sola identidad. El mismo nombre de usuario reúne el perfil, los artículos y el listado del autor.
    • Un embudo de contenido que tú controlas. Las buenas publicaciones pueden promocionarse a tu portada a cambio de una tarifa. Tú apruebas cada una.
    • Los lectores ayudan a mejorar las publicaciones. Otros miembros pueden proponer revisiones. El autor decide qué acepta.

    News Kingdom

    Puntuación, promoción de pago y aprobación en Telegram para el feed principal.

    Perfil público

    La página /{username} que está junto a los artículos del miembro.

    Reserva de nombres de usuario

    Rutas y módulos (verificado en ring/web)

    AspectoRuta
    Página del artículoapp/[locale]/[username]/[slug]/page.tsx
    Página del perfilapp/[locale]/[username]/page.tsx
    Listado por autorapp/[locale]/news/author/[username]/page.tsx (hasta 50 publicados, mediante getMyArticles)
    Editor del miembroapp/[locale]/(protected)/news/create/page.tsx (ArticleEditor audience="member")
    Espacio de trabajo del miembroapp/[locale]/(protected)/my-news/ con components/layout/rails/my-news-rail.tsx
    Bandeja de enmiendas/my-news/{articleId}/amendments (ROUTES.MY_NEWS_AMENDMENTS)
    Utilidades de identificador y ruta (, , )

    Preguntas frecuentes

    Migración

    ¿Seguirán funcionando los enlaces antiguos /blog?

    No. En ring/web no hay ninguna ruta /blog ni redirección. Actualiza los enlaces compartidos a /{username}/{slug}.

    Impacto

    ¿Pueden los lectores guardar artículos de miembros en favoritos?

    Los favoritos funcionan mediante GET y POST /api/user/favorites con el hook useContentFavorite. Ese hook está conectado a la vista de artículo de noticias (components/wrappers/news-article-wrapper.tsx), no a la página /{username}/{slug}.

    Carencias conocidas

    Documentación relacionada

    Related documentation

    News Kingdom architecture

    Siguiente paso: qué ocurre después de que un autor solicita la promoción a la página principal.

    News Module

    Requisito previo: el módulo de noticias que guarda y muestra los artículos de los miembros.

    Public Profile Pages

    Mismo flujo: la página /{username} que comparte el identificador del miembro.

    Username Reservation System

    Depende de: cómo se eligen y protegen los identificadores, que deciden las URL de los blogs.

    1. Docs
    2. /Funcionalidades
    3. /Blogs de miembros

    Actualizado 1 oct 20266 min de escucha

    Blogs de miembros

    Cambio de URL: los artículos de los miembros ahora viven en /{username}/{slug}, junto al perfil del miembro en /{username}. El patrón anterior /blog/{username}/{slug} ya no existe y no hay ninguna ruta /blog. Usa las pestañas Fundador / Desarrollador de la barra lateral para filtrar esta página.

    Los blogs de miembros convierten el módulo de noticias de tu clon en un espacio de publicación para cada miembro. Los artículos se guardan en la misma tabla news que las noticias oficiales, se etiquetan con el identificador del autor y se sirven en la URL propia del autor. Si un autor quiere llegar al feed principal, solicita la promoción y el artículo entra en el pipeline de News Kingdom.

    La documentación anterior decíaComportamiento actual
    /blog/{username} y /blog/{username}/{slug}/{username} (perfil) y /{username}/{slug} (artículo)
    La membresía de pago desbloquea el blogPara escribir se necesita el rol member o superior. Una mejora de membresía de pago otorga member
    El perfil muestra un enlace al blog y una insignia de TelegramNo está en la página de perfil actual. Los autores comparten su enlace desde /my-news
    Sin membresía, la ruta del blog devuelve 404Un artículo devuelve 404 cuando no está publicado, el identificador o el slug no coinciden, o el idioma es distinto

    Por qué importa para tu clon

    • Los miembros se convierten en editores. Cada miembro de pago obtiene un espacio personal con una URL limpia y fácil de compartir bajo tu dominio.
    • Una sola identidad. El mismo nombre de usuario reúne el perfil, los artículos y el listado del autor.
    • Un embudo de contenido que tú controlas. Las buenas publicaciones pueden promocionarse a tu portada a cambio de una tarifa. Tú apruebas cada una.
    • Los lectores ayudan a mejorar las publicaciones. Otros miembros pueden proponer revisiones. El autor decide qué acepta.

    News Kingdom

    Puntuación, promoción de pago y aprobación en Telegram para el feed principal.

    Perfil público

    La página /{username} que está junto a los artículos del miembro.

    Reserva de nombres de usuario

    Rutas y módulos (verificado en ring/web)

    AspectoRuta
    Página del artículoapp/[locale]/[username]/[slug]/page.tsx
    Página del perfilapp/[locale]/[username]/page.tsx
    Listado por autorapp/[locale]/news/author/[username]/page.tsx (hasta 50 publicados, mediante getMyArticles)
    Editor del miembroapp/[locale]/(protected)/news/create/page.tsx (ArticleEditor audience="member")
    Espacio de trabajo del miembroapp/[locale]/(protected)/my-news/ con components/layout/rails/my-news-rail.tsx
    Bandeja de enmiendas/my-news/{articleId}/amendments (ROUTES.MY_NEWS_AMENDMENTS)
    Utilidades de identificador y ruta (, , )

    Preguntas frecuentes

    Migración

    ¿Seguirán funcionando los enlaces antiguos /blog?

    No. En ring/web no hay ninguna ruta /blog ni redirección. Actualiza los enlaces compartidos a /{username}/{slug}.

    Impacto

    ¿Pueden los lectores guardar artículos de miembros en favoritos?

    Los favoritos funcionan mediante GET y POST /api/user/favorites con el hook useContentFavorite. Ese hook está conectado a la vista de artículo de noticias (components/wrappers/news-article-wrapper.tsx), no a la página /{username}/{slug}.

    Carencias conocidas

    Documentación relacionada

    Related documentation

    News Kingdom architecture

    Siguiente paso: qué ocurre después de que un autor solicita la promoción a la página principal.

    News Module

    Requisito previo: el módulo de noticias que guarda y muestra los artículos de los miembros.

    Public Profile Pages

    Mismo flujo: la página /{username} que comparte el identificador del miembro.

    Username Reservation System

    Depende de: cómo se eligen y protegen los identificadores, que deciden las URL de los blogs.

    1. Docs
    2. /Funcionalidades
    3. /Blogs de miembros

    Actualizado 1 oct 20266 min de escucha

    Blogs de miembros

    Cambio de URL: los artículos de los miembros ahora viven en /{username}/{slug}, junto al perfil del miembro en /{username}. El patrón anterior /blog/{username}/{slug} ya no existe y no hay ninguna ruta /blog. Usa las pestañas Fundador / Desarrollador de la barra lateral para filtrar esta página.

    Los blogs de miembros convierten el módulo de noticias de tu clon en un espacio de publicación para cada miembro. Los artículos se guardan en la misma tabla news que las noticias oficiales, se etiquetan con el identificador del autor y se sirven en la URL propia del autor. Si un autor quiere llegar al feed principal, solicita la promoción y el artículo entra en el pipeline de News Kingdom.

    La documentación anterior decíaComportamiento actual
    /blog/{username} y /blog/{username}/{slug}/{username} (perfil) y /{username}/{slug} (artículo)
    La membresía de pago desbloquea el blogPara escribir se necesita el rol member o superior. Una mejora de membresía de pago otorga member
    El perfil muestra un enlace al blog y una insignia de TelegramNo está en la página de perfil actual. Los autores comparten su enlace desde /my-news
    Sin membresía, la ruta del blog devuelve 404Un artículo devuelve 404 cuando no está publicado, el identificador o el slug no coinciden, o el idioma es distinto

    Por qué importa para tu clon

    • Los miembros se convierten en editores. Cada miembro de pago obtiene un espacio personal con una URL limpia y fácil de compartir bajo tu dominio.
    • Una sola identidad. El mismo nombre de usuario reúne el perfil, los artículos y el listado del autor.
    • Un embudo de contenido que tú controlas. Las buenas publicaciones pueden promocionarse a tu portada a cambio de una tarifa. Tú apruebas cada una.
    • Los lectores ayudan a mejorar las publicaciones. Otros miembros pueden proponer revisiones. El autor decide qué acepta.

    News Kingdom

    Puntuación, promoción de pago y aprobación en Telegram para el feed principal.

    Perfil público

    La página /{username} que está junto a los artículos del miembro.

    Reserva de nombres de usuario

    Rutas y módulos (verificado en ring/web)

    AspectoRuta
    Página del artículoapp/[locale]/[username]/[slug]/page.tsx
    Página del perfilapp/[locale]/[username]/page.tsx
    Listado por autorapp/[locale]/news/author/[username]/page.tsx (hasta 50 publicados, mediante getMyArticles)
    Editor del miembroapp/[locale]/(protected)/news/create/page.tsx (ArticleEditor audience="member")
    Espacio de trabajo del miembroapp/[locale]/(protected)/my-news/ con components/layout/rails/my-news-rail.tsx
    Bandeja de enmiendas/my-news/{articleId}/amendments (ROUTES.MY_NEWS_AMENDMENTS)
    Utilidades de identificador y ruta (, , )

    Preguntas frecuentes

    Migración

    ¿Seguirán funcionando los enlaces antiguos /blog?

    No. En ring/web no hay ninguna ruta /blog ni redirección. Actualiza los enlaces compartidos a /{username}/{slug}.

    Impacto

    ¿Pueden los lectores guardar artículos de miembros en favoritos?

    Los favoritos funcionan mediante GET y POST /api/user/favorites con el hook useContentFavorite. Ese hook está conectado a la vista de artículo de noticias (components/wrappers/news-article-wrapper.tsx), no a la página /{username}/{slug}.

    Carencias conocidas

    Documentación relacionada

    Related documentation

    News Kingdom architecture

    Siguiente paso: qué ocurre después de que un autor solicita la promoción a la página principal.

    News Module

    Requisito previo: el módulo de noticias que guarda y muestra los artículos de los miembros.

    Public Profile Pages

    Mismo flujo: la página /{username} que comparte el identificador del miembro.

    Username Reservation System

    Depende de: cómo se eligen y protegen los identificadores, que deciden las URL de los blogs.

    1. Docs
    2. /Funcionalidades
    3. /Blogs de miembros

    Actualizado 1 oct 20266 min de escucha

    Los identificadores determinan las URL de los blogs, así que los nombres reservados importan.

    Suscripciones

    La vía de pago que eleva a un usuario al rol member.

    Escenarios típicos

    1. Comunidad de expertos. Los miembros escriben textos extensos con su propio identificador y los mejores se promocionan a la portada.
    2. Boletín cooperativo. Cada productor mantiene un blog. El equipo de administración elige historias para el feed principal.
    3. Incentivo de membresía. Los usuarios gratuitos pueden leer. Escribir es una ventaja de la membresía de pago.

    Dónde trabajan los miembros

    SuperficieRuta
    Escribir un artículo nuevo/news/create
    Gestionar, compartir y promocionar/my-news
    Artículo público/{username}/{slug}
    Todos los artículos de un autor/news/author/{username}
    lib/blog/blog-path.ts
    normalizeBlogHandle
    profileArticlePathname
    profileArticleHref
    URL absolutalib/site-branding.ts localeBlogArticleUrl(locale, username, slug)
    Acción de guardadoapp/_actions/news.ts
    Permisosfeatures/news/lib/news-permissions.ts

    Cómo se resuelve un artículo

    La página del artículo busca una fila en news que cumpla los cuatro filtros: blogUsername == normalizeBlogHandle(username), slug, locale y status == 'published'. Si ninguna fila coincide, llama a notFound() y los metadatos pasan a noindex. Los identificadores se guardan con una @ inicial, así que /en/alice/hello busca blogUsername: '@alice'.

    blogUsername solo se asigna al crear el artículo, y solo cuando el usuario de la sesión tiene nombre de usuario. Los artículos escritos antes de que el autor eligiera un nombre de usuario nunca reciben identificador, así que no se resolverán en /{username}/{slug}. Para este caso, el panel de /my-news muestra un aviso para definir el nombre de usuario.

    Las rutas estáticas como /store, /news o /about tienen prioridad sobre el segmento dinámico [username]. Un nombre de usuario que coincida con una ruta estática no puede tener una URL de perfil.

    Permisos

    AcciónRegla
    CrearcanCreateNewsArticle: rol member o superior, administrador de la plataforma o confidential
    Editar o eliminarAdministrador de la plataforma o el autor del artículo
    Visibilidad site-wideSolo administradores de la plataforma. Los miembros llegan a ella mediante la aprobación de la promoción
    Visibilidad confidentialSolo usuarios con acceso confidencial
    featuredSe fuerza a false al guardar para quienes no son administradores
    Proponer una revisiónUsuario con sesión iniciada que no es el autor, con canProposeRevision, en artículos publicados

    Escribir, publicar, promocionar

    1. 1

      Crear

      Un miembro abre /news/create. Al guardar, app/_actions/news.ts escribe el artículo mediante createNewsArticle() con blogUsername y registra el primer commit de versión (lib/versioning).

    2. 2

      Publicar y compartir

      Fija status: 'published'. El panel de /my-news construye el enlace público a partir de ROUTES.PUBLIC_PROFILE(handle) y ofrece un botón para copiar el enlace.

    3. 3

      Promocionar (opcional)

      features/news/components/news-promotion-panel.tsx llama a POST /api/news/promotion/submit con { articleId }. Solo el autor puede enviarlo. Consulta News Kingdom para la puntuación, el pago y la aprobación.

    Cada visita a un artículo la cuenta recordArticlePageView() dentro de after(), así que el recuento nunca bloquea el renderizado.

    Los identificadores determinan las URL de los blogs, así que los nombres reservados importan.

    Suscripciones

    La vía de pago que eleva a un usuario al rol member.

    Escenarios típicos

    1. Comunidad de expertos. Los miembros escriben textos extensos con su propio identificador y los mejores se promocionan a la portada.
    2. Boletín cooperativo. Cada productor mantiene un blog. El equipo de administración elige historias para el feed principal.
    3. Incentivo de membresía. Los usuarios gratuitos pueden leer. Escribir es una ventaja de la membresía de pago.

    Dónde trabajan los miembros

    SuperficieRuta
    Escribir un artículo nuevo/news/create
    Gestionar, compartir y promocionar/my-news
    Artículo público/{username}/{slug}
    Todos los artículos de un autor/news/author/{username}
    lib/blog/blog-path.ts
    normalizeBlogHandle
    profileArticlePathname
    profileArticleHref
    URL absolutalib/site-branding.ts localeBlogArticleUrl(locale, username, slug)
    Acción de guardadoapp/_actions/news.ts
    Permisosfeatures/news/lib/news-permissions.ts

    Cómo se resuelve un artículo

    La página del artículo busca una fila en news que cumpla los cuatro filtros: blogUsername == normalizeBlogHandle(username), slug, locale y status == 'published'. Si ninguna fila coincide, llama a notFound() y los metadatos pasan a noindex. Los identificadores se guardan con una @ inicial, así que /en/alice/hello busca blogUsername: '@alice'.

    blogUsername solo se asigna al crear el artículo, y solo cuando el usuario de la sesión tiene nombre de usuario. Los artículos escritos antes de que el autor eligiera un nombre de usuario nunca reciben identificador, así que no se resolverán en /{username}/{slug}. Para este caso, el panel de /my-news muestra un aviso para definir el nombre de usuario.

    Las rutas estáticas como /store, /news o /about tienen prioridad sobre el segmento dinámico [username]. Un nombre de usuario que coincida con una ruta estática no puede tener una URL de perfil.

    Permisos

    AcciónRegla
    CrearcanCreateNewsArticle: rol member o superior, administrador de la plataforma o confidential
    Editar o eliminarAdministrador de la plataforma o el autor del artículo
    Visibilidad site-wideSolo administradores de la plataforma. Los miembros llegan a ella mediante la aprobación de la promoción
    Visibilidad confidentialSolo usuarios con acceso confidencial
    featuredSe fuerza a false al guardar para quienes no son administradores
    Proponer una revisiónUsuario con sesión iniciada que no es el autor, con canProposeRevision, en artículos publicados

    Escribir, publicar, promocionar

    1. 1

      Crear

      Un miembro abre /news/create. Al guardar, app/_actions/news.ts escribe el artículo mediante createNewsArticle() con blogUsername y registra el primer commit de versión (lib/versioning).

    2. 2

      Publicar y compartir

      Fija status: 'published'. El panel de /my-news construye el enlace público a partir de ROUTES.PUBLIC_PROFILE(handle) y ofrece un botón para copiar el enlace.

    3. 3

      Promocionar (opcional)

      features/news/components/news-promotion-panel.tsx llama a POST /api/news/promotion/submit con { articleId }. Solo el autor puede enviarlo. Consulta News Kingdom para la puntuación, el pago y la aprobación.

    Cada visita a un artículo la cuenta recordArticlePageView() dentro de after(), así que el recuento nunca bloquea el renderizado.

    Los identificadores determinan las URL de los blogs, así que los nombres reservados importan.

    Suscripciones

    La vía de pago que eleva a un usuario al rol member.

    Escenarios típicos

    1. Comunidad de expertos. Los miembros escriben textos extensos con su propio identificador y los mejores se promocionan a la portada.
    2. Boletín cooperativo. Cada productor mantiene un blog. El equipo de administración elige historias para el feed principal.
    3. Incentivo de membresía. Los usuarios gratuitos pueden leer. Escribir es una ventaja de la membresía de pago.

    Dónde trabajan los miembros

    SuperficieRuta
    Escribir un artículo nuevo/news/create
    Gestionar, compartir y promocionar/my-news
    Artículo público/{username}/{slug}
    Todos los artículos de un autor/news/author/{username}
    lib/blog/blog-path.ts
    normalizeBlogHandle
    profileArticlePathname
    profileArticleHref
    URL absolutalib/site-branding.ts localeBlogArticleUrl(locale, username, slug)
    Acción de guardadoapp/_actions/news.ts
    Permisosfeatures/news/lib/news-permissions.ts

    Cómo se resuelve un artículo

    La página del artículo busca una fila en news que cumpla los cuatro filtros: blogUsername == normalizeBlogHandle(username), slug, locale y status == 'published'. Si ninguna fila coincide, llama a notFound() y los metadatos pasan a noindex. Los identificadores se guardan con una @ inicial, así que /en/alice/hello busca blogUsername: '@alice'.

    blogUsername solo se asigna al crear el artículo, y solo cuando el usuario de la sesión tiene nombre de usuario. Los artículos escritos antes de que el autor eligiera un nombre de usuario nunca reciben identificador, así que no se resolverán en /{username}/{slug}. Para este caso, el panel de /my-news muestra un aviso para definir el nombre de usuario.

    Las rutas estáticas como /store, /news o /about tienen prioridad sobre el segmento dinámico [username]. Un nombre de usuario que coincida con una ruta estática no puede tener una URL de perfil.

    Permisos

    AcciónRegla
    CrearcanCreateNewsArticle: rol member o superior, administrador de la plataforma o confidential
    Editar o eliminarAdministrador de la plataforma o el autor del artículo
    Visibilidad site-wideSolo administradores de la plataforma. Los miembros llegan a ella mediante la aprobación de la promoción
    Visibilidad confidentialSolo usuarios con acceso confidencial
    featuredSe fuerza a false al guardar para quienes no son administradores
    Proponer una revisiónUsuario con sesión iniciada que no es el autor, con canProposeRevision, en artículos publicados

    Escribir, publicar, promocionar

    1. 1

      Crear

      Un miembro abre /news/create. Al guardar, app/_actions/news.ts escribe el artículo mediante createNewsArticle() con blogUsername y registra el primer commit de versión (lib/versioning).

    2. 2

      Publicar y compartir

      Fija status: 'published'. El panel de /my-news construye el enlace público a partir de ROUTES.PUBLIC_PROFILE(handle) y ofrece un botón para copiar el enlace.

    3. 3

      Promocionar (opcional)

      features/news/components/news-promotion-panel.tsx llama a POST /api/news/promotion/submit con { articleId }. Solo el autor puede enviarlo. Consulta News Kingdom para la puntuación, el pago y la aprobación.

    Cada visita a un artículo la cuenta recordArticlePageView() dentro de after(), así que el recuento nunca bloquea el renderizado.