React Bento Portfolio Grid for a Personal Profile Page
ProSix tiles that introduce one person: a name with a Book a call button and a photo, a blue availability tile, three stacked quote cards, a pair of clocks comparing your time with the visitor's, an email address you copy with one press, and a heatmap of eighteen weeks of work. The shipped content is the author's own profile, Parth Sharma, founder of Wensity, so every personal detail is there to be swapped for yours.

A bento portfolio that answers the first five questions
Bento Grid With Portfolio Profile is a React and Tailwind CSS bento portfolio section: a personal profile laid out as six tiles of different sizes, covering who you are, whether you are free, what people say, where you are and how to reach you, in Next.js or any React app. It works as the top of a personal site or as the about section of a studio page.
A bento grid suits a profile because the questions a visitor brings are of different weight. The name and photo deserve the tall tile; the time zone needs a small one. Giving each answer its own compartment means nobody has to read a bio paragraph to find your email.
Bento profiles became a familiar format through link in bio pages, where the grid was hosted for you and the page was never yours. This is the opposite trade: a single file you own, in your own repository, with tiles that do something. The clock ticks, the email copies, the quote cards shuffle and the heatmap reads from data you pass in.
The six tiles of the bento portfolio grid
On desktop the grid is three columns: the profile tile spans two rows, the quotes and the heatmap each span two columns. Phones read it in a fixed order: profile, availability, quotes, time, email, activity.
Profile
The name renders as the section heading (h2 by default) on one line at every width, sized with container query units. Under it sit the role, a Book a call link and three icon links to X, GitHub and Instagram. The photo bleeds off the bottom edge of the tile.
Open for new projects
The one blue tile, with a fine grain overlay. A dark card reading Next opening: January links to the same booking URL and, on desktop, hangs 72px past the tile's right edge into its neighbour.
Kind words
Three quote cards fanned behind each other. The rear two are buttons labelled with the author's name, and pressing one brings it to the front with a 520ms transform.
Based in Noida
Two tilted cards: the visitor's city and time behind, the profile's city and time in front. The line above states the gap, for example 5 hours 30 minutes ahead of you, computed from both time zones.
Say hello
The address set as large type, local part in a metal gradient and the domain dimmed on its own line, with a Copy email button that flips to Copied without changing width.
Shipping every week
A heatmap of 126 squares, eighteen weeks of seven days, in five levels of blue. The squares fade in week by week the first time half of the grid is on screen.
Who this profile bento is for
Use it when
- A freelancer, consultant or design engineer whose site has to say available, here is how to book, in one screen.
- You work across time zones and want clients to see your hours against theirs without doing the arithmetic.
- You have three short things people have actually said about you, word for word, with their permission.
- You can feed the heatmap from real data such as commits, posts or shipped tickets.
Skip it when
- You need a full portfolio of case studies. This is one section; the projects belong on pages of their own.
- You cannot edit the source. Name, role, photo, socials, email, city, time zone and quotes are constants in the file, not props.
- The profile is for a team rather than a person. Every tile is written in the first person singular.
- You need a list of ten social links. The row is built for three icons.
Replace the author's profile with yours
Everything personal ships as the author's real details, so treat the block as a filled in example, not a template with blanks. Open the file and change PROFILE (name, role, photo URL, city, IANA time zone such as Europe/Berlin, and the month of your next opening), SOCIALS (three links and their labels), EMAIL, and QUOTES (name, avatar and the exact words). The three quotes in the file are real messages about Wensity; never ship them under your name.
The social marks load from assets.wensity.com as single colour SVGs that are inverted per theme, and the Instagram glyph is drawn inline. Swap the src values for your own hosted marks, or replace a link entirely. Keep the photo at a portrait crop: it is set to object-position 50% 58% so a face stays in frame as the tile changes shape.
The props cover the parts that change per page rather than per person. Point bookCallHref at your scheduling link, choose the heading level, and pass activity as an array of 126 numbers from 0 to 4, oldest day first. The sample pattern is generated from a fixed formula so the server and client render the same squares, but it is not anyone's real history.
npx wensity@latest add bento-grid-with-portfolio-profile --type block
import { BentoGridPortfolioProfile } from "@/components/wensity/blocks/bento-grid-with-portfolio-profile";import { weeklyCommitLevels } from "@/lib/github";export default async function Home() {// 126 values from 0 to 4, oldest day first.const activity = await weeklyCommitLevels("your-github-username");return (<BentoGridPortfolioProfileheadingAs="h1"bookCallHref="https://cal.com/your-name/intro"activity={activity}/>);}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
bookCallHref | string | "#" | Used by both the Book a call button and the Next opening card, so one scheduling URL serves both. |
activity | number[] | sample pattern | 126 levels, 0 to 4, one per day and oldest first. Values are rounded and clamped, so raw counts must be bucketed first. |
headingAs | "h1" | "h2" | "h3" | "h2" | Make the name the h1 when this grid is the top of a personal home page. |
className | string | - | Override the #fafafa and #050506 section backgrounds to sit on your page colour. |
What runs in the browser
No animation library
Motion is CSS transitions plus the Web Animations API for the confetti. The only packages are clsx and tailwind-merge for the class helper.
No hydration mismatch on the clock
The time is null until the component mounts, so the server renders --:--:-- and the browser fills in real times. Under reduced motion the clock steps once a minute and drops the seconds.
Clipboard with a fallback
Copy email writes to the clipboard and fires a burst of 38 paper pieces from the button. If the clipboard is blocked it opens a mailto link instead. A polite live region announces Email address copied; reduced motion skips the burst.
Screen readers
The tilted time cards are hidden from assistive tech and replaced by one sentence giving the profile's local time. The heatmap is a single image with an aria-label, so it is not read square by square.
Heading order
The name is the section heading and each other tile title is an h3, so the outline reads as one profile with five sub topics.
Block details
- Category
- Bento Grids
- Renders
- JavaScript animation. Paints first, then animates
- Theme
- Follows the site theme in light and dark
- Dependencies
clsxtailwind-merge- Source
- 813 lines, 36 KB in one file
- Install
wensity add bento-grid-with-portfolio-profile --type block- Tags
- light, dark, bento, portfolio, profile
- Last updated

