From 2eb0ebcd34e85810115f689ba61b409213c30772 Mon Sep 17 00:00:00 2001 From: Elmehdi Aitbrahim Date: Fri, 21 Aug 2026 20:51:25 -0400 Subject: [PATCH] feat(community): plain-language how-to-post section for readers without a GitHub account MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The community page said where the conversation happens but not how to join it. Discussion #472 showed the gap: a first-time, non-technical participant only got in because the whole process was walked through by email. Adds a 'New here? How to post' card above the category list — account required (reading open), real name not required and email never shown, it is just a web page with a comment box — plus a four-step signup walkthrough and one sentence of category guidance (compliance/classification questions belong in Compliance & classification, not Q&A; wrong picks get moved). Each open category card now also deep-links to the composer with its category preselected (discussions/new?category=); Announcements gets no composer link because that category is maintainers-only. Copy in EN, AR and FR; rev and translatedFromRev bumped to 2026-08-21.1 per convention. The site still only reads and links — this explains how to reach the place where interaction happens. Closes #48 --- src/components/pages/CommunityPage.astro | 73 +++++++++- src/i18n/pages/community.ts | 172 ++++++++++++++++++++++- 2 files changed, 239 insertions(+), 6 deletions(-) diff --git a/src/components/pages/CommunityPage.astro b/src/components/pages/CommunityPage.astro index 7c4d6d6..db25e5c 100644 --- a/src/components/pages/CommunityPage.astro +++ b/src/components/pages/CommunityPage.astro @@ -1,6 +1,11 @@ --- import Base from "../../layouts/Base.astro"; -import { community, categoryUrl } from "../../i18n/pages/community"; +import { + community, + categoryUrl, + composerUrl, + maintainerOnlySlugs, +} from "../../i18n/pages/community"; import { alternatesFor, localePath, type Locale } from "../../i18n/config"; import { t } from "../../i18n/ui"; @@ -28,6 +33,32 @@ const chrome = t(locale);
+ {/* #48 — how to reach the conversation, for readers without a GitHub account. */} +
+

{c.howToPost.title}

+
    + { + c.howToPost.facts.map((fact) => ( +
  • + {fact.lead} {fact.rest} +
  • + )) + } +
+
    + { + c.howToPost.steps.map((step) => ( +
  1. + {step.before} + {step.link ? {step.link.label} : null} + {step.after} +
  2. + )) + } +
+

{c.howToPost.categoryGuide}

+
+
    { @@ -37,6 +68,11 @@ const chrome = t(locale);

    {category.name}

    {category.description}

    + {!maintainerOnlySlugs.has(category.slug) && ( + + {c.howToPost.startLabel} + + )} )) } @@ -55,3 +91,38 @@ const chrome = t(locale);
+ + diff --git a/src/i18n/pages/community.ts b/src/i18n/pages/community.ts index be8f95a..335a540 100644 --- a/src/i18n/pages/community.ts +++ b/src/i18n/pages/community.ts @@ -5,6 +5,10 @@ import type { LocalizedPage } from "../config"; * on the engine repo (verified slugs: announcements, compliance-classification, * general, ideas, polls, q-a, show-and-tell), each with one plain paragraph. * The site only reads and links — posting/voting happen on GitHub (non-goal). + * + * `howToPost` (#48) is the reader-facing exception to that silence: it explains + * how to reach the place where interaction happens. It says an account is + * required and a real name is not — never that a pseudonym is anonymity. */ export interface CommunityCategory { name: string; @@ -12,21 +16,62 @@ export interface CommunityCategory { description: string; } +export interface HowToFact { + /** The bolded lead — the rule or promise, in one sentence. */ + lead: string; + /** The rest of the fact, on the same line. */ + rest: string; +} + +export interface HowToStep { + /** Text before the embedded link (the whole step when there is no link). */ + before: string; + /** Rendered as a link between `before` and `after`. */ + link?: { label: string; href: string }; + /** Text after the link (may be empty). */ + after: string; +} + +export interface HowToPostContent { + title: string; + facts: HowToFact[]; + steps: HowToStep[]; + /** One-sentence category guidance, closing the section. */ + categoryGuide: string; + /** Label for the composer link on each open category card. */ + startLabel: string; +} + export interface CommunityContent { rev: string; title: string; description: string; intro: string[]; note: string; + howToPost: HowToPostContent; categories: CommunityCategory[]; translatedFromRev?: string; } const SLUG_BASE = "https://github.com/CodeGateSoftware/keel/discussions/categories"; +const NEW_BASE = "https://github.com/CodeGateSoftware/keel/discussions/new"; + +/** + * GitHub's composer with a category preselected — …/discussions/new?category= + * (verified working for compliance-classification on 2026-08-21). + */ +export const composerUrl = (slug: string) => `${NEW_BASE}?category=${slug}`; + +/** + * Announcement-type categories only let maintainers open discussions, so those + * cards get no composer link — a link that ends in a permission wall would not + * be honest (#48's own rule). + */ +export const maintainerOnlySlugs = new Set(["announcements"]); export const community: LocalizedPage = { en: { - rev: "2026-08-20.2", + rev: "2026-08-21.1", title: "keel Community on GitHub Discussions", description: "Questions, ideas, polls, and classification debate happen on GitHub Discussions. The site only reads and links — interaction stays where the project lives.", @@ -34,6 +79,45 @@ export const community: LocalizedPage = { "Everything community-shaped happens on GitHub Discussions — posting, voting, polling, answering. This website deliberately has none of that: it reads and links, because that is where the project, its history, and its moderation already live.", ], note: "One category deserves a special mention: Compliance & classification. “Should X be treated this way?” is a question, not a bug — and there is a place for it.", + howToPost: { + title: "New here? How to post", + facts: [ + { + lead: "You need a free GitHub account to post", + rest: "— reading is open to everyone.", + }, + { + lead: "You do not need to use your real name.", + rest: "Pick any username you like. Your email address stays private and is never shown.", + }, + { + lead: "It is just a web page with a comment box.", + rest: "Nothing installs on your computer, and you can edit or delete anything you post.", + }, + ], + steps: [ + { + before: "Sign up at ", + link: { label: "github.com/signup", href: "https://github.com/signup" }, + after: " — an email, a password, a username of your choosing.", + }, + { + before: "Enter the code they email you, and complete the “are you human” check. Around two minutes.", + after: "", + }, + { + before: "Use a “Start a discussion” button below — it opens the form with the category already chosen.", + after: "", + }, + { + before: "Title, then your question, then “Start discussion”.", + after: "", + }, + ], + categoryGuide: + "Not sure which category? Compliance & classification for “should X be treated this way”, Q&A for running or configuring keel, General for anything else. Picking the wrong one is not a problem — it can be moved.", + startLabel: "Start a discussion", + }, categories: [ { name: "Announcements", @@ -74,8 +158,8 @@ export const community: LocalizedPage = { }, ar: { - rev: "2026-08-20.2", - translatedFromRev: "2026-08-20.2", + rev: "2026-08-21.1", + translatedFromRev: "2026-08-21.1", title: "مجتمع كيل على نقاشات GitHub", description: "الأسئلة والأفكار واستطلاعات الرأي ونقاش التصنيف تجري في نقاشات GitHub. وهذا الموقع يقرأ ويربط فقط — ويبقى التفاعل حيث يعيش المشروع.", @@ -83,6 +167,45 @@ export const community: LocalizedPage = { "كلُّ ما هو مجتمعيٌّ يحدث في نقاشات GitHub — النشر والتصويت واستطلاع الرأي والإجابة. وهذا الموقع لا يملك شيئًا من ذلك عن قصد: فهو يقرأ ويربط، لأن المشروع وتاريخه وإدارته موجودةٌ هناك أصلًا.", ], note: "وثمّة فئةٌ تستحق ذكرًا خاصًّا: «الامتثال والتصنيف». فسؤال «هل ينبغي أن يُعامَل X بهذه الطريقة؟» سؤالٌ لا بلاغُ خلل — وله مكانٌ مخصّص.", + howToPost: { + title: "جديدٌ هنا؟ كيف تنشر", + facts: [ + { + lead: "تحتاج إلى حساب GitHub مجاني لتنشر", + rest: "— أمّا القراءة فمفتوحةٌ للجميع.", + }, + { + lead: "لستَ مضطرًّا لاستخدام اسمك الحقيقي.", + rest: "اختر أيَّ اسمِ مستخدمٍ شئت. بريدك الإلكتروني يبقى خاصًّا ولا يُعرَض أبدًا.", + }, + { + lead: "إنها مجردُ صفحةِ ويبٍ فيها صندوقُ تعليق.", + rest: "لا شيء يُثبَّت على حاسوبك، ويمكنك تعديل كلِّ ما تنشره أو حذفه.", + }, + ], + steps: [ + { + before: "أنشئ حسابًا على ", + link: { label: "github.com/signup", href: "https://github.com/signup" }, + after: " — بريدٌ إلكتروني، وكلمةُ سرٍّ، واسمُ مستخدمٍ من اختيارك.", + }, + { + before: "أدخِل الرمزَ الذي يصلك بالبريد، ثم أكمِل فحص «هل أنت إنسان». نحو دقيقتين.", + after: "", + }, + { + before: "استخدم زرَّ «ابدأ نقاشًا» في الأسفل — يفتح الاستمارة والفئةُ محدَّدةٌ سلفًا.", + after: "", + }, + { + before: "العنوان أولًا، ثم سؤالك، ثم «ابدأ نقاشًا».", + after: "", + }, + ], + categoryGuide: + "مترددٌ في اختيار الفئة؟ «الامتثال والتصنيف» لأسئلة «هل يُعامَل X بهذه الطريقة؟»، و«الأسئلة والأجوبة» لتشغيل كيل وإعداده، و«عام» لأيِّ شيءٍ آخر. اختيارُ الفئة الخطأ ليس مشكلة — يمكن نقل النقاش.", + startLabel: "ابدأ نقاشًا", + }, categories: [ { name: "Announcements", @@ -123,8 +246,8 @@ export const community: LocalizedPage = { }, fr: { - rev: "2026-08-20.2", - translatedFromRev: "2026-08-20.2", + rev: "2026-08-21.1", + translatedFromRev: "2026-08-21.1", title: "La communauté keel — sur GitHub, par choix", description: "Questions, idées, sondages et débats de classification ont lieu dans les Discussions GitHub de keel. Ce site se contente de lire et de renvoyer : l'échange reste là où vit le projet.", @@ -132,6 +255,45 @@ export const community: LocalizedPage = { "Tout ce qui relève de la communauté se passe dans les Discussions GitHub — publier, voter, sonder, répondre. Ce site n'offre délibérément aucune de ces fonctions : il lit et il renvoie, parce que le projet, son histoire et sa modération vivent déjà là-bas.", ], note: "Une catégorie mérite une mention particulière : Conformité et classification. « X doit-il être traité ainsi ? » est une question, pas un bug — et elle a son espace dédié.", + howToPost: { + title: "Nouveau ici ? Comment publier", + facts: [ + { + lead: "Il faut un compte GitHub gratuit pour publier", + rest: "— la lecture, elle, reste ouverte à tous.", + }, + { + lead: "Votre vrai nom n'est pas nécessaire.", + rest: "Choisissez l'identifiant qu'il vous plaît. Votre adresse e-mail reste privée et n'est jamais affichée.", + }, + { + lead: "C'est juste une page web avec une zone de commentaire.", + rest: "Rien ne s'installe sur votre ordinateur, et vous pouvez modifier ou supprimer tout ce que vous publiez.", + }, + ], + steps: [ + { + before: "Inscrivez-vous sur ", + link: { label: "github.com/signup", href: "https://github.com/signup" }, + after: " — une adresse e-mail, un mot de passe, un identifiant de votre choix.", + }, + { + before: "Saisissez le code reçu par e-mail, puis passez la vérification « êtes-vous humain ». Deux minutes, à peu près.", + after: "", + }, + { + before: "Servez-vous d'un bouton « Lancer une discussion » ci-dessous — il ouvre le formulaire avec la catégorie déjà choisie.", + after: "", + }, + { + before: "Un titre, puis votre question, puis « Lancer la discussion ».", + after: "", + }, + ], + categoryGuide: + "Pas sûr de la catégorie ? « Conformité et classification » pour « X doit-il être traité ainsi ? », « Questions et réponses » pour utiliser ou configurer keel, « Général » pour tout le reste. Se tromper de catégorie n'est pas un problème — une discussion peut être déplacée.", + startLabel: "Lancer une discussion", + }, categories: [ { name: "Announcements",