Blazor WebAssembly application for managing SKU shelf layout in retail environments.
This application is designed for operations professionals in retail who are responsible for organizing and optimizing shelf layouts. The typical user is detail-oriented, familiar with store inventory processes, and values efficiency and collaboration. The tool is intuitive and user-friendly, requiring no advanced technical skills, and helps streamline the daily workflow of managing and visualizing SKU placement on store shelves.
Key features:
- Visualize shelf layouts and SKU lists
- Manual creation of new SKUs and shelves via the UI
- Add Columns with SKUs to shelves and remove them
- Move SKU columns on a shelf (swap columns) using both UI controls and keyboard navigation
- Sort shelf columns by SKU properties (popularity, price, expiration date) and distribute by retail hot zone (left side, middle side, right side)
- Search SKUs by name or ID
- Sort SKUs by popularity, price, or expiration date
- Import/export SKU data (JSON)
- Import/export Shelf data (JSON)
- Persistent storage for shelf layout and SKUs using
LocalStorage
- .NET 9.0 SDK (Preview)
- (Optional) Node.js (
npx serve) or Python (python3 -m http.server) for static server preview
Build the entire solution. From the root directory, run:
dotnet build- To launch the development server:
cd ShelfLayoutManager.UI
dotnet watch run
Your default browser will open automatically. You can now start testing the application locally.
To generate a production-ready build, run the following command from the root directory:
dotnet publish ShelfLayoutManager.UI/ShelfLayoutManager.UI.csproj -c Release -o ./publishThis will compile the solution and place the build output into the publish folder at the root level.
To preview the production build locally, start a static server in the publish/wwwroot directory:
Option 1: Using Node.js
cd publish/wwwroot
npx serveOption 2: Using Python
cd publish/wwwroot
python3 -m http.server 8080Then, open your browser and navigate to the address displayed in the console (e.g., http://localhost:8080).
To deploy the production build:
- Upload the contents of the
publish/wwwrootdirectory to any static web host or CDN. - Ensure your server is configured to serve
index.htmlas the fallback for all routes, in order to support Blazor client-side routing.
Run unit tests from the root of the solution:
dotnet test-
Create or Import a Shelf
- On first launch, you can create a new shelf using the form or import an existing shelf from a JSON file ("Import Shelf" button).
- Once a shelf is loaded or created, the shelf visualization and SKU placement list will be displayed.
-
SKU Placement List
- The right/both side depending on screen resolution shows a list of SKUs available for placement on the shelf.
- You can only add SKUs that have been previously created on the SKU List page.
- When you add a SKU, a new column matching the SKU’s size is automatically created.
-
Managing Columns
- Select a column to view its details.
- Move columns left or right using the arrow buttons or keyboard navigation.
- Remove a column using the "Remove" button.
- Sort columns by popularity, price, expiration date, and by hot zone using the top control panel. You can choose a sorting property (popularity, price, or expiration date) and a target retail hot zone (left, center, or right part of the shelf). When you apply sorting, the columns will be rearranged so that the SKUs with the highest value for the selected property (e.g., most popular, most expensive, or soonest to expire) are placed in the chosen hot zone. For example, if you select "Sort by Price" and "Left Zone," the most expensive SKUs will be placed on the left side of the shelf
-
Import/Export and Reset
- You can import or export the shelf state as a JSON file.
- Warning: Both "Import" and "Reset" operations are destructive and will prompt a confirmation modal before proceeding.
-
Managing SKUs
- Here you can create new SKUs using the form, as well as import or export the entire SKU list as a JSON file.
- You can search SKUs by Name, ID and and sort by price, popularity, or expiration date.
-
Import/Export and Clear
- Importing and clearing the SKU list are also destructive operations and will prompt a confirmation modal to prevent accidental data loss.
-
Clean Architecture:
The solution is structured by Clean Architecture principles:- Domain (
ShelfLayoutManager.Domain): Core business entities and validation logic (no dependencies on infrastructure). - UseCases (
ShelfLayoutManager.UseCases): Application logic and service interfaces. - Adapters (
ShelfLayoutManager.Adapters): Infrastructure implementations (e.g., persistent storage). - UI (
ShelfLayoutManager.UI): Blazor frontend, interacts only with use case interfaces and subscribes to their observables for real-time updates. - ViewModels (
ShelfLayoutManager.ViewModels): Presentation models for the UI, primarily produced as a result of processing and combining observable streams.
- Domain (
-
Frontend:
Implemented withBlazor WebAssembly (.NET 9.0). The UI is reactive and updates in real time as data changes. -
Reactive Programming:
All core data (SKUs, shelves, filters, sorting) is managed as observable streams using
System.Reactive. Services likeSkuManagerandShelfManagerexposeIObservablestreams (e.g.,SkuDictObservable,StandObservable). UI components subscribe to these streams and update automatically when data changes. Filtering, sorting, and view models are built by combining streams withCombineLatest, ensuring real-time, decoupled updates across the app. -
Dependency Injection:
All services (storage, managers) are registered and resolved via .NET's built-in Dependency Injection container. -
Global error and info notifications:
The application uses a centralizedUIEventBusto broadcast error and informational events from any part of the app (including use cases and adapters) to the UI layer. These events are displayed to the user via theEventToastcomponent as non-intrusive toast notifications. This decouples error handling from UI logic, provides a consistent and user-friendly way to display feedback, and ensures users are always informed about errors, warnings, or important actions, regardless of where they occur in the application flow. -
Unit Testing:
All core logic (use cases, validators, services, blazer components, domain entities) is covered by unit tests using
bUnit,xUnitandMoq. -
Accessibility (a11y), Fail-safe design, UX Best practices
- All interactive elements are keyboard-accessible and labeled for screen readers (e.g., aria-labels, labels for inputs).
- Forms provide inline validation and clear error messages.
- The UI is responsive and provides immediate feedback for user actions.
- All user inputs are validated both on the client (via
data annotationsandcustom validators) and in theDomain layer. - Invalid or incomplete data cannot be submitted
- Destructive actions require explicit confirmation.
- Application state is persisted, reducing risk of data loss on reload.**
- Layout adapts for different screen sizes (Starting from Tablet).
- Consistent button placement and icon usage for common actions.
- Global error and info notifications are handled via a
UIEventBusandEventToast, ensuring users are always informed about errors or important events.
| Limitation | Explanation / Future Direction |
|---|---|
| Only one shelf can be managed at a time | Multi-shelf support is planned; the domain model already includes a Stand class for grouping multiple shelves. |
| Only SKU-to-shelf addition is supported; no pre-defined column layout | Each time a SKU is added to a shelf, a new column (SkuColumn) is automatically created with the appropriate size and quantity. This approach was chosen for MVP as it is more user-friendly and requires less effort from the user. However, support for pre-defining shelf columns is planned for future versions, and the current implementation already lays the foundation for this feature. |
| shelf columns cannot be adjusted after creation | Currently, once a SKU column is created (automatically when adding a SKU), its width and other parameters cannot be changed directly. The column size is determined by the SKU dimensions and the global column gap set in the shelf parameters. The foundation for adjustable columns exists thnaks to SkuColumn class, and support for editing column properties will be added in future versions. |
| SKUs cannot be edited (patched), only deleted and recreated | Currently, SKU items cannot be modified after creation; they can only be deleted and new ones created. This is because columns are not yet adjustable, so editing a SKU would have no effect until that feature is implemented. Support for editing SKUs will be added together with adjustable columns in future versions. |
| Shelf parameters cannot be adjusted after creation | Currently, shelf properties (width, height, depth, column gap) are set only at creation and cannot be changed later. The architecture stores these parameters in a dedicated ShelfStaticProps object and validation is supported, making it straightforward to add support for shelf editing in future versions. |
| Manual adjustment of SKU quantity per column is not supported | Currently, when adding a SKU to a shelf, a new column is created and filled to its maximum capacity (or less if available quantity is limited). There is no option to manually specify a partial fill for a column, nor does the system auto-fill existing partially filled columns before creating new ones. This was chosen for MVP simplicity, but future versions may support auto-filling incomplete columns and manual adjustment of column fill, especially once SKU editing is implemented (means when we can change SKU quantity of the card). |
| No full UI error boundary for rendering failures | While most business and infrastructure errors are surfaced to the user via toast notifications, there is currently no global UI error boundary to catch unexpected rendering errors. Im planning to add Error Boundaries in future updates. |
| "Add SKU" button is not disabled when there is no space on the shelf | Currently, the "Add SKU" button in the SKU placement list remains enabled even when there is no available space on the shelf. If the user tries to add a SKU in this state, a toast error message is shown. Disabling the button when the shelf is full would improve UX and prevent unnecessary actions. |
- Support for managing multiple shelves (multi-shelf/stand UI and logic)
- Ability to pre-define and edit shelf columns independently of SKU addition
- Adjustable shelf columns (change width, quantity, and other parameters after creation)
- Ability to edit (patch) existing SKUs and have changes reflected in the shelf layout
- Editable shelf parameters (
Width,Height,Depth,ColumnGap) after shelf creation - Manual adjustment of SKU quantity per column, or smart auto-fill logic that fills existing partially filled columns before creating new ones
- Migration to a more robust persistent storage solution (e.g., server-side database or cloud storage) to enable advanced collaboration, backup, and multi-user support
- Disable Add SKU button when there is no space in the shelf instead of showing error toast.
- Drag-and-drop support for rearranging shelf columns to provide a more intuitive user experience.
- Add UI Error Boundary for unexpected UI errors
- Localization and multi-language support (for international users and teams)
- Migration of shelf visualization to advanced solutions (e.g. Canvas or SVG for smoother, more interactive shelf rendering)
- Mobile screen adaptiveness (currently, the application is optimized for tablets and larger screens)
- Export/import in additional formats (CSV, Excel)
- Bootstrap components are used for rapid MVP development; migration to custom or more advanced UI components may be considered as the project evolves.
- Add the ability to merge the existing SKU list with the imported list, instead of fully replacing it
- Allow users to configure the priority of columns for advanced SKU sorting, not only left, mid, right hot zone.
- Better styles organization in code: SASS preprocessor is already used, but its capabilities (such as variables, mixins, and separating constants into a dedicated layer) are not fully leveraged yet. Refactoring styles into a more modular and maintainable structure is recommended.
- Refactoring of
ShelfEditorPage: As this is the highest-level component, it contains a lot of logic, such as subscriptions and calls toUseCaseservice methods. It would be beneficial to move some of this business logic to a partial class and split parts of the markup into separate components to make the code more readable and maintainable. - Unify test naming, extract repeated error/info messages and other constants, and improve error message clarity.
Need fix for form validation messages now it quck-fixed
| Task | Time Spent |
|---|---|
| Reading docs | 30 min |
| Architecture setup | 4 h |
| Implementation | 18 h~ |
| Unit tests | 6 h |
| Refactor & cleanup | 4 h |
| Writing documentation | 2 h |
| Blazor Web App and Clean Architecture understanding |
4h~ |