diff --git a/backend/api/package.json b/backend/api/package.json
index 5fd90c47..0f4eee41 100644
--- a/backend/api/package.json
+++ b/backend/api/package.json
@@ -1,6 +1,6 @@
{
"name": "@compass/api",
- "version": "1.48.0",
+ "version": "1.49.0",
"private": true,
"description": "Backend API endpoints",
"main": "src/serve.ts",
diff --git a/backend/api/src/get-profiles.ts b/backend/api/src/get-profiles.ts
index 896f9230..ecad2b79 100644
--- a/backend/api/src/get-profiles.ts
+++ b/backend/api/src/get-profiles.ts
@@ -6,6 +6,7 @@ import {
GENDERS,
LANGUAGE_CHOICES,
MBTI_CHOICES,
+ NEUROTYPE_CHOICES,
ORIENTATION_CHOICES,
POLITICAL_CHOICES,
RACE_CHOICES,
@@ -81,6 +82,7 @@ export type profileQueryType = {
languages?: string[] | undefined
religion?: string[] | undefined
orientation?: string[] | undefined
+ neurotype?: string[] | undefined
wants_kids_strength?: number | undefined
has_kids?: number | undefined
is_smoker?: boolean | undefined
@@ -131,6 +133,9 @@ const textFields = [
'religious_beliefs',
'orientation_details',
'gender_details',
+ 'neurotype_details',
+ // Keyword-searchable but deliberately has no filter of its own — see the migration for why.
+ 'accessibility_notes',
]
// Define choice fields to search
@@ -147,6 +152,7 @@ const arrayChoiceFields = [
{field: 'relationship_status', choices: RELATIONSHIP_STATUS_CHOICES},
{field: 'religion', choices: RELIGION_CHOICES},
{field: 'orientation', choices: ORIENTATION_CHOICES},
+ {field: 'neurotype', choices: NEUROTYPE_CHOICES},
{field: 'pref_relation_styles', choices: RELATIONSHIP_CHOICES},
{field: 'pref_romantic_styles', choices: ROMANTIC_CHOICES},
{field: 'languages', choices: LANGUAGE_CHOICES},
@@ -211,6 +217,7 @@ export const loadProfiles = async (props: profileQueryType, db?: SupabaseDirectC
languages,
religion,
orientation,
+ neurotype,
wants_kids_strength,
has_kids,
interests,
@@ -508,6 +515,17 @@ export const loadProfiles = async (props: profileQueryType, db?: SupabaseDirectC
},
),
+ neurotype?.length &&
+ where(
+ // most are neurotypical, so we don't include the people who didn't answer if we're looking for
+ // anything else — a rare value is only meaningful when it was actually stated
+ (!neurotype.includes('neurotypical') ? '' : "neurotype IS NULL OR neurotype = '{}' OR ") +
+ `neurotype && $(neurotype)`,
+ {
+ neurotype,
+ },
+ ),
+
interests?.length && where(getManyToManyClause('interests'), {values: interests.map(Number)}),
causes?.length && where(getManyToManyClause('causes'), {values: causes.map(Number)}),
diff --git a/backend/supabase/migration.sql b/backend/supabase/migration.sql
index 9d5716bb..ef7536bb 100644
--- a/backend/supabase/migration.sql
+++ b/backend/supabase/migration.sql
@@ -58,4 +58,6 @@ BEGIN;
\i backend/supabase/email_unsubscribe_tokens.sql
\i backend/supabase/migrations/20260524_add_orientation_to_profiles.sql
\i backend/supabase/migrations/20260709_add_last_checked_at_to_bookmarked_searches.sql
+\i backend/supabase/migrations/20260724_add_neurotype_to_profiles.sql
+\i backend/supabase/migrations/20260724_add_accessibility_notes_to_profiles.sql
COMMIT;
diff --git a/backend/supabase/migrations/20260724_add_accessibility_notes_to_profiles.sql b/backend/supabase/migrations/20260724_add_accessibility_notes_to_profiles.sql
new file mode 100644
index 00000000..fc55c69c
--- /dev/null
+++ b/backend/supabase/migrations/20260724_add_accessibility_notes_to_profiles.sql
@@ -0,0 +1,10 @@
+-- Add accessibility notes to profiles table
+-- Created: 2026-07-24
+--
+-- Deliberately free text rather than a checkbox taxonomy of conditions: a taxonomy exists mainly to be
+-- filtered on, and filtering people out by disability is exactly what this field must not enable. Free
+-- text keeps framing and depth of disclosure with the member. It is keyword-searchable (see `textFields`
+-- in backend/api/src/get-profiles.ts) but has no filter of its own.
+
+ALTER TABLE profiles
+ ADD COLUMN IF NOT EXISTS accessibility_notes TEXT;
diff --git a/backend/supabase/migrations/20260724_add_neurotype_to_profiles.sql b/backend/supabase/migrations/20260724_add_neurotype_to_profiles.sql
new file mode 100644
index 00000000..0f31ced9
--- /dev/null
+++ b/backend/supabase/migrations/20260724_add_neurotype_to_profiles.sql
@@ -0,0 +1,9 @@
+-- Add neurotype (neurodivergence identity) fields to profiles table
+-- Created: 2026-07-24
+
+ALTER TABLE profiles
+ ADD COLUMN IF NOT EXISTS neurotype TEXT[],
+ ADD COLUMN IF NOT EXISTS neurotype_details TEXT;
+
+-- Create GIN index for array field
+CREATE INDEX IF NOT EXISTS profiles_neurotype_gin ON profiles USING GIN (neurotype);
diff --git a/common/messages/de.json b/common/messages/de.json
index 65cea332..0023d322 100644
--- a/common/messages/de.json
+++ b/common/messages/de.json
@@ -387,6 +387,7 @@
"filter.any_interests": "Jedes Interesse",
"filter.any_language": "Alle Sprachen",
"filter.any_mbti": "Jeder MBTI",
+ "filter.any_neurotype": "Beliebiger Neurotyp",
"filter.any_new_users": "Jegliche neue Nutzer",
"filter.any_orientation": "Jede Orientierung",
"filter.any_politics": "Jede politische Ausrichtung",
@@ -451,6 +452,7 @@
"filter.mine_toggle": "Meine Filter",
"filter.multiple": "Mehrere",
"filter.near": "in der Nähe von",
+ "filter.neurotype.show_more": "Mehr Neurotypen anzeigen",
"filter.orientation.show_more": "Mehr Orientierungen anzeigen",
"filter.raised_in": "Aufgewachsen",
"filter.relationship.any_connection": "Jede Beziehung",
@@ -752,6 +754,7 @@
"privacy.use.text": "Ihre Daten werden nur verwendet, um die Plattform zu betreiben, zu personalisieren und zu verbessern. Wir verkaufen Ihre persönlichen Informationen nicht an Dritte.",
"privacy.use.title": "2. Wie wir Ihre Daten verwenden",
"profile.about.raised_in": "Aufgewachsen in {location}",
+ "profile.accessibility_notes": "Barrierefreiheit",
"profile.age_any": "jeden Alters",
"profile.age_between": "zwischen {min} und {max} Jahren",
"profile.age_exact": "genau {min} Jahre",
@@ -1057,7 +1060,19 @@
"profile.mbti.ESFP": "Unterhalter",
"profile.mutual": "Gegenseitig",
"profile.mutual_interests": "Sie haben beide gemeinsame Interessen: {matches}",
+ "profile.neurotype": "Neurotyp",
+ "profile.neurotype.adhd": "ADHS",
+ "profile.neurotype.autistic": "Autistisch",
+ "profile.neurotype.details_placeholder": "Was hilfreich zu wissen ist über dein Denken oder Kommunizieren…",
+ "profile.neurotype.dyscalculic": "Dyskalkulie",
+ "profile.neurotype.dyslexic": "Legasthenie",
+ "profile.neurotype.hsp": "Hochsensibel (HSP)",
+ "profile.neurotype.neurotypical": "Neurotypisch",
+ "profile.neurotype.show_more": "Weitere Optionen anzeigen",
"profile.not_both_open_to_type": "Sie sind nicht beide für eine(n) {type} offen",
+ "profile.optional.accessibility_notes": "Barrierefreiheit",
+ "profile.optional.accessibility_notes_hint": "Optional und öffentlich wie der Rest deines Profils. Alles Praktische, das ein gutes Treffen erleichtert — Zugangsbedürfnisse, Energielevel, sensorische Vorlieben, ruhigere Orte. Sag so viel oder so wenig, wie du möchtest.",
+ "profile.optional.accessibility_notes_placeholder": "z. B. Ich nutze einen Rollstuhl, stufenlose Orte passen am besten. Fragen sind willkommen.",
"profile.optional.age": "Alter",
"profile.optional.age.error_max": "Bitte gib ein gültiges Alter ein",
"profile.optional.age.error_min": "Du musst mindestens 18 Jahre alt sein",
@@ -1101,6 +1116,7 @@
"profile.optional.languages": "Gesprochene Sprachen",
"profile.optional.location": "Standort",
"profile.optional.mbti": "MBTI-Persönlichkeitstyp",
+ "profile.optional.neurotype": "Neurotyp",
"profile.optional.num_kids": "Aktuelle Anzahl von Kindern",
"profile.optional.og_card": "Profilkarte",
"profile.optional.orientation": "Sexuelle Orientierung",
diff --git a/common/messages/fr.json b/common/messages/fr.json
index 0be6385b..ee031ceb 100644
--- a/common/messages/fr.json
+++ b/common/messages/fr.json
@@ -387,6 +387,7 @@
"filter.any_interests": "Tout intérêt",
"filter.any_language": "Toutes les langues",
"filter.any_mbti": "Tout MBTI",
+ "filter.any_neurotype": "Tout neurotype",
"filter.any_new_users": "Tout nouvel utilisateur",
"filter.any_orientation": "Toute orientation",
"filter.any_politics": "Toute orientation politique",
@@ -451,6 +452,7 @@
"filter.mine_toggle": "Mes filtres",
"filter.multiple": "Multiple",
"filter.near": "près de",
+ "filter.neurotype.show_more": "Afficher plus de neurotypes",
"filter.orientation.show_more": "Afficher plus d'orientations",
"filter.raised_in": "A grandi",
"filter.relationship.any_connection": "Toute relation",
@@ -751,6 +753,7 @@
"privacy.use.text": "Vos données sont utilisées uniquement pour faire fonctionner, personnaliser et améliorer la plateforme. Nous ne vendons pas vos informations personnelles à des tiers.",
"privacy.use.title": "2. Comment nous utilisons vos données",
"profile.about.raised_in": "A grandi à {location}",
+ "profile.accessibility_notes": "Accessibilité",
"profile.age_any": "de tout âge",
"profile.age_between": "entre {min} et {max} ans",
"profile.age_exact": "exactement {min} ans",
@@ -1056,7 +1059,19 @@
"profile.mbti.ESFP": "Animateur",
"profile.mutual": "Mutuel",
"profile.mutual_interests": "Vous avez tous les deux des intérêts communs : {matches}. Contactez-les ci-dessus!",
+ "profile.neurotype": "Neurotype",
+ "profile.neurotype.adhd": "TDAH",
+ "profile.neurotype.autistic": "Autiste",
+ "profile.neurotype.details_placeholder": "Ce qu'il est utile de savoir sur votre façon de penser ou de communiquer…",
+ "profile.neurotype.dyscalculic": "Dyscalculique",
+ "profile.neurotype.dyslexic": "Dyslexique",
+ "profile.neurotype.hsp": "Hypersensible (HSP)",
+ "profile.neurotype.neurotypical": "Neurotypique",
+ "profile.neurotype.show_more": "Afficher plus d'options",
"profile.not_both_open_to_type": "Vous n'êtes pas tous les deux ouverts à un(e) {type}",
+ "profile.optional.accessibility_notes": "Accessibilité",
+ "profile.optional.accessibility_notes_hint": "Facultatif, et public comme le reste de votre profil. Tout ce qui est utile en pratique pour bien vous rencontrer — besoins d'accès, niveau d'énergie, préférences sensorielles, lieux plus calmes. Dites-en autant ou aussi peu que vous voulez.",
+ "profile.optional.accessibility_notes_placeholder": "ex. Je me déplace en fauteuil roulant, les lieux sans marches sont donc plus simples. N'hésitez pas à poser des questions.",
"profile.optional.age": "Âge",
"profile.optional.age.error_max": "Veuillez entrer un âge valide",
"profile.optional.age.error_min": "Vous devez avoir au moins 18 ans",
@@ -1100,6 +1115,7 @@
"profile.optional.languages": "Langues parlées",
"profile.optional.location": "Localisation",
"profile.optional.mbti": "Type de personnalité MBTI",
+ "profile.optional.neurotype": "Neurotype",
"profile.optional.num_kids": "Nombre actuel d'enfants",
"profile.optional.og_card": "Carte de profil",
"profile.optional.orientation": "Orientation sexuelle",
diff --git a/common/src/api/schema.ts b/common/src/api/schema.ts
index 4c6b8354..f6172888 100644
--- a/common/src/api/schema.ts
+++ b/common/src/api/schema.ts
@@ -762,6 +762,7 @@ export const API = (_apiTypeCheck = {
big5_neuroticism_max: z.coerce.number().optional(),
religion: arraybeSchema.optional(),
orientation: arraybeSchema.optional(),
+ neurotype: arraybeSchema.optional(),
pref_relation_styles: arraybeSchema.optional(),
pref_romantic_styles: arraybeSchema.optional(),
diet: arraybeSchema.optional(),
diff --git a/common/src/api/zod-types.ts b/common/src/api/zod-types.ts
index 721ce466..e901e073 100644
--- a/common/src/api/zod-types.ts
+++ b/common/src/api/zod-types.ts
@@ -123,6 +123,9 @@ const optionalProfilesSchema = z.object({
gender_details: z.string().optional().nullable(),
orientation: z.array(z.string()).optional().nullable(),
orientation_details: z.string().optional().nullable(),
+ neurotype: z.array(z.string()).optional().nullable(),
+ neurotype_details: z.string().optional().nullable(),
+ accessibility_notes: z.string().optional().nullable(),
religion: z.array(z.string()).optional().nullable(),
religious_belief_strength: z.number().optional().nullable(),
religious_beliefs: z.string().optional().nullable(),
diff --git a/common/src/choices.ts b/common/src/choices.ts
index e86fd42d..e6d41567 100644
--- a/common/src/choices.ts
+++ b/common/src/choices.ts
@@ -314,6 +314,27 @@ export const EXTRA_ORIENTATIONS = Object.values(ORIENTATION_CHOICES).filter(
(v) => !DEFAULT_ORIENTATIONS.includes(v as any),
)
+// Neurotype is framed as an identity, not a diagnosis: no "undiagnosed" or "prefer not to say" options,
+// and no psychiatric conditions. Anything a member doesn't want structured goes in `neurotype_details`.
+export const NEUROTYPE_CHOICES = {
+ Autistic: 'autistic',
+ ADHD: 'adhd',
+ Neurotypical: 'neurotypical',
+ // No combined "AuDHD" option on purpose — that is ticking Autistic and ADHD together.
+ Dyslexic: 'dyslexic',
+ Dyscalculic: 'dyscalculic',
+ 'Highly sensitive (HSP)': 'hsp',
+} as const
+
+export const DEFAULT_NEUROTYPES = [
+ NEUROTYPE_CHOICES.Autistic,
+ NEUROTYPE_CHOICES.ADHD,
+ NEUROTYPE_CHOICES.Neurotypical,
+]
+export const EXTRA_NEUROTYPES = Object.values(NEUROTYPE_CHOICES).filter(
+ (v) => !DEFAULT_NEUROTYPES.includes(v as any),
+)
+
export const LAST_ONLINE_CHOICES = {
now: 'Currently online',
today: 'Today',
@@ -375,6 +396,7 @@ export const INVERTED_CANNABIS_CHOICES = invert(CANNABIS_CHOICES)
export const INVERTED_SUBSTANCE_INTENTION_CHOICES = invert(SUBSTANCE_INTENTION_CHOICES)
export const INVERTED_SUBSTANCE_PREFERENCE_CHOICES = invert(SUBSTANCE_PREFERENCE_CHOICES)
export const INVERTED_ORIENTATION_CHOICES = invert(ORIENTATION_CHOICES)
+export const INVERTED_NEUROTYPE_CHOICES = invert(NEUROTYPE_CHOICES)
//Exported types for test files to use when referencing the keys of the choices objects
export type PersonalityKey = keyof typeof MBTI_CHOICES
diff --git a/common/src/filters-format.ts b/common/src/filters-format.ts
index 88d21f21..06028269 100644
--- a/common/src/filters-format.ts
+++ b/common/src/filters-format.ts
@@ -5,6 +5,7 @@ import {
INVERTED_GENDERS,
INVERTED_LANGUAGE_CHOICES,
INVERTED_MBTI_CHOICES,
+ INVERTED_NEUROTYPE_CHOICES,
INVERTED_ORIENTATION_CHOICES,
INVERTED_POLITICAL_CHOICES,
INVERTED_PSYCHEDELICS_CHOICES,
@@ -41,6 +42,7 @@ const filterLabels: Record {t('profile.optional.details', 'Details')}