• 4 min read

Turning a sentence into a task without an LLM

Table of Contents

Backlogs is a kanban-based to-do list application that lets users create tasks using natural language. Instead of filling out separate fields for a title, due date, and priority, users can type something like “Finish CS assignment tomorrow” or “Buy groceries next Friday high priority.” The parser extracts the deadline and priority automatically while leaving the rest as the task title.

Why I built it

I built Backlogs as my final project for Harvard’s CS50 Web Programming course.1

On the surface it’s another to-do list app, but I wasn’t interested in rebuilding CRUD for the hundredth time. I wanted to recreate my favorite feature without reaching for an LLM. Since a lot of “AI” features at the time were just wrappers around an API call, I wanted to try if a rule-based parser could handle this one on its own. The kanban board was the other good challenge: I’d never built drag and drop, or an interface this dynamic.

How it turned out

Natural language input

The parser understands natural language and extracts structured information while the user types.

For example,

Buy groceries next Friday high priority

becomes:

  • Task: Buy groceries
  • Due date: Next Friday
  • Priority: High

As keywords are recognized, they’re highlighted immediately so users can see exactly what the parser understands before creating the task.

Input

Responsive kanban board

Tasks can be moved between columns using drag and drop.

The board adapts to different screen sizes, switching from a three-column layout on desktop to a tabbed interface on mobile.

Drag and Drop

Task management

Each task stores its priority and due date, making it easier to organize work and decide what to tackle next.

Task View

Authentication

Users can register, log in, and manage their own personal backlog.

How I built it

The parser is entirely rule based, built from scratch with regular expressions instead of calling an LLM. It recognizes relative dates like “tomorrow” and “next Friday,” explicit dates, and priority keywords before converting them into structured task data. As I kept adding rules I ran into the same lesson from my NLP projects: language is messy, and every time I thought I’d covered all the edge cases, another input proved me wrong.

One part I’m particularly happy with is the highlighted input. Instead of a rich text editor, I overlaid a div on top of a normal text input, rendering highlighted keywords while the input handles typing. A bit hacky, but it gave me full control without a much heavier editor. Task creation and updates happen through AJAX so users can work without refreshing, and the kanban board uses the native HTML5 drag-and-drop API with handlers like dragstart, dragenter, and drop. It became one of the biggest JavaScript modules I’d written at the time, but it worked surprisingly well.

What I learned

Not every language feature needs an LLM. For problems with clear rules and predictable behavior, a deterministic parser is simpler, faster, and easier to debug. If I rebuilt this today I’d probably go hybrid: rules for the predictable cases, an LLM only when input gets genuinely ambiguous.

It also pushed my frontend skills further than expected. Building a responsive kanban board, drag and drop from scratch, and an interactive parser without React forced me to understand how browsers actually work instead of leaning on a framework. That’s probably what I’m most proud of here: almost everything was built from scratch.


Footnotes

  1. Harvard’s CS50 Web Programming with Python and JavaScript was one of the first online CS courses I completed. This project served as my final capstone. It brought together many of the core topics covered throughout the course, including Django, JavaScript, Bootstrap, AJAX, and frontend interaction design. ↩