• To work cleanly on a 'Driod phone (very easy, but important).
  • Quickly add/build this weeks shopping list.
  • To manage dates on shopping lists, so humans do not need to.
  • To be able to swipe-off done items.
  • To be able to swipe-on previous weeks items (as entire list).
  • To be able to swipe-on previous weeks items (as single item).
  • To be able to push a list between client nodes (desktop or phone).
  • Prefer, to be able to host server in LAN only, and have app run in offline mode in the journey and shop.
  • Be able to swap lists with my partner.
  • Prefer system to be isolated from supermarket systems, as I am unaware of any supermarket system that lets you wander between merchants without friction.
  • Stretch: to access current floor plan from supermarket, so items can be ordered in “shop order” automatically.
  • Stretch: to be able to read barcodes from empty packets, via phone camera.
  • Not a goal: stock control for dwelling.
  • Not a goal: chat client or selfie interaction.
  • Not a goal: user logins. This is LAN only.


Since I left school, I rarely handwrite anything, as its not a profitable activity. This means I have an irregular scrawl that a medical doctorate would find awkward. I find paper lists frustrating, slow to access, and whilst in shop, its hard to maintain state. The third issue with dead-tree solutions is there is no easy tool to copy old lists, *and* extend/ alter them. A photocopier would do this, but I do not want to buy a photocopier just for shopping-lists.
I do shopping physically as if you bounce in and out early, it uses the least amount of time (yes faster than net based shopping as you do not need to wait for any deliveries). I split goods between several different supermarkets; as they cover different product ranges (this makes the delivery windows larger again).
One supermarket is a vast metal-framed building and has very poor mobile reception (so querying an items presence or absence is hard). The lack of reception means any server based state is fairly useless. The volumes of data are quite small, I can just host all the data on the phone. Unless you want to share a list whilst out shopping (which I don't do); there is no need for a server whilst out. No remotely accessible server mean no need to think about security, so the dev process costs a lot less. The data/ code will need to be cached on the phone; but that shouldn't be an issue.
Writing this code is optional/ doesn't led to employment, but is a useful maquette.

Aggregated updates

  • UPDATE (will get edited): I have the basic two screens and a menu; data loads and saves locally; edit, add and delete item work; the swipe interactions work; the design is OK on recent phones that have a larger screen. It has a persistence API.


  • In order to complete this project, I have done a survey of build tools (see end). Tooling for Vue3.2 + typescript is immature and fragile. It is stable for vue2.6 and typescript or react X and typescript.
  • I added a state library relatively late in the dev process, as I initially didn't have state. I think I should assume I will get state, so just add vuex etc at the start.
  • I think my 'small project' single CSS file is a sensible process. Previously where I wasn't the first developer, I was amending SCSS inside SCF files (either Vue or React), which didn't seem to add anything for the code/ project at hand. Code that has not been written to be reusable isn't worth trying to reuse.
  • I am getting experience managing JS of different generations inside the same project. In this project I am trying to maximise library use, and have more generic things that can be pulled from libraries; so am having problems like build tool failures more frequently.
  • Some step in the build process, or render process mangles UTF-8 chars in JSX. If you keep the UTF8 in JS strings they are not mangled; this means UTF8 prose needs by added via “v-html”.
  • As this is opensource, the completed product will have tidy naming.
  • As we have been playing with interaction design on this project; the other massive benefit is that we can hold shopping lists for shops that we visit once every six-months, at low admin cost compared to paper.
  • I have no intent to support small-screen phone like an iPhone5, as not needed by target user-group.
  • This project is in Vue, but I made no effort to tidyup legacy versions of anything, or NPM security warnings. I have no security errors at all on the front-end. At Swyvl I was putting dev budget (i.e. staff time) into getting updates on packages as the basic build had >70 security errors of various strengths.* Although a pure JS build chain would be prettier; it is contradicted by all the flags that I need to pass the Node interpreter.
Sketch solutions:
  • [v1] written before code
  • Define simple list Object (remember its Typescript), each item storing name, state, count; and the list having a name an create date
  • For dev performance, use a minimal vue2
  • Have dict of lists storage in localStorage
  • Index “page” that lists current lists, with date
  • View “page” that renders the list
  • Copy list “page” that displays two lists side by side
  • Manually make list “page”
  • Simple REST servers to receive pre-built lists, and publish them back
  • Server also manages JS bundles to drive frontend
  • [v2] after some code
  • Swiping was more of a foreground work-activity than is desirable (its a common library action)
  • I'm adding some interstitial docs in app; purely for code reviewers; I will give both the normal operatives a 2min walk though
  • I plan to use actual file-write for list persistence, rather than a DB or similar. This is a too low volume service to bother with enterprise tooling anywhere.
  • The state sharing (sync with server) will need to be done in a Webworker, as its likely to fail quite often.
  • Obviously the cache building (for installation) is typically done in a Webworker.
  • I have have pushed back for the compare function; as on consideration its not that useful. It shouldn't be hard to do.
Project updates:
  • I ran a few things. `npm` gave me vue3 in March 2022, this project got delayed as I was too busy previously.
  • I am using libraries wrapped by Vue; so the development time should be reduced.
  • I am building this with a common framework based CSS, an architecture choice. IMO “the best button styling” is likely to be common to many business problems; and getting it to behave consistently across a heterogeneous browser population is not a dev cost to repeat for each button. IMO “private CSS per component” only seems to be useful when the CSS is very different from generic business features. For example if you have a Vue component that renders SVG graphs, it would have many CSS statements correct labeling on axis, and the values on the axis; that other business features will not need, or will contradict. These atypical Components need private style sheets; most of my components are about data, and have boring CSS.
  • A value I was aiming at was better control on swipe events/ swipe code. I think it would be useful for more mobile centric work in future. I wanted to get a demo done before I started Swyvl on this; but didn't have time.
  • I would like a /install button, as an example of “clear and simple” UI. I can build this using cacheStorage, but that forces me to make this a HTTPS service. SnakeOil cert here we go... but pls note this is LAN only.
  • As modern JS supports UTF8 and therefore other charsets; I am tending to write “variables with generic software engineering names” in not-English; so it doesn't clash with the keywords which are in English. If this was a commercial project, I would organise the rest of the dev team to have a language that we held in common. I think “série:string” is much better than the average US solution of “MyString:string”. Note IDEs and typed languages are convenient here.
  • For development, I am using the snakeOil cert that is supplied with vite project. As it asks you to confirm the cert each time, this is not a complete solution.
Discussion on tools, vue3 + typescript
  • I don't normally foreground a long list of my failures. However I think these are important notes.
  • vue-cli tooling works; but forces vue2. This uses babel, automagically.
  • vite tooling ~ recommended by Ethan You @youyuxi ~ has less features, doesn't seem to like babel or webpack so much
  • No ts* tool wants to touch *.vue SCF files.
  • vue-tsc exists, but doesn't want to write any JS files. I'm using it to build the d.ts type outline files.
  • Tried using tslint,
  • tried browserify, typescriptifier, but the second one was making empty files without anything other than static loader.
  • Went back to eslint as it supplies better output & have all the linting correct.
  • I have half a solution with esbuild, but still need a thing to convert the SCF files.
  • To compile the Vue files, I have tried vue-template-compiler @vue/compiler-sfc vue-loader@next vue-loader/vueify and vue3-sfc-loader.
  • Remove esbuild. To compile *.vue files with typescript and vue3.2, I try rollup, and official plugins. This fails as it feeds typescript into the JS interpreter. Iterate on each of the available plugins and config file settings.
  • Try again with rollup and rollup-plugin-typescript2 (which is not the official plugin).
  • Rollup.js is framework for compiling and a bundling. I'm only using it to transpile/compile the SCF; as it doesn't crash like other tools do. I'm telling it not to include deps 1; Rollup.js plugins cannot process “ts-json-object” as that library builds exports.default in a weird ~ but valid ~ fashion.
  • I adjusted the import path, so the bundler didn't complain; however it is now leaving out the class though.
  • I added rollup-plugin-legacy to manipulate the legacy JS code packaging, and @rollup/plugin-replace to edit strings.
  • Its not possible to use plugin-replace in the output.plugins; so I tried rollup-plugin-postprocess.
  • With the old vue-cli, files named .vue are converted to JS before any other steps are applied (and import paths remapped). Other tooling keeps fighting this standard.
  • Current hack (used for unit tests): no JS modules, just use IIFE, and use external and global builds.
  • Better outcomes if I change the IIFE to es modules (used in main app); with still using static external libraries though.
  • Know about flags for rollup: --environment INCLUDE_DEPS,BUILD:$buildenv 2 3
  • To get the server code to link properly, I have added --es-module-specifier-resolution=node to the npm script, and “type”: “module”.
  • I was using rollup to covert TS Vue SCF into JS files, as separate files; then doing a second build step to merge everything. I am having RAM limit crashes on the Node process doing transpilation. I have increased the heap limit node --max_old_space_size=8184; and its still doing it. I will change the build process to merge and build; aside from the Vue files; as that will also speed things up; and should side-step 70% of the crashes.
Discussion on typescript features

I learn systems best by breaking them, whilst having all the documentation. Just pressing a “go” button teaches you nothing. I wasn't intending to learn a lot on JS/TS compiling/ transpiling tools; and in a commercial environment I would have changed my architecture after a day of failure. Things I have learned from this small project:

  • I think this book is good 1
  • An reasonable excuse to limit use of arrow functions in code-to-be-reused 2.
  • A reasonable excuse to limit default exports 3. I mostly only do that with components, but hadn't thought about it very much. This (explicit import encouraged) follows common practice on MVC frameworks in Perl.
  • A better breakdown on unit tests in components.
  • Clear use of JS modules; but that is shallow results if you have used Python or something.
  • A very simple reference State feature, which on top of JS modules is trivial (see other languages again).
  • Use of arrow functions to not need to use “this” when its not needed (pure functions which didn't reference local state).
  • Nestjs uses many decorators; these are not technically function calls, and do not want a semi-colon, or have a return value. Decorators must be turned ON in the tsconfig.json.
  • I have added a few interfaces purely for the TS typing analysis (the source was expecting to run inside a JS engine so doesn't have them).
  • As I add unit tests, I am splitting functions abit, and reorganising to avoid any circular dependancies (purely created as I was dumping everything in too few files).
  • Operational deployment for Mocha (fast to do), Jest (fairly fast). “dev-dep” is much larger than would be normal in a commercial project.
  • I have pulled serving the front-end code into the API project; to reduce management overheads abit.

things that I made

Some similar articles in research