CASE STUDY · UX ENGINEER TAKE HOME

LIVE ON VERCEL

From arXiv data to a working research explorer

For a UX Engineer take home, I was given an arXiv dataset and asked to build an interface for exploring research activity. I spent about four hours understanding the data, designing the experience, and deploying the app.

I started with the data because the way I counted and grouped it would shape what users took away from the interface.

The explorer shows a summary of the results before the individual records.
The explorer shows a summary of the results before the individual records.
ROLE
Solo designer and developer
DesignEngineering
TIMELINE · STACK
About 4 hours
React · TypeScript · Vite
358,490
paper and affiliation records
169,332
unique papers
~4 hrs
from data review to deployment
One paper can have several affiliation records, so I show both counts.
TL;DR

I spent the first hour reviewing the data and the next three designing, building, and deploying the app. I kept records and unique papers separate, added filters, and made the source data easy to inspect.

01 · THE DATA

The first design decision was what to count

I spent the first hour exploring the dataset in a notebook. Each row linked a paper to an affiliation, so counting rows as papers would overstate research activity. Names such as “MIT,” “M.I.T.,” and individual departments also appeared separately. I kept record and paper counts distinct, and affiliation names visible, so the explorer would not imply a definitive ranking of institutions.

UNDERSTANDING THE DATA
Rows in the filepaper and affiliation records
358,490
Unique papersdistinct paper IDs
169,332
2.12×
average rows per paper
49.1%
of papers appear more than once
140
most rows for a single paper
Counting rows as papers would more than double the total.
A search for “MIT” finds matching names while keeping each affiliation listed separately.
A search for “MIT” finds matching names while keeping each affiliation listed separately.
02 · DECISIONS

Turning those findings into an interface

With those distinctions clear, I designed a path from a broad dataset to individual records: narrow the results, understand the overall pattern, then inspect the source. Each step needed to make clear what the results represented.

FILTERING THE RESULTS

With over 100,000 affiliation strings, I chose text search over a long dropdown. Subject and year filters provide other ways to narrow the results.

SUMMARY BEFORE DETAIL

Record count, unique papers, and date range appear before the charts and table. This gives users context for how their filters changed the results.

SUPPORTING THE PATH FROM SUMMARY TO DETAIL
Simple charts to fit the scope
I used CSS bars for subjects, affiliations, and yearly activity. They let me show the patterns within the time available without adding a charting library.
Source records behind the summary
I included the first 100 matching rows so users could inspect the papers and affiliations behind each summary.
Values alongside the charts
I added labeled controls, visible focus states, semantic sections, and text values beside the charts. The numbers remain readable without relying on the bars.
REFINING AFFILIATION SEARCHMIT
Substring matchmatches inside words
4,346
Token matchmatches whole words
2,208
The search logic needed the same care as the counts. Searching for “MIT” also matched text inside “Smithsonian,” adding 2,138 unrelated records. I changed short queries to match whole words so those false matches would not inflate the summary.
EXAMPLES OF FALSE MATCHES
Harvard-Smithsonian Center for Astrophysics786
Harvard-Smithsonian CfA337
Smithsonian Astrophysical Observatory114
Center for Astrophysics | Harvard & Smithsonian40
// short queries match whole tokens, not substrings
if (query.length <= 4 && !query.includes(" ")) {
  return normalized.split(" ").includes(query)
}
return normalized.includes(query)
src/utils/filters.ts
03 · THE BUILD

Carrying the data decisions into code

I built the interface in React and TypeScript, keeping filtering and aggregation in separate functions. This let me refine the presentation without mixing it with the counting logic. I used the remaining three hours to build, clean up the code, document the decisions, and deploy the app on Vercel.

src/components/  FilterPanel · SummaryCards · TopList
                 · ActivityByYear · RecordsTable
src/utils/       normalizeRecords · filters · aggregations
                 // pure functions, kept apart from rendering
src/types/       typed arXiv model, end to end
notebooks/       01_data_exploration.ipynb
                 // understand the data before any UI
I kept filtering and aggregation separate from the interface.View repository

ABOUT 1 HOUR EXPLORING THE DATA · 3 HOURS BUILDING AND DOCUMENTING

04 · SCOPE

Deciding what could wait

Getting the explorer deployed meant deciding what to finish within four hours. I prioritized clear counts, useful filters, and access to source records. Affiliation grouping, pagination, and automated tests remained unfinished, so I documented those limits and kept the logic separate to support the next round of work.

WORKING WITHIN FOUR HOURS
LEFT FOR LATER
Grouping affiliation name variants
CURRENT APPROACH
Original names stay visible, with a note explaining the variations.
LEFT FOR LATER
Pagination for the records table
CURRENT APPROACH
The table shows the first 100 matches and the total count.
LEFT FOR LATER
Tests for filtering and aggregation
CURRENT APPROACH
The logic stays separate from the interface so tests can be added.
The remaining work is documented in the README.
The first 100 matching rows behind a search for “MIT.” Spelling variants stay separate, so the counts can be checked against the source.
The first 100 matching rows behind a search for “MIT.” Spelling variants stay separate, so the counts can be checked against the source.
05 · REFLECTION

What I would carry into a larger project

The strongest part of the exercise was connecting data exploration to interface decisions. The biggest open question was whether those decisions supported the way researchers actually explore this data.

KEEP
Let the data shape the design
The first hour in a notebook changed what I counted, how search worked, and which limitations needed to stay visible. That gave me a concrete basis for the interface decisions that followed.
DO DIFFERENTLY
Reserve time for a real research question
I deployed a working explorer, but did not observe anyone using it. Next, I would ask researchers to work through their own questions and see where the filters, summaries, or records help or get in the way.

HOW I CONTRIBUTED

Owning both design and development let me connect the data findings directly to the experience. I set the scope, built the filtering and aggregation logic, and documented the limits so someone reviewing the app could understand its assumptions.

Design
Data presentation · interaction design · accessible controls
Engineering
React and TypeScript · filtering and aggregation · deployment
Product
Scope · priorities · clear metrics · documented tradeoffs
HOW I APPROACH UX ENGINEERING

Within four hours, I turned the dataset into a deployed explorer with clear counts, more precise search, and access to source records. Starting with the data made those choices possible. For me, UX engineering includes the logic behind what people see, because the way we count and match data shapes the conclusions someone can draw from an interface.