One of the most important things I’ve learned during my internship is that user experience is built in the details.
Today’s challenge? Search and filtering for legal cases inside Lura.
Lawyers work with hundreds of cases. Scrolling manually isn’t practical. They need fast, flexible ways to find what they’re looking for. Our job as developers is to create features that feel simple — even if they’re not.
🧠 Why It Matters
In Lura, every case is tied to a workspace, and every document to a case. As the data grows, finding specific content becomes harder. Lawyers need:
- Search by title (e.g., “Doe vs Smith”)
- Tag-based filtering (e.g., “Criminal”, “Pending”)
- Workspace-scoped results (can’t show data across teams)
Without this, the app feels clunky. With it, it becomes a tool that actually helps users think and act faster.
⚙️ How I Built It
📦 Backend: NestJS + Prisma
I built a GET endpoint like /cases?search=...&tag=...&workspace=...
In the controller, I used Prisma to dynamically filter based on query params:
ts
const cases = await prisma.case.findMany({
where: {
title: { contains: search },
workspaceId,
tags: { some: { name: tag } },
},
include: { tags: true }
});
This made the filtering flexible and efficient. Prisma made chaining filters feel natural.
💻 Frontend: Next.js + TailwindCSS
I added:
- A search bar with debounced input (to avoid spamming the backend)
- A tag selector dropdown
- A workspace switcher that resets filters when you move teams
Each interaction triggers a router query update, which then fetches the correct results.
tsx
router.push({
pathname: '/cases',
query: { search, tag, workspace }
});
Then I used useEffect
to trigger fetching on query change. Everything updates without a full reload — just like a proper SPA should.
✨ The Result
Users can now:
- Type to instantly filter by title
- Click tags to narrow down results
- Switch workspaces with isolated results
It feels fast. It feels modern. And more importantly: it helps the user get to work faster.
✅ Takeaways
- Filtering is UX power — it saves time and makes apps feel smarter.
- Prisma’s flexible querying makes dynamic filters easier than expected.
- State and URL sync in Next.js is a must-have for clean navigation.
❓Question for You
What’s your go-to strategy for building smart filtering systems?
Do you prefer using server-side filters, or handle them on the client?