Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion public/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ DebateOwl runs at https://debateowl.com/. It is a separate product from debatela
## Key facts (as of October 2026)

- Who it is for: students, competitive debaters and their coaches.
- Who runs it: Ádám Gáborjáni, an independent student developer in Hungary. Pi-Stack (pi-stack.org) is the name he publishes his projects under, and Programcode is his GitHub username. Contact: hello@debateowl.com.
- 8 prep modes: Case generator, Brainstorm, Factoids, Flowchart, Case attacker, Ask coach, Crossfire and Sparring. Plus 3 utilities: Library, Debate timer and History.
- Case format: A DebateOwl case is written the way school debaters prepare: an opening, two to four arguments each with an explanation, evidence and why it matters, "If they say… we answer…" replies, a closing line and the sources it used.
- Second speech (R2): no new arguments; about two minutes reinforcing our arguments, then about four minutes of "If they say X, we answer Y" replies.
Expand All @@ -21,7 +22,7 @@ DebateOwl runs at https://debateowl.com/. It is a separate product from debatela

- [Home](https://debateowl.com/): what DebateOwl is, the 8 prep modes, pricing and FAQ
- [Pricing](https://debateowl.com/debateowl-pricing): trial, Pro and what each includes
- [About](https://debateowl.com/about): what DebateOwl is, who makes it and its former name
- [About](https://debateowl.com/about): what DebateOwl is, who runs it and its former name
- [Contact](https://debateowl.com/contact): email hello@debateowl.com for support and feedback, privacy@debateowl.com for privacy and data requests
- [Press kit and facts](https://debateowl.com/press): a one-sentence definition, former name, maker, languages, pricing, logo downloads and what DebateOwl is not
- [Full text](https://debateowl.com/llms-full.txt): this file plus the plain text of the home page, About, Which AI is best for debate? and the press kit
Expand Down
14 changes: 8 additions & 6 deletions scripts/check-site.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// references do not resolve or whose WebSite and SoftwareApplication are not
// named for the product, or a page whose publisher or about names an @id the
// home page does not define, or a home-page Organization not named for the
// product or without its logo and parent;
// product or without its logo and founder;
// - an indexed page without the favicon and 192px icon links, or whose meta
// author is not the organization;
// - two indexed pages with the same <title>, which then compete for one query;
Expand Down Expand Up @@ -174,14 +174,16 @@ function checkStructuredData(where, data, body) {
const sameAs = organization.sameAs;
// sameAs is optional (site.json lists only profiles that spell the name "DebateOwl"), but when present it is a non-empty list of https URLs.
if (sameAs !== undefined && (!Array.isArray(sameAs) || !sameAs.length || sameAs.some((url) => !url.startsWith('https://')))) report(where, 'Organization.sameAs is not a list of https URLs');
// One name for one entity: the Organization on this domain is the product, and the company
// that builds it is its parent, never a sameAs.
// One name for one entity: the Organization on this domain is the product, and the person
// who runs it is its founder, never a sameAs.
if (organization.name !== SITE.product) report(where, `Organization.name is "${organization.name}", not the product name "${SITE.product}"`);
const logo = organization.logo ?? {};
if (logo['@type'] !== 'ImageObject' || !logo.url?.startsWith(`${SITE_ORIGIN}/`) || !logo.width || !logo.height) report(where, 'Organization.logo is not an ImageObject on this site with a width and height');
const parent = organization.parentOrganization ?? {};
if (!parent.name || !parent.url) report(where, 'Organization.parentOrganization has no name and url');
else if (sameAs?.includes(parent.url)) report(where, `Organization.sameAs lists the parent ${parent.url}`);
const founder = organization.founder ?? {};
if (founder['@type'] !== 'Person' || !founder.name || !founder.url) report(where, 'Organization.founder is not a Person with a name and url');
else if (sameAs?.includes(founder.url)) report(where, `Organization.sameAs lists the founder ${founder.url}`);
// Pi-Stack is the name the founder publishes under, not a company: no parent organization or legal name.
if (organization.parentOrganization || organization.legalName) report(where, 'Organization has a parentOrganization or legalName');
const alternates = byType('WebSite').alternateName ?? [];
if (!alternates.some((name) => name !== SITE.product)) report(where, 'WebSite.alternateName only repeats the name');
}
Expand Down
4 changes: 3 additions & 1 deletion scripts/generate_seo_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
BRAND = SITE["brand"]
PRODUCT = SITE["product"]
ORGANIZATION = SITE["organization"]
OPERATOR = ORGANIZATION["operator"]
FORMERLY = SITE["formerly"]
PRICING = SITE["pricing"]
# Prices and plan facts are stated "as of" this month; move it when they are rechecked.
Expand Down Expand Up @@ -872,6 +873,7 @@ def llms_txt():
## Key facts (as of {FACTS_AS_OF})

- Who it is for: students, competitive debaters and their coaches.
- Who runs it: {OPERATOR["name"]}, an independent student developer in {OPERATOR["country"]}. Pi-Stack ({OPERATOR["publishesAs"]["url"].removeprefix("https://").rstrip("/")}) is the name he publishes his projects under, and {OPERATOR["github"].rsplit("/", 1)[1]} is his GitHub username. Contact: {SITE["contactEmail"]}.
- {len(PREP_MODES)} prep modes: {names(PREP_MODES)}. Plus {len(UTILITIES)} utilities: {names(UTILITIES)}.
- Case format: {CASE_FORMAT}
- {SITE["secondSpeech"]}
Expand All @@ -886,7 +888,7 @@ def llms_txt():

- [Home]({BASE}/): what {PRODUCT} is, the {len(PREP_MODES)} prep modes, pricing and FAQ
- [Pricing]({page_url("debateowl-pricing")}): trial, Pro and what each includes
- [About]({BASE}/about): what {PRODUCT} is, who makes it and its former name
- [About]({BASE}/about): what {PRODUCT} is, who runs it and its former name
- [Contact]({BASE}/contact): email {SITE["contactEmail"]} for support and feedback, {SITE["privacyEmail"]} for privacy and data requests
- [Press kit and facts]({BASE}/press): a one-sentence definition, former name, maker, languages, pricing, logo downloads and what {PRODUCT} is not
- [Full text]({BASE}/llms-full.txt): this file plus the plain text of the home page, About, Which AI is best for debate? and the press kit
Expand Down
11 changes: 8 additions & 3 deletions src/config/site.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,14 @@
"description": "DebateOwl (formerly DebateLab at debate.pi-stack.org) is an AI debate prep and practice app for students and competitive debaters.",
"disambiguatingDescription": "DebateOwl is an AI debate prep and practice app for students, not a sports or computer-vision product.",
"sameAs": ["https://github.com/Programcode/DebateOwl"],
"parent": {
"name": "Pi-Stack",
"url": "https://pi-stack.org/"
"operator": {
"name": "Ádám Gáborjáni",
"country": "Hungary",
"github": "https://github.com/Programcode",
"publishesAs": {
"name": "Pi-Stack",
"url": "https://pi-stack.org/"
}
}
},
"factsCheckedOn": "2026-10-20",
Expand Down
14 changes: 8 additions & 6 deletions src/lib/seo/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ export const ORGANIZATION_ID = `${SITE_ORIGIN}/#organization`;

/**
* The Organization behind the site, named for the product so search engines
* see one name for one entity. Pi-Stack, which builds it, is its parent, not a
* sameAs: a sameAs profile is the same entity elsewhere. site.json lists only
* profiles that spell the name "DebateOwl" and that DebateOwl itself runs; with
* none, the node has no sameAs. /press, the fact sheet, is its subjectOf.
* see one name for one entity. Its founder is the person who runs it; Pi-Stack
* is only the name he publishes under, not a company, so it appears as his URL
* and never as a parent organization or legal name. A sameAs profile is the same
* entity elsewhere: site.json lists only profiles that spell the name "DebateOwl"
* and that DebateOwl itself runs; with none, the node has no sameAs. /press, the
* fact sheet, is its subjectOf.
*/
export function organizationNode() {
const { name, logo, description, disambiguatingDescription, sameAs, parent } = site.organization;
const { name, logo, description, disambiguatingDescription, sameAs, operator } = site.organization;
return {
'@type': 'Organization',
'@id': ORGANIZATION_ID,
Expand All @@ -29,7 +31,7 @@ export function organizationNode() {
disambiguatingDescription,
email: site.contactEmail,
contactPoint: { '@type': 'ContactPoint', contactType: 'customer support', email: site.contactEmail, availableLanguage: ['en', 'hu', 'es'] },
parentOrganization: { '@type': 'Organization', '@id': `${parent.url}#organization`, name: parent.name, url: parent.url },
founder: { '@type': 'Person', name: operator.name, url: operator.publishesAs.url, sameAs: [operator.github] },
...(sameAs.length ? { sameAs } : {}),
subjectOf: { '@type': 'WebPage', '@id': `${SITE_ORIGIN}/press#webpage`, url: `${SITE_ORIGIN}/press`, name: PAGE_HEADS['/press'].title },
};
Expand Down
14 changes: 8 additions & 6 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@
"about": "About",
"contact": "Contact",
"press": "Press kit",
"copyright": "© 2026 Pi-Stack. All rights reserved.",
"copyright": "© 2026 Ádám Gáborjáni. All rights reserved.",
"formerly": "{{product}}, formerly DebateLab.",
"navLabel": "Footer",
"pricingGuide": "Pricing details",
Expand Down Expand Up @@ -1895,8 +1895,8 @@
"question": "What is {{product}}?",
"answer": "<home>{{product}}</home> is an AI debate prep and practice app for students and competitive debaters. It helps you write a case, find the weak points in an argument, research evidence with citations and practice timed rounds against an AI opponent.",
"notThis": "{{product}} is a debate app for students, not a sports or computer-vision product. The <press>press kit</press> has the short facts and the logo.",
"makerHeading": "Who makes it",
"maker": "{{product}} is built by a student developer and made by <pistack>Pi-Stack</pistack>.",
"makerHeading": "Who runs {{product}}",
"maker": "{{product}} is run by Ádám Gáborjáni, an independent student developer in Hungary. Pi-Stack (<pistack>pi-stack.org</pistack>) is the name he publishes his projects under, and <github>Programcode</github> is his GitHub username. Contact: <email>{{email}}</email>.",
"nameHeading": "The name",
"name": "{{product}} was called DebateLab, at debate.pi-stack.org, until {{date}}.",
"pricingHeading": "Pricing",
Expand All @@ -1916,7 +1916,7 @@
"formerlyLabel": "Former name",
"formerly": "{{name}}, at {{host}}, renamed on {{date}}",
"makerLabel": "Maker",
"maker": "Adam (<github>Programcode</github> on GitHub), a student developer in Hungary, published by <pistack>Pi-Stack</pistack>",
"maker": "Ádám Gáborjáni (<github>Programcode</github> on GitHub), an independent student developer in Hungary, who publishes his projects as Pi-Stack (<pistack>pi-stack.org</pistack>)",
"launchedLabel": "Launched",
"launched": "2026, under the name {{name}}",
"languagesLabel": "Languages",
Expand Down Expand Up @@ -1944,7 +1944,9 @@
"termsPage": {
"title": "Terms of Service",
"lastUpdated": "Last updated",
"date": "October 28, 2026",
"date": "November 2, 2026",
"operatorLabel": "Operator",
"operator": "{{product}} is operated by Ádám Gáborjáni, Hungary, publishing as Pi-Stack (<pistack>pi-stack.org</pistack>). Contact: <contact>{{contactEmail}}</contact>.",
"s1": "Acceptance of Terms",
"p1": "By using DebateOwl, you agree to these terms. If you do not agree, do not use the service.",
"s2": "Service Description",
Expand Down Expand Up @@ -2733,7 +2735,7 @@
},
"about": {
"title": "About {{product}} | {{brand}}",
"description": "{{product}} is an AI debate prep and practice app for students and competitive debaters, built by a student developer and made by Pi-Stack."
"description": "{{product}} is an AI debate prep and practice app for students and competitive debaters, run by Ádám Gáborjáni, an independent student developer in Hungary."
},
"contact": {
"title": "Contact | {{brand}}",
Expand Down
14 changes: 8 additions & 6 deletions src/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@
"about": "Acerca de",
"contact": "Contacto",
"press": "Kit de prensa",
"copyright": "© 2026 Pi-Stack. Todos los derechos reservados.",
"copyright": "© 2026 Ádám Gáborjáni. Todos los derechos reservados.",
"formerly": "{{product}}, antes DebateLab.",
"navLabel": "Pie de página",
"pricingGuide": "Detalles de precios",
Expand Down Expand Up @@ -1895,8 +1895,8 @@
"question": "¿Qué es {{product}}?",
"answer": "<home>{{product}}</home> es una app de preparación y práctica de debate con IA para estudiantes y debatientes de competición. Te ayuda a escribir un caso, encontrar los puntos débiles de un argumento, buscar evidencia con citas y practicar rondas cronometradas contra un oponente de IA.",
"notThis": "{{product}} es una app de debate para estudiantes, no un producto de deportes ni de visión por computadora. El <press>kit de prensa</press> reúne los datos básicos y el logotipo.",
"makerHeading": "Quién lo hace",
"maker": "{{product}} lo desarrolla una persona estudiante y lo publica <pistack>Pi-Stack</pistack>.",
"makerHeading": "Quién gestiona {{product}}",
"maker": "{{product}} lo gestiona Ádám Gáborjáni, un estudiante y desarrollador independiente de Hungría. Pi-Stack (<pistack>pi-stack.org</pistack>) es el nombre con el que publica sus proyectos, y <github>Programcode</github> es su nombre de usuario en GitHub. Contacto: <email>{{email}}</email>.",
"nameHeading": "El nombre",
"name": "{{product}} se llamaba DebateLab, en debate.pi-stack.org, hasta el {{date}}.",
"pricingHeading": "Precios",
Expand All @@ -1916,7 +1916,7 @@
"formerlyLabel": "Nombre anterior",
"formerly": "{{name}}, en {{host}}, renombrado el {{date}}",
"makerLabel": "Creador",
"maker": "Adam (<github>Programcode</github> en GitHub), estudiante y desarrollador en Hungría; lo publica <pistack>Pi-Stack</pistack>",
"maker": "Ádám Gáborjáni (<github>Programcode</github> en GitHub), estudiante y desarrollador independiente en Hungría, que publica sus proyectos como Pi-Stack (<pistack>pi-stack.org</pistack>)",
"launchedLabel": "Lanzamiento",
"launched": "2026, con el nombre {{name}}",
"languagesLabel": "Idiomas",
Expand Down Expand Up @@ -1944,7 +1944,9 @@
"termsPage": {
"title": "Términos de servicio",
"lastUpdated": "Última actualización",
"date": "28 de octubre de 2026",
"date": "2 de noviembre de 2026",
"operatorLabel": "Responsable",
"operator": "{{product}} lo gestiona Ádám Gáborjáni, en Hungría, que publica como Pi-Stack (<pistack>pi-stack.org</pistack>). Contacto: <contact>{{contactEmail}}</contact>.",
"s1": "Aceptación de términos",
"p1": "Al usar DebateOwl, aceptas estos términos. Si no estás de acuerdo, no uses el servicio.",
"s2": "Descripción del servicio",
Expand Down Expand Up @@ -2733,7 +2735,7 @@
},
"about": {
"title": "Acerca de {{product}} | {{brand}}",
"description": "{{product}} es una app de preparación y práctica de debate con IA para estudiantes, desarrollada por una persona estudiante y publicada por Pi-Stack."
"description": "{{product}} es una app de preparación y práctica de debate con IA para estudiantes, gestionada por Ádám Gáborjáni, un estudiante y desarrollador independiente de Hungría."
},
"contact": {
"title": "Contacto | {{brand}}",
Expand Down
14 changes: 8 additions & 6 deletions src/locales/hu.json
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@
"about": "Rólunk",
"contact": "Kapcsolat",
"press": "Sajtóanyag",
"copyright": "© 2026 Pi-Stack. Minden jog fenntartva.",
"copyright": "© 2026 Gáborjáni Ádám. Minden jog fenntartva.",
"formerly": "{{product}}, korábban DebateLab.",
"navLabel": "Lábléc",
"pricingGuide": "Árak részletei",
Expand Down Expand Up @@ -1895,8 +1895,8 @@
"question": "Mi az a {{product}}?",
"answer": "A <home>{{product}}</home> MI-alapú vitafelkészítő és gyakorló alkalmazás diákoknak és versenyzőknek. Segít megírni az esetet, megtalálni egy érvelés gyenge pontjait, hivatkozásokkal ellátott bizonyítékot keresni, és időre gyakorolni egy MI-ellenféllel.",
"notThis": "A {{product}} vitaalkalmazás diákoknak, nem sport- vagy gépilátás-termék. A <press>sajtóanyagban</press> megtalálod a rövid adatokat és a logót.",
"makerHeading": "Ki készíti",
"maker": "A {{product}} alkalmazást egy diák fejlesztő építi, és a <pistack>Pi-Stack</pistack> adja ki.",
"makerHeading": "Ki üzemelteti a {{product}}-t",
"maker": "A {{product}}-t Gáborjáni Ádám, egy magyarországi független diákfejlesztő üzemelteti. A Pi-Stack (<pistack>pi-stack.org</pistack>) az a név, amelyen a projektjeit közzéteszi, a <github>Programcode</github> pedig a GitHub-felhasználóneve. Kapcsolat: <email>{{email}}</email>.",
"nameHeading": "A név",
"name": "A {{product}} neve {{date}}-ig DebateLab volt, a debate.pi-stack.org címen.",
"pricingHeading": "Árak",
Expand All @@ -1916,7 +1916,7 @@
"formerlyLabel": "Korábbi név",
"formerly": "{{name}}, a {{host}} címen; átnevezve: {{date}}",
"makerLabel": "Készítő",
"maker": "Ádám (a GitHubon <github>Programcode</github>), magyarországi diák fejlesztő; kiadó: <pistack>Pi-Stack</pistack>",
"maker": "Gáborjáni Ádám (a GitHubon <github>Programcode</github>), magyarországi független diákfejlesztő, aki Pi-Stack néven teszi közzé a projektjeit (<pistack>pi-stack.org</pistack>)",
"launchedLabel": "Indulás",
"launched": "2026, {{name}} néven",
"languagesLabel": "Nyelvek",
Expand Down Expand Up @@ -1944,7 +1944,9 @@
"termsPage": {
"title": "Felhasználási feltételek",
"lastUpdated": "Utolsó frissítés",
"date": "2026. október 28.",
"date": "2026. november 2.",
"operatorLabel": "Üzemeltető",
"operator": "A {{product}}-t Gáborjáni Ádám, egy magyarországi független diákfejlesztő üzemelteti, aki Pi-Stack néven teszi közzé a projektjeit (<pistack>pi-stack.org</pistack>). Kapcsolat: <contact>{{contactEmail}}</contact>.",
"s1": "Feltételek elfogadása",
"p1": "A DebateOwl használatával elfogadod ezeket a feltételeket. Ha nem értesz egyet, ne használd a szolgáltatást.",
"s2": "Szolgáltatás leírása",
Expand Down Expand Up @@ -2733,7 +2735,7 @@
},
"about": {
"title": "A {{product}} bemutatása | {{brand}}",
"description": "A {{product}} MI-alapú vitafelkészítő és gyakorló alkalmazás diákoknak és versenyzőknek, amelyet egy diák fejlesztő épít, és a Pi-Stack ad ki."
"description": "A {{product}} MI-alapú vitafelkészítő és gyakorló alkalmazás diákoknak és versenyzőknek, amelyet Gáborjáni Ádám, egy magyarországi független diákfejlesztő üzemeltet."
},
"contact": {
"title": "Kapcsolat | {{brand}}",
Expand Down
13 changes: 11 additions & 2 deletions src/pages/AboutPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default function AboutPage() {
const { t, i18n } = useTranslation();
usePageHead('/about');
const product = site.product;
const { operator } = site.organization;
const renamedOn = new Intl.DateTimeFormat(i18n.language, { day: 'numeric', month: 'long', year: 'numeric', timeZone: 'UTC' })
.format(new Date(`${site.formerly.until}T00:00:00Z`));

Expand All @@ -30,9 +31,17 @@ export default function AboutPage() {
</p>
</section>
<section>
<h2 className="text-lg font-semibold">{t('aboutPage.makerHeading')}</h2>
<h2 className="text-lg font-semibold">{t('aboutPage.makerHeading', { product })}</h2>
<p>
<Trans i18nKey="aboutPage.maker" values={{ product }} components={{ pistack: <a href={site.organization.parent.url} className={linkClass} /> }} />
<Trans
i18nKey="aboutPage.maker"
values={{ product, email: site.contactEmail }}
components={{
pistack: <a href={operator.publishesAs.url} className={linkClass} />,
github: <a href={operator.github} className={linkClass} />,
email: <a href={`mailto:${site.contactEmail}`} className={linkClass} />,
}}
/>
</p>
</section>
<section>
Expand Down
Loading
Loading