# Profile page

> A two-column profile page: an identity column (avatar, name, handle, links, one action, bio, widgets) beside about, experience, skills, projects, writing and testimonials. The owner also sees their apps and account details.

Source: https://docs.nasaqui.com/components/profile-page

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/profile-page.json
```

A page about a person, in two columns. The identity column holds the avatar, name, `@handle`, headline, location, availability and links, one full-width action, the bio and the join date, with personal widgets below it (local clock, weather, numbers, now). The content column holds your own sections first, then about, experience (with an overlap-aware total), grouped skills, projects (a featured story, then a grid with category tabs), latest writing and testimonials. Sections that list things show a count. Sections without data are left out.

The columns sit side by side from 64rem of container width. On narrower containers the identity comes first and the widgets last.

**Owner view.** Pass `onEdit` or `editHref` when the member is looking at their own page. "Edit profile" replaces the contact button, the closing call to action is left out, and two private sections appear: **Apps** (the products they use, with the official mark, plan, role, organisation and last use) and **Account** (email, language, time zone, member since, whatever details you pass). A member with no apps sees an empty state with one "Browse apps" action, never an empty grid.

## When to use

- A portfolio, a personal site or a team-member page.

## When not to use

- An in-app user card: use `ProfileCard`.
- A company landing page: use the marketing blocks.

## Import

```tsx
import { ProfilePage } from "@fadymondy/nasaq/web";
```

## Quick start

```tsx
<ProfilePage profile={profile} blogHref="/blog" postHref={(p) => `/blog/${p.slug}`} onContact={openForm} />
```

The owner's view of the same page:

```tsx
<ProfilePage
  profile={profile}
  editHref="/settings/profile"
  apps={[{ id: "mahaam", name: "Mahaam", icon: mahaamMark, href: "https://mahaam.app", plan: "Pro", role: "Owner", org: "3x1", lastUsed: "2026-09-28" }]}
  appsHref="/apps"
  account={[
    { label: "Email", value: "laylah@example.com" },
    { label: "Member since", value: "March 2024" },
  ]}
/>
```

## Anatomy

```
ProfilePage           data-slot="profile-page"
├─ ProfileSidebar     Avatar, name, @handle, headline, details, one action, SocialLinks, bio, joined
├─ content column     children, ProfileApps*, ProfileAccount*, ProfileAbout, ProfileExperience,
│                     ProfileSkills, ProfileProjects, ProfileWriting, ProfileTestimonials
├─ aside              LocalClock, WeatherWidget, StatsWidget, NowWidget (under the sidebar)
└─ ProfileContact     visitors only
                      * owner only
```

## API

### `ProfilePage`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `profile` | `ProfileData` | required | All content. |
| `onContact?` | `() => void` | mailto | Contact button handler. Without it the button opens `mailto:` to `profile.email`. |
| `onEdit?` / `editHref?` | `() => void` / `string` | none | Either one turns on the owner view: "Edit profile" replaces contact, apps and account show, the closing call to action is left out. |
| `apps?` | `ProfileApp[]` | none | Owner only. The products they use. An empty array shows the empty state. |
| `appsHref?` | `string` | none | Owner only. Where "Browse apps" goes. |
| `account?` | `ProfileAccountDetail[]` | none | Owner only. `{ label, value }` rows for the account section. |
| `children?` | `ReactNode` | none | Your own sections, shown first in the content column. Use `ProfileSection`. |
| `postHref?` / `blogHref?` | function / string | none | Links for the writing section. |
| `now?` | `Date \| number` | real time | Freeze the clock and tenure. |
| `widgets?` | `boolean` | `true` | Show the widgets column. |
| `labels?` | `Partial<ProfilePageLabels>` | locale | Override strings. |

`ProfileData` fields: `name`, `handle`, `headline`, `bio`, `joined` (ISO date), `avatar`, `location`, `timeZone`, `workingHours`, `availability` (`open`, `limited`, `closed`), `availabilityNote`, `about` (Markdown), `email`, `links`, `experience` (`ProfileJob[]`), `skills`, `projects` (`ProfileProject[]`), `posts`, `testimonials`, `stats`, `now`, `nowUpdated`, `weather`, `cvHref`.

### Sections

`ProfileSection` takes `title`, `description`, `action` and `count` (shown as a badge beside the title). `ProfileApp` is a `Product` (from product switcher) plus `role`, `org`, `plan` and `lastUsed`. `ProfileAccountDetail` is `{ label, value }`.

`ProfileSidebar` (the identity column; takes `profile`, `onContact`, `onEdit`, `editHref`, `action` to replace the button, and children below the bio), `ProfileApps` (`apps`, `browseHref`), `ProfileAccount` (`details`, `description`), `ProfileHero` (the older single-column header), `ProfileSection`, `ProfileAbout`, `ProfileExperience`, `ProfileSkills`, `ProfileProjects`, `ProfileWriting`, `ProfileTestimonials` and `ProfileContact` are exported so you can compose your own order. Each takes its data, optional `labels` and section props.

### Model helpers

Exported from `personal-widgets`: `tenureBetween`, `totalExperience` (merges overlapping roles), `groupSkills`, `distinct`, `isWorkingNow`, `offsetHours`, `partsIn`, `isKnownTimeZone`.

## Accessibility

Each section is a `<section>` labelled by its heading; there is one h1, the name in the sidebar. Counts are part of the heading text for screen readers. Each app card is one link. Project tabs follow the tabs pattern. The project cards use one link each. Availability is text, the dot is decoration.

## RTL & i18n

English and Arabic strings, overridable. Names and companies are wrapped in `<bdi>` so mixed-script text does not reorder. Latin digits.

## Styling

Container queries, tokens only. Avatar size is a class on `Avatar`.

## Do / Don't

- Do give `timeZone` if you want the clock; leave it out to hide it.
- Do keep the headline to one sentence.
- Do show app marks as they are: `ProductIcon` renders the official mark, never a generic icon or a recoloured one.
- Don't show apps or account details to visitors. They only render in the owner view.
- Don't put more than about five links in the hero.
- The page does not generate a PDF. The CV button links to a file you provide with `cvHref`.

## Related

[`PersonalWidgets`](https://docs.nasaqui.com/components/personal-widgets), [`BlogIndex`](https://docs.nasaqui.com/components/blog-index), [`Timeline`](https://docs.nasaqui.com/components/timeline), [`FeatureStory`](https://docs.nasaqui.com/components/feature-story).

## Lab

Story `Components/Website/Profile Page` (Default, Owner View, Owner View Arabic, Owner View New) and page story `Pages/Public/Profile`.

## Code

### React

```tsx
<ProfilePage profile={profile} blogHref="/blog" postHref={(p) => `/blog/${p.slug}`} onContact={openForm} />
```

### shadcn

```tsx
<ProfilePage profile={profile} blogHref="/blog" postHref={(p) => `/blog/${p.slug}`} onContact={openForm} />
```

### Vue

```vue
<script setup lang="ts">
import { NqProfilePage, type ProfileData } from "@fadymondy/nasaq/vue";

const profile: ProfileData = {
  name: "Laylah Haddad",
  handle: "@laylah",
  headline: "Product designer who ships design systems for Arabic and English products.",
  joined: "2024-03-12",
  location: "Riyadh",
  timeZone: "Asia/Riyadh",
  availability: "limited",
  availabilityNote: "from November",
  email: "laylah@example.com",
  about: "I design **calm, bilingual** interfaces and the systems behind them.",
  links: [
    { kind: "github", label: "GitHub", href: "https://github.com/laylah" },
    { kind: "website", label: "Website", href: "https://laylah.example.com" },
  ],
  experience: [
    { id: "j1", role: "Lead designer", company: "Tamkeen", start: "2022-01-01", summary: "Owns the design system." },
    { id: "j2", role: "Designer", company: "Studio Nour", start: "2019-06-01", end: "2021-12-31" },
  ],
  skills: [
    { name: "Figma", group: "Design", level: 5 },
    { name: "Vue", group: "Code", level: 3 },
  ],
  projects: [
    { slug: "ledger", title: "Ledger", description: "A bilingual bookkeeping app.", category: "Product", featured: true, points: ["RTL first", "Offline"] },
    { slug: "kit", title: "Open kit", description: "A small icon kit.", category: "Open source", tags: ["svg"] },
  ],
  testimonials: [{ quote: "The calmest handoff I have had.", name: "Omar Nasser", role: "CTO, Tamkeen" }],
};

const postHref = (p: { slug: string }) => `/blog/${p.slug}`;
const openForm = () => {};
</script>

<template>
  <NqProfilePage :profile="profile" blog-href="/blog" :post-href="postHref" contact-button @contact="openForm" />
</template>
```

### Blade

```blade
@php
    $profile = [
        'name' => 'Laylah Haddad',
        'handle' => '@laylah',
        'headline' => 'Product designer who ships design systems for Arabic and English products.',
        'joined' => '2024-03-12',
        'location' => 'Riyadh',
        'timeZone' => 'Asia/Riyadh',
        'availability' => 'limited',
        'availabilityNote' => 'from November',
        'email' => 'laylah@example.com',
        'about' => 'I design **calm, bilingual** interfaces and the systems behind them.',
        'links' => [
            ['kind' => 'github', 'label' => 'GitHub', 'href' => 'https://github.com/laylah'],
            ['kind' => 'website', 'label' => 'Website', 'href' => 'https://laylah.example.com'],
        ],
        'experience' => [
            ['id' => 'j1', 'role' => 'Lead designer', 'company' => 'Tamkeen', 'start' => '2022-01-01', 'summary' => 'Owns the design system.'],
            ['id' => 'j2', 'role' => 'Designer', 'company' => 'Studio Nour', 'start' => '2019-06-01', 'end' => '2021-12-31'],
        ],
        'skills' => [
            ['name' => 'Figma', 'group' => 'Design', 'level' => 5],
            ['name' => 'Vue', 'group' => 'Code', 'level' => 3],
        ],
        'projects' => [
            ['slug' => 'ledger', 'title' => 'Ledger', 'description' => 'A bilingual bookkeeping app.', 'category' => 'Product', 'featured' => true, 'points' => ['RTL first', 'Offline']],
            ['slug' => 'kit', 'title' => 'Open kit', 'description' => 'A small icon kit.', 'category' => 'Open source', 'tags' => ['svg']],
        ],
        'testimonials' => [['quote' => 'The calmest handoff I have had.', 'name' => 'Omar Nasser', 'role' => 'CTO, Tamkeen']],
    ];
@endphp
<x-nq::profile-page :profile="$profile" blog-href="/blog" post-href="/blog/{slug}" contact-button :now="'2026-09-30T00:00:00Z'" />
```

### HTML + Alpine

```html
<div data-slot="profile-page" x-data="nqProfilePage" class="@container mx-auto flex w-full max-w-6xl flex-col gap-10 px-4 py-8 @2xl:px-6 @2xl:py-12">
    <div class="grid grid-cols-1 gap-10 @4xl:grid-cols-[17rem_minmax(0,1fr)] @4xl:grid-rows-[auto_1fr] @4xl:gap-x-12">
        <header data-slot="profile-sidebar" x-data="nqProfilePage" class="flex min-w-0 flex-col gap-5 @4xl:col-start-1 @4xl:row-start-1">
    <div class="flex items-center gap-4 @4xl:flex-col @4xl:items-start">
        <span data-slot="avatar" x-data="nqAvatar(0)"
    class="inline-flex select-none items-center justify-center overflow-hidden bg-secondary align-middle font-medium text-secondary-foreground rounded-full size-20 shrink-0 text-h1 ring-1 ring-border @2xl:size-28 @4xl:size-56 @4xl:text-display">
                    <span data-slot="avatar-fallback" class="flex size-full items-center justify-center" x-bind="fallback"
             role="img" aria-label="Laylah Haddad" >LH</span>
    </span>
        <div class="flex min-w-0 flex-col gap-1">
            <h1 dir="auto" class="text-balance text-h1 text-foreground">Laylah Haddad</h1>
            <p dir="ltr" class="truncate text-start font-mono text-body-sm text-muted-foreground">@laylah</p>        </div>
    </div>
            <ul aria-label="Profile details" class="flex list-none flex-col gap-2 p-0">
                            <li><span data-slot="availability-badge" data-status="limited"
    class="inline-flex shrink-0 items-center gap-1.5 rounded-[4px] border px-2 text-body-sm font-medium [&_svg]:size-3 border-nq-warning/40 bg-nq-warning-soft text-nq-warning-text h-auto min-h-6 max-w-full flex-wrap py-0.5 text-start whitespace-normal">
    <span aria-hidden="true" class="size-1.5 rounded-full bg-current "></span>
    Limited availability
    <span class="font-normal opacity-80">from November</span></span>
</li>
                                        <li class="flex min-w-0 items-center gap-2 text-body-sm text-foreground"><svg data-slot="icon" aria-hidden="true" class="size-4 shrink-0 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"/>
  <circle cx="12" cy="10" r="3"/>
</svg><bdi class="truncate">Riyadh</bdi></li>
                                                        <li class="flex min-w-0 items-center gap-2 text-body-sm text-foreground">
                    <svg viewBox="0 0 98 96" width="20" height="20" aria-hidden="true" focusable="false" class="size-4 shrink-0">
    <path d="M41.4395 69.3848C28.8066 67.8535 19.9062 58.7617 19.9062 46.9902C19.9062 42.2051 21.6289 37.0371 24.5 33.5918C23.2559 30.4336 23.4473 23.7344 24.8828 20.959C28.7109 20.4805 33.8789 22.4902 36.9414 25.2656C40.5781 24.1172 44.4062 23.543 49.0957 23.543C53.7852 23.543 57.6133 24.1172 61.0586 25.1699C64.0254 22.4902 69.2891 20.4805 73.1172 20.959C74.457 23.543 74.6484 30.2422 73.4043 33.4961C76.4668 37.1328 78.0937 42.0137 78.0937 46.9902C78.0937 58.7617 69.1934 67.6621 56.3691 69.2891C59.623 71.3945 61.8242 75.9883 61.8242 81.252L61.8242 91.2051C61.8242 94.0762 64.2168 95.7031 67.0879 94.5547C84.4102 87.9512 98 70.6289 98 49.1914C98 22.1074 75.9883 6.69539e-07 48.9043 4.309e-07C21.8203 1.92261e-07 -1.9479e-07 22.1074 -4.3343e-07 49.1914C-6.20631e-07 70.4375 13.4941 88.0469 31.6777 94.6504C34.2617 95.6074 36.75 93.8848 36.75 91.3008L36.75 83.6445C35.4102 84.2188 33.6875 84.6016 32.1562 84.6016C25.8398 84.6016 22.1074 81.1563 19.4277 74.7441C18.375 72.1602 17.2266 70.6289 15.0254 70.3418C13.877 70.2461 13.4941 69.7676 13.4941 69.1934C13.4941 68.0449 15.4082 67.1836 17.3223 67.1836C20.0977 67.1836 22.4902 68.9063 24.9785 72.4473C26.8926 75.2227 28.9023 76.4668 31.2949 76.4668C33.6875 76.4668 35.2187 75.6055 37.4199 73.4043C39.0469 71.7773 40.291 70.3418 41.4395 69.3848Z"  class="fill-black dark:fill-white"  />
</svg>
                                        <a href="https://github.com/laylah"  target="_blank" rel="noopener noreferrer"   aria-label="GitHub: GitHub"  dir="ltr" class="truncate rounded-[2px] outline-none hover:underline hover:decoration-nq-line-strong hover:underline-offset-4 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus">GitHub</a>
                </li>
                                            <li class="flex min-w-0 items-center gap-2 text-body-sm text-foreground">
                    <svg data-slot="icon" aria-hidden="true" class="size-4 shrink-0 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="10"/>
  <path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/>
  <path d="M2 12h20"/>
</svg>                                        <a href="https://laylah.example.com"  target="_blank" rel="noopener noreferrer"   aria-label="Website: laylah.example.com"  dir="ltr" class="truncate rounded-[2px] outline-none hover:underline hover:decoration-nq-line-strong hover:underline-offset-4 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus">laylah.example.com</a>
                </li>
                    </ul>
                <div class="flex flex-col gap-2">
                                                <button data-slot="button"
     type="button"                         x-on:click="contact()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)] w-full">
        <svg data-slot="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"/>
  <rect x="2" y="4" width="20" height="16" rx="2"/>
</svg>Get in touch</button>
                                                    </div>
                <div data-slot="separator" role="separator" data-orientation="horizontal"
        class="shrink-0 bg-border h-px w-full"></div>
        <div class="flex flex-col gap-3">
            <p dir="auto" class="text-pretty text-body-sm text-nq-fg-body">Product designer who ships design systems for Arabic and English products.</p>                            <p class="inline-flex items-center gap-1.5 text-caption text-muted-foreground"><svg data-slot="icon" aria-hidden="true" class="size-3.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M8 2v3"/>
  <path d="M16 2v3"/>
  <rect x="3" y="3" width="18" height="18" rx="2"/>
  <path d="M3 9h18"/>
  <path d="M8 13h.01"/>
  <path d="M12 13h.01"/>
  <path d="M16 13h.01"/>
  <path d="M8 17h.01"/>
  <path d="M12 17h.01"/>
  <path d="M16 17h.01"/>
</svg>Joined March 2024</p>
                    </div>
</header>
        <div class="flex min-w-0 flex-col gap-12 @4xl:col-start-2 @4xl:row-span-2 @4xl:row-start-1">
                                    <section data-slot="profile-section" aria-labelledby="nq-profile-e316d2ce" class="flex flex-col gap-4">
    <div data-slot="section-header" class="flex items-end justify-between gap-4">
        <div class="flex min-w-0 flex-col gap-1">
            <h2 id="nq-profile-e316d2ce" class="text-h2 text-foreground">
                                    About
                            </h2>
                    </div>
            </div>
    <div data-slot="markdown" class="flex min-w-0 flex-col gap-3 text-body text-nq-fg-body max-w-prose"><p data-slot="text" dir="auto" class="text-body text-nq-fg-body text-start">I design <strong class="font-semibold text-foreground">calm, bilingual</strong> interfaces and the systems behind them.</p>
</div>
</section>
            <section data-slot="profile-section" aria-labelledby="nq-profile-3487bb3a" class="flex flex-col gap-4">
    <div data-slot="section-header" class="flex items-end justify-between gap-4">
        <div class="flex min-w-0 flex-col gap-1">
            <h2 id="nq-profile-3487bb3a" class="text-h2 text-foreground">
                                    Experience
                            </h2>
                            <p class="text-pretty text-body-sm text-muted-foreground">Where I have worked, newest first. 7 yr 2 mo of experience</p>
                    </div>
            </div>
    <ol data-slot="timeline" class="m-0 flex list-none flex-col p-0"><li data-slot="timeline-item" class="group/timeline grid grid-cols-[2rem_1fr] gap-x-3">
    <div class="flex flex-col items-center">
        <span data-slot="timeline-marker" class="flex size-8 shrink-0 items-center justify-center">
                            <span class="flex size-8 items-center justify-center rounded-full border border-border bg-secondary text-muted-foreground [&_svg]:size-4"><svg data-slot="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/>
  <rect width="20" height="14" x="2" y="6" rx="2"/>
</svg></span>
                    </span>
        <span aria-hidden="true" data-slot="timeline-rail" class="my-1 w-px flex-1 bg-border group-last/timeline:hidden"></span>
    </div>
    <div data-slot="timeline-content" class="flex min-w-0 flex-col gap-1 pb-6 pt-1 group-last/timeline:pb-0">
        <div class="flex items-baseline justify-between gap-3">
            <p class="min-w-0 text-body-sm font-medium text-foreground"><span dir="auto" class="flex flex-wrap items-center gap-x-2">
                        <bdi>Lead designer</bdi>
                        <span class="font-normal text-muted-foreground">
                                                            <bdi>Tamkeen</bdi>
                                                    </span>
                        <span data-slot="badge"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-nq-success/40 bg-nq-success-soft text-nq-success-text">Current</span>
                    </span></p>
                    </div>
                    <p class="text-body-sm text-muted-foreground"><span class="flex flex-wrap gap-x-2">
                        <span>Jan 2022 – Present</span>
                        <span aria-hidden="true">·</span>
                        <span>4 yr 8 mo</span>
                                            </span></p>
                            <div class="flex flex-wrap items-center gap-2"><div class="mt-2 flex w-full basis-full flex-col gap-2 pb-6">
                        <p dir="auto" class="text-body-sm text-nq-fg-body">Owns the design system.</p>                                                                    </div></div>
            </div>
</li>
                                <li data-slot="timeline-item" class="group/timeline grid grid-cols-[2rem_1fr] gap-x-3">
    <div class="flex flex-col items-center">
        <span data-slot="timeline-marker" class="flex size-8 shrink-0 items-center justify-center">
                            <span class="flex size-8 items-center justify-center rounded-full border border-border bg-secondary text-muted-foreground [&_svg]:size-4"><svg data-slot="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/>
  <rect width="20" height="14" x="2" y="6" rx="2"/>
</svg></span>
                    </span>
        <span aria-hidden="true" data-slot="timeline-rail" class="my-1 w-px flex-1 bg-border group-last/timeline:hidden"></span>
    </div>
    <div data-slot="timeline-content" class="flex min-w-0 flex-col gap-1 pb-6 pt-1 group-last/timeline:pb-0">
        <div class="flex items-baseline justify-between gap-3">
            <p class="min-w-0 text-body-sm font-medium text-foreground"><span dir="auto" class="flex flex-wrap items-center gap-x-2">
                        <bdi>Designer</bdi>
                        <span class="font-normal text-muted-foreground">
                                                            <bdi>Studio Nour</bdi>
                                                    </span>
                                            </span></p>
                    </div>
                    <p class="text-body-sm text-muted-foreground"><span class="flex flex-wrap gap-x-2">
                        <span>Jun 2019 – Dec 2021</span>
                        <span aria-hidden="true">·</span>
                        <span>2 yr 6 mo</span>
                                            </span></p>
                    </div>
</li></ol>
</section>
            <section data-slot="profile-section" aria-labelledby="nq-profile-99e13632" class="flex flex-col gap-4">
    <div data-slot="section-header" class="flex items-end justify-between gap-4">
        <div class="flex min-w-0 flex-col gap-1">
            <h2 id="nq-profile-99e13632" class="text-h2 text-foreground">
                                    Skills
                            </h2>
                            <p class="text-pretty text-body-sm text-muted-foreground">What I use most, strongest first.</p>
                    </div>
            </div>
    <div data-slot="skills-widget" class="flex flex-col gap-5">
            <div class="flex flex-col gap-2">
            <p class="eyebrow">Design</p>            <ul class="flex flex-wrap gap-2">
                                    <li class="inline-flex h-control-sm items-center gap-2 rounded-control border border-border bg-card px-2.5 text-body-sm text-foreground">
                        <bdi>Figma</bdi>
                                                    <span role="img" aria-label="Level 5 of 5" class="flex gap-0.5">
                                <span class="size-1.5 rounded-full bg-primary"></span><span class="size-1.5 rounded-full bg-primary"></span><span class="size-1.5 rounded-full bg-primary"></span><span class="size-1.5 rounded-full bg-primary"></span><span class="size-1.5 rounded-full bg-primary"></span>                            </span>
                                            </li>
                            </ul>
        </div>
            <div class="flex flex-col gap-2">
            <p class="eyebrow">Code</p>            <ul class="flex flex-wrap gap-2">
                                    <li class="inline-flex h-control-sm items-center gap-2 rounded-control border border-border bg-card px-2.5 text-body-sm text-foreground">
                        <bdi>Vue</bdi>
                                                    <span role="img" aria-label="Level 3 of 5" class="flex gap-0.5">
                                <span class="size-1.5 rounded-full bg-primary"></span><span class="size-1.5 rounded-full bg-primary"></span><span class="size-1.5 rounded-full bg-primary"></span><span class="size-1.5 rounded-full bg-nq-line"></span><span class="size-1.5 rounded-full bg-nq-line"></span>                            </span>
                                            </li>
                            </ul>
        </div>
    </div>
</section>
            <section data-slot="profile-section" aria-labelledby="nq-profile-d98c5848" class="flex flex-col gap-4">
    <div data-slot="section-header" class="flex items-end justify-between gap-4">
        <div class="flex min-w-0 flex-col gap-1">
            <h2 id="nq-profile-d98c5848" class="text-h2 text-foreground">
                                    <span class="inline-flex items-center gap-2">Projects<span data-slot="badge"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-border bg-secondary text-foreground tabular-nums">2</span>
</span>
                            </h2>
                            <p class="text-pretty text-body-sm text-muted-foreground">Selected work.</p>
                    </div>
            </div>
    <div data-slot="feature-story" class="@container">
    <section aria-labelledby="nq-feature-4dcb5735" class="grid grid-cols-1 items-center gap-8 @3xl:grid-cols-2 @3xl:gap-12 rounded-card border border-border bg-card p-4 @3xl:p-6">
        <div class="flex min-w-0 flex-col items-start gap-4">
                            <div class="flex items-center gap-2 text-label text-muted-foreground">
                                        Featured project
                </div>
                        <h3 id="nq-feature-4dcb5735" class="text-balance text-h1 text-foreground">Ledger</h3>
                            <p class="text-pretty text-body text-muted-foreground">A bilingual bookkeeping app.</p>
                                        <ul class="flex flex-col gap-2">
                                            <li class="flex items-start gap-2 text-body-sm text-foreground">
                            <svg aria-hidden="true" class="mt-0.5 size-4 shrink-0 text-nq-brand" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg>                            <span>RTL first</span>
                        </li>
                                            <li class="flex items-start gap-2 text-body-sm text-foreground">
                            <svg aria-hidden="true" class="mt-0.5 size-4 shrink-0 text-nq-brand" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg>                            <span>Offline</span>
                        </li>
                                    </ul>
                                </div>
                    <div class="min-w-0"><div data-slot="post-cover" class="relative w-full overflow-hidden rounded-card border border-border bg-secondary">
            <div aria-hidden="true" style="--cover-a: var(--nq-tag-red); --cover-a-soft: var(--nq-tag-red-soft); --cover-b-soft: var(--nq-tag-green-soft); --cover-x: 64%; --cover-y: 30%"
            class="size-full bg-[radial-gradient(circle_at_var(--cover-x)_var(--cover-y),var(--cover-a-soft),transparent_55%),linear-gradient(135deg,var(--cover-a-soft),var(--cover-b-soft))]">
            <div class="absolute -bottom-1/4 -end-[8%] size-2/5 rounded-full border-2 border-[var(--cover-a)] opacity-40"></div>
            <div class="absolute start-[10%] top-[16%] size-6 rounded-full bg-[var(--cover-a)] opacity-30"></div>
        </div>
    </div></div>
            </section>
</div>
        <div data-slot="tabs" data-orientation="horizontal" x-data="nqTabs('all')" x-modelable="value" x-id="['nq-tabs']" class="flex flex-col gap-4">
    <div data-slot="tabs-panel" x-bind="panel('all')"
        class="outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus"><ul class="grid grid-cols-1 gap-4 @2xl:grid-cols-2">
                                            <li class="flex">
                            <div class="min-w-0 flex-1">
                                <div data-slot="project-card" class="flex flex-col rounded-card border border-border bg-card text-card-foreground group/project relative h-full gap-0 overflow-hidden py-0 transition-colors duration-150 ease-nq hover:bg-nq-hover"><div data-slot="post-cover" class="relative w-full overflow-hidden bg-secondary rounded-none border-0 border-b border-border">
            <div aria-hidden="true" style="--cover-a: var(--nq-tag-blue); --cover-a-soft: var(--nq-tag-blue-soft); --cover-b-soft: var(--nq-tag-orange-soft); --cover-x: 21%; --cover-y: 54%"
            class="size-full bg-[radial-gradient(circle_at_var(--cover-x)_var(--cover-y),var(--cover-a-soft),transparent_55%),linear-gradient(135deg,var(--cover-a-soft),var(--cover-b-soft))]">
            <div class="absolute -bottom-1/4 -end-[8%] size-2/5 rounded-full border-2 border-[var(--cover-a)] opacity-40"></div>
            <div class="absolute start-[10%] top-[16%] size-6 rounded-full bg-[var(--cover-a)] opacity-30"></div>
        </div>
    </div>
                                    <div class="flex flex-1 flex-col items-start gap-2 p-4">
                                        <span data-slot="badge"  style="--tag-solid: var(--nq-tag-red); --tag-soft: var(--nq-tag-red-soft)"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-transparent bg-[var(--tag-soft)] text-[var(--tag-solid)]">Open source</span>
                                        <h3 dir="auto" class="text-h3 text-foreground">
                                            Open kit                                        </h3>
                                        <p dir="auto" class="line-clamp-3 text-body-sm text-muted-foreground">A small icon kit.</p>
                                                                                    <ul class="flex flex-wrap gap-1.5"><li><span data-slot="badge"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-border text-muted-foreground"><bdi>svg</bdi></span>
</li></ul>
                                                                                                                    </div></div>
                            </div>
                        </li>
                                    </ul></div>
                    <div data-slot="tabs-panel" x-bind="panel('Open source')"
     hidden     class="outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus"><ul class="grid grid-cols-1 gap-4 @2xl:grid-cols-2">
                                            <li class="flex">
                            <div class="min-w-0 flex-1">
                                <div data-slot="project-card" class="flex flex-col rounded-card border border-border bg-card text-card-foreground group/project relative h-full gap-0 overflow-hidden py-0 transition-colors duration-150 ease-nq hover:bg-nq-hover"><div data-slot="post-cover" class="relative w-full overflow-hidden bg-secondary rounded-none border-0 border-b border-border">
            <div aria-hidden="true" style="--cover-a: var(--nq-tag-blue); --cover-a-soft: var(--nq-tag-blue-soft); --cover-b-soft: var(--nq-tag-orange-soft); --cover-x: 21%; --cover-y: 54%"
            class="size-full bg-[radial-gradient(circle_at_var(--cover-x)_var(--cover-y),var(--cover-a-soft),transparent_55%),linear-gradient(135deg,var(--cover-a-soft),var(--cover-b-soft))]">
            <div class="absolute -bottom-1/4 -end-[8%] size-2/5 rounded-full border-2 border-[var(--cover-a)] opacity-40"></div>
            <div class="absolute start-[10%] top-[16%] size-6 rounded-full bg-[var(--cover-a)] opacity-30"></div>
        </div>
    </div>
                                    <div class="flex flex-1 flex-col items-start gap-2 p-4">
                                        <span data-slot="badge"  style="--tag-solid: var(--nq-tag-red); --tag-soft: var(--nq-tag-red-soft)"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-transparent bg-[var(--tag-soft)] text-[var(--tag-solid)]">Open source</span>
                                        <h3 dir="auto" class="text-h3 text-foreground">
                                            Open kit                                        </h3>
                                        <p dir="auto" class="line-clamp-3 text-body-sm text-muted-foreground">A small icon kit.</p>
                                                                                    <ul class="flex flex-wrap gap-1.5"><li><span data-slot="badge"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-border text-muted-foreground"><bdi>svg</bdi></span>
</li></ul>
                                                                                                                    </div></div>
                            </div>
                        </li>
                                    </ul></div>
</div>
</section>
                        <section data-slot="profile-section" aria-labelledby="nq-profile-8b4247f4" class="flex flex-col gap-4">
    <div data-slot="section-header" class="flex items-end justify-between gap-4">
        <div class="flex min-w-0 flex-col gap-1">
            <h2 id="nq-profile-8b4247f4" class="text-h2 text-foreground">
                                    <span class="inline-flex items-center gap-2">Kind words<span data-slot="badge"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-border bg-secondary text-foreground tabular-nums">1</span>
</span>
                            </h2>
                            <p class="text-pretty text-body-sm text-muted-foreground">From people I have worked with.</p>
                    </div>
            </div>
    <ul class="grid grid-cols-1 gap-4 @2xl:grid-cols-2">
                    <li class="flex">
                <div data-slot="card" class="flex flex-col rounded-card border border-border bg-card text-card-foreground w-full gap-3 p-4"><svg data-slot="icon" aria-hidden="true" class="size-5 text-nq-accent-text" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z"/>
  <path d="M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z"/>
</svg>                    <blockquote dir="auto" class="text-pretty text-body text-foreground">The calmest handoff I have had.</blockquote>
                    <footer class="mt-auto flex items-center gap-2.5">
                        <span data-slot="avatar" x-data="nqAvatar(0)"
    class="inline-flex shrink-0 select-none items-center justify-center overflow-hidden bg-secondary align-middle font-medium text-secondary-foreground size-8 text-caption rounded-full">
                    <span data-slot="avatar-fallback" class="flex size-full items-center justify-center" x-bind="fallback"
             role="img" aria-label="Omar Nasser" >ON</span>
    </span>
                        <div class="flex flex-col leading-tight">
                            <bdi class="text-label text-foreground">Omar Nasser</bdi>
                            <span class="text-caption text-muted-foreground">CTO, Tamkeen</span>                        </div>
                    </footer></div>
            </li>
            </ul>
</section>
        </div>
                    <aside aria-label="Profile sections" class="grid grid-cols-1 content-start gap-4 @xl:grid-cols-2 @4xl:col-start-1 @4xl:row-start-2 @4xl:grid-cols-1">
                <div data-slot="local-clock" x-data="nqLocalClock(JSON.parse('{\u0022timeZone\u0022:\u0022Asia\\\/Riyadh\u0022,\u0022locale\u0022:\u0022en\u0022,\u0022now\u0022:1790726400000,\u0022labels\u0022:{\u0022working\u0022:\u0022Working hours\u0022,\u0022offHours\u0022:\u0022Outside working hours\u0022,\u0022sameTime\u0022:\u0022Same time as you\u0022,\u0022ahead\u0022:\u0022{n}h ahead of you\u0022,\u0022behind\u0022:\u0022{n}h behind you\u0022}}'))"
    class="flex flex-col gap-2 rounded-card border border-border bg-card py-4 text-card-foreground">
    <div data-slot="card-header" class="grid auto-rows-min items-start gap-1 px-4"><div data-slot="card-title" class="text-label text-foreground">Local time</div></div>
    <div data-slot="card-content" class="flex flex-col gap-1 px-4">
        <p class="flex items-baseline gap-2">
            <time x-bind:datetime="iso" x-text="time" datetime="2026-09-30T00:00:00+00:00" class="text-h1 tabular-nums text-foreground" dir="ltr">3:00 AM</time>
            <span class="text-body-sm text-muted-foreground">in Riyadh</span>        </p>
        <p class="flex items-center gap-1.5 text-body-sm text-muted-foreground">
            <span aria-hidden="true" x-bind:class="working ? 'bg-nq-success' : 'bg-nq-line-strong'" class="size-2 rounded-full bg-nq-line-strong"></span>
            <span x-text="statusText">Outside working hours</span>
        </p>
        <p class="text-caption text-muted-foreground" x-text="offsetText">3h ahead of you</p>
    </div>
</div>
                                                            </aside>
            </div>
            <section data-slot="profile-contact" x-data="nqProfilePage" aria-labelledby="nq-profile-contact-178d6999" class="flex flex-col items-start gap-4 rounded-card border border-border bg-card p-6 @2xl:flex-row @2xl:items-center @2xl:justify-between">
    <div class="flex min-w-0 flex-col gap-2">
        <span data-slot="availability-badge" data-status="limited"
    class="inline-flex h-6 shrink-0 items-center gap-1.5 whitespace-nowrap rounded-[4px] border px-2 text-body-sm font-medium [&_svg]:size-3 border-nq-warning/40 bg-nq-warning-soft text-nq-warning-text">
    <span aria-hidden="true" class="size-1.5 rounded-full bg-current "></span>
    Limited availability
    <span class="font-normal opacity-80">from November</span></span>
        <h2 id="nq-profile-contact-178d6999" class="text-balance text-h1 text-foreground">Let&#039;s build something together</h2>
        <p class="max-w-xl text-pretty text-body text-muted-foreground">Tell me about your project. I usually reply within two working days.</p>
    </div>
            <button data-slot="button"
     type="button"                         x-on:click="contact()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-[calc(var(--nq-control)+8px)] px-5 text-body">
        <svg data-slot="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"/>
  <rect x="2" y="4" width="20" height="16" rx="2"/>
</svg>Get in touch</button>
    </section>
    </div>
```
