---
title: "Profile Account Widgets"
description: "/profile Professional tab — Organization Davinci-droplist, Position/Skills tag clouds, and My Curriculum Vitae markdown editor with mobile full-bleed Save & Exit drafts"
locale: "en"
---
# Profile Account Widgets

> **Info**
> Use **Founder** / **Developer** tabs in the docs sidebar to filter this page. Public `/{username}` surfaces are separate — see [Public Profile Pages](/docs/features/public-profile.md). Entity catalog powering Organization is documented under [Entities](/docs/features/entities.md).

Signed-in members manage account vitals on **`/profile`**. The **Professional** tab ships three composed widgets under `components/profile/` (app UI — **not** MDX ring-widgets):

| Widget | Job |
|--------|-----|
| **OrganizationEntitySelect** | Pick organization from all Entities via **Davinci-droplist** |
| **PositionTagCloud** / **SkillsTagCloud** | Multi-tag FsModal clouds (shared `ProfileTagCloud`) |
| **CurriculumVitaeWidget** | Markdown CV editor + `profile:cv` file upload |

Human catalog (with Davinci-droplist call sites): `components/docs/WIDGETS-README.md` → **App UI profile widgets**. Machine index: `AI-CONTEXT/concepts/ring-docs.nodus.json` → `ring_widgets.index.sections.app_ui_profile`.

### For founders

## Why this matters for your clone

Professional fields turn a bare account into a **hireable / partnerable face**: which organization the member represents, which roles and skills they claim, and a CV they can edit on a phone without fighting chrome padding.

Typical scenarios:

1. Member opens `/profile` → Professional → taps **Organization** → searchable Entity list (FsModal) → selection saves immediately.
2. Member adds **Position** / **Skills** tags from the known catalog or custom text; selected chips stay visible **inside** the picker modal.
3. Member taps **Edit** on **My Curriculum Vitae**, writes markdown fullscreen on mobile, relies on local **draft autosave**, then **Save & Exit** to persist into the profile.

  
- **[Public profile](/docs/features/public-profile.md)** — After username claim, public trust face at /{username}.

  
- **[Entities](/docs/features/entities.md)** — Organization droplist reads the same Entities catalog members join and showcase.

  
- **[Username reservation](/docs/features/username-reservation.md)** — @handle lives on Messengers tab (above Telegram) — not in the Professional hero.

### For developers

## Module map (verified)

| Surface | Path |
|---------|------|
| Account shell | `features/auth/components/profile-content.tsx` |
| Organization | `components/profile/organization-entity-select.tsx` → `DavinciDroplist` → `GET /api/entities` |
| Tag clouds | `components/profile/profile-tag-cloud.tsx` (+ `position-tag-cloud.tsx`, `skills-tag-cloud.tsx`) |
| Tag catalogs | `features/auth/lib/profile-tags.ts`, `position-tags.ts`, `skill-tags.ts` |
| CV widget | `components/profile/curriculum-vitae-widget.tsx` |
| CV editor | dynamic `WikiRichEditor` (`features/wiki/components/wiki-rich-editor.tsx`) — markdown SSOT |
| Persist | `updateProfile` Server Action — `curriculumVitae` / `organization` / `position` / `skills` FormData |
| Upload | `POST /api/uploads` purpose `profile:cv` (`lib/uploads/upload-types.ts`) |
| Storage shape | `users.data.curriculumVitae` (`CurriculumVitae` in `features/auth/types.ts`) |
| Drafts | `useLocalStorage` key `profile_cv_draft_{userId}` + `useDebounce` (same hydration-safe pattern as chat composer) |
| Shell | `FsModal` — mobile `hideTitleOnMobile`, `closeClassName="max-sm:hidden"`, footer Close + Save & Exit |

### Davinci-droplist placement

`OrganizationEntitySelect` is a **migrated** Davinci-droplist call site (theme enhancer §7 / DL11), alongside `CountrySelect`, `TimezoneSelect`, `ProductRepSelect`, `VendorEntitySelect`. `ProfileTagCloud` reuses `DavinciDroplistItem` + QuickSearchFilter inside FsModal for multi-tag confirm (not single-select close-on-tap).

### CV mobile editor chrome

```
max-sm: full viewport, body padding 0, header hidden
footer: [Close] ············ [Save & Exit]
draft:  useLocalStorage autosave while open
action: Save & Exit → updateProfile → clear draft → close
```

Desktop keeps Cancel + Save labels and the default top-right `.modal-close-button`.

### Wire Organization

Import `OrganizationEntitySelect` into the Professional tab; pass current `organization` string and `onSaved` to refresh local profile state after `updateProfile`.

### Wire Position / Skills

Use `PositionTagCloud` / `SkillsTagCloud` wrappers (or `ProfileTagCloud` directly with a `field` + `knownTags`). Selected chips render both outside and inside the FsModal.

### Wire Curriculum Vitae

Mount `CurriculumVitaeWidget` with `value={user.curriculumVitae}`. Ensure upload purpose `profile:cv` is allowed in upload-core and that `updateProfile` parses `curriculumVitae` JSON into `users.data`.

```ts
// Draft key SSOT (curriculum-vitae-widget.tsx)
const draftKey = userId ? `profile_cv_draft_${userId}` : 'profile_cv_draft'
const [storedDraft, setStoredDraft] = useLocalStorage(draftKey, '')
```

- [features/public-profile](/docs/features/public-profile.md) — Next-step: public /{username} trust face after Professional fields are filled.

- [features/entities](/docs/features/entities.md) — Depends-on: OrganizationEntitySelect lists Entities from GET /api/entities.

- [features/authentication](/docs/features/authentication.md) — Same-workflow: /profile vitals and Auth.js session.update after updateProfile.

- [features/scientific-editor](/docs/features/scientific-editor.md) — See-also: publications use useAutoSave against /api/publications; CV drafts use useLocalStorage instead.

- [features/doc-system](/docs/features/doc-system.md) — Deep-dive: WIDGETS-README App UI profile widgets + ring-docs.nodus app_ui_profile section.
