Draw the three portfolio links on the profile page - #137
Open
toruiwasa wants to merge 1 commit into
Open
Conversation
`website_url`, `github_url` and `linkedin_url` have been in the model, the draft, the validation and the editor form since the columns landed, and nothing rendered them. This draws them on `/p/<handle>`, which is the last of #84's four scope items — the other three were already in `practitioners.ts:310-313`, `profile-draft.ts:112-114` and `profile-validation.ts:94-96`. ## Where they go A section of their own, after the focus tags and before the CTA row. The reading order becomes who somebody is, what Bluehex checked, what they work on, where else to find them, and then how to reach them. Below the credentials rather than beside the name, because the badge is what the page is read for and a row of exits above it invites a visitor to leave before reaching the part that was checked. Outside the credentials block for the opposite reason: nothing here is attested, and proximity alone would claim otherwise. That is not only the ADR's line — `clear_profile_verification()` has exactly three triggers, on `name`, on a claim, and on `contact_email` while unclaimed, and no link is among them. Separate from the CTA row because #84 calls these `a row of ordinary links rather than a call to action`, which is the distinction it was split from #85 along. So they are plain underlined links matching `See the certificate` in the same file, not the pill `Book a meeting` wears. An empty field renders nothing, and a profile with no links renders no section at all rather than a rule with nothing under it. ## portfolioLinks The list is built in `@/lib/practitioners` rather than inline, because nothing else can reach it: the page is a client component with no component test to run against it, and `e2e/routes.spec.ts` visits `/` and `/contact` and never `/p/[handle]`. As JSX the ordering and the drop-if-empty rule would be asserted by nobody. #131 states the same rule for the same file. It takes a `Pick` rather than a whole `Profile`, following `profilePath`. `bookingUrl` is absent from that type on purpose — leaving it out is cheaper than remembering to filter it at the call site, and it keeps the two rows from collapsing into one later. Named for the ticket's word rather than for the field docstring's, which calls all four of these columns "published links". Three of them are the portfolio and the fourth is a booking, so a helper called `publishedLinks` that returned three would have invited exactly the question the split exists to answer. ## Comments corrected Three comments described the links as undrawn, two of them naming #84 and #85 as the reason. All three would have shipped as false with this change: the header of `profile-detail.tsx`, `directory.ts` above `PROFILE_COLUMNS`, and `toProfile` in `directory-mapping.ts`. That leaves `availability` as the one column in the `anon` grant that no public surface draws yet. The new wording says that rather than claiming it is drawn nowhere at all, because the editor does draw it, through `my_profile()` rather than through this list. `services` is undrawn too, and both stay flagged. ## Checks `pnpm lint`, `pnpm test` (276, four of them new) and `pnpm build` are green. The four link patterns in `supabase/seed.sql` were opened at `/p/seed0001` through `/p/seed0004`, which covers two links, one link, none, and one alongside a booking button. No approved seed profile holds all three, so that combination was produced by editing a local row for the screenshot and putting it back, and it is pinned by a unit test as well. `pnpm test:e2e` passes 20/20 with no Supabase configured, which is the state the empty-directory test documents. With a local `.env.local` that one test fails on both projects because the seeded roster is not empty; that is true on `main` as well.
toruiwasa
marked this pull request as ready for review
August 25, 2026 11:23
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #84.
Summary
The three portfolio links now render on
/p/<handle>. The model, the draft, the validation and the editor form already carried them, so this is the last of the four scope items.portfolioLinksin@/lib/practitionersbuilds the list, with four unit tests.profile-detail.tsx,directory.tsanddirectory-mapping.tsare corrected too.What it looks like
No links, so no section.
/p/seed0003One link, beside a booking button.
/p/seed0004Two links, with the first of the three missing.
All three, in model order.
The seed has no approved profile for the last two combinations, so those rows were edited locally for the screenshot and put back. The branch does not touch
supabase/seed.sql.What I decided without asking
drawing the rest is #84 and #85as a description of code that now draws them.Verification
pnpm lint,pnpm test(276, four new) andpnpm buildare green.pnpm test:e2epasses 20 of 20 with no Supabase configured. With a local.env.localthean empty directory renders the invitationtest fails instead, onmainas well as here.Checklist
pnpm lintpassed, where applicablepnpm test:e2epassed, where applicableCo-Authored-By,Generated with, or tool-attribution trailers