# CRM contact profile

> A teal CRM contact screen: a profile slides in, a health-score ring fills to 82 and the activity timeline stacks up.

- Category: Developer tools
- Version: 1.0
- Source: https://ownlyplans.com/bhaskar/crm-contact-profile/

## Overview

A calm customer profile page with a contact list on the left. Priya Sharma opens with a ring that fills to a health score of 82, three timeline events rise in one by one and a "Next step" button appears. Topic inspired by OpenDesign's public dashboard prompt list; this prompt and design are written from scratch.

## Tech stack

- CSS
- Dashboard
- HTML

## Build steps

### 1. Paste the prompt

The AI builds the contact list and the profile card.

Prompt:

```text
Build a single-file HTML CRM contact profile screen, 1280x720, soft teal background #eef6f5, ink #10302d, accent teal #14b8a6, indigo #6366f1. White cards with 22px radius and a soft teal shadow. System fonts, no libraries.
Left card "Contacts": five rows (coloured circle avatar, name, company line). The second row, "Priya Sharma - Acme Corp - Champion", is the selected one and gets a pale teal background.
Right card (profile): large gradient avatar, name "Priya Sharma", subtitle "VP Operations - Acme Corp", two pills (green "Customer", indigo "Renewal Q1"). On the right a 104px health score ring (SVG circle, stroke-dasharray 289) with a number in the centre that counts up to 82 using a CSS @property integer animation. Below, a vertical timeline with a teal line and dot markers: "Opened pricing proposal", "Call: renewal terms", "Signed 12-month contract", each with a small grey detail line.
Bottom right: a dark rounded button "Next step: send renewal quote".
Motion (8 second loop): the profile card slides in from the right, the ring fills and the number counts, timeline events fade up one after another, the Next step button scales in last. Everything fades out at the end and restarts.
Respect prefers-reduced-motion. Return only the complete HTML.
```

### 2. Check the health ring

It should fill to 82 as the number counts up.

### 3. Check the timeline

Three events should appear one at a time.

**Done when:** You can see it working in the browser.

### 4. Make it real

Load contacts and events from your CRM instead of the sample text.

## Assets

### prompt.md — The full prompt.

~~~~
# CRM contact profile

Copy this prompt into Claude, Cursor or Lovable.

```text
Build a single-file HTML CRM contact profile screen, 1280x720, soft teal background #eef6f5, ink #10302d, accent teal #14b8a6, indigo #6366f1. White cards with 22px radius and a soft teal shadow. System fonts, no libraries.
Left card "Contacts": five rows (coloured circle avatar, name, company line). The second row, "Priya Sharma - Acme Corp - Champion", is the selected one and gets a pale teal background.
Right card (profile): large gradient avatar, name "Priya Sharma", subtitle "VP Operations - Acme Corp", two pills (green "Customer", indigo "Renewal Q1"). On the right a 104px health score ring (SVG circle, stroke-dasharray 289) with a number in the centre that counts up to 82 using a CSS @property integer animation. Below, a vertical timeline with a teal line and dot markers: "Opened pricing proposal", "Call: renewal terms", "Signed 12-month contract", each with a small grey detail line.
Bottom right: a dark rounded button "Next step: send renewal quote".
Motion (8 second loop): the profile card slides in from the right, the ring fills and the number counts, timeline events fade up one after another, the Next step button scales in last. Everything fades out at the end and restarts.
Respect prefers-reduced-motion. Return only the complete HTML.
```
~~~~

### index.html.md — Complete code of the result in the video.

~~~~
# index.html

The finished result as one file. Save it as index.html and open it.

```html
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>CRM contact profile</title><style>*{box-sizing:border-box;margin:0;padding:0}
html,body{width:1280px;height:720px;overflow:hidden}
body{font-family:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;-webkit-font-smoothing:antialiased}
@property --n{syntax:'<integer>';inherits:false;initial-value:0}
.stage{position:absolute;inset:0;animation:cyc 8s linear infinite both}
@keyframes cyc{0%{opacity:0}4%{opacity:1}94%{opacity:1}100%{opacity:0}}
body:not(.go) *,body:not(.go) *::before,body:not(.go) *::after{animation-play-state:paused!important}
.cnt::after{content:counter(n)}.cnt{counter-reset:n var(--n)}
@media (prefers-reduced-motion:reduce){*{animation:none!important}}


body{background:#eef6f5;color:#10302d}
.list{position:absolute;left:36px;top:36px;bottom:36px;width:340px;background:#fff;border-radius:22px;padding:22px;box-shadow:0 18px 40px -28px #0b5d55}
.list h2{font-size:13px;letter-spacing:.08em;text-transform:uppercase;color:#5f8b86;margin-bottom:16px}
.ct{display:flex;gap:12px;align-items:center;padding:12px;border-radius:14px;margin-bottom:6px;font-size:14px}
.ct i{width:38px;height:38px;border-radius:50%;background:#7dd3c8;flex:none}.ct small{display:block;color:#6f8f8b;font-size:12px}
.ct.sel{background:#e3f5f2;animation:sel 8s infinite both}
@keyframes sel{0%,6%{background:#fff}12%,100%{background:#d4f0eb}}
.prof{position:absolute;left:408px;top:36px;right:36px;bottom:36px;background:#fff;border-radius:22px;padding:30px 36px;box-shadow:0 18px 40px -28px #0b5d55;animation:pf 8s infinite both}
@keyframes pf{0%,8%{opacity:0;transform:translateX(24px)}16%,100%{opacity:1;transform:none}}
.hd{display:flex;gap:20px;align-items:center}.av{width:84px;height:84px;border-radius:50%;background:linear-gradient(135deg,#14b8a6,#6366f1)}
.hd h1{font-size:30px;letter-spacing:-.03em}.hd p{color:#6f8f8b;margin:4px 0 8px}.ch{display:inline-block;font-size:12px;font-weight:700;padding:5px 11px;border-radius:99px;background:#d9f7e6;color:#13794a;margin-right:6px}.ch.b{background:#e0e7ff;color:#3b49b8}
.ring{margin-left:auto;position:relative;width:104px;height:104px}.ring svg{transform:rotate(-90deg)}.ring b{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:26px}
.rg{stroke-dasharray:289;animation:rg 8s infinite both}@keyframes rg{0%,14%{stroke-dashoffset:289}44%,100%{stroke-dashoffset:52}}
.sc{animation:sc 8s infinite both}@keyframes sc{0%,14%{--n:0}44%,100%{--n:82}}
.tl{margin-top:30px;border-left:2px solid #d4ebe7;margin-left:10px;padding-left:26px}
.ev{position:relative;margin-bottom:20px;opacity:0;animation:ev 8s infinite both}.ev::before{content:"";position:absolute;left:-35px;top:4px;width:14px;height:14px;border-radius:50%;background:#14b8a6;border:3px solid #fff;box-shadow:0 0 0 2px #14b8a6}
.ev b{font-size:15px;display:block}.ev span{font-size:13px;color:#6f8f8b}
.e1{animation-name:e1}.e2{animation-name:e2}.e3{animation-name:e3}
@keyframes e1{0%,28%{opacity:0;transform:translateY(12px)}36%,100%{opacity:1;transform:none}}
@keyframes e2{0%,44%{opacity:0;transform:translateY(12px)}52%,100%{opacity:1;transform:none}}
@keyframes e3{0%,60%{opacity:0;transform:translateY(12px)}68%,100%{opacity:1;transform:none}}
.next{position:absolute;right:36px;bottom:30px;background:#10302d;color:#fff;border-radius:14px;padding:14px 20px;font-weight:700;opacity:0;animation:nx 8s infinite both}
@keyframes nx{0%,76%{opacity:0;transform:scale(.8)}82%,100%{opacity:1;transform:none}}
</style></head><body><div class="stage">
<div class="list"><h2>Contacts</h2>
<div class="ct"><i></i><div>Dana Whitfield<small>Orbit Retail</small></div></div>
<div class="ct sel"><i style="background:#a5b4fc"></i><div>Priya Sharma<small>Acme Corp - Champion</small></div></div>
<div class="ct"><i style="background:#fcd34d"></i><div>Marco Bellini<small>Tidal Foods</small></div></div>
<div class="ct"><i style="background:#fda4af"></i><div>Lena Okafor<small>Helio Bank</small></div></div>
<div class="ct"><i style="background:#86efac"></i><div>Tom Reyes<small>Pine &amp; Co</small></div></div></div>
<div class="prof"><div class="hd"><div class="av"></div><div><h1>Priya Sharma</h1><p>VP Operations - Acme Corp</p><span class="ch">Customer</span><span class="ch b">Renewal Q1</span></div>
<div class="ring"><svg width="104" height="104"><circle cx="52" cy="52" r="46" fill="none" stroke="#e1f1ee" stroke-width="10"/><circle class="rg" cx="52" cy="52" r="46" fill="none" stroke="#14b8a6" stroke-width="10" stroke-linecap="round"/></svg><b><span class="cnt sc"></span></b></div></div>
<div class="tl"><div class="ev e1"><b>Opened pricing proposal</b><span>Today, 9:42 - viewed 3 times</span></div><div class="ev e2"><b>Call: renewal terms</b><span>Yesterday - 28 min with Sam</span></div><div class="ev e3"><b>Signed 12-month contract</b><span>Nov 2025 - $48,000</span></div></div>
<div class="next">Next step: send renewal quote</div></div></div><script>window.start=function(){document.body.classList.add("go")};if(!/[?&]rec/.test(location.search))start();</script></body></html>
```
~~~~


## Build instructions by tool

### Claude Code

Open a terminal in an empty folder, run `claude`, then paste the prompt.

```text
Build the "CRM contact profile" app from the OwnlyPlans blueprint at https://ownlyplans.com/bhaskar/crm-contact-profile/.
Stack: CSS, Dashboard, HTML.
Follow the plan's steps in order: Paste the prompt → Check the health ring → Check the timeline → Make it real.
Download the full plan (Markdown) from the link above and keep it in the project root as PLAN.md.
Ask me before adding anything not in the plan. (Prepared for Claude Code.)
```

### Cursor

Open an empty folder in Cursor, start an Agent chat, then paste the prompt.

```text
Build the "CRM contact profile" app from the OwnlyPlans blueprint at https://ownlyplans.com/bhaskar/crm-contact-profile/.
Stack: CSS, Dashboard, HTML.
Follow the plan's steps in order: Paste the prompt → Check the health ring → Check the timeline → Make it real.
Download the full plan (Markdown) from the link above and keep it in the project root as PLAN.md.
Ask me before adding anything not in the plan. (Prepared for Cursor.)
```

### Lovable

Start a new Lovable project and paste the prompt as your first message.

```text
Build the "CRM contact profile" app from the OwnlyPlans blueprint at https://ownlyplans.com/bhaskar/crm-contact-profile/.
Stack: CSS, Dashboard, HTML.
Follow the plan's steps in order: Paste the prompt → Check the health ring → Check the timeline → Make it real.
Download the full plan (Markdown) from the link above and keep it in the project root as PLAN.md.
Ask me before adding anything not in the plan. (Prepared for Lovable.)
```

## Definition of done

- Every build step is complete and the app runs locally.
- The main user flow works end to end.
- Share your build on OwnlyPlans with a demo link, build time and tool.
