diff --git a/.env.local.example b/.env.local.example
index dae0eb8..a51caa8 100644
--- a/.env.local.example
+++ b/.env.local.example
@@ -73,3 +73,11 @@ AUTH_ZITADEL_ISSUER=https://auth.catholicdigitalcommons.org
# openssl rand -base64 32
# Different value per env (prod / staging / dev); never share between them.
AUTH_SECRET=
+
+# AUTH_URL: only needed if NEXT_PUBLIC_SITE_URL isn't already set to the
+# public origin. lib/auth.ts auto-promotes NEXT_PUBLIC_SITE_URL → AUTH_URL
+# when AUTH_URL is unset, which covers the Plesk Passenger case where
+# Next.js standalone otherwise generates an OIDC redirect_uri pointing at
+# the bind address (0.0.0.0:3000) instead of the public hostname. Set this
+# explicitly if you need to override (e.g. behind multiple proxies).
+# AUTH_URL=
diff --git a/app/[lang]/my-bio/page.tsx b/app/[lang]/my-bio/page.tsx
new file mode 100644
index 0000000..4fa4473
--- /dev/null
+++ b/app/[lang]/my-bio/page.tsx
@@ -0,0 +1,104 @@
+import { redirect } from 'next/navigation'
+import { getTranslations } from 'next-intl/server'
+import { auth } from '@/lib/auth'
+import {
+ BioApiError,
+ fetchMyTeamMember,
+ fetchTeamMemberPost,
+ type BioDiscovery,
+ type BioPostContent,
+} from '@/lib/bio-api'
+import BioEditor from '@/components/BioEditor'
+
+// Server component for /[lang]/my-bio. Resolves the caller's linked
+// team_member post, picks an initial language (Zitadel locale → URL
+// locale → first available), fetches that language's current content,
+// and hands everything to the client-side editor.
+//
+// Anonymous → redirect to sign-in.
+// Authenticated but no team_member link → friendly "contact ops" message
+// (no internal error surfaced).
+export default async function MyBioPage({
+ params,
+}: {
+ params: Promise<{ lang: string }>
+}) {
+ const { lang: urlLocale } = await params
+ const session = await auth()
+ if (!session?.user) {
+ redirect('/api/auth/signin')
+ }
+ const t = await getTranslations('MyBio')
+
+ let discovery: BioDiscovery
+ try {
+ discovery = await fetchMyTeamMember(session)
+ } catch (err) {
+ if (err instanceof BioApiError && (err.status === 401 || err.status === 403)) {
+ return (
+
+