Концепции, ценность и типичные сценарии клонирования — меньше кода.
Концепции, ценность и типичные сценарии клонирования — меньше кода.
Preparing Ring content
Preparing Ring content
Preparing Ring content
Изменение URL: статьи участников теперь размещаются по адресу /{username}/{slug}, рядом с профилем участника на /{username}. Старого шаблона /blog/{username}/{slug} больше нет, и маршрута /blog не существует. Используйте вкладки Основатель / Разработчик на боковой панели, чтобы отфильтровать эту страницу.
Блоги участников превращают модуль новостей вашего клона в пространство для публикаций каждого участника. Статьи хранятся в той же таблице news, что и официальные новости, помечаются именем автора и отдаются по собственному URL автора. Если автор хочет попасть в главную ленту, он подаёт запрос на продвижение, и статья попадает в конвейер News Kingdom.
| Раньше в документации | Текущее поведение |
|---|---|
/blog/{username} и /blog/{username}/{slug} | /{username} (профиль) и /{username}/{slug} (статья) |
| Платное членство открывает блог | Для написания нужна роль member или выше. Платное повышение членства выдаёт роль member |
| Профиль показывает ссылку на блог и значок Telegram | На текущей странице профиля этого нет. Авторы делятся ссылкой из /my-news |
| Без членства маршрут блога возвращает 404 | Статья возвращает 404, если она не опубликована, имя или slug не совпадают либо отличается язык |
Нет. В ring/web нет ни маршрута /blog, ни перенаправления. Обновите распространённые ссылки на /{username}/{slug}.
Избранное работает через GET и POST /api/user/favorites с хуком useContentFavorite. Этот хук подключён к просмотру новостной статьи (components/wrappers/news-article-wrapper.tsx), а не к странице /{username}/{slug}.
Следующий шаг: что происходит после того, как автор подаёт запрос на продвижение на главную страницу.
Предпосылка: модуль новостей, который хранит и отображает статьи участников.
Тот же процесс: страница /{username}, которая использует то же имя участника.
Зависимость: как выбираются и защищаются имена, от которых зависят URL блогов.
Изменение URL: статьи участников теперь размещаются по адресу /{username}/{slug}, рядом с профилем участника на /{username}. Старого шаблона /blog/{username}/{slug} больше нет, и маршрута /blog не существует. Используйте вкладки Основатель / Разработчик на боковой панели, чтобы отфильтровать эту страницу.
Блоги участников превращают модуль новостей вашего клона в пространство для публикаций каждого участника. Статьи хранятся в той же таблице news, что и официальные новости, помечаются именем автора и отдаются по собственному URL автора. Если автор хочет попасть в главную ленту, он подаёт запрос на продвижение, и статья попадает в конвейер News Kingdom.
| Раньше в документации | Текущее поведение |
|---|---|
/blog/{username} и /blog/{username}/{slug} | /{username} (профиль) и /{username}/{slug} (статья) |
| Платное членство открывает блог | Для написания нужна роль member или выше. Платное повышение членства выдаёт роль member |
| Профиль показывает ссылку на блог и значок Telegram | На текущей странице профиля этого нет. Авторы делятся ссылкой из /my-news |
| Без членства маршрут блога возвращает 404 | Статья возвращает 404, если она не опубликована, имя или slug не совпадают либо отличается язык |
Нет. В ring/web нет ни маршрута /blog, ни перенаправления. Обновите распространённые ссылки на /{username}/{slug}.
Избранное работает через GET и POST /api/user/favorites с хуком useContentFavorite. Этот хук подключён к просмотру новостной статьи (components/wrappers/news-article-wrapper.tsx), а не к странице /{username}/{slug}.
Следующий шаг: что происходит после того, как автор подаёт запрос на продвижение на главную страницу.
Предпосылка: модуль новостей, который хранит и отображает статьи участников.
Тот же процесс: страница /{username}, которая использует то же имя участника.
Зависимость: как выбираются и защищаются имена, от которых зависят URL блогов.
Изменение URL: статьи участников теперь размещаются по адресу /{username}/{slug}, рядом с профилем участника на /{username}. Старого шаблона /blog/{username}/{slug} больше нет, и маршрута /blog не существует. Используйте вкладки Основатель / Разработчик на боковой панели, чтобы отфильтровать эту страницу.
Блоги участников превращают модуль новостей вашего клона в пространство для публикаций каждого участника. Статьи хранятся в той же таблице news, что и официальные новости, помечаются именем автора и отдаются по собственному URL автора. Если автор хочет попасть в главную ленту, он подаёт запрос на продвижение, и статья попадает в конвейер News Kingdom.
| Раньше в документации | Текущее поведение |
|---|---|
/blog/{username} и /blog/{username}/{slug} | /{username} (профиль) и /{username}/{slug} (статья) |
| Платное членство открывает блог | Для написания нужна роль member или выше. Платное повышение членства выдаёт роль member |
| Профиль показывает ссылку на блог и значок Telegram | На текущей странице профиля этого нет. Авторы делятся ссылкой из /my-news |
| Без членства маршрут блога возвращает 404 | Статья возвращает 404, если она не опубликована, имя или slug не совпадают либо отличается язык |
Нет. В ring/web нет ни маршрута /blog, ни перенаправления. Обновите распространённые ссылки на /{username}/{slug}.
Избранное работает через GET и POST /api/user/favorites с хуком useContentFavorite. Этот хук подключён к просмотру новостной статьи (components/wrappers/news-article-wrapper.tsx), а не к странице /{username}/{slug}.
Следующий шаг: что происходит после того, как автор подаёт запрос на продвижение на главную страницу.
Предпосылка: модуль новостей, который хранит и отображает статьи участников.
Тот же процесс: страница /{username}, которая использует то же имя участника.
Зависимость: как выбираются и защищаются имена, от которых зависят URL блогов.
Имена определяют URL блогов, поэтому зарезервированные имена имеют значение.
| Раздел | Путь |
|---|---|
| Написать новую статью | /news/create |
| Управлять, делиться и продвигать | /my-news |
| Публичная статья | /{username}/{slug} |
| Все статьи одного автора | /news/author/{username} |
lib/blog/blog-path.tsnormalizeBlogHandleprofileArticlePathnameprofileArticleHref| Абсолютный URL | lib/site-branding.ts localeBlogArticleUrl(locale, username, slug) |
| Действие сохранения | app/_actions/news.ts |
| Разрешения | features/news/lib/news-permissions.ts |
Страница статьи ищет в news одну строку, которая соответствует всем четырём фильтрам: blogUsername == normalizeBlogHandle(username), slug, locale и status == 'published'. Если ни одна строка не подходит, она вызывает notFound(), а метаданные переходят на noindex. Имена хранятся с начальным @, поэтому /en/alice/hello ищет blogUsername: '@alice'.
blogUsername проставляется только при создании и только тогда, когда у пользователя сессии есть имя пользователя. Статьи, написанные до того, как автор выбрал имя, никогда его не получают, поэтому они не будут открываться по адресу /{username}/{slug}. Для такого случая панель /my-news показывает подсказку задать имя пользователя.
Статические маршруты, например /store, /news или /about, имеют приоритет над динамическим сегментом [username]. Имя пользователя, совпадающее со статическим маршрутом, не может иметь URL профиля.
| Действие | Правило |
|---|---|
| Создание | canCreateNewsArticle: роль member или выше, администратор платформы или confidential |
| Редактирование или удаление | Администратор платформы или автор статьи |
Видимость site-wide | Только администраторы платформы. Участники получают её через одобрение продвижения |
Видимость confidential | Только пользователи с конфиденциальным доступом |
featured | При сохранении принудительно false для не-администраторов |
| Предложить правку | Вошедший пользователь, не являющийся автором, с canProposeRevision, для опубликованных статей |
Создание
Участник открывает /news/create. При сохранении app/_actions/news.ts записывает статью через createNewsArticle() с blogUsername и фиксирует первый коммит версии (lib/versioning).
Публикация и распространение
Установите status: 'published'. Панель /my-news формирует публичную ссылку из ROUTES.PUBLIC_PROFILE(handle) и предлагает кнопку копирования ссылки.
Продвижение (необязательно)
features/news/components/news-promotion-panel.tsx вызывает POST /api/news/promotion/submit с { articleId }. Подавать может только автор. Оценка, оплата и одобрение описаны в News Kingdom.
Каждый просмотр статьи учитывает recordArticlePageView() внутри after(), поэтому подсчёт никогда не блокирует рендеринг.
Имена определяют URL блогов, поэтому зарезервированные имена имеют значение.
| Раздел | Путь |
|---|---|
| Написать новую статью | /news/create |
| Управлять, делиться и продвигать | /my-news |
| Публичная статья | /{username}/{slug} |
| Все статьи одного автора | /news/author/{username} |
lib/blog/blog-path.tsnormalizeBlogHandleprofileArticlePathnameprofileArticleHref| Абсолютный URL | lib/site-branding.ts localeBlogArticleUrl(locale, username, slug) |
| Действие сохранения | app/_actions/news.ts |
| Разрешения | features/news/lib/news-permissions.ts |
Страница статьи ищет в news одну строку, которая соответствует всем четырём фильтрам: blogUsername == normalizeBlogHandle(username), slug, locale и status == 'published'. Если ни одна строка не подходит, она вызывает notFound(), а метаданные переходят на noindex. Имена хранятся с начальным @, поэтому /en/alice/hello ищет blogUsername: '@alice'.
blogUsername проставляется только при создании и только тогда, когда у пользователя сессии есть имя пользователя. Статьи, написанные до того, как автор выбрал имя, никогда его не получают, поэтому они не будут открываться по адресу /{username}/{slug}. Для такого случая панель /my-news показывает подсказку задать имя пользователя.
Статические маршруты, например /store, /news или /about, имеют приоритет над динамическим сегментом [username]. Имя пользователя, совпадающее со статическим маршрутом, не может иметь URL профиля.
| Действие | Правило |
|---|---|
| Создание | canCreateNewsArticle: роль member или выше, администратор платформы или confidential |
| Редактирование или удаление | Администратор платформы или автор статьи |
Видимость site-wide | Только администраторы платформы. Участники получают её через одобрение продвижения |
Видимость confidential | Только пользователи с конфиденциальным доступом |
featured | При сохранении принудительно false для не-администраторов |
| Предложить правку | Вошедший пользователь, не являющийся автором, с canProposeRevision, для опубликованных статей |
Создание
Участник открывает /news/create. При сохранении app/_actions/news.ts записывает статью через createNewsArticle() с blogUsername и фиксирует первый коммит версии (lib/versioning).
Публикация и распространение
Установите status: 'published'. Панель /my-news формирует публичную ссылку из ROUTES.PUBLIC_PROFILE(handle) и предлагает кнопку копирования ссылки.
Продвижение (необязательно)
features/news/components/news-promotion-panel.tsx вызывает POST /api/news/promotion/submit с { articleId }. Подавать может только автор. Оценка, оплата и одобрение описаны в News Kingdom.
Каждый просмотр статьи учитывает recordArticlePageView() внутри after(), поэтому подсчёт никогда не блокирует рендеринг.
Имена определяют URL блогов, поэтому зарезервированные имена имеют значение.
| Раздел | Путь |
|---|---|
| Написать новую статью | /news/create |
| Управлять, делиться и продвигать | /my-news |
| Публичная статья | /{username}/{slug} |
| Все статьи одного автора | /news/author/{username} |
lib/blog/blog-path.tsnormalizeBlogHandleprofileArticlePathnameprofileArticleHref| Абсолютный URL | lib/site-branding.ts localeBlogArticleUrl(locale, username, slug) |
| Действие сохранения | app/_actions/news.ts |
| Разрешения | features/news/lib/news-permissions.ts |
Страница статьи ищет в news одну строку, которая соответствует всем четырём фильтрам: blogUsername == normalizeBlogHandle(username), slug, locale и status == 'published'. Если ни одна строка не подходит, она вызывает notFound(), а метаданные переходят на noindex. Имена хранятся с начальным @, поэтому /en/alice/hello ищет blogUsername: '@alice'.
blogUsername проставляется только при создании и только тогда, когда у пользователя сессии есть имя пользователя. Статьи, написанные до того, как автор выбрал имя, никогда его не получают, поэтому они не будут открываться по адресу /{username}/{slug}. Для такого случая панель /my-news показывает подсказку задать имя пользователя.
Статические маршруты, например /store, /news или /about, имеют приоритет над динамическим сегментом [username]. Имя пользователя, совпадающее со статическим маршрутом, не может иметь URL профиля.
| Действие | Правило |
|---|---|
| Создание | canCreateNewsArticle: роль member или выше, администратор платформы или confidential |
| Редактирование или удаление | Администратор платформы или автор статьи |
Видимость site-wide | Только администраторы платформы. Участники получают её через одобрение продвижения |
Видимость confidential | Только пользователи с конфиденциальным доступом |
featured | При сохранении принудительно false для не-администраторов |
| Предложить правку | Вошедший пользователь, не являющийся автором, с canProposeRevision, для опубликованных статей |
Создание
Участник открывает /news/create. При сохранении app/_actions/news.ts записывает статью через createNewsArticle() с blogUsername и фиксирует первый коммит версии (lib/versioning).
Публикация и распространение
Установите status: 'published'. Панель /my-news формирует публичную ссылку из ROUTES.PUBLIC_PROFILE(handle) и предлагает кнопку копирования ссылки.
Продвижение (необязательно)
features/news/components/news-promotion-panel.tsx вызывает POST /api/news/promotion/submit с { articleId }. Подавать может только автор. Оценка, оплата и одобрение описаны в News Kingdom.
Каждый просмотр статьи учитывает recordArticlePageView() внутри after(), поэтому подсчёт никогда не блокирует рендеринг.