SSW Foursquare

Rules to Better Websites - Development - 53 Rules

  1. Do you know the steps to do after adding a website page?

    In order to keep the content you add is healthy (doesn't have grammar or spelling mistakes), follow the below steps once you add a page:

    1. Check the rule in MS Word (or Grammarly) to see if it has spelling or grammar mistakes
    2. Run Link Auditor and Code Auditor on that page
    3. Check the report and fix the errors (if any)
      Repeat step 2 and 3 until Link Auditor and Code Auditor get all green ticks
  2. Do you have a structured website?

    The following structure allows you to keep your website clean of clutter:

    • /Images - for all static images
    • /Images/Dynamic - for all images used in dynamically generated pages Note: The reason we recommend 2 images directories is so we can exclude images used by dynamically generated pages from our link checking program. This is so we can work out the true orphan images (they multiply coat-hangers)
    • /Download - downloadable content, like PDFs and documents
    • /Includes - for all include files
    • /Bin - for mdb's, dll's and udl's
    • /Shop - for the shopping basket and related pages
    • /Clients - for the client login page and related pages
    • /Reports - for any SQL Server Reporting Services
    • /zsMaintenance - for the administration section to modify website settings
    • /zsValidate  - for all web server status and validation checks

    The root directory should be clean, having only:

    • default (.aspx, .asp, .htm)
    • global.asa
    • application.sln
  3. Do you always have a default/index page?

    Many times a website contains directories that don't have an index page, and this means a user navigating via the URL, see a 404 error. You don't want this to happen, so make sure you always have an index page in every directory, even if it's just to show the files inside it.

    It is usually a default.aspx file, however depending on the webserver configuration; it might be index.html or index.php etc.

  4. Do you have a stylesheet file for all your formatting?

    A stylesheet file (.CSS) should be used to dictate how the fonts, headings, tables, captions and everything else on your HTML should be displayed.

    This makes your site very easy to maintain. If you ever want to change the entire look and feel you should only have to change one file.

  5. Do you know when to use scoped CSS?

    On large frontend projects with lots of components it's common to have issues with your CSS classes overwriting each other or conflicting.There are a few different ways to solve this.

    It can be very frustrating when CSS classes overwrite and behave differently to how we want them to.

    overwritten style
    Figure: Overwritten CSS can make our site styles break

    Debugging this can be a nightmare on larger projects with huge amounts of styling as you need to comb through the entire file to find what's overwriting the style.

    h1 {
      color: red;
    /* 3000 more lines of code... */

    Utility Classes

    One solution to this problem is using a CSS framework such as Tailwind.


    • Faster setup
    • Simple to use
    • Faster development speed once devs are familiar with it


    • Poor readability as you add more classes
    • Learning curve for class names

    Scoped CSS

    Most frontend frameworks such as Blazor, Angular and React support scoped CSS, allowing you set CSS classes on a component level.

    When you create a scoped CSS file, those classes are only accessible to the component that the CSS file is associated with.

    This is useful as you don't need to worry about class names or CSS values conflicting with eachother like you would if all the classes are set at the root level.It also makes it much easier to change styling on individual components without breaking the styling on other classes.


    • Can reuse class names in each component without conflicts


    • Styles have to be manually written


    In Blazor scoped CSS files are associated with components with dot syntax.
    For example, if we have a component called MyComponent.razor, we can create a file called MyComponent.razor.css and the classes set in that file will only apply to MyComponent.


    Blazor supports having scoped CSS classes inherited by child components.

      <MyChildComponent />

    In MyComponent.razor.cs, if we use the ::deep psuedo selector on a class, it will be applied to MyChildComponent.

    ::deep .myClass {
      /* Styling goes here */

    Blazor CSS Isolation - Microsoft Docs


    When you create a component in Angular, a scoped CSS file is automatically created for it along with the HTML and TypeScript files.

    |- myComponent.component.html
    |- myComponent.component.css
    |- myComponent.component.spec.ts
    |- myComponent.component.ts

    Angular also offers the ::ng-deep pseudo selector, but there are some considerations when using this.

    Component Styles - Angular Docs


    We can achieve local, component-level styles in React by using importing from a file ending in module.css:

    /* component.module.css */
    .heading {
      font-weight: 700;
    import styles from "component.module.css";
    const Component = () => {
      return (
        <h1 style={styles.heading}>Bold Heading Here</h1>

    This will then render the element with a component specific class, differentiated from other .heading elements:

    <h1 class="Component_heading__nEBhk">Bold Heading Here</h1>
  6. Do you close quotations of all your HTML attributes?

    Make sure there are equivalent closing quotations for HTML attributes. A small mistake of missing a quotation could lead to undesired results on a web page.

    <span style="font-size:12pt; background: #ccc;>

    Figure: Bad code - Can you spot the missing quote? Code Auditor can

    <span style="font-size:12pt; background: #ccc;"></span>

    Figure: All OK

    As you can see from the above example, just missing a quotation makes the whole layout of the text different. So be very careful that you make sure you have closed all opening quotations of attributes with equivalent closing quotations.

    We have a program called SSW Code Auditor to check for this rule.

  7. Do you know the best way to display code on your website?

    Any website designer that needs to display code should be aware that there is a very simple method for simply formatting code, and there is a slow and complex method.

    The complex method requires formatting each line with HTML tags (such as <br> and  ) to ensure the code looks nice and pretty.

    The simpler method uses <pre> tags. Pre (standing for "preformatted") means that the code is formatted exactly as it is written in the HTML window. This means the page designer can format code in a very simple fashion, without worrying about tags.

    Note:  <code> tags should not be used because they only provide the font Courier - you still have to manually indent all of your code as in the bad code display example below.

    <font face="Courier, Times, Arial, Verdana" size="3">
      public class Configuration { public static string MySetting { get; } }

    Figure: Bad code display example - using <font>

      public class Configuration { public static string MySetting { get; } }

    Figure: Bad code display example - using <code>

      public class Configuration
        public static string MySetting { get; }

    Figure: Good code display example - using <pre>

    Tip:  Do not use auto-format (Ctrl-K, Ctrl-F) in Visual Studio when updating page with <pre> tags, or it will destroy all the code formatting. We have made a suggestion to Microsoft to fix this.

  8. Do you use heading tags where appropriate (H1, H2, H3...)?

    You should understand the hierarchy and try to use the heading tags (<H1>, <H2> or <H3>...) for titles and subtitles.

    You should only use one H1 tag on a page. Search engines weight this heavily and can get confused by multiple main headings.

    The following are benefits of using heading tags:

    • Improves the ranking with the search engines (extra weighting is given to text in H1 and H2)
    • Makes cleaner and leaner HTML

    Note: It's also important to customize these headings via CSS, making the font bigger, bold or in a different color. This way page looks nice and organized.

      <span class="Heading">Introduction</span>
      Lets chatter about...

    Figure: Bad example - Using span tags and CSS classes to insert headings to content


    Figure: Good example - Using heading tags

  9. Do you chose effective anchor names?

    These are the things you should consider when creating an anchor link:

    1. Make it meaningful - When you define anchors names, use meaningful names. When you are sending the URL by email it helps indicate what you are talking about. Avoid list numbers, as they often change. An anchor like "#13" becomes incorrect when the order changes.
    2. Know they are case sensitive - Are and the same? The answer is "no" because they might be not case sensitive when they test in some browsers.
    3. Don't add spacing - When you are defining an anchor name, make sure there are no spaces within the name
    <a name="Some Anchor Name"></a>

    Bad example - Spaces within anchor name

    <a name="SomeAnchorName"></a>

    Good example - No spaces within anchor name

    1. Don't define names starting with a # - This is a common mistake because the # is used on the "href"

    When you are defining an anchor name you do not use a hashtag.
    Bear in mind that when you are referencing an anchor you do use a hashtag.

    <a name="#SomeAnchorName"></a>

    Bad example - Hashtag on anchor name

    <a name="SomeAnchorName"></a>

    Good example - No hashtag on anchor name

    We have a program called SSW Code Auditor to check for #3 and #4 on this rule.

  10. Do you design your website to improve your Google Ranking?

    Google is by a country mile the most popular search engine in the world. It's popular because it seems to rank pages so accurately and quickly time and time again. The secret to its success is its top secret PageRank Algorithm. Google developed its page ranking system in an effort to increase the quality of search results and has left all of its competitors for dead. As a result search engine optimization (SEO) gurus are always looking to find new ways to increase their Google rankings.

    As we all know, a website is a pretty nifty thing to have for a myriad of different reasons. But the truth is that it's worth is derived from the people that surf it, and if no one is surfing it, then it becomes useless. So who's the biggest website referrer? The answer is Google in almost every case.

    Design your website with this in mind. In the eyes of a search engine, there are good and bad ways that you can design your website.

    See more ways to improve your Google rankings and other search engine optimization tips.

  11. Do you include Google Analytics in your website?

    Google Analytics gives you a great insight into how, when and where your website is used. If you're not using an analytics package in your website, you're flying blind when it comes to understanding how, when and where your website is used.

    By using Google Analytics, you will be able to see what your visitors are viewing and what they aren't, what they spend large amount's of time on, what pages are causing errors, what pages are directing visitors to you, which browsers and devices are being used to see your site and more. All this information help you better structure your site to what your visitors like. It also allows you to compare site traffic from one month to another.

    The most useful reports:

    • Which are the most popular pages of your website
    • Which sites are referring the most hits to you
    • Which keywords are bringing users to your site
    • If you have downloads, which are the most popular

    To add Google Analytics to your website:

    1. Log into your Google account,
    2. Go to Admin ,
    3. Ensure both Account and Property
    4. Specify your website details,
    5. Find your Tracking Code,
    6. And add the script to your website

    tracking code property
    Figure: Navigate to the Tracking Code property

    From this page, you will be able to get a JavaScript snippet to include in your application.

    20 08 2014 3 30 55 PM compressor
    Figure: Include this JavaScript in your web application

    20 08 2014 10 53 15 AM compressor
    Figure: The JavaScript code in HTML

    Once deployed, this script will start tracking metrics and interacting with Google Analytics.

    You are good to go!

    Adding Google Analytics to your blog

    Using the above instructions, you can add Google Analytics to any website, including any blog. However, you may also find that your blogging platform or theme provides a way to set up Google Analytics using a plugin or other simple approach. Check your theme's documentation - sometimes it's as simple as adding the tracking code to configuration. Of course, adding the above JavaScript is easy enough in any case.

  12. Do you make your site easy to maintain?

    If you have database driven pages on your website, you need a way of updating the data quickly and easily. Each page should have an 'Edit' link - only visible when the site is running internally or in administrator mode - that takes you directly to the page for editing the content on that page.

    The exception to this is if you are using open-source data. SSW.People is a good example of this.

    Figure: "New" and "Edit" links allow SSW Employees to maintain testimonial entries easily

    wordpress edit
    Figure: "Edit" button on WordPress admin bar

    github edit
    Figure: Good Example - "Edit" button on an Open Source page

    From Github, you can edit and submit a pull request. See (SSW People) or (SSW Rules) for more details.

    This is better than sending a 'Change from X to Y' email as the work can be done immediately with less work and management requirements.

  13. Do you have a useful 404 error page?

    Error page, you say? You worked hard to make sure my site has no errors!! Well, surfers don't always type URLs accurately. No website is immune to such errors.

    A well-designed custom error page encourages surfers to remain in your site and help them to the right page. Although it's possible to redirect error codes straight to your homepage, that doesn't tell visitors what's going on. It's more user-friendly to explain that there was a problem and provide some alternatives. Supply a link to your home page or other links, or offer your site's search function if you have one.

    <customErrors mode="Off"></customErrors>

    Figure: Bad example - The default code on web.config

    <customErrors mode="RemoteOnly" defaultRedirect="/ssw/ErrorPage.aspx">
    <error statusCode="404" redirect="/ssw/SSWCustomError404.aspx">

    Figure: Good example - The custom code in the web.config

    For ASP.NET website, the detailed information would be presented to the remote machines when an unhandled error occurs if the customErrors mode is off.

    This error information is useful for the developer to do debugging. However, it would leak out some confidential information which could be used to get into your system by the hackers. We can assume that if a SQL exception occurs by accident, which may expose database sensitive information (e.g. connection string; SQL script). So, to prevent these leaks, you should set the "mode" attribute of the tag <customerrors> to "RemoteOnly" or "On" in the web.config file and create a user-friendly customized error page to replace the detailed error information.

    <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm"></customErrors>

    Figure: Good example - Turning on "customErrors" protects sensitive information against Hacker

    404 bad
    Figure: Bad example - Unhandled error

    404 good
    Figure: Good example - Custom error page

  14. Do you avoid changing the URL on a 404 error?

    When you request a URL of a file that doesn't exist, you will get an error message. You should make sure that the URL in the browser doesn't change. This way, it's easy for the user to correct.

    E.g. The user doesn't have to retype the whole URL if there is a spelling mistake or a forgotten/mixed up letter.

    In ASP.NET you are allowed to define a custom error page. When a user tries to access a URL which doesn't exist, ASP.NET changes the URL and redirects to the custom error page. The original URL is passed as a parameter to the new URL.

    Note: This is for ASP.NET, not ASP.NET Core, the newer iteration handles this situation in a more user-friendly manner by default.

    The advantage of this solution is, that the page looks nice and you can customize it according to the design and layout of your whole site.

    The disadvantage is, that ASP.NET changes the URL. So if the user wants to correct the URL they entered, for example, because they just mixed up a letter, then this means quite a lot of work for them. They have to retype the whole URL or at least copy and paste the parameter out of the new URL. This is very uncomfortable for the user.

    Figure: Bad example - URL changes

    Our solution is to show the customized error page while not change the original URL. So if the user wants to do any corrections, e.g. a mixed up letter, they can do that by just editing the URL in the address bar.The advantages of this solution are, that the site looks nice and matches the design of the whole site and that the user can easily change the original URL they typed.

    You can try any page name that doesn't exist like xxx.asp on the URL and it will open our 404 error page. The original URL is not changed in the address bar. It should look like this:

    404 good 1710232021928
    Figure: Good example - Customized 404 error page without change the URL

    To show the customized error page while not change the original URL, you can use Server.Transfer() to keep the original URL.


    Figure: Custom error page handler in Global.asax

  15. Do you always put JavaScript in a separate file?

    ASP.NET injects many lines during page rendering, so if you are using inline JavaScript, the line numbers will change during client side JavaScript debugging in VS.NET, FireBug or IE8 developer Tools.

    Figure: Bad Code - Using Inline JavaScript

    Figure: Bad Code - On PostBack Line numbers are changed for Inline JavaScript

    Figure: Good Code - Using JavaScript on Separate file

    So you should always put JavaScript in a separate file. Then the line numbers will stay consistent during debugging.Keeping JavaScript in a separate file is also good for production as it improves performance due to browser caching.

    Note: During development, remember to hit CTRL-F5 to force the browser to re-fetch the files from the server or you may be debugging old version of the JavaScript file.

  16. Do you always use query strings?

    When you build a web application, any dynamic page you think a user may wish to bookmark directly should be controlled through query string values rather than form values. In other words, search mechanisms should use the HTTP GET Request and Querystring values, rather than a POST with Form values. This allows:

    • Bookmarking of the pages
    • Gives the user to the ability to change the query string values in the address bar, rather than having to go back to the input form.

    Figure: The URL should always have all the parameters the user enters. Here Google is a good example

    You may hear that query strings are bad and they leave you wide open to SQL Injection Attacks (especially when you use SQL statements in the URL). I don't subscribe to the security issues being the determining factor... if I am determined enough, I can write a little application to send POST data to the webpage instead of in the query string. Both methods are open to SQL injection and invalid parameters, so you need to code to prevent that either way.

    The bottom line is that if you are not giving appropriate parameters in the query string then you are reducing functionality.

    Note: We all agree bookmarks are useful - it's the same for query strings.

  17. Do you optimise your website favicon?

    Favicons are more than just a single icon, and they require proper optimisation to display correctly on all devices.

    What is a Favicon?

    Favicons are most commonly used to display a custom icon on a browser tab, but they can also be used to alter the display of your website in other cases such as Android, iPhone, Windows, and Mac icons.

    How to Check Your Favicon

    Even if your website has a favicon, it may not be fully compliant.You can use to check your website.

    bad favicon 1
    Figure: Bad example - Favicon does not display properly on all devices
    bad favicon 2
    Figure: Bad example - Favicon does not display properly on all devices

    good favicon 1
    Figure: Good example - Favicon displays properly on all devices
    good favicon 2
    Figure: Good example - Favicon displays properly on all devices

    How to Update Your Favicon also has a favicon generator that you can use to generate a set of icons and meta tags from a single image.

    The site will guide you through all the settings and display a preview of how your favicon will look on each device.

    favicon generator
    Figure: Choosing our favicon settings

    Once you're happy with how it looks, click Generate your Favicons and HTML code and you will be given instructions on how to install your new favicon with a number of popular technologies, such as HTML5, ASP.NET Core and NodeJS.

  18. Do you avoid deploying source code on the production server?

    When you are deploying an ASP.NET project (no matter it's a website or a Web application), do not copy all files of this project to the production server because source code will be deployed during this simple copy and it makes easier for others to access or tamper the source code of your site.

    Instead, please use 'Publish' utility to deploy your website or Web application. This utility can remove the source code from the site.

    1. Website Project

    Publish Website dialog box is designed to precompile and deploy your website to a new location (whatever it is, ftp://, http:// or drive:\path). During the deployment, source code are removed automatically. Besides, the precompilation process finds any compilation errors and identifies the errors in the configuration file.j

    To access this dialog box, please open a website that you want to deploy and click Build menu, then click Publish Website .

    Figure: How to open Publish Website dialog box

    Figure: Publish Website dialog box

    See more about Publishing Websites.

    2. Web Application Project

    The Publish Web dialog box enables you to build and publish a Web application project to a new location. Like Publish Website dialog box, this utility can remove source code. However you have to select Only files needed to run this application to specify it. Other benefit of this utility is that potential errors and compile-time errors in the Web.config file and in other non-code files can be found.

    To access this dialog box, open a Web application project that you want to publish and click Publish ApplicationName on the Build menu.

    Figure: How to open Publish Web dialog ('WebApp' is the name of this application)

    Figure: Publish Web dialog box

    See more about How to Publish Web Applications.

  19. Do you avoid using UNCs in HREFs?

    Initially, errors of this nature would be picked up in the link checking utility. However, that is not the case because the link checker will not report any problems if you run it locally - which is the normal method.

    The reason it won't see the problems is because the link checking utility does not check hard coded links to local servers (e.g. localserver/ssw/Default.aspx). Therefore, it is testing a page that will exist internally, but the page will not exist when uploaded to the web (e.g.

    <a href="//ant/ssw/LookOut.htm"></a>

    Bad example

    <a href="/ssw/LookOut.htm"></a>

    Good example

  20. Do you check if your website is running?

    If you want to know your website is working or not, you need to add a ping check to the machine also an HTTP Content Scan to the website in WhatsUp. We use WhatsUp to do real-time monitoring.Follow these steps to check your website in WhatsUp:

    1. Add your website as a new device.
      Figure: New device
    2. Ping monitor is added automatically.
      Figure: Ping monitor
    3. Add an HTTP Content Scan monitor.
      Figure: HTTP Content Scan
    4. Edit the scan script. In the script, you can see 2 keywords "Send" and "Expect". "Send" expression is an HTTP request to your website. "Expect" expression is a regular expression to check the key word in response from your website.

    Figure: Edit scan script

    1. Add the monitor to your device.
      Figure: Add monitor

      Once a device is down or up, a WhatsUp action will tell SQL Reporting Services to send out a notification report. Our report looks like this:
      Figure: Website doesn't work

    Figure: Website works

  21. Do you have a PWA (Progressive Web App)?

    Progressive Web Apps have transformed the mobile web practices to provide a native app like experiences for the users. They work just like native apps and include features such as smoother navigations, offline modes and push notifications, but are much more economical and do not use the device storage.

    Progressive Web Apps are reliable which means they load instantly and the performance isn't compromised even if the network is shaky.

    On the mobile the 'Add to homescreen' option can be used to create an icon on you phone.

    PWAs also account for higher user engagements and conversions which is probably why many organizations are now adapting this technology to grow their businesses.

    In order to be a PWA, your app should:

    • Use a responsive design - So it works on desktop or mobile
    • Be fast - Use a service worker to precache the app resources (HTML, CSS, JavaScript, images) needed to run, and cache the data at runtime to improve performance
    • Be installable - Use a web app manifest and the beforeinstallprompt event to notify the user that it is installable

    Examples of Progressive Web Apps can be seen at 10 Best Progressive Web Apps.

    pwa bad example
    Figure: Bad example - Aliexpress get a mark of 6/12 (see tooltip) and cannot be used as a PWA

    pwa example
    Figure: Accessing a PWA on your mobile will prompt adding it on your Home screen. E.g.

    You can check the Progressive Web App score of your application using Chrome's Developer tools.

    Note: See how to generate a PWA report on Run Lighthouse in Chrome DevTools.

    PWA tools
    Figure: Good example - Aim for a good Progressive Web App score

  22. Do you improve web page performance with lazy loading of media assets?

    If you are dealing with Content Management System (CMS), you are likely to play with pages with large amount of images and embedded videos. To improve the performance of those pages, and save bandwidth for the readers, loading content asynchronously (also called “lazy loading”) is recommended.

    It means the browsers will only load images and embedded videos in the visible area by default, then load the rest images and videos while users are scrolling down to them.

    Real case scenario

    On our SSW Rules website, one of the pages’ initial loading size of images reduced from 4.8MB to 500KB after being applied “lazy loading” of images:

    load images 1
    Figure: Bad example - Load all images by default

    load images 2
    Figure: Good example - Do not load all images by default, only load them when they are visible while scrolling down the browsers

    The page's initial loading size of JS scripts reduced from 2.3MB to 518KB after being applied “lazy loading” of embedded YouTube videos:

    load images 3
    Figure: Bad example – Load all embedded YouTube videos by default

    load images 4
    Figure: Good example - Do not load all embedded YouTube videos by default, only load them when they are visible while scrolling down the browsers

    Implementing lazy loading for images

    1. Check if the browser supports IntersectionObserver, if the browser supports IntersectionObserver, we will only load images and videos in the areas are visible to users by default. If the browser doesn’t support it, we will have to load all images and embedded videos on the page immediately after the page is loaded.

      if (!("IntersectionObserver" in window)) {
       console.log("No Intersection");
      } else {
       console.log("Support intersection");

    Note: You can use a polyfill library to add IntersectionObserver support to older browsers.

    1. If the browser supports IntersectionObserver, in your page html, change the “src” of “<img>” to “data-src”

      <img alt="flight.jpg" src="" />


      <img alt="flight.jpg" data-src="" />
    2. Use the below Javascript to change “data-src” back to “src” for the <img> html objects, which become visible, so that those images will be loaded

      function onIntersection(entries) {
       // Loop through the entries
       entries.forEach((entry) => {
         // Are we in viewport?
         if (entry.intersectionRatio > 0) {
           // Stop watching and load the image
      function preloadImage(target) {
       if (target.getAttribute("data-src")) {
         target.setAttribute("src", target.getAttribute("data-src"));
      // Get images of class lazy
      const images = document.querySelectorAll(".sswRuleSummaryUCDiv img");
      const config = {
       // If image gets within 50px go get it
       rootMargin: "50px 0px",
       threshold: 0.01,
      let observer = new IntersectionObserver(onIntersection, config);
      images.forEach((image) => {
    3. More details can be found at Updating jQuery-based Lazy Image Loading to IntersectionObserver article.

    Implementing lazy loading for embedded YouTube videos

    1. Use the same code as lazy loading images above, to check if IntersectionObserver is supported by browsers
    2. In your page html code, convert “<iframe>” to “<div>” (width, height, src has been converted too):




      <!-- (1) video wrapper in div instead of iframe -->
       <!-- (2) the "play" button -->
       <div class="play-button"></div>
    3. Use the below code to convert “<div>” to “<iframe>” to load the embedded videos when they are visible while scrolling down:

      let youtube = document.querySelectorAll("div[data-iframesrc]");
      for (var i = 0; i < youtube.length; i++) {
       let source =
         "" +
         youtube[i].dataset.iframecode +
       let image = new Image();
       image.src = source;
         (function () {
       youtube[i].addEventListener("click", function () {
         let iframe = document.createElement("iframe");
         iframe.setAttribute("frameborder", "0");
         iframe.setAttribute("allowfullscreen", "");
         iframe.setAttribute("width", this.dataset.iframewidth);
         iframe.setAttribute("height", this.dataset.iframeheight);
           this.dataset.iframesrc + "?rel=0&showinfo=0&autoplay=1"
         this.innerHTML = "";

    More details can be found at How to “Lazy Load” Embedded YouTube Videos.

  23. Do you use the right site search for your website?

    When it comes to site search, managing various search requirements can be challenging. Using the appropriate search tools can greatly improve the overall search experience. Here are some options to help you create an effective search feature for your website.



    Algolia is a cloud-based search platform that offers a powerful and customizable search-as-a-service solution. It is known for its excellent real-time search performance.

    ✅ Excellent performance: Algolia is known for its fast and efficient search performance
    ✅ Developer-Friendly APIs and Rich Features
    ✅ Provides a free plan suitable for small projects
    ✅ Hosted Search: Algolia is a fully hosted search solution, eliminating the need for server setup and maintenance

    ❌ Cost can become a concern at scale due to pricing model
    ❌ Closed-source


    Typesense is designed for simplicity and integration, making it a suitable choice for smaller to medium-sized applications that require a user-friendly search experience.

    ✅ Designed for simplicity and ease of integration
    ✅ Good performance, supports complex queries
    ✅ Open source and free version available (self-hosting required)
    ✅ Suitable for smaller to medium-sized applications

    ❌ May have limitations in handling very large datasets or extremely complex use cases
    ❌ Limited advanced customization options compared to Elasticsearch


    Video: Next Generation Search Engine with Meilisearch (15 min)

    Meilisearch is a search engine that focuses on providing a simple and easy-to-use search solution with features like prefix searching, typo tolerance, and fast response times out of the box. It's designed to be developer-friendly and can be quick to set up for basic search needs.

    ✅ Easy to use and quick to setup for basic search needs
    ✅ Open source and free version available (self-hosting required) ✅ Good performance and built-in typo tolerance for user-friendly searching

    ❌ May have limitations in handling very large datasets or extremely complex use cases
    ❌ Less suitable for complex search requirements



    Elasticsearch is a search engine based on the Lucene and designed as a backend search engine. It's a powerful, scalable, and feature-rich option suitable for large-scale and complex search needs, but it requires significant server management and expertise.

    ✅ Scalable and suitable for handling large datasets and complex use cases
    ✅ Supports advanced features like text analysis, multilingual search, and more
    ✅ Open-Source Version Available (self-hosting required)

    ❌ Requires more effort and expertise to set up and configure
    ❌ Free version requires self-hosting, may incur additional operational costs


    Selecting the right site search tool depends on your project's specific requirements, budget, and expertise.If you have a budget, you can consider choosing Algolia. It solves the problem of complex configuration and allows you to set up on-site search quickly with just a few lines of code.If you prefer a free and more customized option, both Typesense and Meilisearch are good choices to consider.Elasticsearch is effective and particularly good at searching and analyzing logs. You can use it for on-site searches too, but unless your website is huge, using Elasticsearch might be excessive, and setting it up could get very complicated.

  24. Do you know not to use LinkButton?

    If we want to refresh and data bind the same page from client side, we can use the javascript function calls "__doPostBack". We shouldn't fire this post back in LinkButton. Otherwise, there will be an error.

    Figure: Right click the link with __doPostBack event

    Figure: New window with incorrect URL

    <asp:Panel runat="server" ID="mUpdatePanel" OnLoad="mUpdatePanel_Load">
     <asp:Label runat="server" ID="lblTime" />
     <br />
     <asp:GridView ID="gvList" runat="server" AutoGenerateColumns="false">
     <asp:BoundField DataField="ID" HeaderText="ID" />
     <asp:BoundField DataField="Name" HeaderText="Name" />
     <br />
     ID:<asp:TextBox ID="txtID" runat="server"/>
     Name:<asp:TextBox ID="txtName" runat="server"/>
    protected void mUpdatePanel_Load(object sender, EventArgs e)
     lblTime.Text = DateTime.Now.ToLongTimeString();
     ArrayList mList = (ArrayList)ViewState["List"];
     if (txtName.Text.Length > 0)
     Client mClient = new Client();
     mClient.ID = Int32.Parse(txtID.Text);
     mClient.Name = txtName.Text;
     ViewState["List"] = mList;
     gvList.DataSource = mList;

    Sample Code

    <a href="javascript:__doPostBack('mUpdatePanel','');">Refresh</a>

    Bad code

    <input type="button" onclick="javascript:__doPostBack('mUpdatePanel','');" value="Refresh" />

    Good code

    We have a program called SSW Code Auditor to check for this rule.

  25. Do you know why you choose .NET Core?

    Cross platform

    .NET Core works on multiple platforms like MacOS, Linux and Windows. So developers can code on their operating system of choice using Visual Studio, Visual Studio for Mac or Visual Studio Code, working on the same code base as developers on a different operating system, and best of all they can also deploy to Linux.


    .NET Core is fast, and you get that performance out of the box.

    dotnet core performance
    Figure: ASP.NET Core easily trounces ASP.NET 4 in number of requests per second (view source)

  26. Do you name web pages to be consistent with database tables?

    In a database-driven page, it is important that the name of the page is based on the data that the page contains. For example, if a page shows client details and is based on the Client table, then the page should be called Client.aspx.Other examples are:

  27. Do you provide modern contact options?

    The evolution of website development can be summarized by:

    • 1990 - Cool website – content focus (static HTML content)
    • 1995 - Cool graphics – interface focus (dynamic HTML content)
    • 2000 - Nice flow – usability focus (focus on user experience)
    • 2005 - Good marketing – conversion focus (SEO and visitors to customers conversion)
    • 2010 - Happy customer– interactions focus (customer experience)

    It's important that your website is focused on CX (Customer Experience) which means you need modern contact options.

    moderncontact bad
    Figure: Bad example - The only way to contact the company is via email

    moderncontact good
    Figure: Good example - Chat is available along with other ways of contact, such as voip, IM, KB etc

    Zendesk explain how you can use mulitple channels of support to give your customers a better CX

  28. Do you remove the debug attribute in Web.config compilation element?

    The debug attribute in the web.config file is very useful for ASP.NET developers. When an error occurs the developer gets detailed error report containing the stack trace, line number and what the error is.

    But when debug attribute in the Web.config file is set to true it generates symbolic information (.pdb file) every time the compiler compiles your views as well as disables code optimization. So, it slows down the execution of every page.

    So if you are a developer remember to remove the debug attribute and instead use custom error messages for your web pages

    We have a program called SSW Code Auditor to check for this rule.

  29. Do you run load tests on your website?

    You don't want to see your company's website on the front page of the news after it fails to deal with high levels of load.

    Load testing helps you to ensure that your apps can scale and stay up when peak traffic hits. Load testing is typically initiated for high-traffic seasonal events such as tax filing season, Black Friday, Christmas, summer sales, etc. but you should be regularly running load testing during development to catch any issues as early as possible.

    Once you have a website up and running, it is important to make sure that it keeps running under load. Local testing of the website will not always reveal the latent problems in the website when it is subjected to thousands of users.

    Typical issues that result from failures to handle high loads are:

    • 503 "Service Is Temporarily Unavailable" errors
    • Very slow page load times
    • Application crashes due to:

      • Insufficient resources - so application pools are recycled
      • Too many concurrent users - causing race conditions
      • Too many users trying to connect to the database - causing connection pool exhaustion

    Load testing can help you to reveal these issues before you go live. Some issues might be resolved by getting a better web server, while others might require code changes and optimizations.

    Load testing tools are designed to help you perform load testing, by recording metrics about the application as the load is varied and allowing you to visualize where user load impacts performance and/or causes application errors.

    Visual Studio 2019 Enterprise Edition is the last version of Visual Studio with built-in load testing functionality. However, it only supports Internet Explorer so Visual Studio is not a recommended load testing option .

    Note: Azure Load Testing is a fully managed load-testing service that enables you to generate high-scale load. It uses JMeter to generate the loads. Note that this service is currently only in Preview.

  30. Do you use CSS Validation Service to check your CSS file?

    CSS Validation Service allows you to check your webpage against the W3C recommendations. When developing web pages you want to create a clean and valid web page. It makes it easier for someone else to read and add new parts to a web page. Every web language like CSS has its own Syntax it must follow in order to produce a clean and valid web page, CSS Validation Service allows you to achieve that goal.

    Go to CSS Validation Service:

    1. Enter the URL or ppload file or by Direct Input to check
    2. Review the results and make changes to fix errors
  31. Do you choose the best way to send emails for your application?

    Sending email from your application is easy, most programming languages allow you to send an email. Formatting and getting proper feedback and data on your emails is a bit more complicated.

    Enterprise software generally need to send emails for a range of reasons e.g. inviting users, multifactor authentication, registering users, marketing campaigns, so it is important to know the best ways to send an email.

    1. Built-In Email commands

    Generally, programming languages have a built-in way to send email e.g. PowerShell with Send-MailMessage and System.Net.Mail in .Net, and those commands generally use an SMTP server (external or internal).If you need a quick and dirty email, this is a good way.

    2. Microsoft Graph API - Microsoft Recommended

    Microsoft's recommended way of sending mail is through the Graph API. This is much more secure than just using any built-in commands and the command itself to send it is not much more complicated.You can check how to send email through the Graph API

    3. Sendgrid - Recommended if you need a lot of features

    Another way to send email is to use a third-party solution e.g. Sendgrid that gives you many more features over the normal email-sending mechanisms above e.g:

    • Integrated API
    • Click tracking
    • Spam management
  32. Do you use jQuery instead of JavaScript?

    jQuery is the MUST HAVE tool for web developers. There are 3 good reasons why you should use jQuery.

    1. Cross Browsers (Edge, Firefox, Safari, Opera, Chrome)
    2. Powerful and easy to use

      • Same selectos as CSS
      • Designer can learn it fast
      • More readable JavaScript code
    3. Plugins - Tons of useful plugins and functionalities
    window.onload = function () {

    Figure: Bad example - Using JavaScript 'onload' event

    $(document).ready(function () {

    Figure: Good example - Using jQuery document 'ready' event

  33. Do you use Link Auditor to tell you about bad links?

    Many developers work with sites that have grown large over time and have consequently become difficult to maintain. They fix problems as customer report bugs. A better approach is to use SSW Link Auditor, a tool that will analyze your whole site and report bad links and many other problems.

  34. Do you use Markdown to store your content?

    You want users to easily edit content, so you put an "edit" button on the page. From there, you can choose between the power of HTML or the limitations of Markdown.

    edit button
    Figure: "Edit" button to encourage users updating the content

    HTML is frightening for unfamiliar users, as one wrong tag or an inline styling can break the whole page view.

    Markdown is simpler and encourages more editing without breaking the page.

    The original spec for Markdown does not specify the syntax unambiguously – so there are different flavours of the spec available. Some popular ones include:

    The Markdown Cheatsheet is a great page to reference when learning Markdown.

    Depending on the Markdown parser you choose, there are many plugins that allow you to extend it. SugarLearning and SSW.People provide more extensive cheatsheets which include a number of custom templates and plugins:

    Figure: Markdown Icon

    Tip: To make it extra easy for editors, use TinaCMS into your Markdown-based project to provide a WYSIWYG (what you see is what you get) editor experience.


    Video: "Markdown - How to use it, What is it and Why Use it | Ask a Dev" (9 min)

    Using GitHub and Markdown to store you content by Thiago Passos (4 min)

    Don't store content as HTML - It's a trap

    Rich HTML Editors make your life easier at the beginning and produce content that looks nice and clean, but behind the scenes, it generates HTML which can get out of control quickly especially if you need to edit the source code (E.g. include a special style). It becomes incredibly difficult to maintain over time.

    Some examples of rich HTML editors that you can embed in your web applications:

    Note: None of these are recommended because of the HTML that is generated.

    HTML bad
    Figure: Bad example - HTML generated by a rich editor gets harder to maintain over time

    Store content in Markdown

    Content is typically either stored in files (eg. git) or a database. When stored in files, it is common to use a static site generator with a JAMStack approach (e.g. Gatsby, Vuepress, Hexo, etc). That is, you commit content into git and a CI/CD pipeline is executed. The resulting files (HTML and CSS) are then served from storage which is cheaper and typically more scalable than compute resources in the cloud. In this case, the workflow will be a development style workflow (commit to git, push, etc) and the editor will be the one you choose. (e.g. GitHub editor or VS Code) These editors are not likely to produce a rich editing experience, nor do they need to.

    For a non-technical audience, it helps to store your content as Markdown in a database and convert to HTML on the fly. This removes the code repository/CI/CD pipelines and can feel more natural for a non-developer audience. In this case, you will provide an editor and it is recommended that this be a rich editor.

    Markdown rich editors

    The Markdown rich editors are not as good as the HTML ones, but at least the content they produce is maintainable over time.

    Some example of rich Markdown editors are:

    markdown good
    Figure: Good example - Markdown looks clean

    Markdown can have rich content too

    Markdown is simple and limited, but you can make it richer.

    One way is to use inline HTML, this allows you to use HTML tags that you are familiar with (only if you need to) and embed things like YouTube videos or JavaScript.

    use html in markdown
    Figure: OK Example – you can use raw HTML in your Markdown, and mostly it will work pretty well. But you can’t use Markdown’s syntactic sugar in the HTML

    The other way is to use templates or containers:

    danger html and markdown
    Figure: Bad example – The danger of using HTML in your Markdown files is that you add too much formatting e.g. use Bootstrap classes that create a tight coupling between the content and the presentation

    A better way is to use a plugin (if your Markdown engine supports it).

    vuepress custom container
    Figure: Good example – VuePress has a custom container that generates nice alert boxes like Bootstrap but without tying the presentation to the CSS framework in the content

    Unfortunately, Markdown does not support YouTube videos embedding out of the box. However, there is a workaround to embed it.

    [![What is SSW TV](](

    Figure: Good example - Workaround to embed YouTube video using YouTube's generated thumbnail

    If your site is using "markdown-it" parser, you can also install "markdown-it-video" to allow YouTube videos directly embedded into the page, rather than providing just an image and a link.


    Figure: Better example - YouTube video embedding using a plugin

    Markdown to HTML rendering processes

    markdown rendering
    Figure: The Markdown rendered either Client-side or Server-side

  35. Do you know the best practices for Frontmatter in markdown?

    Frontmatter is a critical component in Markdown files, especially when generating static sites or handling content management. It allows authors and developers to embed metadata directly at the beginning of a Markdown document. This metadata can include information about the document's title, author, date, and other attributes. A well-structured Frontmatter ensures that the Markdown processor can quickly extract the necessary metadata and use it for various purposes, like generating page titles or categorizing posts.

    However, when not structured properly, it can lead to parsing errors, inconsistencies, and even disrupt the rendering of the entire page. To avoid these pitfalls and ensure a seamless integration of your Markdown files, it's essential to follow best practices when defining Frontmatter.

    Tip: You can simplify the workflow for editors unfamiliar with Git or Markdown by utilizing Tina, a CMS with user-friendly interface integrated with your Git repository.

    Use Key-Value Pair Organization

    Frontmatter is metadata serialized into a plain text format primarily yaml but can also be toml, or json. In Frontmatter, each key represents an attribute, like the title or the author, and the value associated with it provides specific information related to that attribute.

    • Keys are always strings and should be descriptive enough to indicate the type of data they hold
    • Values can be strings, numbers, dates, or even arrays, depending on the data you're representing

    Using key-value pairs ensures a standardized format, which in turn makes it easier for both humans and machines to read and interpret the data. Moreover, this structured approach ensures that Markdown processors can reliably extract and utilize the metadata, whether it's for rendering a webpage title, categorizing posts, or any other function.However, avoid non-standard practices like mixing data types or adding unnecessary complexity:

    title+author: My Article by John

    Figure: Bad example - Non-standard practices can lead to parsing errors and inconsistencies

    title: My Article
    author: Bob Northwind
    date: 2023-10-31

    Figure: Good example - Clear key-value pairs make it easy to understand and extract the metadata

    Use Arrays for Complex Data

    Arrays in Frontmatter are particularly useful when you have to represent multiple values for a single attribute. In Markdown, an array is essentially a list of values that are associated with a common key.

    • Why Use Arrays? Sometimes, a single key might have multiple associated values. Instead of creating multiple keys, or stringing values together, arrays provide a clean and organized method to capture this complex data
    • Accessibility: Arrays make it straightforward for Markdown processors to loop through multiple values, making tasks like generating a list of tags or authors on a webpage much simpler
    • Flexibility: Arrays can hold strings, numbers, or even other objects, giving you a versatile tool to represent complex structures

    However, avoid the common mistake of listing values in a continuous string. This format is harder to parse, and you lose the distinct advantage of the array's structure:

    authors: John Doe, Jane Smith, Bob Johnson

    Figure: Bad example - Listing values in a string reduces clarity and makes data extraction challenging

    Here's how you can effectively use arrays:

      - Bob Northwind
      - Jane Smith
      - Bob Johnson

    Figure: Good example - Using arrays helps in listing multiple values under a single key efficiently

    Use Meaningful Keys

    The keys you choose for your Frontmatter should be meaningful and descriptive. They act as identifiers for the associated values, so it's essential that they clearly convey the data they represent.

    • Descriptive Names: Instead of using desc, use description. Instead of auth, use author
    • Consistency: Stick to a consistent naming convention, whether it's camelCase, snake_case, or kebab-case

    Avoid non-descriptive keys:

    t: My Article
    auth: Bob Northwind

    Figure: Bad example - Shortened or unclear keys can lead to confusion

    Use clear, meaningful keys:

    title: My Article
    author: Bob Northwind

    Figure: Good example - Descriptive keys make Frontmatter easy to understand and work with

    Use Explicit Datatypes

    It's crucial to be explicit about datatypes in Frontmatter. This clarity helps Markdown processors understand how to handle the provided metadata correctly.

    • Strings vs. Numbers: If you're representing a year, use a number, e.g., 2023. If you're mentioning a title or name, use a string, e.g., "My Article"
    • Booleans: For binary choices, like true or false, use booleans. For example, published: true

    Avoid ambiguous datatypes:

    year: '2023'
    published: "yes"

    Figure: Bad example - Ambiguous datatypes can lead to parsing errors

    Be explicit with your datatypes:

    year: 2023
    published: true

    Figure: Good example - Explicit datatypes ensure accurate data representation and extraction

    Avoid Inline HTML

    While Markdown allows the integration of inline HTML, it's recommended to avoid using it within Frontmatter. Using HTML can lead to rendering issues, especially when the Markdown is processed by static site generators or other tools.

    • Simplicity: Sticking to Markdown syntax within Frontmatter keeps the metadata clean and straightforward
    • Portability: By avoiding HTML, you ensure that the Frontmatter remains compatible with various Markdown processors and platforms

    However, some might try to use HTML for additional formatting or structure:

    title: <em>My</em> Article
    author: <strong>Bob Northwind</strong>

    Figure: Bad example - Using inline HTML can cause unexpected rendering or parsing issues

    Stick to plain Markdown:

    title: "My Article"
      - name: "Bob Northwind"
        role: "Writer"
    published: true
    year: 2023
      - Technology
      - Writing
      - Markdown
      created_at: "2023-10-30"
      modified_at: "2023-11-06"

    Figure: Good example - Keeping Frontmatter free of HTML ensures consistent rendering

  36. Do you have a page owner for each webpage?

    Managing webpages can be challenging, especially in projects with many contributors. When editing a page, a common problem is not knowing who the original author was. This is bad, because it's important not to change something that was there for a reason!

    The best way to solve this is by having a page owner for each webpage.


    A designated page owner ensures someone is responsible for the accuracy of the page content. It avoids confusion about who to approach for major changes, and it allows the page owner to keep an eye on changes.


    1. Markdown files - Add an 'owner' field in the frontmatter metadata for each page.
    2. New pages - The field should be required when creating a page.
    3. Pull requests - Automatically add the page owner as a reviewer for any pull requests that modify their page.

    Tip: this can be done automatically with a GitHub Action (or similar automation)

    ✅ The "owner" (person responsible) is aware of and can approve any changes

    ✅ People know who to consult about changes to the page

    🤔 We don't use CODEOWNERS for this because we don't want to block pull requests for minor edits

    ❌ When trying to work out who is the page owner, version history is not good enough - often the creator of a page is not the actual author e.g. a dev makes the page for a Marketing person

    no author bad
    Figure: Bad example - No owner field. Impossible to see who wrote this page!

    page owner good
    Figure: Good example - Frontmatter with an 'author' field.

  37. Markdown – Do you set the language on code blocks?

    You should have a syntax highlighter to show pieces of code on your pages for a better readability.


    See this json file for all supported languages and their aliases we can use in SSW Rules.

    let iceCream = 'chocolate';
    if (iceCream === 'chocolate') {
      alert('Yay, I love chocolate ice cream!');    
    } else {
      alert('Awwww, but chocolate is my favorite...');    

    Figure: Bad example - No syntax highlighting

    let iceCream = 'chocolate';
    if (iceCream === 'chocolate') {
      alert('Yay, I love chocolate ice cream!');    
    } else {
      alert('Awwww, but chocolate is my favorite...');    

    Figure: Good example - This JavaScript code block shows its syntax highlighted

  38. Do you use Markup Validation Service to check your HTML and XHTML code?

    Markup Validation Service allows you to check your web page against the W3C recommendations. When developing web pages you want to create a clean and valid web page. It makes it easier for someone else to read and add new parts to a web page. Every web language like HTML has its own syntax it must follow in order to produce a clean and valid web page, Markup Validation Service allows you to achieve that goal.

    Go to Markup Validation Service:

    1. Enter the URL or upload file to check
    2. Review the results and make changes to fix errors
  39. Do you use Unicode Hex codes for special HTML characters?

    In HTML coding, using special characters into HTML content elevates visual appeal and enhances the user experience. Utilizing Unicode Hex codes is a powerful technique to accurately render these special characters in HTML.

    Benefits of Using Unicode Hex Codes

    • Compatibility: Unicode Hex codes ensure consistent display across platforms, browsers, and devices, guaranteeing that special characters appear correctly regardless of the user's system or font support.
    • Versatility: Unicode encompasses a wide range of characters, including symbols, emojis, foreign language characters, and mathematical symbols. By employing Unicode Hex codes, you can seamlessly incorporate various special characters into your HTML content.
    • Accessibility: Unicode Hex codes contribute to enhanced accessibility by accurately representing special characters, enabling visually impaired users or those using screen readers to access and comprehend the content effectively.

    Practical Examples

    • Registered Trademark Symbol (®): Represented by the Unicode Hex code &#x00AE;.
    • Heart Emoji (❤): Displayed using the Unicode Hex code &#x2764;.
    • Euro Symbol (€): Utilize the Unicode Hex code &#x20AC;.

    By integrating these Unicode Hex codes into your HTML, you ensure consistent rendering of special characters across browsers and devices.

  40. Do you know how to generate PDFs for download?

    Some projects call for being able to export data as a PDF. In these instances, it's great to be able to fully generate the file in the back-end and then provide it for download.

    As with most software problems, there's many ways to achieve the same end result, each with their pros and cons.

    There are many paid .NET libraries available which can generate PDFs for you like:

    If the project has budget for a paid PDF solution, these are great and will get you generating PDFs quickly.


    ✅ Mostly works out-of-the-box
    ✅ Potential for commercial support from the library developer


    ❌ Project might not have the budget for such an option
    ❌ Is often closed source (see more)

    Free libraries

    Unfortunately, the vast majority of libraries which can generate PDFs directly are paid. To get around this, the PDF generation function of a browser testing library can be used instead. Using this method, the desired content is rendered in a headless browser and that browser is then used to generate a PDF.


    ✅ Free!
    Open source
    ✅ Can easily reuse existing web layouts


    ❌ Support is often limited
    ❌ May require more configuration to get working


    One library which makes this really easy (and is free!) is Playwright.

    Generating a PDF here takes just a few lines, see the demo and docs for more info.

    public async Task<byte[]> ExportView(string url, CancellationToken cancellationToken)
        var playwright = await Playwright.CreateAsync();
        var browser = await playwright.Chromium.LaunchAsync();
        var page = await browser.NewPageAsync();
        await page.GotoAsync(url);
        if (cancellationToken.IsCancellationRequested) { return Array.Empty<byte>(); }
        return await page.PdfAsync(new PagePdfOptions { Format = "A4" });

    Figure: A simple method to return a PDF using Playwright

  41. Do you centralize downloadable files?

    Efficient management of downloadable content, like PDFs and documents, is a critical component of website maintenance. Simplify the process of making files public on your website by following these guidelines.

    Centralized file storage

    • Primary directory - Use 'public/downloads' as the central directory for all downloadable files to simplify organization, updating, and tracking of content
    • Subdirectory use (optional) - If needed, employ subdirectories for additional organization (based on the volume and diversity of the files)
    • Uniform linking - Direct all download links to this central location to eliminate duplication and streamline site maintenance

    Efficient file naming

    • Descriptive naming - Use clear, descriptive file names with SEO-friendly keywords for easy identification and discoverability
    • Version control - Keep version information within documents, not in file names, to maintain consistent URLs

    Optimizing file accessibility

    • File compression - Compress larger files to improve download speed and site performance
    • Accessibility compliance - Ensure that all files comply with ADA and WCAG guidelines

    bad example centralize downloadable files
    Figure: Bad example - Saving the same file in multiple places (cumbersome to update)

    good example centralize downloadable files
    Figure: Good example - Single URL for file, referenced across websites (simplifies updates and generates backlinks)

    Step-by-step guide

    1. Optimize files - Compress file sizes without compromising quality and use clear, descriptive filenames
    2. Upload files - Place files in the central directory or relevant subdirectories
    3. Streamline URLs - Use and reference a single, stable URL for each file to avoid creating multiple links for the same content
    4. Ensure accessibility - Ensure that the files are accessible and functional across different browsers and devices

    Improve your website's management of downloadable content by centralizing file storage, utilizing clear naming conventions, and ensuring accessibility.

  42. Do you use Open Graph to control how your links are shared?

    Open Graph is a metadata tag that allows you to control what content shows up when a page is shared on social media networks.

    It should be placed on the <head> section of your page. The most used properties are:

    <meta property="og:title" content="Your Custom Title" />
    <meta property="og:description" content="Your custom description of the page." />
    <meta property="og:image" content="https://www.YourCustomImage.jpg"/>

    open graph bad
    Figure: Bad example - Shared link has no image and the title was "guessed" by LinkedIn

    opengraph good
    Figure: Good example - Shared link has a nice image and title, both defined via Open Graph tags

    Note: For LinkedIn you might need to add the prefix as following:

    <metaprefix="og:" property='og:title' content="Microsoft Azure | SSW Consulting - Sydney, Brisbane, Melbourne"/>

    More information and other properties can be found at The Open Graph protocol.

  43. Do you use server side comments?

    Use server side comments:

    • Use <%-- Comment Here --%> instead of <!-- Comment Here --> (Does not get rendered to the client, saves us a few precious kilobytes)
    • Use CTRL + K, C to comment and CTRL + K, U to uncomment
  44. Do you use the best static site tech stack?

    Pure HTML pages are the fastest website around. However, server-side scripting languages enable richer functionality. Static sites solve this problem by providing the best of both worlds. Static sites are

    • Cheap
    • Easy to use
    • Fast

    On the other hand, complex functionality can be a bit more limited and time consuming to implement.

    Here are some popular static site generators:

    NameNextJS (Recommended)GatsbyAstroScullyGridsomeJekyll
    LanguageReactReactMost major JS frameworks via islandsAngularVueLiquid
    Data HandlingFully customisableGraphQLFully customisableFully customisableGraphQLSource code data files
    Data SourcesFully customisableFilesystems, CMS, APIs, Databases, Local filesFully customisableFully customisableSource Plugins, APIs, Local filesLocal files
    GitHub Pages IntegrationRequires setupSeamless deployment via config filesDeployment via GitHub ActionsDeployment via GitHub ActionsSeamless deployment via config filesWorks out of the box
    Decap CMS (formerly Netlify CMS) integration

    google trends nextjs
    Figure: Google trends for the above SSGs. In a substantial lead is NextJS, followed by Gatsby.

    Figure: NextJS and Gatsby are the major competitors that have been duking it out, lately Next.js has exploded in popularity

    Two examples of static sites in action are SSW People and SSW Rules.

    There are a few hosting options to choose from including:

  45. Do you know why Next.js is awesome?

    React is a powerful JavaScript library for building user interfaces. However, it doesn't provide built-in support for server-side rendering (SSR). This lack of SSR can lead to slow website load times and poor search engine optimization (SEO). That's where Next.js comes in. Next.js is a framework built on top of React that provides several features and benefits for building high-performance websites.

    A quick summary of Next.js (pay attention to the first 2.5 min)

    Video: Next.js in 100 Seconds // Plus Full Beginner's Tutorial (11 min)

    A deeper dive on Next.js

    Video: Theo Browne: Next.js is a backend framework (11 min)

    ✅ Reasons to choose Next.js

    Here are some reasons to consider using Next.js instead of React alone:

    1. Incremental Static Regeneration: Next.js allows you to create or update static pages after you’ve built your site. Incremental Static Regeneration (ISR) enables you to use static-generation on a per-page basis, without needing to rebuild the entire site. With ISR, you can retain the benefits of static while scaling to millions of pages.
    2. TypeScript: Next.js provides an integrated TypeScript experience, including zero-configuration set up and built-in types for Pages, APIs, and more.
    3. Internationalized Routing: Next.js has built-in support for internationalized (i18n) routing since v10.0.0. You can provide a list of locales, the default locale, and domain-specific locales and Next.js will automatically handle the routing.
    4. API routes: API routes provide a solution to build your API with Next.js. Any file inside the folder pages/api is mapped to /api/* and will be treated as an API endpoint instead of a page. They are server-side only bundles and won't increase your client-side bundle size.
    5. Server-side rendering: Next.js provides built-in support for SSR, which can significantly improve website performance and SEO by rendering pages on the server and sending HTML to the client.
    6. Dynamic Import: Next.js supports lazy loading external libraries with import() and React components with next/dynamic. Deferred loading helps improve the initial loading performance by decreasing the amount of JavaScript necessary to render the page. Components or libraries are only imported and included in the JavaScript bundle when they're used. next/dynamic is a composite extension of React.lazy and Suspense, components can delay hydration until the Suspense boundary is resolved.
    7. Automatic code splitting: Next.js automatically splits code into smaller chunks, which can improve website performance by reducing the initial load time.
    8. Built-in CSS, image, and font optimization: Next.js has built-in support for optimizing CSS, images and fonts. These can help reduce website load times and improve performance.
    9. Automatic Static Optimization: Next.js automatically determines that a page is static (can be prerendered) if it has no blocking data requirements. This feature allows Next.js to emit hybrid applications that contain both server-rendered and statically generated pages.
    10. MDX: MDX is a superset of markdown that lets you write JSX directly in your markdown files. It is a powerful way to add dynamic interactivity, and embed components within your content, helping you to bring your pages to life.
    11. Incremental adoption: Next.js allows developers to add server-side rendering and other advanced features incrementally to an existing React application, making it easy to adopt and integrate into existing projects.
    12. Codemods: Next.js provides Codemod transformations to help upgrade your Next.js codebase when a feature is deprecated. Codemods are transformations that run on your codebase programmatically. This allows for a large amount of changes to be applied without having to manually go through every file.


    By using Next.js instead of React alone, developers can reduce the pain points users may experience and build high-performance websites more efficiently. However, it's important to note that Next.js may not be the best choice for every project, and developers should evaluate their project's specific needs and requirements before making a decision.

  46. Do you know the best CMS solutions for websites?

    You don’t want to build solutions from scratch, so take what business value you can from a CMS: don't reinvent the wheel.

    A CMS allows business users to build and manage websites without having to write any code.

    Top CMS vendors (including eCommerce and websites)

    These CMS platforms work really nicely for simple scenarios. If they fit your business case then use them.

    Source: WordPress Market Share Statistics (2011-2024)

    Top CMS vendors for enterprise websites (.NET based)

    When you have a complex business case, you need something more customizable. That's where enterprise CMSs come into play.

    Source: Top 5 .NET Based CMS Platforms For Your Business (Updated 2023)

    cms oct2022
    Figure: Google trends of the above .NET CMSs. The leading (but most expensive) is SiteCore, and in second is Umbraco (which is much cheaper)

    View current trend information for these products.

    Top headless CMS

    Source: 16 Best Headless CMS For Publishers in 2023

    Other headless CMS (.NET based)

    cmsheadless oct2022
    Figure: Google trends of the above Headless CMSs. The leading is the open-source Strapi, which is inexpensive, but not as feature rich as Contentful (second) and Kontent (third)

    View current trend information for these products.

    Headless CMS vs Traditional CMS

    A Traditional CMS is a monolith, which means it has both a front-end and back-end. It uses server side technology like PHP (Wordpress, Joomla, Magento) or ASP.Net (DNN, Umbraco, Sitefinity) and a single database. All pages are served by one or many backend servers.

    A Headless CMS deals strictly with the content. Created content is accessed via Application Programming Interfaces (APIs), which gives you full flexibility on how you build the front-end for your website. Headless CMSs are also very appropriate for JAMstack sites: see the State of Jamstack 2021 Report by Kentico for more information.

    For example, you can use a Headless CMS with a super fast Static Site Generator (SSG): see the rule on the best static site tech.

    Source: UDig - Traditional CMS vs Headless CMS

    Traditional CMSs like Sitecore and Kentico Xperience have their place, especially if you have no developers and you’re comfortable with serious vendor lock-in. Headless CMSs and static sites for the win. -Adam Cogan

    Here is a breakdown of Traditional CMS architecture vs Headless CMS architecture:

    cms architecture traditional
    Figure: Traditional CMS Architecture

    cms architecture headless
    Figure: Headless CMS Architecture

    ✅ Traditional CMS - Pros

    • Simple and fast - For setup and maintenance
    • Less reliance on developers - You won't be as reliant on developers to make changes, and may be able to forgo them completely for small-medium projects. More complex CMSs will require developer involvement but non-developers still have some customisation control
    • Simple to control look and feel - Using available themes and templates
    • Large community support
    • Out of the box integrations - Payments, social media, etc

    ❌ Traditional CMS - Cons

    • Performance is not amazing - The frontend is coupled with the backend
    • Does not scale very well - All pages render server side, so you will need more servers if you have lots of traffic
    • Locked-in - Content is only available on browsers and not on native mobile apps
    • Limited flexibility - You are limited to themes and templates, e.g. if you want to build a multi-step form
    • You need developers with particular CMS skills - If you have a big website or are using complicated CMS features, you will need CMS developers - e.g. for SiteCore or Sitefinity
    • It is not an API first solution

    ✅ Headless CMS - Pros

    • Super fast - Fast initial load time when using Static Site Generator (SSG)
    • Scales very well - When using Static Site Generator, and the frontend can be cached via CDN
    • Ultimate flexibility with how to use content - Can use a Single Page Application (SPA), Static Site Generator (SSG) or even native mobile apps. Not restricted by themes, templates or vendor, and you can have multiple frontends with 1 headless CMS backend
    • Many options to build frontend - NextJs, HUGO. Gatsby, React, Angular, etc. This makes it easier and cheaper to find developers
    • Easy publishing - The same content can be published to different platforms at the same time (website, web app, native mobile app)

    ❌ Headless CMS - Cons

    • Very reliant on frontend developers - Anything beyond basic content changes will require frontend dev involvement
    • Greater overhead - To maintain the code base, DevOps, etc
    • Limited preview functionality - Kontent provides in-context editing via Spotlight, however most Headless CMSs do not. Netlify CMS can help in this case

    Hybrid CMS

    Some CMSs (e.g. Optimizely offer a hybrid approach including both headless integration and a fully featured UI. As such, you can get the best of both worlds by going down this route. However, pursuing this option comes at a premium with prices matching or exceeding traditional CMSs. An entry level figure for Hybrid CMSs is approximately $50,000 but this figure can quickly increase to several hundred thousand $ as you include add-ons and other features.

    Headless CMS Comparison: Kontent vs Contentful

    Let's compare two popular CMSs.


    Content Modelling - The ability to model your website components, and see how they are used in your website Collections - Allows you to manage content dependent on your business and geographical structure. This eliminates the use of silos, which make it more difficult to manage your data

    Website optimisation - See the Kontent's useful docs on this topic.

    NameKontent (Recommended) - Video (3 mins)Contentful - Video (1 min)
    In-Context EditingInfo
    Personalized Experiences✅ via Uniform✅ via Uniform
    SSO and MFA
    GraphQL SupportSoon: October 2021
    Content Modelling
    Unlimited Content Types
    Content Collaboration✅ + Simultaneous Editing
    Task ManagementInfo + better functionalityInfo
    Website Optimisation
    Roadmap TransparencyBetter: feature release roadmapGood: Info
    Australian Compliance✅ stored in an Australian Azure Data Center❌ stored in a United States AWS Data Center
    Dev/Staging/Prod Data MigrationProd only by default - Add migration script and pipelineProd only by default - Add migration script and pipeline
    Email CampaignsUse 3rd party best of breed tool e.g. MailChimpUse 3rd party best of breed tool e.g. MailChimp
    User Tracking e.g. Leads, funnelsExternal CRM e.g. Salesforce Pardot, Dynamics 365 MarketingExternal CRM e.g. Salesforce Pardot, Dynamics 365 Marketing
    StatisticsExternal Analytics e.g. Google AnalyticsExternal Analytics e.g. Google Analytics
    Developer Friendly
    PricingPremium: $30,000 pa (cheaper with scaling)Team: $24,000 pa (with Compose + Launch)

    Assuming you want enterprise features, Kontent is preferred as the Headless CMS of choice over Contentful.

    Source: Kentico Kontent vs. Contentful

    Dead CMSs

    • Microsoft SharePoint for public sites
  47. Do you use Git-based Content Management Systems (CMS)?

    Developers love Git 😍, and while it was originally built as a version control system for source code, it's now used to power all kinds of awesome tools - including Content Management Systems (CMS)! So how is a Git-based CMS different to a traditional CMS platform, and why would you want to use one?

    Video: Git-based Content Management Systems | Gordon Beeming | SSW Rules (4 min)

    Difference between traditional and Git-based CMS platforms

    When traditional content management systems (CMS) were designed to cater to the needs of marketers, they prioritized ease of use but often lacked the flexibility crucial for developers. Modern developers, accustomed to continuous integration and continuous delivery (CI/CD) processes inspired by DevOps principles, thrive on workflows that enhance productivity.

    Most traditional CMS platforms rely on centralized databases and content storage services that not only impose limitations but also prescribe the overall capabilities of the content repository and the CMS. Conversely, a Git-based CMS offers version control for both content and configuration together - meaning you have much greater flexibility (and speedier development!) when compared with a traditional CMS.

    Git-based CMS platforms

    Below is a list of some of the most popular tools:

    TinaCMS is an open-source CMS that integrates with various static site generators. It's designed to be lightweight and flexible, allowing inline editing and real-time preview.


    • Open-source
    • Git-based versioning & workflows
    • GitHub Contributions
    • MDX Support for rich reusable components
    • Editorial Workflows
    • Supports Single Sign-On (SSO)


    • Manage Pull Request in GitHub
    • Some minor UX issues
    • Pricing Tiers


    CrafterCMS is a headless CMS designed for high-performance content applications. It's not traditionally categorized strictly under "Git-based CMSs," but it does provide Git-based versioning and workflow capabilities, which makes it highly scalable and suitable for managing complex content structures.


    • Git-based versioning & workflows
    • Open-source
    • Docker Image
    • Supports most UI Frameworks
    • GraphQL support
    • Unlimited Sites, Projects, Users


    • Does not support MDX
    • Need a user account

    There is also an enterprise version of CrafterCMS that has more features, like Internationalization and Generative AI. However that solution is $$$ Super expensive.


    Publii is a static site generator that offers a desktop app, providing a user-friendly interface for managing content offline. It integrates well with Git and supports syncing with various hosting services. It can get overlooked because it's seen more as a site generator with CMS features rather than a pure CMS.


    • Open-source
    • Privacy focused
    • Can sync content with git


    • Does not support MDX
    • No GitHub contributions
    • Desktop Based Only


    Contentrain is a headless CMS that offers a Git-based workflow, aligning the content editing process closely with the codebase. It's quite new in the market, and is quite niche (JSON and no GitHub).


    • Pricing is comparable/affordable to most API-based CMSs
    • Real-time collaboration
    • Git-based versioning & workflows
    • Internationalization


    • JSON based content
    • No GitHub contributions
    • Need a user account


    StaticCMS is a newer entry in the field and offers a Git-based, open-source CMS. It's designed to work well with static site generators and is a lesser-known brand. StaticCMS is a fork of Decap CMS (previously Netlify CMS).


    • Editorial Workflow (in Beta)
    • Open Authoring (in Beta)
    • GitHub Contributions


    • No MDX support
    • No live-preview (markdown preview only)
  48. Do you know the best online documentation site?


    When it comes to creating, managing, and hosting documentation, choosing the right tool can significantly impact productivity and user satisfaction.

    Poor documentation platforms can lead to confusion, inefficiency, and a lack of engagement.

    Conversely, selecting the right tool can enhance clarity, collaboration, and overall user experience.

    Top Documentation Sites

    Here are some of the top online documentation sites:



    • Git-based
    • Open-source
    • Inline editing and real-time preview.
    • Supports Markdown and JSON files.
    • Flexible and customizable with a strong focus on content editing experience.

    Use Case:

    • Best for developers looking for a headless CMS with a great content editing experience.



    • Easy creation of documentation with a Markdown editor.
    • Version control and collaboration features.
    • Hosting and customizable themes.

    Use Case:

    • Ideal for teams needing a collaborative platform for project documentation.



    • Focuses on API documentation with interactive and dynamic features.
    • Built-in analytics to track usage and engagement.
    • Supports code snippets, changelogs, and user authentication.

    Use Case:

    • Best for creating and managing API documentation with user analytics.



    • Open-source project by Facebook.
    • Easy setup and maintenance of open-source project documentation.
    • Uses Markdown and integrates with React.

    Use Case:

    • Suitable for open-source projects and developers familiar with React.



    • Static site generator geared towards project documentation.
    • Written in Python and uses Markdown.
    • Various themes and plugins.

    Use Case:

    • Great for Python developers needing extensive project documentation.



    • Lightweight documentation site generator.
    • No statically built HTML files; loads Markdown files dynamically.
    • Easy integration with existing projects.

    Use Case:

    • Ideal for lightweight, quick documentation needs.



    • Fast static site generator.
    • Supports Markdown with many themes.
    • Suitable for simple and complex documentation.

    Use Case:

    • Versatile option for both small and large documentation projects.


    Choosing the right documentation site depends on your specific needs, including the type of documentation, desired features, and the development environment.

    By evaluating these options, you can select a tool that enhances clarity, collaboration, and overall user satisfaction.

  49. Do you use Web Compiler extension?

    You can use Visual Studio's Web Compiler extension to create a bundle.css and test if CSS was compiled successfully.

    More information and download at Visual Studio Marketplace.

    web compiler find error
    Figure: Web Compiler can find missing curly braces

    Unfortunately different kinds of errors, like are not caught.

    web compiler didnt find error
    Figure: Curly braces in the wrong place, but still compiled successfully

    In addition, Gulp is wrongly successful too:

    gulp didnt find error
    Figure: Gulp couldn't find the curly braces error

  50. Do you keep your npm and yarn packages up to date?

    Video: NPM package hell 🔥... How to avoid going insane with Brook Jeynes (4 min)

    NPM packages often get new releases (adding new functionalities, fixing bugs or vulnerabilities). It is important to keep the packages updated as much as possible during the development of your application. The best way to do that is to update all the packages every time you add a new package to your application, and include the npm outdated and npm audit reports in the Sprint Review. These commands are also available with yarn with yarn outdated and yarn audit.

    # NPM
    npm outdated
    npm audit
    # Yarn
    yarn outdated
    yarn audit

    Running npm outdated returns an overview of your packages versions showing:

    • The current version your project is using
    • The wanted version, i.e. the maximum version of the package that satisfies the semver range specified in package.json
    • The latest version of the package

    The packages output from this command will also show up in different colours:

    • Red indicates the package version is below the wanted version
    • Yellow indicates the package version is at the wanted version but below the latest version

    npm outdated
    Figure: Use 'npm outdated'

    npm audit returns an audit on your packages for vulnerabilities. It also provides information on how to resolve them.

    npm audit
    Figure: Use 'npm audit' to discover vulnerabilities in your application

    To add a new package, use:

    # NPM
    npm install package-name
    # Yarn
    yarn add package-name

    To update your packages, use:

    # NPM
    npm update package-name
    # Yarn
    yarn upgrade package-name

    Yarn also has a useful tool called yarn upgrade-interactive that allows you to see which packages are outdated, and upgrade them all at once.

    upgrade interactive
    Figure: Using yarn upgrade-interactive

    Note: Use yarn upgrade-interactive --latest to see outdated packages with breaking changes.

  51. Do you perform migration procedures with an approved plan?

    A migration from one technology to another is a process fraught with danger. Everyone would love the "upgrade" button to work perfectly but it doesn't. Expect any migration to fail first go. Any statement that "I didn't expect to have any problems" shows inexcusable optimism.

    A plan for a migration will typically include:

    1. Business purpose for migration
    2. Test migration
    3. User Acceptance Testing of the test migration
    4. Rollback procedure
    5. Decommissioning procedure

    Approved plans are mandatory for a migrations such as:

    1. Exchange Server 2003 to 2007
    2. ISA Server to a hardware firewall
    3. Phone system to VoIP
    4. etc.
  52. Do you know the best ways to manage your bundle size?

    Shipping a large JavaScript bundle can be catastrophic for your web app - resulting in longer load times and a poor user experience using a web app. It is very easy for this to be the case when using a web framework such as React or Angular, as adding packages to an already large amount of framework code can result in a bloated JavaScript bundle.

    Despite the efforts made by tools like Webpack, Rollup or Vite to optimize your JavaScript bundle, these may not be sufficient if your project has an excessive number of NPM packages. Each package introduces additional code to your bundle, and unnecessary or redundant packages can quickly inflate its size. Identifying and eliminating such packages can help keep your bundle lean and efficient. Here are some tools that can help with this process:


    Depcheck is a great CLI tool that scans your project to automatically detect unused dependencies in a project, giving you a clear and concise list of unused packages in a repository.

    npx depcheck

    Figure: A list of the unused dependencies in a project

    Note: It is important to be mindful when using this tool of packages that are still in use in the project, either in the build steps or otherwise (e.g. tailwindcss in the example above is not explicitly imported in the project, but is still used behind the scenes).


    Bundlephobia is a great tool for quickly seeing the bundle size of NPM packages. You can find the bundle size of any NPM package by going to the URL:{{ PACKAGENAMEHERE }}.

    You can also upload a package.json file to display a list of packages in your project, allowing you to easily see which NPM packages have the largest size in the project. You can find it at

    bundlephobia list
    Figure: The list of packages from the package.json file, sorted by size

    Note: It is important to understand that not all of the packages in your package.json file are shipped to the client, this is primarily a tool used to assess specific client-side packages that you suspect may have a large bundle size (for example, some packages may only be used by the server or within the build steps of the project i.e. typescript or tailwindcss).

    Import Cost VSCode Extension

    The Import Cost extension for VSCode, developed by Wix shows the size of each NPM package you import, which can provide useful visual feedback on how large the packages you importing actually are. You search the extension on the Visual Studio Code Extension Marketplace at Import Cost.

    import cost
    Figure: The extension in action - shows you how large each package is, as you import it

    Webpack Bundle Analyzer

    If your JavaScript project is using Webpack (most React/NextJS projects will be), you can use the NPM package webpack-bundle-analyzer to easily visualise the size of the NPM dependencies contained in the client bundle.

    If you are using NextJS, it is advised to use Next's custom implementation of the package - @next/bundle-analyzer.

    webpack bundle analyzer
    Figure: The bundle map for the NextJS SSW Website

  53. Do you allow users to comment and rate your pages?

    If you have published content on the internet, it's a good idea to allow your visitors to comment and rate your pages. Collecting feedback is a great way to make it easier to maintain your content. You can see which content is out of date, and which content is more highly regarded by your user base. This lets you focus on creating the most relevant content that you can. As well as providing you with feedback, allowing people to participate makes them feel more engaged with your content, broadening your reach.

    There are a few ways that you can easily add comments and interactivity such as using widgets from:

    Main Options


    ✅ Pros:

    • Uses GitHub discussions to store comments
    • Uses GitHub login - most people already have this
    • Simple and lightweight
    • Always free
    • Open source
    • No tracking scripts
    • No ads

    ❌ Cons:

    • No moderation features


    ✅ Pros:

    • Moderation features
    • Spam protection features

    ❌ Cons:

    • Heavy - adds lots of tracking scripts
    • Need a separate login
    • Paid (Unless you want ugly ads 🤮)

    Other options

    • Utterances - Very similar to Giscus, but uses GitHub Issues instead of Discussions. Giscus is recommended over Utterances as using Issues for comments will pollute your backlog.
    • Yotpo

    The following video shows an overview of Yotpo ratings which we've implemented for our SSW Rules.

    Good Example: Yotpo ratings on the SSW Rules site

We open source. Powered by GitHub