Shell
Software Engineer, Technical Consultant
Visit website →Background
A technical consulting engagement through the Berkeley M.E.T. program, which selected five students to work inside Shell as engineers. I worked on internal tools, most of it on a new hiring database that replaces the spreadsheets, inbox threads and exports that recruiting had been stitching together by hand.
React and TypeScript on the frontend, Python and FastAPI on PostgreSQL behind it, the same shape of stack I use elsewhere. I worked across both sides, from the schema and the API up through the screens recruiters and hiring managers use.
The users are recruiters, not engineers, and the data is people's personal information. Those two facts shaped most decisions: the tool has to be faster than the spreadsheet it replaces or nobody switches, and every candidate record has to be visible only to the people who should see it.
One record per candidate
Candidates reach recruiting from several directions at once: a career fair list, a referral, an application, a spreadsheet a hiring manager kept on their own. Each source used to create its own row, so one person could sit in three places with three different statuses, and nobody could say how many candidates were actually in a pipeline.
I moved identity into the database: every import resolves against existing candidates on normalized email and name before it writes, so a second source updates the person instead of creating them again. The ambiguous cases go to a merge view that shows both records side by side, and every status change is written to a history table, so where a candidate stands and how they got there are both answerable.
Faster than the spreadsheet
Recruiters live in Excel, so the bar is not correctness, it is that moving to the tool never feels slower. Lists come in with different column names and formats, so an import maps columns once, previews what will be created versus updated before anything is written, and can be undone as a single unit. A bad upload is an undo, not a cleanup project.
The pipeline view is built for working in bulk: saved filters per user, inline edits, and actions over a whole selection, because the real unit of work is "everyone who interviewed this week," not one candidate at a time.
Access to personal data
A hiring database is mostly personal information, so access is enforced in the API rather than hidden in the UI. Recruiters see their own pipelines, hiring managers see the candidates for their roles, and fields like contact details and interview feedback are scoped by role, so a page can never show more than the request was allowed to fetch. Reads of sensitive records are logged, and candidates who are no longer in process are cleared on a retention schedule rather than living in the table forever.
