Saturday, 30 November 2024

Project 2 - UI Scaffolding progress

 Over the last couple of weeks I have been working on scaffolding the key features of my simple article publishing project, while trying to actively avoid getting distracted by constant fiddling with the fine details of UX.  As a reminder, I am trying to create a very simple, but feature complete SAAS website so that I can build a better understanding of how to integrate the back-end services like Auth, Database, Payments, Helpdesk for a real SAAS site.

In my previous post I detailed how I am using a services pattern and in-memory repositories to separate the front-end UI from these back-end concerns, to avoid having to solve too many problems at once.  This also allows me to focus on making sure that the key features of the site - which in general are the features that will attract paying customers - are valid, working and stable. This prevents losing time implementing back-end integrations for features that are in flux, or which are poorly thought out.

As a case in point,  one of the key features for an article editing an publishing site is actually being able to create and edit an article.  My initial idea here was to use a markdown style approach - users would enter wiki-style markdown which would get transformed into a page when the article was previewed or published.

By implementing the UI first, it quickly became apparent that this approach was clumsy, overly technical and would turn off a lot of prospective customers. Instead I opted to implement a rich text editor based on VueQuill, and this greatly streamlined the user experience for creating articles - which is one of the core features of the site. Focusing on the core UI enabled me to make this switch with minimal impact - as no backend changes needed to be made.

Rule of thumb for future SAAS work: scaffold the core features first. Focus on getting the stuff that users are gong to pay for working before worrying about pesky details like security, db schema, payments etc.

Anyway, here is the list of features that are more or less working:

(remember, the UX here is a work-in-progress!)

The site is a responsive layout, with a fixed width for user interaction and fluid gutters. This may change in future, but it seems to make sense for now.  

It has a dedicated members/dashboard area that supports navigation, managing articles, managing the user's account and getting help/support

Each member page is an 'invisible scroller', enabling the user to scroll content vertically without requiring browser scroll bars. Each page also has built-in feedback features, providing common notification and dialog services for page actions:



The article management features are implemented using a master/detail list pattern, where the user can create, edit, delete, publish, unpublish and view their articles



Article creation or editing uses VueQuill as a WYSIWYG rich text editor:


There is a scaffolded Account management page:


and a scaffolded support page, using a hosted support form from FreshDesk (more about this in future posts)


Published articles are available for viewing by the public:


Obviously the site is by no means complete, but the core UI features are mostly there. 

The main outstanding feature is implementing the business model for the site - adding (or restricting!) features based on user payments.  This will be my next focus, and I'll try and report progress in the next post.







Saturday, 16 November 2024

Interlude - some distractions

 A few things have been happening lately which have reduced the velocity of my current project: 

  1. I had some ideas for my 'big idea' SAAS that I wanted to spike out
  2. Liberal democracy and the rule of law apparently imploded in the United States.
  3. BlueSky took off and I've been having a lot of fun being a post goblin on a site that feels like Twitter in 2010.

The items above contributed to a motivation slump for Project 2.  There is a lot going on and it is difficult to find to motivation for building a fully fledged solution purely as an academic exercise - even if the learning potential is huge.

That being said t,  one of my key self-improvement objectives is to actually finish projects that I start and NOT give up when I hit a slump.   I will get this thing 'functionally' complete and deployed even if it is just for personal bragging rights.

Apart from the above distractions, I think there are two things killing my want to continue with this project

  1. It is basically pointless as a SAAS - the chances of making money are so low as to be non-existent
  2. UX design is really hard. I can write competent code, but even with all of the tools of Vuetify and modern CSS at my disposal I can't make it so that the website 'looks professional'.  There are just too many UX tricks of the trade that I don't seem to know. Having the artistic talents of a brick also does not help.
Item 1 I can probably cope with. Ultimately this  project 'is a learning by doing' exercise and I just need to suck up the fact that it probably isn't going to be anything else.  

Item 2 is a really an issue for me. When working on the solution I get easily distracted by the low quality look and feel and then started fiddling with things to 'improve it'.  This doesn't usually have a good outcome (ok, the end results are terrible) and wastes a lot of time.    

Moving forwards I am going to have to be more disciplined about this and stick to also scaffolding the UX .  Once the site is functionally complete I will look for a pre-built template that I can migrate it to.  

I need to eat some humble pie here. For most of my career I have looked at UX designers and thought 
"that's all you do? I could do that if I could be bothered but I want to write code instead".  It turns out that no - I can't do that and I don't have the bandwidth to learn.  

Today's personal lesson is to stick to your strengths and download/buy/hire for the skills you don't.  

Sunday, 10 November 2024

Project 2 - Simplest SAAS - Service Scaffolding

 In this post I'll discuss how I intend to scaffold the article site SAAS so that I can build out the key features without having to worry about integration with back-end services.

The basic idea here will be to take a layered approach, and use an implementation of the Service Layer pattern to encapsulate all of the core business functions of the site.  There will be services responsible for each of the key features of the site - one for user management, one for article management etc.  Services will act as mediators between the Vue components and and back-end logic. The Vue components in the site will only interact with these services and will  never interact directly with a back-end provider.

In addition I will use the Dependency Injection pattern to construct these services.  Where one of these logical service has a dependency on a high layer,  a typescript Interface will be used to define the operations of that layer, and the service will be constructed with a class that implements that interface. 

The Dependency Injection pattern makes it possible to swap different implementations of the service dependencies without requiring the service to be modified.  The Vue components are isolated from any changes to how the back-end dependencies are written,

This in-turn will enable me to create in-memory, scaffolded versions of these key dependencies (user auth, persistence, payment etc)  to get the site running, then enable me to swap to actual implementations with minimal work.  This has the nice advantage of enabling back-end services to be swapped out without affecting the user interface. For example, with this approach I can potentially switch between database host providers minimal impact on the UI. It also simplifies testing - the services can be tested with mocked or faked versions of dependencies if required.

For working with persistent data,  the Repository pattern is often used with Dependency Injection.  A Repository is a specialised service dependency that abstracts all persistence (database) operations behind a well-defined interface - which is exactly what we want!

Here is an example of how this will work for the design requirement of providing the user with a list of the articles that they own.    

  1. The List Articles page (a Vue component) will invoke the get_user_articles() method that is defined on the Article Service.
  2. The Article service will be constructed with an instance of a class that implements the IArticleRepository interface. This interface also defines a get_user_articles() method 
  3. There can be multiple classes that implement this interface.  Any of them can be chosen at design time to construct the service
  4. Initially, I will use an Repository implementation that uses a simple in-memory store to persist user articles (this will reset every time the site is started).  Eventually I will replace this with a Repository implementation that uses a hosted database.
  5. The List Articles page doesn't care which implementation of IArticleRepository is used. It only interacts with the Article Service, and the behaviour of this service never changes. 
  6. This means that the List Articles page can be safely built to work with a simple in-memory implementation of the repository, and no changes to this component will be required when the Article Service is swapped to using a repository implementation that works with a  hosted database



One other thing I should also mention is that the data types that are sent to and from the the dependent layers should also be defined. This enables a type safe definition of each interface.  For the example above, as well as defining the IArticleRepository interface, we should also define an Article type for the repository to return.  These data types can be thought of as the Models in our design.

Using this approach takes some initial set up but I believe that it will pay significant dividends in enabling me to set up a fully featured user interface without having to worry about the complexities of integrating back-end services. I can focus on implementing the core features of the site first and save significant time on my first few iterations.

Leaping into the unknown

I haven't posted in a while because the work situation went non-linear. To cut a long (and very boring) story short, I am being made red...