From ce56513f3aa886639b0b1b43185338f807768585 Mon Sep 17 00:00:00 2001 From: barckcode Date: Mon, 19 Oct 2026 14:58:16 +0200 Subject: [PATCH 1/2] =?UTF-8?q?fix(landing):=20say=20that=20the=2014,99?= =?UTF-8?q?=E2=82=AC=20community=20tier=20has=20no=20inference=20or=20API?= =?UTF-8?q?=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prospects bought the 14,99€ NaN Community plan expecting the personal API key the 70€ tier sells, and cancelled within the hour. Their cancellation feedback says where they read it: "NO SE PUEDE USAR SIN CONTRATAR EL PLAN DE $70" (pricing card promised an inference upgrade on demand), "I bougth these because the docs said that I can create an API KEY" (the FAQ said "each member gets a personal API key", and the docs said "you have to be a member of the NaN community", which a 14,99€ buyer satisfies literally). The negative half of the offer is now stated before the Checkout: - pricing card: a note under the bullets, rendered as its own element, plus a bullet that no longer promises an inference upgrade on demand; - the cluster FAQ and both docs intros name nan_member (70€/mo) as the plan that owns the key, in English and Spanish; - the dead i18n docs keys are corrected too, so they cannot ship stale. Evidence: 31 cancellations in one week on this tier, 20 of them under an hour after Checkout, with the comments above in Stripe cancellation_details. Tests pin the four surfaces in both locales, and the docs are read from disk so the fix cannot be remembered in only one language. --- i18n/en.json | 7 +-- i18n/es.json | 7 +-- src/components/nan/home/Pricing.astro | 20 ++++++++ src/content/docs-es/getting-started.mdx | 2 +- src/content/docs-es/intro.md | 2 +- src/content/docs/getting-started.mdx | 2 +- src/content/docs/intro.md | 2 +- src/tests/landing/pricing.test.ts | 63 +++++++++++++++++++++++++ 8 files changed, 95 insertions(+), 10 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index 35b31b7c..bfc5585f 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -361,8 +361,9 @@ "Member-only channels", "Live discussions, builds, AMAs", "Events, workshops and hackathons", - "Upgrade to inference whenever you want" + "Inference not included: it lives in nan_member" ], + "communityNote": "Discord and events only: no API key and no model calls. Inference is included in nan_member (70€/mo).", "communityCond": "No commitment. Cancel anytime. Billed in euros from any region.", "communityCta": "Join the community", "premiumIncludes": [ @@ -424,7 +425,7 @@ }, { "q": "How does the cluster work?", - "a": "The models run 24/7 on a shared inference cluster. Each member gets a personal API key compatible with OpenAI: change the base_url and you're in." + "a": "The models run 24/7 on a shared inference cluster. Each nan_member (70€/mo, inference included) gets a personal API key compatible with OpenAI: change the base_url and you're in. The 14,99€ NaN Community plan runs no models and has no API key." }, { "q": "Is it really unlimited tokens?", @@ -521,7 +522,7 @@ "leadA": "This doc explains how to connect your tools to our GPUs. The cluster runs open models with an OpenAI-compatible API. If something accepts a ", "leadB": ", it works with NaN.", "apiKeyH": "Your API key", - "apiKeyP1": "To get your API key you must be a NaN community member. Generate it from your user settings under ", + "apiKeyP1": "To get your API key you need the nan_member plan (70€/mo, inference included). The 14,99€ NaN Community plan has no inference and cannot create a key. Generate it from your user settings under ", "apiKeyStrong": "API Keys", "apiKeyP2": " on ", "apiKeyP3": ". It is personal and non-transferable.", diff --git a/i18n/es.json b/i18n/es.json index 2732302c..b47976d6 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -361,8 +361,9 @@ "Canales solo para miembros", "Charlas en directo, builds, AMAs", "Eventos, workshops y hackathons", - "Pasa a inferencia cuando quieras" + "Inferencia no incluida: está en nan_member" ], + "communityNote": "Solo Discord y eventos: sin API key y sin llamadas a modelos. La inferencia está incluida en nan_member (70€/mes).", "communityCond": "Sin compromiso. Cancela cuando quieras. Se factura en euros desde cualquier región.", "communityCta": "Únete a la comunidad", "premiumIncludes": [ @@ -424,7 +425,7 @@ }, { "q": "¿Cómo funciona el cluster?", - "a": "Los modelos corren 24/7 en un cluster de inferencia compartido. Cada miembro recibe una API key personal compatible con OpenAI: cambias el base_url y ya estás dentro." + "a": "Los modelos corren 24/7 en un cluster de inferencia compartido. Cada miembro de nan_member (70€/mes, con inferencia incluida) recibe una API key personal compatible con OpenAI: cambias el base_url y ya estás dentro. El plan NaN Community de 14,99€ no corre modelos y no tiene API key." }, { "q": "¿De verdad son tokens ilimitados?", @@ -521,7 +522,7 @@ "leadA": "Esta doc explica cómo conectar tus herramientas a nuestras GPUs. El cluster corre modelos abiertos con una API compatible con OpenAI. Si algo acepta un ", "leadB": ", funciona con NaN.", "apiKeyH": "Tu API key", - "apiKeyP1": "Para conseguir tu API key tienes que ser miembro de la comunidad NaN. Genérala desde los ajustes de tu usuario, en ", + "apiKeyP1": "Para conseguir tu API key necesitas el plan nan_member (70€/mes, con inferencia incluida). El plan NaN Community de 14,99€ no tiene inferencia y no puede generar una key. Genérala desde los ajustes de tu usuario, en ", "apiKeyStrong": "API Keys", "apiKeyP2": ", en ", "apiKeyP3": ". Es personal e intransferible.", diff --git a/src/components/nan/home/Pricing.astro b/src/components/nan/home/Pricing.astro index ef8baa43..0fbf44fc 100644 --- a/src/components/nan/home/Pricing.astro +++ b/src/components/nan/home/Pricing.astro @@ -26,6 +26,7 @@ const tiers = [ badge: tt.premiumBadge, ref: true, includes: tt.premiumIncludes, + note: null, cond: tt.premiumCond, cta: tt.premiumCta, href: signupUrl('premium'), @@ -38,6 +39,7 @@ const tiers = [ badge: tt.inferenceIncluded, ref: true, includes: tt.memberIncludes, + note: null, cond: tt.memberCond, cta: tt.memberCta, href: signupUrl('inference'), @@ -50,6 +52,10 @@ const tiers = [ badge: null, ref: false, includes: tt.communityIncludes, + // The negative half of the offer, stated before the Checkout rather than + // only on /community: prospects bought 14,99€ expecting the API key the + // 70€ tier sells and cancelled within the hour. See communityNote. + note: tt.communityNote, cond: tt.communityCond, cta: tt.communityCta, href: signupUrl('community'), @@ -101,6 +107,7 @@ const wsDocs = lang === 'es' ? '/es/docs/workspaces' : '/docs/workspaces'; + {tier.note &&

{tier.note}

} **Para conseguir tu API Key** -> Tienes que ser miembro de la comunidad de NaN. Puedes generar tu API Key desde los ajustes de usuario, en el apartado "API Keys" de la [plataforma](https://cloud.nan.builders/). La key es personal e intransferible. +> Necesitas el plan **nan_member** (70€/mes): es el que incluye inferencia. Puedes generar tu API Key desde los ajustes de usuario, en el apartado "API Keys" de la [plataforma](https://cloud.nan.builders/). El plan NaN Community de 14,99€ cubre solo Discord y eventos: no corre modelos y no puede generar una key. La key es personal e intransferible. ## Lo esencial diff --git a/src/content/docs/getting-started.mdx b/src/content/docs/getting-started.mdx index e4c62ce9..79c37f7f 100644 --- a/src/content/docs/getting-started.mdx +++ b/src/content/docs/getting-started.mdx @@ -23,7 +23,7 @@ The NaN API is OpenAI-compatible. You only need two things, a **base URL** and a ### Get your API key -You have to be a member of the NaN community. Go to [cloud.nan.builders](https://cloud.nan.builders/), open your user settings and go to the **API Keys** section to generate yours. +You need the **nan_member** plan (70€/mo, inference included). The 14,99€ NaN Community plan runs no models, so it has no API key. Go to [cloud.nan.builders](https://cloud.nan.builders/), open your user settings and go to the **API Keys** section to generate yours. The key is personal, non-transferable, and shown only once: copy it as soon as you generate it. If you lose it, nothing breaks, generate another one and delete the old one from the same panel. diff --git a/src/content/docs/intro.md b/src/content/docs/intro.md index dfb8d6db..6b6f5f47 100644 --- a/src/content/docs/intro.md +++ b/src/content/docs/intro.md @@ -10,7 +10,7 @@ group: Get started This documentation explains how to connect your tools to our GPUs. The cluster runs open models behind an OpenAI-compatible API. If something accepts a `base URL` and an `API key`, it works with NaN. The exception is a tool that speaks a different protocol: [Claude Code](/docs/claude-code) talks to Anthropic's API, not to an OpenAI-compatible one, so it reaches the cluster through OpenCode or through a local gateway. Its page explains both. > **To get your API Key** -> You have to be a member of the NaN community. You can generate your API Key from the user settings, under "API Keys" on the [platform](https://cloud.nan.builders/). The key is personal and non-transferable. +> You need the **nan_member** plan (70€/mo): it is the one with inference included. Generate the key from the user settings, under "API Keys", on the [platform](https://cloud.nan.builders/). The 14,99€ NaN Community plan covers Discord and events only, so it runs no models and cannot create a key. The key is personal and non-transferable. ## The essentials diff --git a/src/tests/landing/pricing.test.ts b/src/tests/landing/pricing.test.ts index fc5a3e55..7ce66de3 100644 --- a/src/tests/landing/pricing.test.ts +++ b/src/tests/landing/pricing.test.ts @@ -270,3 +270,66 @@ describe('Pricing section — workspaces block', () => { expect(source.indexOf('id="workspaces"')).toBeGreaterThan(source.indexOf('tiers.map(')); }); }); + +/** + * The 14,99€ community tier sells Discord and events. It has never sold + * inference, but three surfaces said otherwise or said it ambiguously, and + * prospects paid, found out, and cancelled within the hour: + * + * - the pricing card's last bullet promised "upgrade to inference whenever + * you want", while the upgrade is a manual invite when capacity frees up; + * - the FAQ said "each member gets a personal API key", on a page whose + * cheapest tier is "NaN Community"; + * - the docs said "you have to be a member of the NaN community", which the + * 14,99€ buyer satisfies literally and cannot act on. + * + * Members wrote it verbatim in their cancellation feedback ("NO SE PUEDE USAR + * SIN CONTRATAR EL PLAN DE $70", "the docs said that I can create an API + * KEY"), so these asserts are the memory of that bill. + */ +describe.each(locales)('Pricing copy — community tier is Discord only (%s)', (locale) => { + test('states before the Checkout that inference and the API key are not included', () => { + const note = t('nan.pricing.communityNote', locale); + expect(note).toMatch(/nan_member/); + expect(note).toMatch(/API key/i); + expect(note).toMatch(/70€/); + expect(note).toMatch(/(no API key|sin API key)/i); + }); + + test('the bullets never promise inference on demand', () => { + const copy = tArr('nan.pricing.communityIncludes', locale).join(' '); + expect(copy).toMatch(/(not included|no incluida)/i); + expect(copy).not.toMatch(/upgrade to inference whenever|API key personal/i); + expect(copy).not.toMatch(/Personal API key compatible|API key personal compatible/i); + }); + + test('the cluster FAQ names the plan that owns the key', () => { + const faq = tObj<{ items?: FaqItem[] }>('nan.faq', locale); + const answer = (faq.items ?? []).map((item) => item.a).find((a) => /API key/i.test(a)); + expect(answer).toBeDefined(); + expect(answer).toMatch(/nan_member/); + expect(answer).toMatch(/70€/); + }); + + test('the card renders the note, so the copy cannot sit unused in the dictionary', () => { + expect(tiers).toContain('note: tt.communityNote'); + expect(source).toContain('{tier.note &&

{tier.note}

}'); + }); + + /** + * The docs are where the churned members said they read it, and both locales + * ship their own files, so both are read here rather than trusting the fix to + * be remembered twice. + */ + test('the docs send a buyer to nan_member before saying how to create a key', () => { + const files = + locale === 'en' + ? ['src/content/docs/intro.md', 'src/content/docs/getting-started.mdx'] + : ['src/content/docs-es/intro.md', 'src/content/docs-es/getting-started.mdx']; + for (const file of files) { + const body = readFileSync(resolve(here, '../../../', file), 'utf-8'); + expect(body, file).toMatch(/nan_member/); + expect(body, file).not.toMatch(/(have to be a member of the NaN community|ser miembro de la comunidad de? ?NaN)/i); + } + }); +}); From bb4d6bf9f1e90aa15cc8473efc48de5c174e5a2e Mon Sep 17 00:00:00 2001 From: barckcode Date: Mon, 19 Oct 2026 15:30:06 +0200 Subject: [PATCH 2/2] refactor(landing): one negative line for the community tier; docs name both inference plans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Applies the three non-blocking notes from the blocking UX review: - The negative bullet is gone: a "not included" line inside a bulleted list of inclusions inherits the violet included dot and reads as a feature. The single negative line is communityNote, rendered directly above the CTA. - nan.pricing.sub said inference is "the superpower you add", which read as an add-on to the cheap tier. It now says it is added on nan_member. - The docs named only nan_member as the plan that owns the API key. GLM 5.3 premium (200€/mo) also includes it, so both are named (EN/ES), which was the Security reviewer's accuracy nit. The bullets test is now stricter in the useful direction: the list must not mention inference or an API key at all, so the note cannot be duplicated back into it, and pricing.sub must name nan_member. --- i18n/en.json | 5 ++--- i18n/es.json | 5 ++--- src/content/docs-es/getting-started.mdx | 2 +- src/content/docs-es/intro.md | 2 +- src/content/docs/getting-started.mdx | 2 +- src/content/docs/intro.md | 2 +- src/tests/landing/pricing.test.ts | 14 +++++++++++--- 7 files changed, 19 insertions(+), 13 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index bfc5585f..4f6d23a5 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -341,7 +341,7 @@ "label": "membership", "title1": "One community.", "title2": "Two tiers. One premium path.", - "sub": "The community is the product. Inference is the superpower you add; GLM 5.3 is the frontier option for members.", + "sub": "The community is the product. Inference is the superpower you add on nan_member; GLM 5.3 is the frontier option for members.", "perVat": "/mo · VAT included", "perTaxes": "/mo · taxes included", "inferenceIncluded": "inference included", @@ -360,8 +360,7 @@ "Discord access", "Member-only channels", "Live discussions, builds, AMAs", - "Events, workshops and hackathons", - "Inference not included: it lives in nan_member" + "Events, workshops and hackathons" ], "communityNote": "Discord and events only: no API key and no model calls. Inference is included in nan_member (70€/mo).", "communityCond": "No commitment. Cancel anytime. Billed in euros from any region.", diff --git a/i18n/es.json b/i18n/es.json index b47976d6..06cb0df1 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -341,7 +341,7 @@ "label": "membresía", "title1": "Una comunidad.", "title2": "Dos tiers. Un camino premium.", - "sub": "La comunidad es el producto. La inferencia es el superpoder que le añades; GLM 5.3 es la opción frontier para miembros.", + "sub": "La comunidad es el producto. La inferencia es el superpoder que se añade con nan_member; GLM 5.3 es la opción frontier para miembros.", "perVat": "/mes · IVA incluido", "perTaxes": "/mes · impuestos incluidos", "inferenceIncluded": "inferencia incluida", @@ -360,8 +360,7 @@ "Acceso a Discord", "Canales solo para miembros", "Charlas en directo, builds, AMAs", - "Eventos, workshops y hackathons", - "Inferencia no incluida: está en nan_member" + "Eventos, workshops y hackathons" ], "communityNote": "Solo Discord y eventos: sin API key y sin llamadas a modelos. La inferencia está incluida en nan_member (70€/mes).", "communityCond": "Sin compromiso. Cancela cuando quieras. Se factura en euros desde cualquier región.", diff --git a/src/content/docs-es/getting-started.mdx b/src/content/docs-es/getting-started.mdx index 1cd7b334..9024148c 100644 --- a/src/content/docs-es/getting-started.mdx +++ b/src/content/docs-es/getting-started.mdx @@ -23,7 +23,7 @@ La API de NaN es compatible con OpenAI. Solo necesitas dos datos, una **base URL ### Consigue tu API key -Necesitas el plan **nan_member** (70€/mes, con inferencia incluida). El plan NaN Community de 14,99€ no corre modelos, así que no tiene API key. Entra en [cloud.nan.builders](https://cloud.nan.builders/), abre los ajustes de usuario y ve a la sección **API Keys** para generar la tuya. +Necesitas **nan_member** (70€/mes) o GLM 5.3 premium (200€/mes): los dos incluyen inferencia. El plan NaN Community de 14,99€ no corre modelos, así que no tiene API key. Entra en [cloud.nan.builders](https://cloud.nan.builders/), abre los ajustes de usuario y ve a la sección **API Keys** para generar la tuya. La clave es personal e intransferible, y se muestra una sola vez: cópiala en cuanto la generes. Si la pierdes, no pasa nada, genera otra y borra la vieja desde el mismo panel. diff --git a/src/content/docs-es/intro.md b/src/content/docs-es/intro.md index f68773c3..364d0176 100644 --- a/src/content/docs-es/intro.md +++ b/src/content/docs-es/intro.md @@ -10,7 +10,7 @@ group: Primeros pasos Esta documentación explica cómo conectar tus herramientas a nuestras GPUs. El clúster ejecuta modelos abiertos con una API compatible con OpenAI. Si algo acepta una `base URL` y una `API key`, funciona con NaN. La excepción es una herramienta que hable otro protocolo: [Claude Code](/es/docs/claude-code) habla con la API de Anthropic, no con una compatible con OpenAI, así que llega al clúster a través de OpenCode o de una pasarela local. Su página explica las dos formas. > **Para conseguir tu API Key** -> Necesitas el plan **nan_member** (70€/mes): es el que incluye inferencia. Puedes generar tu API Key desde los ajustes de usuario, en el apartado "API Keys" de la [plataforma](https://cloud.nan.builders/). El plan NaN Community de 14,99€ cubre solo Discord y eventos: no corre modelos y no puede generar una key. La key es personal e intransferible. +> Necesitas un plan con inferencia: **nan_member** (70€/mes) o GLM 5.3 premium (200€/mes). Puedes generar tu API Key desde los ajustes de usuario, en el apartado "API Keys" de la [plataforma](https://cloud.nan.builders/). El plan NaN Community de 14,99€ cubre solo Discord y eventos: no corre modelos y no puede generar una key. La key es personal e intransferible. ## Lo esencial diff --git a/src/content/docs/getting-started.mdx b/src/content/docs/getting-started.mdx index 79c37f7f..c342e739 100644 --- a/src/content/docs/getting-started.mdx +++ b/src/content/docs/getting-started.mdx @@ -23,7 +23,7 @@ The NaN API is OpenAI-compatible. You only need two things, a **base URL** and a ### Get your API key -You need the **nan_member** plan (70€/mo, inference included). The 14,99€ NaN Community plan runs no models, so it has no API key. Go to [cloud.nan.builders](https://cloud.nan.builders/), open your user settings and go to the **API Keys** section to generate yours. +You need **nan_member** (70€/mo) or GLM 5.3 premium (200€/mo): both include inference. The 14,99€ NaN Community plan runs no models, so it has no API key. Go to [cloud.nan.builders](https://cloud.nan.builders/), open your user settings and go to the **API Keys** section to generate yours. The key is personal, non-transferable, and shown only once: copy it as soon as you generate it. If you lose it, nothing breaks, generate another one and delete the old one from the same panel. diff --git a/src/content/docs/intro.md b/src/content/docs/intro.md index 6b6f5f47..bcda7537 100644 --- a/src/content/docs/intro.md +++ b/src/content/docs/intro.md @@ -10,7 +10,7 @@ group: Get started This documentation explains how to connect your tools to our GPUs. The cluster runs open models behind an OpenAI-compatible API. If something accepts a `base URL` and an `API key`, it works with NaN. The exception is a tool that speaks a different protocol: [Claude Code](/docs/claude-code) talks to Anthropic's API, not to an OpenAI-compatible one, so it reaches the cluster through OpenCode or through a local gateway. Its page explains both. > **To get your API Key** -> You need the **nan_member** plan (70€/mo): it is the one with inference included. Generate the key from the user settings, under "API Keys", on the [platform](https://cloud.nan.builders/). The 14,99€ NaN Community plan covers Discord and events only, so it runs no models and cannot create a key. The key is personal and non-transferable. +> You need an inference plan: **nan_member** (70€/mo) or GLM 5.3 premium (200€/mo). Generate the key from the user settings, under "API Keys", on the [platform](https://cloud.nan.builders/). The 14,99€ NaN Community plan covers Discord and events only, so it runs no models and cannot create a key. The key is personal and non-transferable. ## The essentials diff --git a/src/tests/landing/pricing.test.ts b/src/tests/landing/pricing.test.ts index 7ce66de3..d427390f 100644 --- a/src/tests/landing/pricing.test.ts +++ b/src/tests/landing/pricing.test.ts @@ -296,11 +296,19 @@ describe.each(locales)('Pricing copy — community tier is Discord only (%s)', ( expect(note).toMatch(/(no API key|sin API key)/i); }); + /** + * The bullets sell what the plan gives. Inference is the note's job, so the + * list must not mention it at all: a negative line in a bulleted list of + * inclusions inherits the violet "included" dot and reads as a feature. + */ test('the bullets never promise inference on demand', () => { const copy = tArr('nan.pricing.communityIncludes', locale).join(' '); - expect(copy).toMatch(/(not included|no incluida)/i); - expect(copy).not.toMatch(/upgrade to inference whenever|API key personal/i); - expect(copy).not.toMatch(/Personal API key compatible|API key personal compatible/i); + expect(copy).not.toMatch(/inference|inferencia|API key/i); + }); + + test('the section intro does not sell inference as an add-on to the cheap tier', () => { + const sub = t('nan.pricing.sub', locale); + expect(sub).toMatch(/nan_member/); }); test('the cluster FAQ names the plan that owns the key', () => {