Skip to content
Loopa

Next.js visual feedback

From the element you clicked to the component that rendered it

Loopa is source-aware annotation for Next.js. A comment on a captured page can carry the JSX/TSX location that rendered the element, the build it came from and how confident that link is.

nextjs-heroMotion slot

Rendered page ↔ TSX

A selected element can point back toward the code that rendered it.

Beyond coordinates

Why screenshot coordinates are not enough

A pin on a screenshot says where someone looked. It does not say which component to open, which breakpoint they were on, or whether the code has changed since. In a component-based app the same button can come from a shared component, a page and a CMS field at once.

nextjs-contextMotion slot

Pin vs. context

Coordinates alone do not tell anyone what to change.
  • Where on the page

    Screenshot pin: x/y position on an image

    Loopa: Route, DOM element and selector on a stored capture

  • At what size

    Screenshot pin: Whatever the reviewer's window was

    Loopa: Recorded capture and review viewport

  • Which code

    Screenshot pin: Guessed from visible text

    Loopa: Source candidate from a stamp, when the build has one

  • Which version

    Screenshot pin: Unknown

    Loopa: Registered build commit, checked against the source index

  • After a redesign

    Screenshot pin: Pin floats over the wrong thing

    Loopa: Original capture and anchor stay available

Source candidates

Connecting rendered elements to source code

Loopa does not guess files from class names or visible text alone. Source context is evidence recorded at capture time from your own build, so it can be checked against the commit you are about to change.

  1. Your build stamps rendered elements

    Source stamps are attributes such as data-insp-path="app/pricing/page.tsx:22:7" that record which JSX/TSX location rendered each host element. They come from a build-time transform in your Next.js app.

  2. Your build serves a source index

    A small JSON index served alongside the build lists the stamped files and the git commit they were built from.

  3. Capture records the evidence

    When Loopa captures a route, it reads the stamps and the index, and checks the index commit against the build you registered for the capture.

  4. Annotations get candidates

    When you select an element, Loopa looks for a stamp on it or on its nearest stamped ancestor and stores the result as a candidate, with how it was found.

nextjs-mappingMotion slot

From stamps to candidates

Candidates come from build evidence captured with the page.

Side by side

The rendered element and its source candidate

Select a button on the captured page; the inspector shows where it was rendered and, separately, where its text came from.

preview.example.com/pricing
Start free trial1
components/pricing/plan-card.tsxIllustrative example
export function PlanCard({ plan }: PlanCardProps) {  return (    <Card>      <CardTitle>{plan.name}</CardTitle>      <Button size="lg">{plan.cta}</Button>    </Card>  );}
Rendered by plan-card.tsx:35:7 candidate · selfContent from 2 indexed files ambiguous
nextjs-side-by-sideMotion slot

Side by side

Render location and content origin can differ, and both are shown.

What is recorded

Source information on an annotation

Each field says where it came from. Page metadata is treated as untrusted input, so an agent can weigh it rather than follow it blindly.

Source context (simplified)

render location
components/pricing/plan-card.tsx:35:7From a source stamp; relation self or ancestor
content origin
Candidate file for the visible text, when the index has a unique matchUnknown or ambiguous otherwise
build
Registered commit SHA, and whether it was built clean
index state
loaded, no stamps, missing, invalid, unregistered, dirty or mismatched build
provenance
Captured stamp, untrusted page metadata
visual context
Route, element, selector, viewport and screenshot: always present

Confidence and fallbacks

When the evidence is unclear, Loopa says so

A wrong file is worse than no file: it sends a person or an agent to the wrong place with confidence. Loopa keeps the three cases apart.

candidate

Stamp found on the element or an ancestor

The file, line and column are stored with their relation (self or ancestor) and the matching build. Strong evidence, still labelled as a candidate.

ambiguous

Several plausible origins

Visible text that matches more than one indexed file is marked ambiguous instead of picking one. Where an element was rendered and where its text came from are kept as separate fields.

unknown

No usable source evidence

No stamps, no index, an index for a different build, or a build with uncommitted changes. The reason is recorded and the annotation keeps its full visual context.

nextjs-fallbackMotion slot

Candidate, ambiguous, unknown

Missing source evidence degrades gracefully instead of guessing.

With coding agents

Less searching, fewer confident guesses

An agent that knows the candidate file and the build can start in the right place and confirm it against the checkout. When there is no candidate, it knows to search instead of assuming.

What your agent receives
  • Starts in the right file

    Candidates point at the component and line, not a whole repository.

  • Knows the base

    The batch names the repository and commit the feedback was given on.

  • Sees the uncertainty

    Ambiguous and unknown states come through as data.

  • Keeps visual intent

    Screenshot and element context travel with every item.

Set up source-aware review

Register your build, capture a route and see which annotations get source candidates.