Danso

2025 · Solo build, front end, backend and database

POS

An interactive point-of-sale web app with separate interfaces for administrators, managers, and cashiers.

  • JavaScript
  • Node.js
  • Express
  • PostgreSQL
The POS cashier screen during a sale

Context

A point-of-sale system serves three people with incompatible needs. A cashier wants the fastest possible path through a sale. A manager wants stock levels and takings. An administrator wants control over users and configuration.

Building one interface that serves all three badly is the common failure. This project treats them as three interfaces over shared data instead.

My role

This was a solo school project. Because I was building it alone, I had the freedom to own the entire application, from designing the role-specific interfaces to building the Node.js and Express backend and the PostgreSQL database behind them.

Key decisions

Separate interfaces rather than permission-gated menus. Hiding the controls a cashier cannot use still leaves them navigating a manager's information architecture. Each role gets a layout shaped around its own task instead.

Speed over completeness on the cashier screen. That flow runs hundreds of times a day, so it is keyboard-driven and reachable in the fewest possible interactions, even where that meant leaving features out of that particular view.

I first considered a more conventional tablet-style layout built around point-and-click menus. I rejected it: it might look more modern, but a keyboard-driven flow is much faster for a cashier in practice.

The hard part

The most stubborn problem I faced actually happened on the backend. During development, all the product images in the POS system suddenly stopped rendering. My immediate assumption was that the image assets hadn't been uploaded or were somehow deleted from the database.

However, after checking the file system, I found that the images were all there, just accidentally placed in the wrong directory where the backend server couldn't serve them statically. The fix was as simple as moving the folder into the correct directory and restarting the backend server.

Outcome, and what I would do differently

Built as a student project and complete as an interface.

I would write it in TypeScript. It is plain JavaScript, and a domain built on prices, quantities and running totals is exactly where a type system earns its cost. Porting it is the clearest improvement available.