Ctrl K
ComunidadGuías…

lib/comparisons.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import type { Namespace } from "@/lib/i18n-keys";

import type { PublicRouteKey } from "@/lib/public-routes";

/**
 * The public comparison catalog for Linear, Jira, and Notion.
 * Compare documented workflows and billing models, acknowledge each product's
 * strengths, and keep current Minddy capabilities separate from competitor claims.
 * Refresh the review date only after checking the linked official sources.
 */
export const COMPARISON_REVIEWED_AT = "2026-09-05";

export interface Comparison {
  /** URL segment for `/alternatives/<slug>`. */
  slug: string;
  /** Proper name of the competitor — never translated, never in the i18n catalog. */
  name: string;
  /** `lib/public-routes.ts` entry that serves this page. */
  routeKey: PublicRouteKey;
  /** Namespace i18n of texts specific to this comparison. */
  namespace: Namespace;
  /** Its public pricing page: the reader should be able to check for themselves. */
  pricingUrl: string;
  /** Its official product documentation, used to substantiate feature claims. */
  docsUrl: string;
  /** Official evidence for the corresponding comparison row. */
  sources: Partial<Record<ComparisonRow, string>>;
}

export const COMPARISONS = [
  {
    slug: "linear",
    name: "Linear",
    routeKey: "alternativeLinear",
    namespace: "AlternativeLinear",
    pricingUrl: "https://linear.app/pricing",
    docsUrl: "https://linear.app/docs",
    sources: {
      teammate: "https://linear.app/pricing",
      agents: "https://linear.app/docs/coding-sessions",
      pages: "https://linear.app/docs/default-team-pages",
      feedback: "https://linear.app/docs/customer-requests",
      setup: "https://linear.app/docs/conceptual-model",
      builtFor: "https://linear.app/docs/initiatives",
    },
  },
  {
    slug: "jira",
    name: "Jira",
    routeKey: "alternativeJira",
    namespace: "AlternativeJira",
    pricingUrl: "https://www.atlassian.com/software/jira/pricing",
    docsUrl: "https://support.atlassian.com/jira-software-cloud/",
    sources: {
      teammate: "https://support.atlassian.com/subscriptions-and-billing/docs/manage-users-and-user-tiers/",
      agents: "https://www.atlassian.com/platform/rovo-mcp",
      pages: "https://support.atlassian.com/confluence-cloud/docs/create-and-edit-content/",
      feedback: "https://support.atlassian.com/jira-product-discovery/docs/create-and-manage-insights/",
      hosting: "https://www.atlassian.com/licensing/data-center-end-of-life",
      setup: "https://support.atlassian.com/jira-software-cloud/docs/what-are-jira-workflows/",
    },
  },
  {
    slug: "notion",
    name: "Notion",
    routeKey: "alternativeNotion",
    namespace: "AlternativeNotion",
    pricingUrl: "https://www.notion.com/pricing",
    docsUrl: "https://www.notion.com/help",
    sources: {
      teammate: "https://www.notion.com/help/add-members-admins-guests-and-groups",
      agents: "https://www.notion.com/help/mcp-connections-for-custom-agents",
      pages: "https://www.notion.com/help/guides/getting-started-with-projects-and-tasks",
      feedback: "https://www.notion.com/pricing",
      setup: "https://www.notion.com/help/guides/getting-started-with-projects-and-tasks",
    },
  },
] as const satisfies ReadonlyArray<Comparison>;

/**
 * The table rows, in order. i18n keys: `Alternatives.row_<key>` for
 * the label, `Alternatives.minddy_<key>` for minddy's cell, and
 * `<competitorNamespace>.them_<key>` for theirs.
 *
 * Only TEXT cells, no checkboxes: a cross in a competitor's
 * column reads like an accusation, and asks one to be sure of an absent
 * — which one cannot be.
 */
export const COMPARISON_ROWS = [
  "source",
  "teammate",
  "agents",
  "pages",
  "feedback",
  "hosting",
  "setup",
  "builtFor",
] as const;

export type ComparisonRow = (typeof COMPARISON_ROWS)[number];

/** The three arguments of each column of prose, on both sides. */
export const COMPARISON_POINTS = [1, 2, 3] as const;

/** Current minddy capabilities that deserve more than one table cell. */
export const COMPARISON_FEATURES = [
  "agents",
  "pages",
  "numo",
  "routines",
  "planning",
  "feedback",
  "capture",
  "openSource",
] as const;

export type ComparisonFeature = (typeof COMPARISON_FEATURES)[number];

/**
 * The public guide that explains each feature in depth, by documentation ID.
 * Comparison pages link to these guides so their claims can be checked against
 * the manual. Features without a dedicated guide have no entry.
 */
export const COMPARISON_FEATURE_GUIDES = {
  agents: "minddy-mcp",
  numo: "numo",
  pages: "pages",
  routines: "scheduled-routines",
  planning: "objectives",
  feedback: "feedback",
} as const satisfies Partial<Record<ComparisonFeature, string>>;

export function comparisonBySlug(slug: string): Comparison | null {
  return COMPARISONS.find((entry) => entry.slug === slug) ?? null;
}