Making it yours
Everything on this site comes from data, not components. Four files, and you can be finished in twenty minutes.
| File | What it holds |
|---|---|
site.config.ts | Name, URL, role, headline, About, nav, social links |
content/projects.ts | The Projects section |
content/experience.ts | The Experience section |
cv.config.ts | Everything printed on the PDF CV |
Start with site.config.ts. It feeds the header, the page titles, the social cards, the feed, the sitemap and the structured data, so a name changed there changes everywhere.
The one field to set before deploying
url: "https://adalovelace.dev", // no trailing slash
The links in your feed, your sitemap and your social cards are absolute and built from this. Leave it wrong and every one of them points somewhere that does not exist.
The headline
It is stored in three pieces rather than one string:
headline: {
greeting: "Hey there.",
intro: "I'm",
accent: "Ada",
},
That is so the accent can be tinted on the page and drawn the same way on the social card, which never sees the page's markup. One string would mean writing your name twice and hoping the two stay in step.
Projects
Order in the array is order on the page:
{
name: "Project A",
description: "One sentence. What it is, not how it was built.",
summary: "The longer line, shown when somebody hovers the name.",
href: "https://github.com/you/project-a",
label: "github.com/project-a",
mark: "circle", // circle | square | triangle
period: "Ongoing",
stack: ["TypeScript", "Go", "CLI"],
},
Leave out href and label and the row renders without the repository chip, which is how you show closed-source work you can still describe.
mark is the shape beside the name. Three plain ones ship with the template; add your own SVG to src/components/icons.tsx and put it in projectMarks. They all draw inside a 16×16 box, so nothing shifts when you swap one.
Hover a project name and you get a card with summary and stack in it. That is Base UI's PreviewCard doing the open delay, the keyboard focus, the placement near a viewport edge and the dismissal on Escape, none of which a :hover rule can do.
Social links
socials: [
{ label: "GitHub", href: "https://github.com/adalovelace" },
{ label: "Email", href: "mailto:hello@adalovelace.dev" },
],
These render as a sentence at the end of About, each name with its mark beside it. The sentence is built from the list (commas, the "or", the full stop), so adding or removing one rewrites it and you never touch a component.
There is no strip of social icons anywhere, on purpose. A grouped row of logos reads as a widget rather than as something you wrote, and unlabeled glyphs make the reader decode them one at a time.
The CV
cv.config.ts is the whole PDF: profile, experience, projects, education, skills. pnpm build renders it to /cv.pdf and the Experience heading links to it.
It is laid out to survive an applicant tracking system, which is what reads a CV before a person does: one column, real text rather than a picture of text, and section headings with the plain names those parsers look for.
Your phone number is the exception. It is read from the environment so it never lands in a public git history:
cp .env.example .env.local
# then set CV_PHONE
Leave it unset and the line is simply left off.
Signing off
The About section ends with your name. Set signature to an SVG in public/ and it draws above that: your own handwriting, vector so it stays crisp anywhere. The template ships the slot and not the signature, because a stranger's handwriting under your own words is worse than none.