<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Stefan.Lu</title>
    <link>https://www.stefan.lu/</link>
    
    <image>
      <url>https://www.stefan.lu/feed-icon.png</url>
      <title>Stefan.Lu</title>
      <link>https://www.stefan.lu/</link>
    </image>
    
    <atom:link href="https://www.stefan.lu/feed.xml" rel="self" type="application/rss+xml"/>
    
    <description>The website and blog of Stefan Lugtigheid / Stefan.Lu, a freelance product developer based in the Netherlands.</description>
    <pubDate>Sat, 23 Dec 2023 14:40:41 GMT</pubDate>
    <generator>http://hexo.io/</generator>
    
    <item>
      <title>Danish law firm Kromann Reumert successfully implements TIQ Time</title>
      <link>https://www.stefan.lu/blog/kromann-reumert-implements-tiq-time/</link>
      <guid>https://www.stefan.lu/blog/kromann-reumert-implements-tiq-time/</guid>
      <pubDate>Thu, 06 Jan 2022 23:00:00 GMT</pubDate>
      
      <description>Danish law firm Kromann Reumert successfully implements TIQ Time</description>
      
      
      
      <content:encoded><![CDATA[<p><em>This is a copy of a <a href="https://www.tiqtime.com/blog/danish-law-firm-kromann-reumert-successfully-implements-tiq-tim">press release</a> for TIQ Time, one of the main projects I’ve been working on for several years.</em></p><p>TIQ, a global leader in automated time tracking systems for law firms and other professional services organisations, is proud to announce that Danish leading full-service law firm Kromann Reumert successfully deployed TIQ Time to its 300 fee-earners.</p><a id="more"></a><p>Kromann Reumert employs a team of around 500 dedicated people across their three offices in Copenhagen, Aarhus, and London. The firm was looking to replace its existing, custom-build and SharePoint-based time recording system.</p><p>Kromann Reumert’s Head of IT Jacob Brønnum-Schou:</p><blockquote><p>Our existing time recording system was too static, making it very hard to introduce new features. We decided to explore the market to find a company that was 100% focused on time tracking and recording solutions. The funny thing was that we kept running into TIQ at various places around Europe. TIQ could provide a solution – TIQ Time – that supported our dynamic approach and was more intelligent than the old software.</p></blockquote><p>Kromann Reumert also looked at other solutions available in the market. Jacob explained:</p><blockquote><p>During our search, we discovered that competing companies came up with project proposals like we ran them in the past and that doesn’t fit with Kromann Reumert anymore. We like to run agile projects and focus on a single solution only, not a slew of other applications co-offered with time tracking solutions. I was sometimes under the impression that many companies out there don’t listen enough to existing requirements and try to sell a complete strategy instead of a simple solution.</p></blockquote><p>The approach Kromann Reumert used towards the implementation was quite daring. Instead of a standard Proof of Concept (PoC) during which new software is installed in a test environment, Jacob decided to do the PoC in the production environment to determine if migrating users from the old system to TIQ would be a smooth process. Jacob:</p><blockquote><p>TIQ accepted this challenge and built our environment in just over a month time. We then trained the 20 pilot users for half an hour, after which they started to use TIQ Time for the first time. The most interesting observation was that we didn’t receive any technical support calls. After the pilot group worked for more than a month with TIQ Time, we decided to roll out the rest of the firm in batches of users.</p></blockquote><p>Kromann Reumert decided to train all fee-earners instead of letting TIQ do the training. Jacob explains why: “We took this approach because we have many business rules in place that need to be respected by people writing time and sending invoices. These rules are firm-specific and have nothing to do with the TIQ application itself.”</p><p>Jacob made another exciting observation that users pro-actively asked to be migrated to TIQ Time after discovering how pleased migrated colleagues were with the new system. This month, Kromann Reumert will migrate the last batch of users, after which the firm can close the project with confidence.</p><h2 id="About-Kromann-Reumert"><a href="#About-Kromann-Reumert" class="headerlink" title="About Kromann Reumert"></a>About Kromann Reumert</h2><p>Kromann Reumert is a leading law firm in Denmark with offices in Copenhagen, Aarhus and London. The firm employs a team of almost 500 dedicated people who work together to provide quality services for their clients. Currently, the number of employees include around 300 lawyers covering a long list of practice areas.</p><h2 id="About-TIQ-Time"><a href="#About-TIQ-Time" class="headerlink" title="About TIQ Time"></a>About TIQ Time</h2><p>TIQ Time helps lawyers build a complete and consistent timesheet, helping firms to reduce leakage, increase their bottom-line and optimise insights and transparency in service delivery.</p><p>I’ve been involved with the design, development and management of TIQ Time since day one. My activities for TIQ Time include:</p><ul><li>product design</li><li>product development</li><li>front-end development</li><li>product management</li><li>product strategy</li></ul><p>Want to read more? Check out all related posts under <a href="/tag/legal-tech">legal tech</a>.</p><hr><h5 id="More-information"><a href="#More-information" class="headerlink" title="More information"></a>More information</h5><ul><li><a href="https://www.tiqtime.com/blog/danish-law-firm-kromann-reumert-successfully-implements-tiq-time">Original press release by TIQ Time</a></li><li><a href="https://kromannreumert.com/">Kromann Reumert</a></li></ul><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: all images by <a href="https://kromannreumert.com/">Kromann Reumert</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/legal-tech/">legal tech</category>
      
      
      <comments>https://www.stefan.lu/blog/kromann-reumert-implements-tiq-time/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>ECOVIS STLex - Studio Legale Tributario adopts TIQ Time to drive change</title>
      <link>https://www.stefan.lu/blog/ecovis-stlex-adopts-tiq-time/</link>
      <guid>https://www.stefan.lu/blog/ecovis-stlex-adopts-tiq-time/</guid>
      <pubDate>Wed, 08 Dec 2021 23:00:00 GMT</pubDate>
      
      <description>ECOVIS STLex - Studio Legale Tributario adopts TIQ Time to drive change</description>
      
      
      
      <content:encoded><![CDATA[<p><em>This is a copy of a <a href="https://www.tiqtime.com/blog/ecovis-stlex-studio-legale-tributario-adopts-tiq-time-to-drive-change">press release</a> for TIQ Time, one of the main projects I’ve been working on for several years.</em></p><p>TIQ, provider of cloud-based time capture technology for legal professionals, has implemented the solution at Ecovis STLex Studio Legale Tributario.</p><p>TIQ is delighted to announce the formal rollout of its innovative time tracking software at the Torino, Milan and Genova offices of the global consulting firm Ecovis International. All fee earners practicing law and tax consulting at ECOVIS STLex Italy are now using TIQ Time to unlock critical data insights and reduce time leakage.</p><a id="more"></a><p>Emilio Martinotti, Managing Partner at ECOVIS STLex Italy: </p><blockquote><p>We used to track our time in our ERP system, which was a particularly slow and manual process. The fact that the time entries in TIQ Time are already filled out and the description is very precise is, in my opinion, great. As a result, we have seen an improvement in the range of 20% to 30% in the number of hours captured in our consultants’ timesheets.</p></blockquote><p>ECOVIS STLex Italy sought an innovative solution to address some pain points the firm’s consultants were experiencing with tracking time. Using TIQ’s suggested time entries, fee-earners now speed up and spent less time filling out timesheets, therefore increasing productivity and reducing the cost of administrative work. The use of narrative templates, both for captured entries and manual entries, improved the quality and consistency of time entries, making it easier to gain insights for service delivery and allowing a day-by-day upload of the activities performed.</p><p>Martinotti:</p><blockquote><p>We have many clients that ask for work to be completed on a fixed fee basis. If you agree that it’s €10,000 for the job, then you need to know how much work you can feasibly do for that amount of money. TIQ Time not only captures all the hours our consultants are working, but also develops business intelligence. We even expect further improvements in the automatic matching of captured time with each assignment and in the dashboards.</p></blockquote><h2 id="Implementing-TIQ-Time-at-ECOVIS-STLex"><a href="#Implementing-TIQ-Time-at-ECOVIS-STLex" class="headerlink" title="Implementing TIQ Time at ECOVIS STLex"></a>Implementing TIQ Time at ECOVIS STLex</h2><p>Before formally adopting TIQ Time, ECOVIS STLex Italy spoke at length another Italian law firm which had implemented TIQ. The firm’s leaders wanted a solution that provided end-to-end support throughout the implementation period – and beyond.</p><blockquote><p>“As a managing partner in charge of technological improvement, it was great for me to talk directly with an existing client of TIQ Time. In fact, I think this was one of the reasons we decided to proceed with TIQ. The customer success team was incredibly helpful too. We really liked the support they provided initially, presenting and explaining the service and training our team. It is important that an IT vendor is not just selling a solution but also helping us manage the change.”</p></blockquote><h2 id="About-ECOVIS-STLex-Italy"><a href="#About-ECOVIS-STLex-Italy" class="headerlink" title="About ECOVIS STLex Italy"></a>About ECOVIS STLex Italy</h2><p>ECOVIS STLex - Studio Legale Tributario is a professional firm performing Tax, legal, accounting, audit, management, payroll, outsourcing consulting and services. ECOVIS STLex is the member firm of ECOVIS ® International in Italy. To date, the professional association counts about 12 partners, 44 professionals, 42 staff, 4 Of Counsel and therefore more than 100 people in the three offices of Milan, Genoa and Turin.</p><h2 id="About-TIQ-Time"><a href="#About-TIQ-Time" class="headerlink" title="About TIQ Time"></a>About TIQ Time</h2><p>TIQ Time helps lawyers build a complete and consistent timesheet, helping firms to reduce leakage, increase their bottom-line and optimise insights and transparency in service delivery.</p><p>I’ve been involved with the design, development and management of TIQ Time since day one. My activities for TIQ Time include:</p><ul><li>product design</li><li>product development</li><li>front-end development</li><li>product management</li><li>product strategy</li></ul><p>Want to read more? Check out all related posts under <a href="/tag/legal-tech">legal tech</a>.</p><hr><h5 id="More-information"><a href="#More-information" class="headerlink" title="More information"></a>More information</h5><ul><li><a href="https://www.tiqtime.com/blog/ecovis-stlex-studio-legale-tributario-adopts-tiq-time-to-drive-change">Original press release by TIQ Time</a></li><li><a href="https://www.ecovis.com/global/office/ecovis-st-lex-studio-legale-tributario">STLex Studio Legale Tributario</a></li></ul><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: all images by <a href="https://www.ecovis.com/global/office/ecovis-st-lex-studio-legale-tributario">STLex Studio Legale Tributario</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/legal-tech/">legal tech</category>
      
      
      <comments>https://www.stefan.lu/blog/ecovis-stlex-adopts-tiq-time/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Leading European law firm Cuatrecasas selects TIQ&#39;s automated time tracking system</title>
      <link>https://www.stefan.lu/blog/european-law-firm-cuatrecasas-selects-tiq/</link>
      <guid>https://www.stefan.lu/blog/european-law-firm-cuatrecasas-selects-tiq/</guid>
      <pubDate>Wed, 01 Dec 2021 23:00:00 GMT</pubDate>
      
      <description>Leading European law firm Cuatrecasas selects TIQ&#39;s automated time tracking system</description>
      
      
      
      <content:encoded><![CDATA[<p><em>This is a copy of a <a href="https://www.tiqtime.com/blog/cuatrecasas-selects-tiqs-automated-time-tracking-system">press release</a> for TIQ Time, one of the main projects I’ve been working on for several years.</em></p><p>From proof of concept to successful go-live in just four months using a 100% virtual implementation methodology.</p><p>TIQ, a global leader in automated time tracking systems for law firms and other professional services organisations, announced today that European leading full-service law firm Cuatrecasas replaced its legacy Intapp time tracking solution with TIQ’s best-of-breed time capture solution.</p><a id="more"></a><p>TIQ Time is a fully automated cloud-based time tracking and capturing system, helping law firms to reduce time leakage, thereby increasing bottom-line results while at the same time increasing transparency in service delivery. TIQ Time integrates with productivity software like Microsoft Office and document management systems, collaboration software like Microsoft Teams and Zoom and all major practice management systems. These integrations allow fee earners to work with the most modern time capturing solution available while not disturbing existing business processes.</p><p>For Cuatrecasas, TIQ developed new integrations to connect TIQ Time with SAP (practice management) and NetDocuments (document management). Another option worth mentioning is the Zoom integration, making it possible for Cuatrecasas to capture all time spent by fee earners while meeting online.</p><p>Francesc Muñoz, Cuatrecasas’ CIO, commented: </p><blockquote><p>The software is excellent, and the integrations with other systems work very fast and are stable. Overall, the performance is much better than what we had before. Working with TIQ was a very positive experience, and for our firm, it also helped that TIQ is a European-based company.</p></blockquote><p>During the whole project – from sales to implementation – no physical meetings took place between TIQ and Cuatrecasas. The project was delivered remotely – on time and budget – without any issues. Muñoz: </p><blockquote><p>We have never met the guys from TIQ, only their CEO Nick Schils. The first time I met Nick was in July, weeks after the system went live in our firm.</p></blockquote><p>Cuatrecasas project co-lead Roberto López commented:</p><blockquote><p>Our users are pleased with the new time tracking solution. The little feedback we have received so far is very positive. The fact that we received little feedback is actually the best news because swapping systems always causes inconvenience for the users. Apparently, this swap resulted in little resistance for change.</p></blockquote><p>User training was kept to a minimum: a 30-minute online training session combined with a go-live video was all it took to get the firm going with the new software. The first billing cycle - one month after go-live, completed successfully without any noticeable issues.</p><p>TIQ’s CEO Nick Schils:</p><blockquote><p>Working together with Francesc, Roberto, and the rest of the Cuatrecasas team was an incredible and effective experience. The level of IT knowledge and experience at Cuatrecasas resulted in a smooth integration and onboarding. At TIQ, we are proud to onboard one of Europe’s largest law firms, and it is a great step towards the future. This project is an amazing example of what can be achieved with a world-class team and as a forerunner in the digital transformation of law firms. By leveraging the modern architecture offered by TIQ’s software, Cuatrecasas can utilise the insights from TIQ optimally, from IT to day-to-day operations and finance.</p></blockquote><h2 id="About-Cuatrecasas"><a href="#About-Cuatrecasas" class="headerlink" title="About Cuatrecasas"></a>About Cuatrecasas</h2><p>Specialising in all areas of business law, Cuatrecasas is present in 14 countries, with a strong focus on Spain, Portugal and Latin America. Over 1,700 professionals based at 27 offices work as a single team: they collaborate, share challenges and work together to exceed clients’ expectations consistently</p><h2 id="About-TIQ-Time"><a href="#About-TIQ-Time" class="headerlink" title="About TIQ Time"></a>About TIQ Time</h2><p>TIQ Time helps lawyers build a complete and consistent timesheet, helping firms to reduce leakage, increase their bottom-line and optimise insights and transparency in service delivery.</p><p>I’ve been involved with the design, development and management of TIQ Time since day one. My activities for TIQ Time include:</p><ul><li>product design</li><li>product development</li><li>front-end development</li><li>product management</li><li>product strategy</li></ul><p>Want to read more? Check out all related posts under <a href="/tag/legal-tech">legal tech</a>.</p><hr><h5 id="More-information"><a href="#More-information" class="headerlink" title="More information"></a>More information</h5><ul><li><a href="https://www.tiqtime.com/blog/cuatrecasas-selects-tiqs-automated-time-tracking-system">Original press release by TIQ Time</a></li><li><a href="https://www.cuatrecasas.com/en/global/">Cuatrecasas</a></li></ul><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: all images by <a href="https://www.cuatrecasas.com/en/global/">Cuatrecasas</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/legal-tech/">legal tech</category>
      
      
      <comments>https://www.stefan.lu/blog/european-law-firm-cuatrecasas-selects-tiq/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Danish Law Firm Molt Wengel Implemented TIQ Time to improve time recording</title>
      <link>https://www.stefan.lu/blog/danish-law-firm-molt-wengel-implemented-tiq-time/</link>
      <guid>https://www.stefan.lu/blog/danish-law-firm-molt-wengel-implemented-tiq-time/</guid>
      <pubDate>Wed, 26 May 2021 22:00:00 GMT</pubDate>
      
      <description>Danish Law Firm Molt Wengel Implemented TIQ Time to improve time recording</description>
      
      
      
      <content:encoded><![CDATA[<p><em>This is a copy of a <a href="https://www.tiqtime.com/blog/danish-construction-law-firm-molt-wengel-selects-tiq-time-to-improve-time-recording">press release</a> for TIQ Time, one of the main projects I’ve been working on for several years.</em></p><p>Molt Wengel, the largest provider of specialist legal advice to the Danish construction industry, has implemented TIQ Time. The best-of-breed time capture solution is rolled out to all legal specialists at the firm with a view of improving time tracking hygiene.</p><a id="more"></a><p>TIQ is pleased to announce that leading Danish construction law firm Molt Wengel implemented TIQ’s time capture software. Molt Wengel selected TIQ Time to address time tracking accuracy within the firm and to make the process of tracking time easier for its lawyers.</p><p>Kristoffer Giro, IT and Administrative Support Officer at Molt Wengel:</p><blockquote><p>TIQ has made a significant improvement for the lawyers in their time tracking. One nuisance for our lawyers was to think back to all the small activities, like responding to an email in between the larger tasks. TIQ Time automatically captures those activities, such as sending an email or working on a document. The biggest benefit we’ve noticed is that the lawyers can review and approve all their time entries at the end of the day in a user friendly and modern interface, specifically designed for legal professionals.</p></blockquote><p>TIQ Time integrates with the existing software in law firms to automatically capture time. When lawyers spend time drafting documents in word processors, sending emails, or attending meetings, TIQ generates time entries for those activities. Lawyers then open the application to approve, amend, or reject the time entries generated for them. This works to both improve the accuracy of time entries and reduce the time spent creating them.</p><p>Kristoffer Giro, IT and Administrative Support Officer at Molt Wengel:</p><blockquote><p>When choosing software, we always consider the user-friendliness of the software and we look for solutions that are the best-of-breed. We also pride ourselves on being first movers. Implementing TIQ Time makes sense on the basis of our criteria.</p></blockquote><p>Nick Schils, Founder and CEO of TIQ Time:</p><blockquote><p>It is fantastic to see that the lawyers at Molt Wengel are benefitting from our software. TIQ Time is designed to perform as a specialty legal solution that streamlines and simplifies the process of tracking time. We are delighted to hear the lawyers at Molt Wengel are choosing TIQ Time over their former time tracking software. It demonstrates to us that we’re developing the software to be user-friendly and to deliver real time savings. Molt Wengel’s onboarding fits perfectly with the current developments in the Nordics and is a good example of our increasing growth in the region.</p></blockquote><h2 id="About-Molt-Wengel"><a href="#About-Molt-Wengel" class="headerlink" title="About Molt Wengel"></a>About Molt Wengel</h2><p>Located in Copenhagen, Molt Wengel is a Danish law firm specialising in national as well as international construction law. As strategic partners to the construction industry, we are dedicated to finding solutions that help our clients avoid deadlocks through dialogue, understanding and progress. Furthermore, we are the largest provider of specialist legal advice to the Danish construction industry. Our team comprises more than 25 legal specialists.</p><p>As specialists in construction law, our work starts where clauses and a passion for construction meet to create valuable advising for our clients. Our clients include leading players in the Danish and international construction industries, including contractors, private and public employers, and consultants. Our experience and expertise have given us a unique and considerable insight into how to avoid, mitigate, and handle challenges in complex construction projects.</p><h2 id="About-TIQ-Time"><a href="#About-TIQ-Time" class="headerlink" title="About TIQ Time"></a>About TIQ Time</h2><p>TIQ Time helps lawyers build a complete and consistent timesheet, helping firms to reduce leakage, increase their bottom-line and optimise insights and transparency in service delivery.</p><p>I’ve been involved with the design, development and management of TIQ Time since day one. My activities for TIQ Time include:</p><ul><li>product design</li><li>product development</li><li>front-end development</li><li>product management</li><li>product strategy</li></ul><p>Want to read more? Check out all related posts under <a href="/tag/legal-tech">legal tech</a>.</p><hr><h5 id="More-information"><a href="#More-information" class="headerlink" title="More information"></a>More information</h5><ul><li><a href="https://www.tiqtime.com/blog/danish-construction-law-firm-molt-wengel-selects-tiq-time-to-improve-time-recording">Original press release by TIQ Time</a></li><li><a href="https://mowe.dk/">Molt Wengel</a></li></ul><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: all images by <a href="https://mowe.dk/">Molt Wengel</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/legal-tech/">legal tech</category>
      
      
      <comments>https://www.stefan.lu/blog/danish-law-firm-molt-wengel-implemented-tiq-time/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Leading Italian Firm RP Legal &amp; Tax chooses TIQ Time as its new time tracking software</title>
      <link>https://www.stefan.lu/blog/italian-firm-rp-legal-tax-chooses-tiq-time/</link>
      <guid>https://www.stefan.lu/blog/italian-firm-rp-legal-tax-chooses-tiq-time/</guid>
      <pubDate>Wed, 28 Apr 2021 22:00:00 GMT</pubDate>
      
      <description>Leading Italian Firm RP Legal &amp; Tax chooses TIQ Time as its new time tracking software</description>
      
      
      
      <content:encoded><![CDATA[<p><em>This is a copy of a <a href="https://www.tiqtime.com/blog/leading-italian-firm-rp-legal-tax-chooses-tiq-time-as-its-new-time-tracking-software">press release</a> for TIQ Time, one of the main projects I’ve been working on for several years.</em></p><p>CRS Group, the official TIQ Time system integrator in Italy, has implemented the best-of-breed time tracking solution at leading law firm RP Legal &amp; Tax. The software has been adopted by more than 150 lawyers across the firm’s 7 offices.</p><a id="more"></a><p>TIQ is pleased to announce that leading Italian firm RP Legal &amp; Tax implemented TIQ’s time registration software. RP Legal &amp; Tax has been investigating legal service providers extensively as part of its planned upgrade and chose TIQ Time to further improve time recording.</p><p>Paolo Grandi, Partner and Member of the Board at RP Legal &amp; Tax: </p><blockquote><p>After an extensive selection process, we’ve found that TIQ Time offers a user experience that exceeds other products on the market. We were looking for a system specifically focused on the legal market to make sure that filling out timesheets is as easy as possible for our lawyers.</p></blockquote><p>TIQ Time helps RP Legal &amp; Tax lawyers build complete and consistent time entries via an add-on to the Practice Management System and Document Management System. To ensure that timesheet entry is as easy as possible for every fee-earner, TIQ automatically captures the time spent on activities, such as drafting documents, emails and meetings.</p><p>Paolo Grandi, Partner and Member of the Board at RP Legal &amp; Tax:</p><blockquote><p>“With our previous system, we found that time management was very time consuming. It was a manual process - with manual search and manual entry. By automating the process of time tracking, TIQ saves our lawyer’s time. More importantly, we’ve already noticed that our lawyers are tracking their time more consistent and we’re expecting to see an increase in revenue as a result.</p></blockquote><p>Following the implementation of TIQ Time at other top-tier Italian law firms, CRS Group, was now responsible for rolling out the cloud solution at RP Legal &amp; Tax as well.</p><p>Roberto Castiglia, Partner at CRS Group:</p><blockquote><p>We are happy to partner with TIQ as the exclusive system integrator in Italy. We’re delighted with the results from all the implementations. It’s incredible to see how quickly TIQ Time enhances the relationship between law firms and their clients, thanks to the transparency and insights the software delivers.</p></blockquote><p>As part of the upgrade, RP Legal &amp; Tax wanted a time capture solution that was easy-to-use, responsive, and agile. However, since their software upgrade was happening incrementally, they sought a solution that integrates with both the older and newer practice management systems.</p><p>Nick Schils, CEO at TIQ:</p><blockquote><p>We are delighted to welcome RP Legal &amp; Tax to our customer base. The partnership with system integrator CRS Group allows us to offer the most advanced time tracking solutions in the Italian market. For RP Legal &amp; Tax, this means they can provide their fee-earners a way to effortlessly construct clear narratives and capture all activities throughout the day. We look forward to welcoming more Italian customers this year.</p></blockquote><h2 id="About-RP-Legal-amp-Tax"><a href="#About-RP-Legal-amp-Tax" class="headerlink" title="About RP Legal &amp; Tax"></a>About RP Legal &amp; Tax</h2><p>RP Legal &amp; Tax is an independent Italian law and tax firm, founded in 1949, with 7 offices throughout Italy, major international links, and more than one hundred and seventy highly skilled professionals providing full-service assistance. Its partners and consultants are recognised as leading authorities in their chosen disciplines.</p><p>RP Legal &amp; Tax provides both international clients who do business in Italy and Italian clients abroad with first-class legal and tax advice, along with the necessary support to bridge the cultural gaps which are an inevitable feature of any international business venture. The firm credits its constant exchange of information and know-how between its leading professionals for its global view on all relevant legal issues, particularly in complex matters.</p><h2 id="About-CRS-Group"><a href="#About-CRS-Group" class="headerlink" title="About CRS Group"></a>About CRS Group</h2><p>CRS was founded in 1994 to respond to the request for assistance and IT support from professional firms and SMEs. Assistance is almost always tailor made and, thanks to the strategic approach, we operate with the aim of optimizing every investment or technological choice in the long term. Our staff, constantly updated, works with passion and attention to detail to bring innovative solutions to customers, experimenting with consolidated, emerging technologies or even hypothesizing new scenarios.</p><p>We take care of operation and security of our clients. Focused on high level partnership with major player on the market. We are a team of 40 passionate and close-knit people who work together and alongside client companies to solve problems by flexibly and creatively improving their efficiency and productivity. IT solutions and assistance with remote and onsite services in real time.</p><h2 id="About-TIQ-Time"><a href="#About-TIQ-Time" class="headerlink" title="About TIQ Time"></a>About TIQ Time</h2><p>TIQ Time helps lawyers build a complete and consistent timesheet, helping firms to reduce leakage, increase their bottom-line and optimise insights and transparency in service delivery.</p><p>I’ve been involved with the design, development and management of TIQ Time since day one. My activities for TIQ Time include:</p><ul><li>product design</li><li>product development</li><li>front-end development</li><li>product management</li><li>product strategy</li></ul><p>Want to read more? Check out all related posts under <a href="/tag/legal-tech">legal tech</a>.</p><hr><h5 id="More-information"><a href="#More-information" class="headerlink" title="More information"></a>More information</h5><ul><li><a href="https://www.tiqtime.com/blog/leading-italian-firm-rp-legal-tax-chooses-tiq-time-as-its-new-time-tracking-software">Original press release by TIQ Time</a></li><li><a href="https://www.rplt.it/">RP Legal &amp; Tax</a></li></ul><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: all images by <a href="https://www.rplt.it/">RP Legal &amp; Tax</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/legal-tech/">legal tech</category>
      
      
      <comments>https://www.stefan.lu/blog/italian-firm-rp-legal-tax-chooses-tiq-time/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Norway&#39;s Firm of the Year 2020 Thommessen shares results of a successful TIQ Time implementation</title>
      <link>https://www.stefan.lu/blog/thommessen-shares-results-of-successful-tiq-time-implementation/</link>
      <guid>https://www.stefan.lu/blog/thommessen-shares-results-of-successful-tiq-time-implementation/</guid>
      <pubDate>Wed, 24 Mar 2021 23:00:00 GMT</pubDate>
      
      <description>TIQ is pleased to announce that Thommessen implemented TIQ&#39;s time registration software firm-wide.</description>
      
      
      
      <content:encoded><![CDATA[<p><em>This is a copy of a <a href="https://www.tiqtime.com/blog/thommessen-shares-results-of-a-successful-tiq-time-implementation">press release</a> for TIQ Time, one of the main projects I’ve been working on for several years.</em></p><p>The leading Nordic law firm Thommessen has implemented best-of-breed time registration software TIQ Time. The software is used by all lawyers and staff across the firm’s offices in Oslo, Stavanger, Bergen, and London.</p><a id="more"></a><p>TIQ is pleased to announce that Thommessen implemented TIQ’s time registration software firm wide. 300 of Thommessen’s lawyers and staff adopted TIQ Time when the firm updated its existing ERP to include more specialised and more modern tools.</p><p>Trine Melsether, Chief Digital Officer at Thommessen: </p><blockquote><p>Time tracking is at the core of the legal business model. You don’t want your lawyers to spend a lot of time tracking their billable hours, you want them to spend it adding value for clients. From the first moment, our lawyers were very engaged with TIQ Time, and understood the value the service would deliver. The fact that TIQ is focused fully on the legal market creates trust and made it a safe choice for our firm.</p></blockquote><p>The firm’s previous solution - a timesheet native to the ERP system - lacked certain functionality, causing frustration among the lawyers. TIQ’s time capture service alleviates these frustrations. Its interface is easy-to-use and offers modern time recording features, including fully automated time capture alongside manual timers. The software is supported on desktop and mobile devices. In this case, TIQ Time was rolled out on top of the ERP installation and iManage Worksite.</p><p>Nick Schils, CEO at TIQ Time:</p><blockquote><p>One of the promises we make our customers is that we never charge consulting fees when it comes to onboarding, integration and implementation. We believe that as a true Software-as-a- Service company, an effortless roll-out and adoption should be part of the core of the product. Over the years, this philosophy has translated to a sophisticated approach where TIQ Time can be adopted by leading firms, such as Thommessen, within days.</p></blockquote><p>Trine Melsether, CDO:</p><blockquote><p>Our challenge was that we were switching our ERP system, which meant that we had to roll out TIQ Time to all users at once. On Friday our lawyers were working with the previous solution, and on Monday everybody started using TIQ Time. The transition was amazingly smooth, and worked from day one.</p></blockquote><h2 id="About-Thommessen"><a href="#About-Thommessen" class="headerlink" title="About Thommessen"></a>About Thommessen</h2><p>Thommessen is one of Norway’s leading commercial law firms, with offices in Oslo, Bergen, Stavanger and London. Since its foundation in 1856, the firm has been closely involved in most of the defining developments in Norwegian industry and commerce. Thommessen’s clients are Norwegian and international businesses, in both the private and public sector. The firm assists businesses with transactions, complex projects, and dispute resolution in all commercial law disciplines. Several of Thommessen’s lawyers are leading experts in their field in Norway, and a number of them are admitted to the Supreme Court.</p><h2 id="About-TIQ-Time"><a href="#About-TIQ-Time" class="headerlink" title="About TIQ Time"></a>About TIQ Time</h2><p>TIQ Time helps lawyers build a complete and consistent timesheet, helping firms to reduce leakage, increase their bottom-line and optimise insights and transparency in service delivery.</p><p>I’ve been involved with the design, development and management of TIQ Time since day one. My activities for TIQ Time include:</p><ul><li>product design</li><li>product development</li><li>front-end development</li><li>product management</li><li>product strategy</li></ul><p>Want to read more? Check out all related posts under <a href="/tag/legal-tech">legal tech</a>.</p><hr><h5 id="More-information"><a href="#More-information" class="headerlink" title="More information"></a>More information</h5><ul><li><a href="https://www.tiqtime.com/blog/thommessen-shares-results-of-a-successful-tiq-time-implementation">Original press release by TIQ Time</a></li><li><a href="https://www.thommessen.no/en/">Advokatfirmaet Thommessen</a></li></ul><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: all images by <a href="https://www.thommessen.no/en/">Advokatfirmaet Thommessen</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/legal-tech/">legal tech</category>
      
      
      <comments>https://www.stefan.lu/blog/thommessen-shares-results-of-successful-tiq-time-implementation/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Portolano Cavallo selects TIQ Time</title>
      <link>https://www.stefan.lu/blog/portolano-cavallo-selects-tiq-time/</link>
      <guid>https://www.stefan.lu/blog/portolano-cavallo-selects-tiq-time/</guid>
      <pubDate>Wed, 27 Jan 2021 23:00:00 GMT</pubDate>
      
      <description>Italian law firm with offices in Milan, Rome and New York selects TIQ&#39;s best-of-breed time tracking solution.</description>
      
      
      
      <content:encoded><![CDATA[<p><em>This is a copy of a <a href="https://www.tiqtime.com/blog/portolano-cavallo-selects-tiq-time-as-its-firm-wide-time-entry-portolano-cavallo-selects-tiq-solution">press release</a> for TIQ Time, one of the main projects I’ve been working on for several years.</em></p><p>TIQ has announced that Portolano Cavallo, the leading digital-tech and Life Sciences Italian law firm, selected TIQ Time to improve time registration. All fee earners are live on TIQ’s best-of-breed time tracking solution to fill out their timesheets.</p><a id="more"></a><p>TIQ Time helps Portolano Cavallo’s fee-earners construct high quality and consistent narratives for all time entries by using smart suggestions based on captured activities. The software automatically creates an overview of the time that lawyers spent on documents, emails, meetings and other activities. The use of narrative templates, both for captured entries and manual entries, will improve the quality of time entries with less effort than before. The full implemention is deliverd by CRS IT Consulting &amp; Management.</p><p>Yan Pecoraro, Leading Partner at Portolano:</p><blockquote><p>We have never considered time entry a nuisance: instead, we have always striven to maximum accuracy to ensure full transparency about our work to clients, and to appropriately communicate added value. TIQ Time maximizes our ability to do so, facilitating real- time entries and accurate narratives.</p></blockquote><h2 id="About-TIQ-Time"><a href="#About-TIQ-Time" class="headerlink" title="About TIQ Time"></a>About TIQ Time</h2><p>TIQ Time helps lawyers build a complete and consistent timesheet, helping firms to reduce leakage, increase their bottom-line and optimise insights and transparency in service delivery.</p><p>I’ve been involved with the design, development and management of TIQ Time since day one. My activities for TIQ Time include:</p><ul><li>product design</li><li>product development</li><li>front-end development</li><li>product management</li><li>product strategy</li></ul><p>Want to read more? Check out all related posts under <a href="/tag/legal-tech">legal tech</a>.</p><hr><h5 id="More-information"><a href="#More-information" class="headerlink" title="More information"></a>More information</h5><ul><li><a href="https://www.tiqtime.com/blog/portolano-cavallo-selects-tiq-time-as-its-firm-wide-time-entry-portolano-cavallo-selects-tiq-solution">Original press release by TIQ Time</a></li><li><a href="https://portolano.it/">Portolano Cavallo Studio Legale</a></li></ul><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: all images by <a href="https://www.portolano.it/">Portolano</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/legal-tech/">legal tech</category>
      
      
      <comments>https://www.stefan.lu/blog/portolano-cavallo-selects-tiq-time/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Multifunctional Wall Covering (patented)</title>
      <link>https://www.stefan.lu/work/multifunctional-wall-covering/</link>
      <guid>https://www.stefan.lu/work/multifunctional-wall-covering/</guid>
      <pubDate>Thu, 03 Dec 2020 23:00:00 GMT</pubDate>
      
      <description>Description of the development process of the patented multi functional wallcovering innovation</description>
      
      
      
      <content:encoded><![CDATA[<p>Multifunctional Wall Covering is a very broad description of a patented innovation I have been working on together with dQconcepts B.V. from 2017 until its launch in 2020. Like the name says, it has multiple functions; it is printable, can be applied seamlessly and has acoustic properties. In this post I will tell you a bit more about the journey.</p><a id="more"></a><p>As usual, let’s start with a picture and description of the end product.</p><p><img src="01.jpg" alt="Multifunciontal Wall Covering with a photo print"></p><h2 id="What-is-Multifunctional-Wall-Covering"><a href="#What-is-Multifunctional-Wall-Covering" class="headerlink" title="What is Multifunctional Wall Covering?"></a>What is Multifunctional Wall Covering?</h2><p>Multifunctional wall covering is a printable polyester wall covering material material that can be applied horizontally. It’s supplied in a roll that covers the wall from floor to ceiling in a single piece for walls up to 12 meters in length.</p><p><img src="02.jpg" alt="Multifunciontal Wall Covering with a custom Motiflow pattern"></p><p>Apart from being seamless and printable, it has acoustic properties, meaning that it can improve and environments acoustics by eliminating echo. This is especially useful for open office environments that usually contain a lot of hard materials. Instead of investing in acoustic treatment, covering one or two walls with this material will drastically improve the acoustic climate of the office due to its large surface area - and at a competitive price and without sacrificing office space!</p><p>A full list of the material properties:</p><ul><li>Printable polyester wall covering</li><li>Seamless application of up to 12m in one piece</li><li>Acoustic properties (ISO 11654 &alpha;<sub>w</sub> value of 0,25(H))</li><li>Can be applied to uneven walls with gaps up to 4mm</li><li>Can be removed without damaging the wall</li><li>Odorless due to water based printing technique</li><li>Fire retardant (current classification: C-s1,d1)</li></ul><h2 id="My-work-for-this-project"><a href="#My-work-for-this-project" class="headerlink" title="My work for this project"></a>My work for this project</h2><p>For this project I was asked to participate by dQconcepts B.V., with whom I’ve worked in the past on <a href="/work/mixblocks/" title="Mixblocks - Musical building blocks on the iPhone">Mixblocks - Musical building blocks on the iPhone</a> and <a href="/work/sam-recycled-bird-feeder/" title="SAM: 100% recycled bird feeder">SAM: 100% recycled bird feeder</a>. dQconcepts shared the idea for this project and together we’ve solved the main puzzle: finding the right combination of materials to create an end product that:</p><ul><li>has all the right properties (as listed above)</li><li>complies with rules and regulations (EN 15102)</li><li>can be mass produced</li><li>can be printed using commonly available machinery in the market today</li><li>can be applied by a single person</li><li>can be sold at a competitive price</li></ul><p>As you can imagine, this makes the project considerably more difficult than just buying off-the-shelf materials. Unfortunately I cannot share any technical details about how we have managed to solve this puzzle due to the competitive position of the product.</p><h2 id="Patented-Technology"><a href="#Patented-Technology" class="headerlink" title="Patented Technology"></a>Patented Technology</h2><p>Parallel to the sourcing the materials and exploring methods to produce the wall covering, dQconcepts B.V. has started a patent application and the product has been patented in multiple geographic regions, including the European Union and USA.</p><h2 id="Probo-MultiTexPro-174"><a href="#Probo-MultiTexPro-174" class="headerlink" title="Probo MultiTexPro&#174;"></a>Probo MultiTexPro&#174;</h2><p>This project is patented innovative material, but we do not intend to start a printing business. The first licensed vendor and producer of the base material is Dutch company Probo B.V. They sell the Multifunctional Wall Covering to their resellers under the name <a href="https://www.probo.nl/multitexpro">MultiTexPro&#174;</a>. Check out their website if you’re interested!</p><h2 id="My-responsibilities"><a href="#My-responsibilities" class="headerlink" title="My responsibilities"></a>My responsibilities</h2><ul><li><strong>Product development</strong>: from first test to final material</li><li><strong>Prototyping</strong>: from manufacturing material by hand to initial testing on existing production machines</li><li><strong>Product strategy</strong>: continuous involvement</li></ul><hr><h5 id="More-information"><a href="#More-information" class="headerlink" title="More information"></a>More information</h5><ul><li><a href="https://www.probo.nl/multitexpro">MultiTexPro website by Probo</a></li></ul><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: all images by <a href="https://www.probo.nl/">Probo</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//work/">work</category>
      
      
      <category domain="https://www.stefan.lu/tag/product-development/">product development</category>
      
      <category domain="https://www.stefan.lu/tag/product-management/">product management</category>
      
      <category domain="https://www.stefan.lu/tag/innovation/">innovation</category>
      
      
      <comments>https://www.stefan.lu/work/multifunctional-wall-covering/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>ESMEE: a peanut butter bird feeder made from recycled beverage containers</title>
      <link>https://www.stefan.lu/work/singing-friend-esmee/</link>
      <guid>https://www.stefan.lu/work/singing-friend-esmee/</guid>
      <pubDate>Mon, 16 Nov 2020 23:00:00 GMT</pubDate>
      
      <description>A writeup about the development process of the ESMEE birdfeeder for Singing Friend, a bird feeder made from recycled plastic waste</description>
      
      
      <enclosure url="https://www.stefan.lu/header-sf-esmee.jpg" type="image"/>
      
      
      <content:encoded><![CDATA[<p>In 2018 and 2019 I’ve been involved with the development of the <a href="/work/sam-recycled-bird-feeder/" title="SAM bird feeder">SAM bird feeder</a> and the <a href="/work/singing-friend-bird-feeders-2019/" title="ANNA bird feeder">ANNA bird feeder</a>. To complete the line of bird feeders for <a href="https://www.singingfriend.com/">Singing Friend</a>, the next challenge was to design a peanut butter bird feeder using the same recycled material.</p><a id="more"></a><h2 id="The-result"><a href="#The-result" class="headerlink" title="The result"></a>The result</h2><p>Let’s start with some pictures of the end result:</p><p><img src="01.jpg" alt="Singing Friend ESMEE bird feeder"></p><p><img src="02.jpg" alt="Singing Friend ESMEE bird feeder in use"></p><p><img src="03.jpg" alt="Singing Friend ESMEE bird feeder packaging"></p><h2 id="The-challenges"><a href="#The-challenges" class="headerlink" title="The challenges"></a>The challenges</h2><p>The design process proved to be a lot more difficult than the previous bird feeders we’ve done together with Singing Friend, particularly because the size and weight of the peanut butter jars that are inserted into the feeder. <a href="https://www.studio-oso.nl/">Studio OSO</a> managed to design it in such a way that it retains the signature visual style of the <a href="/work/sam-recycled-bird-feeder/" title="SAM">SAM</a> and <a href="/work/singing-friend-bird-feeders-2019/" title="ANNA">ANNA</a> feeders while keeping material usage to a minimum.</p><h2 id="The-development-process"><a href="#The-development-process" class="headerlink" title="The development process"></a>The development process</h2><p>If you’re interested in the technical side of these projects, I would suggest having a look at my previous post about the SAM, in which I’ve provided more in-depth information about the recycled material and the product development process. You can find it here: <a href="/work/sam-recycled-bird-feeder/" title="SAM: 100% recycled bird feeder">SAM: 100% recycled bird feeder</a>.</p><h2 id="Featured-in-the-WWF-webshop"><a href="#Featured-in-the-WWF-webshop" class="headerlink" title="Featured in the WWF webshop!"></a>Featured in the WWF webshop!</h2><p><img src="04.jpg" alt="Singing Friend ESMEE bird feeder in WWF webshop"></p><p>The customer, <a href="https://www.singingfriend.com/">SingingFriend</a>, has put a lot of effort into making their product offering more sustainable. As a result, all the recycled bird feeders are actively endorsed by the WWF as a sustainable choice! You can check out the products here: </p><ul><li><a href="https://www.wwf.nl/webshop/duurzaam/gerecycled-materiaal/esmee-pindakaaspothouder">https://www.wwf.nl/webshop/duurzaam/gerecycled-materiaal/esmee-pindakaaspothouder</a></li><li><a href="https://www.wwf.nl/webshop/duurzaam/gerecycled-materiaal/sam-vetbolhouder">https://www.wwf.nl/webshop/duurzaam/gerecycled-materiaal/sam-vetbolhouder</a></li></ul><h2 id="My-responsibilities"><a href="#My-responsibilities" class="headerlink" title="My responsibilities"></a>My responsibilities</h2><ul><li><strong>Product strategy</strong>: as founder of Shapeforce</li><li><strong>Product development</strong>: as a member of the development team</li></ul><hr><h5 id="More-information"><a href="#More-information" class="headerlink" title="More information"></a>More information</h5><ul><li><a href="https://www.singingfriend.com/">SingingFriend</a></li><li><a href="/work/singing-friend-bird-feeders-2019/" title="Singing Friend 100% recycled bird feeders (2019)">Singing Friend 100% recycled bird feeders (2019)</a></li><li><a href="/work/sam-recycled-bird-feeder/" title="SAM: 100% recycled bird feeder">SAM: 100% recycled bird feeder</a></li></ul><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: all images by <a href="https://www.singingfriend.com/">Singing Friend</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//work/">work</category>
      
      
      <category domain="https://www.stefan.lu/tag/product-development/">product development</category>
      
      <category domain="https://www.stefan.lu/tag/product-management/">product management</category>
      
      <category domain="https://www.stefan.lu/tag/innovation/">innovation</category>
      
      <category domain="https://www.stefan.lu/tag/recycling/">recycling</category>
      
      <category domain="https://www.stefan.lu/tag/sustainability/">sustainability</category>
      
      
      <comments>https://www.stefan.lu/work/singing-friend-esmee/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Automatically create Hexo asset folders for existing posts</title>
      <link>https://www.stefan.lu/blog/auto-create-hexo-asset-folders-existing-posts/</link>
      <guid>https://www.stefan.lu/blog/auto-create-hexo-asset-folders-existing-posts/</guid>
      <pubDate>Mon, 19 Oct 2020 22:00:00 GMT</pubDate>
      
      <description>Script to automatically create asset folders for existing posts in Hexo static site generator</description>
      
      
      
      <content:encoded><![CDATA[<p>Hexo supports <a href="https://hexo.io/docs/asset-folders">Asset Folders</a> to neatly store assets for posts in a corresponding folder. When converting my blog from Jekyll to Hexo, I had to create a ton of asset folders and have written a little script for it.  In this post I’ll share it for anybody to save some time figuring this out.</p><a id="more"></a><h2 id="The-solution"><a href="#The-solution" class="headerlink" title="The solution"></a>The solution</h2><p>If you have existing posts in Markdown, this script should work right away:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">mkdir</span> <span class="token variable"><span class="token variable">$(</span><span class="token function">basename</span> -a -s .md ./*.md<span class="token variable">)</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>If your files have a different extension, change .md to match the extension you’re using and it should work.</p>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/code/">code</category>
      
      <category domain="https://www.stefan.lu/tag/web-development/">web development</category>
      
      <category domain="https://www.stefan.lu/tag/hexo/">hexo</category>
      
      
      <comments>https://www.stefan.lu/blog/auto-create-hexo-asset-folders-existing-posts/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>List category posts without pagination in Hexo</title>
      <link>https://www.stefan.lu/blog/hexo-list-posts-without-pagination/</link>
      <guid>https://www.stefan.lu/blog/hexo-list-posts-without-pagination/</guid>
      <pubDate>Sun, 18 Oct 2020 22:00:00 GMT</pubDate>
      
      <description>Short description to disable pagination for a single page in Hexo static site generator</description>
      
      
      
      <content:encoded><![CDATA[<p>When converting my blog from Jekyll to Hexo, I ran into a practical issue. I wanted a list of posts on a page for my <a href="/work">Work</a> page, but Hexo applies pagination by default. It took me a while to find out to solve this, so hopefully this post will save you some time.</p><a id="more"></a><h2 id="The-solution"><a href="#The-solution" class="headerlink" title="The solution"></a>The solution</h2><p>After playing around with the Hexo API, I found this solution to get all posts from a category, in this case the page category:</p><pre class="line-numbers language-ejs" data-language="ejs"><code class="language-ejs"><span class="token ejs language-ejs"><span class="token delimiter punctuation">&lt;%</span><span class="token comment"># template.ejs </span><span class="token delimiter punctuation">%></span></span><span class="token ejs language-ejs"><span class="token delimiter punctuation">&lt;%</span><span class="token language-javascript">     <span class="token keyword">var</span> posts <span class="token operator">=</span> site<span class="token punctuation">.</span>categories<span class="token punctuation">.</span>data<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span>        <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">category</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> <span class="token keyword">return</span> category<span class="token punctuation">.</span>name <span class="token operator">===</span> page<span class="token punctuation">.</span>category <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>        <span class="token punctuation">.</span>posts<span class="token punctuation">.</span><span class="token function">sort</span><span class="token punctuation">(</span><span class="token string">'date'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">reverse</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span><span class="token delimiter punctuation">%></span></span><span class="token ejs language-ejs"><span class="token delimiter punctuation">&lt;%</span><span class="token comment"># and then somewhere else in the template.. </span><span class="token delimiter punctuation">%></span></span><span class="token ejs language-ejs"><span class="token delimiter punctuation">&lt;%</span><span class="token language-javascript"> posts<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">post</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> </span><span class="token delimiter punctuation">%></span></span>    <span class="token ejs language-ejs"><span class="token delimiter punctuation">&lt;%</span><span class="token comment"># your post here </span><span class="token delimiter punctuation">%></span></span><span class="token ejs language-ejs"><span class="token delimiter punctuation">&lt;%</span><span class="token language-javascript"> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span> </span><span class="token delimiter punctuation">%></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/code/">code</category>
      
      <category domain="https://www.stefan.lu/tag/web-development/">web development</category>
      
      <category domain="https://www.stefan.lu/tag/hexo/">hexo</category>
      
      
      <comments>https://www.stefan.lu/blog/hexo-list-posts-without-pagination/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>How to create a custom homepage in Hexo</title>
      <link>https://www.stefan.lu/blog/create-custom-homepage-in-hexo/</link>
      <guid>https://www.stefan.lu/blog/create-custom-homepage-in-hexo/</guid>
      <pubDate>Sat, 17 Oct 2020 22:00:00 GMT</pubDate>
      
      <description>Show writeup about creating a custom homepage in the Hexo static site generator</description>
      
      
      
      <content:encoded><![CDATA[<p>When converting my blog from Jekyll to Hexo, Hexo ignored my custom homepage. It took me a while to find out to solve this, so hopefully this post will save you some time.</p><a id="more"></a><h2 id="The-solution"><a href="#The-solution" class="headerlink" title="The solution"></a>The solution</h2><p>By default, Hexo ignores a custom homepage if you place it in <code>/source/index.md</code>. By default, you can add a page as a partial but that’s not a very elegant way to solve the issue.</p><p>If you’re using Hexo 3 like I do, you can solve this by removing the hexo-generator-index package. By default this package creates an archive of posts as a home page, but that’s not what we want. It can be removed by running:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> remove hexo-generator-index<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>You can now put your index page in <code>/source/index.md</code>.</p><p>Don’t forget to set the layout in the front matter:</p><pre class="line-numbers language-md" data-language="md"><code class="language-md"><span class="token hr punctuation">---</span>layout: pagetitle: homepage<span class="token title important">date: 2020-10-17<span class="token punctuation">---</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><hr><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li><a href="https://github.com/hexojs/hexo/issues/1077">How to make a custom homepage in hexo 3 - GitHub</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/code/">code</category>
      
      <category domain="https://www.stefan.lu/tag/web-development/">web development</category>
      
      <category domain="https://www.stefan.lu/tag/hexo/">hexo</category>
      
      
      <comments>https://www.stefan.lu/blog/create-custom-homepage-in-hexo/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Migrating from Jekyll to Hexo</title>
      <link>https://www.stefan.lu/blog/migrating-from-jekyll-to-hexo/</link>
      <guid>https://www.stefan.lu/blog/migrating-from-jekyll-to-hexo/</guid>
      <pubDate>Fri, 16 Oct 2020 22:00:00 GMT</pubDate>
      
      <description>A writeup about the steps needed to convert a Jekyll powered static website to Hexo</description>
      
      
      
      <content:encoded><![CDATA[<p>I’ve been running my personal website for about 3 years now and am very happy running a static site generator. I’ve picked <a href="https://jekyllrb.com/">Jekyll</a> in the past because it was the most viable option at the time. Today, static site generators are more popular and I’ve decided to switch to <a href="https://hexo.io/">Hexo</a>.</p><p>In this post I will summarize the steps taken to convert the Jekyll codebase to Hexo.</p><a id="more"></a><h2 id="Why-I-moved-from-Jekyll-to-Hexo"><a href="#Why-I-moved-from-Jekyll-to-Hexo" class="headerlink" title="Why I moved from Jekyll to Hexo"></a>Why I moved from Jekyll to Hexo</h2><p>I don’t want to take too much of your time with this. Basically I’m way more comfortable with Javascript than I am with Ruby. Hexo is written in Javascript, so it feels more natural to me than Jekyll (which is written in Ruby). </p><p>From all the Javascript based options available, Hexo has everything I need included in the default package so I don’t need to modify too much, depend on plugins or use very powerful frameworks for a simple blog (yes <a href="https://www.gatsbyjs.com/">Gatsby</a>, that’s you).</p><h2 id="Step-1-Create-Hexo-project-from-scratch"><a href="#Step-1-Create-Hexo-project-from-scratch" class="headerlink" title="Step 1: Create Hexo project from scratch"></a>Step 1: Create Hexo project from scratch</h2><p><strong>Prerequisites</strong><br>For this post I’m assuming you have <code>Node.js</code> and <code>npm</code> installed already.</p><p>Now open a shell where you want to create your new Hexo project and follow along:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token comment"># Install the Hexo CLI</span><span class="token function">npm</span> <span class="token function">install</span> -g hexo-cli<span class="token comment"># Initate a new Hexo project in the ./hexo-site folder</span>hexo init hexo-site<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre><p>After this, open the <code>hexo-site</code> folder in your favourite editor.</p><h2 id="Step-2-Basic-configuration"><a href="#Step-2-Basic-configuration" class="headerlink" title="Step 2: Basic configuration"></a>Step 2: Basic configuration</h2><p>I found I had to modify these settings to match the settings of my Jekyll setup. The <code>post_asset_folder</code> setting helps to organise post images etc., which I found was missing in Jekyll.</p><p>Edit <code>_config.yml</code> and have a look at your general settings, paying attention to the specific settings below to closely mimic Jekyll:</p><pre class="line-numbers language-yaml" data-language="yaml"><code class="language-yaml"><span class="token key atrule">permalink</span><span class="token punctuation">:</span> <span class="token punctuation">:</span>category/<span class="token punctuation">:</span>title/<span class="token key atrule">new_post_name</span><span class="token punctuation">:</span> <span class="token punctuation">:</span>year/<span class="token punctuation">:</span>year<span class="token punctuation">-</span><span class="token punctuation">:</span>month<span class="token punctuation">-</span><span class="token punctuation">:</span>day<span class="token punctuation">-</span><span class="token punctuation">:</span>title.md<span class="token key atrule">pretty_urls</span><span class="token punctuation">:</span>  <span class="token key atrule">trailing_index</span><span class="token punctuation">:</span> <span class="token boolean important">false</span> <span class="token comment"># Set to false to remove trailing 'index.html' from permalinks</span>  <span class="token key atrule">trailing_html</span><span class="token punctuation">:</span> <span class="token boolean important">false</span> <span class="token comment"># Set to false to remove trailing '.html' from permalinks</span><span class="token key atrule">post_asset_folder</span><span class="token punctuation">:</span> <span class="token boolean important">true</span> <span class="token comment"># optional</span><span class="token key atrule">pagination_dir</span><span class="token punctuation">:</span> .<span class="token key atrule">category_dir</span><span class="token punctuation">:</span> /<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h2 id="Step-3-Move-posts-to-Hexo"><a href="#Step-3-Move-posts-to-Hexo" class="headerlink" title="Step 3: Move posts to Hexo"></a>Step 3: Move posts to Hexo</h2><p>This step is straighforward, just move the <code>/_posts</code> folder in Jekyll to <code>/source/_posts</code> in the Hexo folder.</p><p>If you have enabled the optional <code>post_asset_folder</code> setting in the config file, Hexo expects each post file to be accompanied by a folder that matches the filename (e.g. post <code>/_posts/my-first-post.md</code> has matching folder <code>/_posts/my-first-post/</code>.</p><p>To create the matching folders automatically, have a look at my separate post here: <a href="/blog/auto-create-hexo-asset-folders-existing-posts/" title="Automatically create Hexo asset folders for existing posts">Automatically create Hexo asset folders for existing posts</a></p><h2 id="Step-4-Posts-conversion"><a href="#Step-4-Posts-conversion" class="headerlink" title="Step 4: Posts conversion"></a>Step 4: Posts conversion</h2><p>You can try to run the command <code>hexo server</code> now. If you’re migrating from a ver simple Jekyll setup, it might actually work. In my case however, I had to convert a number of posts to be compatible with Hexo. This was mostly because I’ve used Liquid template tags like <code>&#123;% highlight %&#125;</code> or <code>&#123;% include %&#125;</code> in my posts. Liquid does not work in Hexo by default.</p><p>For the conversion, almost all problems could easily be resolved by using the correct <a href="https://hexo.io/docs/helpers">Hexo Helper</a> for the problem. Once I discovered this, the conversion went pretty smooth and I only had to write 1 <a href="https://hexo.io/api/helper">custom Hexo Helper</a> to get my posts.</p><h2 id="Step-5-Template-conversion"><a href="#Step-5-Template-conversion" class="headerlink" title="Step 5: Template conversion"></a>Step 5: Template conversion</h2><p>At this point, your posts should work but the output from <code>hexo server</code> probably doesn’t look like your previous blog at all. That’s because the Jekyll templates have to be migrated and converted.</p><p>Create a new folder in the <code>/themes</code> folder with a name of your choice. I would recommend to have a look at the default template that’s in the folder and try to match the default template structure at first. The default Hexo folder structure allows you to neatly organise your files and it’s one of the things I like about Hexo.</p><p>Hexo uses <a href="https://ejs.co/">EJS templates</a> for its templates by default. This isn’t what Jekyll uses, so they need to be converted.</p><p>I can’t really help you here, but studying the default template in the <code>/themes</code> folder and basic EJS knowledge was enough for me to get this done.</p><p>By default Hexo comes with a few settings I didn’t really like. I’ve created separate posts for this, I’ve listed them below at the end of this post.</p><h2 id="Step-6-Moving-styles-to-Hexo"><a href="#Step-6-Moving-styles-to-Hexo" class="headerlink" title="Step 6: Moving styles to Hexo"></a>Step 6: Moving styles to Hexo</h2><p>For this I’m assuming you’re using Sass SCSS for your styles.</p><p>Move your styles to <code>/themes/[your-theme]/source/_scss/</code></p><p>Next, make sure you have the Hexo SCSS renderer installed. If not, run:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> --save hexo-renderer-scss<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>This should generate the styles for you in the <code>public/css</code> folder when rendering with the <code>hexo generate</code> command.</p><p>You can reference the CSS files in your templates like this using the <a href="https://hexo.io/docs/helpers#css">CSS Helper function</a>:</p><pre class="line-numbers language-ejs" data-language="ejs"><code class="language-ejs"><span class="token ejs language-ejs"><span class="token delimiter punctuation">&lt;%-</span><span class="token language-javascript"> <span class="token function">css</span><span class="token punctuation">(</span><span class="token string">'css/style'</span><span class="token punctuation">)</span> </span><span class="token delimiter punctuation">%></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><h2 id="Step-7-Moving-scripts-to-Hexo"><a href="#Step-7-Moving-scripts-to-Hexo" class="headerlink" title="Step 7: Moving scripts to Hexo"></a>Step 7: Moving scripts to Hexo</h2><p>This step is pretty straightforward. Move your JavaScript files to <code>/themes/[your-theme]/source/js</code> and they will be rendered to <code>/public/js</code>. You can use the <a href="https://hexo.io/docs/helpers#js">JS Helper function</a> to reference the JavaScripts in your templates:</p><pre class="line-numbers language-ejs" data-language="ejs"><code class="language-ejs"><span class="token ejs language-ejs"><span class="token delimiter punctuation">&lt;%-</span><span class="token language-javascript"> <span class="token function">js</span><span class="token punctuation">(</span><span class="token string">'js/script.js'</span><span class="token punctuation">)</span> </span><span class="token delimiter punctuation">%></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><h2 id="Step-8-Moving-assets-to-Hexo"><a href="#Step-8-Moving-assets-to-Hexo" class="headerlink" title="Step 8: Moving assets to Hexo"></a>Step 8: Moving assets to Hexo</h2><p>Any folder created in the <code>/source</code> directory that is not prefixed with an underscore (_) character, gets copied to the <code>/public</code> folder when rendering. So your <code>favicon.ico</code> file can be put directly inside the <code>/source</code> folder. You can also create subfolders to organise your assets a bit more (recommended).</p><p>As for post assets (e.g. images) that get referenced in the posts, you can either create a separate folder or use the <code>post_assets_folder</code> option mentioned in Step 2. If you’ve configure the post assets folder, put all post assets in their corresponding folders in the <code>/source/_posts</code> folder.</p><h2 id="Further-reading"><a href="#Further-reading" class="headerlink" title="Further reading"></a>Further reading</h2><p>You should now have a fully functional Hexo blog. To keep this post simple and readable, I haven’t covered the more advanced topics yet.</p><p>I will write additional posts on more advanced topics in the near future and will directly link them here for your convenience.</p><p><em>Template Customization</em></p><ul><li><a href="/blog/auto-create-hexo-asset-folders-existing-posts/" title="Automatically create Hexo asset folders for existing posts">Automatically create Hexo asset folders for existing posts</a></li><li><a href="/blog/create-custom-homepage-in-hexo/" title="How to create a custom homepage in Hexo">How to create a custom homepage in Hexo</a></li><li><a href="/blog/hexo-list-posts-without-pagination/" title="List category posts without pagination in Hexo">List category posts without pagination in Hexo</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/software-development/">software development</category>
      
      <category domain="https://www.stefan.lu/tag/code/">code</category>
      
      <category domain="https://www.stefan.lu/tag/web-development/">web development</category>
      
      <category domain="https://www.stefan.lu/tag/jekyll/">jekyll</category>
      
      <category domain="https://www.stefan.lu/tag/hexo/">hexo</category>
      
      
      <comments>https://www.stefan.lu/blog/migrating-from-jekyll-to-hexo/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Running Craft CMS in a Docker container on Microsoft Azure</title>
      <link>https://www.stefan.lu/blog/running-craft-cms-in-docker-on-microsoft-azure/</link>
      <guid>https://www.stefan.lu/blog/running-craft-cms-in-docker-on-microsoft-azure/</guid>
      <pubDate>Fri, 07 Aug 2020 22:00:00 GMT</pubDate>
      
      <description>A quick writeup about the problems encountered when running Craft CMS using Docker Compose on Microsoft Azure</description>
      
      
      
      <content:encoded><![CDATA[<p>For the deployment of the <a href="/work/tiq-marketing-2020/" title="TIQ marketing website 2020 redesign">TIQ marketing website 2020 redesign</a> we decided to Dockerize the application and run in on Azure. I couldn’t find a lot about this setup on the Internet, so I’ve put in the time to figure it out. Hopefully it can save you some time.</p><a id="more"></a><h2 id="Docker-Compose-on-Azure"><a href="#Docker-Compose-on-Azure" class="headerlink" title="Docker Compose on Azure"></a>Docker Compose on Azure</h2><p>Since Docker Compose is in “Public Preview Azure, it’s a bit more difficult to assert whether you’ve made a mistake or ran into a limitation of the Preview. You can read more about the <a href="https://docs.microsoft.com/en-us/azure/app-service/configure-custom-container#preview-limitations">limitation of the Preview</a> before going down this road. Pay special attention to the fine print on this page: </p><blockquote><p>“Any other options not explicitly called out are ignored in Public Preview”</p></blockquote><p>Consider yourself warned.</p><p>Although Microsoft <a href="https://docs.microsoft.com/en-us/azure/app-service/quickstart-multi-container">starts with the S1 App Service Plan for Wordpress</a>, the memory consumption was a bit too high for my taste (usually 40-50% on an inactive state). I can recommend using the P1V2 instance for Craft CMS, which offers twice the RAM in the same price range.</p><h2 id="Building-a-good-image"><a href="#Building-a-good-image" class="headerlink" title="Building a good image"></a>Building a good image</h2><p>I can recommend having a look at the <a href="https://github.com/urbantrout/craftcms">urbantrout/craftcms image</a>. What I like about it, is the clean separation of services. I’ve learned a lot from this Docker image, but finally decided to build my own due to custom needs. </p><p><strong>Note</strong>: the sample Docker Compose configuration will not work out of the box on Azure, because it uses the  volumes_from option which is unsupported in the Azure Public Preview. See “Issue #2” below for a workaround.</p><h2 id="Database-options"><a href="#Database-options" class="headerlink" title="Database options"></a>Database options</h2><p>For running a database, there are two options:</p><ol><li>Run the database in a container</li><li>Use a separate SQL database to connect with</li></ol><p>It’s usually <a href="https://vsupalov.com/database-in-docker/">not recommended</a> to run a database in a container for production environments.</p><h2 id="A-solution-for-automated-backups"><a href="#A-solution-for-automated-backups" class="headerlink" title="A solution for automated backups"></a>A solution for automated backups</h2><p>However you set up your database, it’s always a good plan to have a backup. I also wanted to keep a backup of all the assets that get uploaded using the Control Panel.</p><p>Azure allows you to mount a File Share on a Docker container (Settings &gt; Configuration &gt; Path Mappings). </p><p>For example, if your volume is named craft_backups:</p><pre class="line-numbers language-yaml" data-language="yaml"><code class="language-yaml"><span class="token comment"># docker-compose.yml</span><span class="token comment"># ...</span>    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>      <span class="token punctuation">-</span> craft_backups<span class="token punctuation">:</span>/backups    <span class="token key atrule">environment</span><span class="token punctuation">:</span>      <span class="token punctuation">-</span> <span class="token key atrule">BACKUP_INTERVAL</span><span class="token punctuation">:</span> <span class="token number">21600</span> <span class="token comment"># in seconds</span><span class="token comment"># ...</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>Now the File Share contents are available under the /backups path, you can use them for making backups. After spending some time trying out both, I’ve settled with some simple backup/restore shell scripts.</p><p>Call these scripts when starting your container:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token comment"># /scripts/startup.sh</span><span class="token function-name function">restore</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    /scripts/restore.sh<span class="token punctuation">&#125;</span><span class="token function-name function">backup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token keyword">while</span> <span class="token boolean">true</span>    <span class="token keyword">do</span>         <span class="token function">sleep</span> <span class="token variable">$BACKUP_INTERVAL</span>        /scripts/backup.sh <span class="token operator">&amp;</span>    <span class="token keyword">done</span><span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>The backup script, called every xx seconds (as set in the BACKUP_INTERVAL environment variable):</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token comment"># /scripts/backup.sh</span><span class="token comment">#!/bin/bash</span><span class="token assign-left variable">webroot</span><span class="token operator">=</span><span class="token string">'/var/www/html'</span><span class="token comment"># Periodic backup of database + assets to /backups</span><span class="token variable">$webroot</span>/craft backup/db <span class="token punctuation">\</span><span class="token operator">&amp;&amp;</span> <span class="token function">cp</span> -r <span class="token variable">$webroot</span>/storage/backups/*.sql /backups/database <span class="token punctuation">\</span><span class="token operator">&amp;&amp;</span> <span class="token function">cp</span> -r <span class="token variable">$webroot</span>/web/YOUR_ASSETS /backups/assets<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>The restore script, called once during the container startup:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token comment"># /scripts/restore.sh</span><span class="token comment">#!/bin/bash</span><span class="token builtin class-name">set</span> -x -e<span class="token assign-left variable">webroot</span><span class="token operator">=</span><span class="token string">'/var/www/html'</span><span class="token assign-left variable">backup_dir</span><span class="token operator">=</span><span class="token string">"/var/www/html/storage/backups"</span><span class="token assign-left variable">backup_file</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token function">ls</span> /backups/database -t <span class="token operator">|</span> <span class="token function">grep</span> ^YOUR_CRAFT_SITE_NAME_.*<span class="token punctuation">\</span>.sql$ <span class="token operator">|</span> <span class="token function">head</span> -n <span class="token number">1</span><span class="token variable">)</span></span><span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token operator">!</span> -d <span class="token variable">$backup_dir</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">then</span>    <span class="token function">mkdir</span> -p <span class="token variable">$backup_dir</span><span class="token keyword">fi</span><span class="token function">cp</span> /backups/database/<span class="token variable">$backup_file</span> <span class="token variable">$backup_dir</span>/<span class="token variable">$backup_file</span><span class="token function">cp</span> -r /backups/assets/YOUR_ASSETS <span class="token variable">$webroot</span>/web<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h2 id="Issue-1-the-Azure-web-interface"><a href="#Issue-1-the-Azure-web-interface" class="headerlink" title="Issue #1: the Azure web interface"></a>Issue #1: the Azure web interface</h2><p>Uploading and updating the Docker Compose file from the Azure interface isn’t the best experience. Sometimes it’s slow or unresponsive. Increase your productivity by using the Azure CLI. I’ve created a shell script to make it easier to run frequently used Azure commands during development:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token comment"># azure.sh</span><span class="token comment">#!/usr/bin/env bash</span><span class="token builtin class-name">set</span> -x -e<span class="token keyword">case</span> <span class="token variable">$1</span> <span class="token keyword">in</span>    update<span class="token punctuation">)</span>        az webapp config container <span class="token builtin class-name">set</span> --resource-group RESOURCE_GROUP_NAME --name RESOURCE_NAME --multicontainer-config-type compose --multicontainer-config-file docker-compose.yml        <span class="token punctuation">;</span><span class="token punctuation">;</span>    <span class="token function">tail</span><span class="token punctuation">)</span>        az webapp log <span class="token function">tail</span> --resource-group RESOURCE_GROUP_NAME --name RESOURCE_NAME        <span class="token punctuation">;</span><span class="token punctuation">;</span>    start<span class="token punctuation">)</span>        az webapp start --resource-group RESOURCE_GROUP_NAME --name RESOURCE_NAME        <span class="token punctuation">;</span><span class="token punctuation">;</span>    stop<span class="token punctuation">)</span>        az webapp stop --resource-group RESOURCE_GROUP_NAME --name RESOURCE_NAME        <span class="token punctuation">;</span><span class="token punctuation">;</span>    *<span class="token punctuation">)</span>        <span class="token builtin class-name">echo</span> <span class="token string">"Please provide a command"</span>        <span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token keyword">esac</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h2 id="Issue-2-lack-of-volumes-from-support"><a href="#Issue-2-lack-of-volumes-from-support" class="headerlink" title="Issue #2: (lack of) volumes_from support"></a>Issue #2: (lack of) volumes_from support</h2><p>The Nginx container needs access to the static assets that reside in the webroot of the Craft CMS container. Instead of using the volumes_from option, this can also be achieved with a shared volume between the containers:</p><pre class="line-numbers language-yaml" data-language="yaml"><code class="language-yaml"><span class="token comment"># docker-compose.yml</span><span class="token key atrule">services</span><span class="token punctuation">:</span>  <span class="token key atrule">nginx</span><span class="token punctuation">:</span>    <span class="token key atrule">depends_on</span><span class="token punctuation">:</span>      <span class="token punctuation">-</span> craft    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>      <span class="token punctuation">-</span> web<span class="token punctuation">:</span>/var/www/html/web  <span class="token punctuation">...</span>  <span class="token key atrule">craft</span><span class="token punctuation">:</span>    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>      <span class="token punctuation">-</span> web<span class="token punctuation">:</span>/var/www/html/web  <span class="token punctuation">...</span><span class="token key atrule">volumes</span><span class="token punctuation">:</span>  web<span class="token punctuation">:</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>Hopefully this will speed up your time getting started with Docker Compose on Azure!</p><hr><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: <a href="https://www.sketchappsources.com/free-source/4480-security-icons-sketch-freebie-resource.html">24 Security Icons by Erdem Kirmitci</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/code/">code</category>
      
      <category domain="https://www.stefan.lu/tag/web-development/">web development</category>
      
      
      <comments>https://www.stefan.lu/blog/running-craft-cms-in-docker-on-microsoft-azure/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Using Webpack &amp; Vue.js with .NET Core in 2020</title>
      <link>https://www.stefan.lu/blog/using-webpack-with-net-core/</link>
      <guid>https://www.stefan.lu/blog/using-webpack-with-net-core/</guid>
      <pubDate>Mon, 06 Jul 2020 22:00:00 GMT</pubDate>
      
      <description>A detailed writeup about how to set up your .NET Core project to support Webpack and Vue.js after the deprecation of the Microsoft.AspNetCore.SpaServices package.</description>
      
      
      <enclosure url="https://www.stefan.lu/header-webpack-net-core.jpg" type="image"/>
      
      
      <content:encoded><![CDATA[<p>ASP.NET used to have a nice Webpack integration with the officially supported <code>Microsoft.AspNetCore.SpaServices</code> Nuget package. In August 2019 Microsoft announced that it would be deprecating this package and suggested a new integration mechanism with <code>Microsoft.AspNetCore.SpaServices.Extensions</code>.</p><p>Since I use this with Vue.js and the new integration mechanism doesn’t offer the same functionality, I’ll share how I managed to get up and running again in this post.</p><a id="more"></a><h2 id="The-problem-and-what-Microsoft-suggests"><a href="#The-problem-and-what-Microsoft-suggests" class="headerlink" title="The problem and what Microsoft suggests"></a>The problem and what Microsoft suggests</h2><p>In this announcement, Microsoft made the official statement:</p><p><a href="https://github.com/dotnet/aspnetcore/issues/12890">[Announcement] Obsoleting Microsoft.AspNetCore.SpaServices and Microsoft.AspNetCore.NodeServices</a></p><p>As you can see, there’s still an active discussion after a year, mainly because Microsoft suggests to migrate to a new integration mechanism that lacks a lot of functionality.</p><h2 id="A-working-solution"><a href="#A-working-solution" class="headerlink" title="A working solution"></a>A working solution</h2><p>Let me start by stating this isn’t the ideal solution, but it works (Hot Module Replacement too). </p><p>It consists of a few steps:</p><ol><li>Start the development server from Startup.cs</li><li>Add NPM scripts that get called by .NET Core</li><li>Update Webpack configuration with webpack-dev-server</li><li>Configure publishing &amp; production builds</li></ol><p>In the rest of the article I’m assuming you have a basic working setup and knowledge of the technologies we’re working with. I’ve replaced irrelevant code  with “…” to increate readability.</p><h2 id="1-Start-the-development-server-from-Startup-cs"><a href="#1-Start-the-development-server-from-Startup-cs" class="headerlink" title="1. Start the development server from Startup.cs"></a>1. Start the development server from Startup.cs</h2><p>This step is pretty straightforward. update <strong>Startup.cs</strong> to include this:</p><pre class="line-numbers language-csharp" data-language="csharp"><code class="language-csharp"><span class="token keyword">using</span> <span class="token namespace">Microsoft<span class="token punctuation">.</span>AspNetCore<span class="token punctuation">.</span>SpaServices<span class="token punctuation">.</span>ReactDevelopmentServer</span><span class="token punctuation">;</span><span class="token range operator">..</span><span class="token punctuation">.</span><span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Configure</span><span class="token punctuation">(</span><span class="token class-name">IApplicationBuilder</span> app<span class="token punctuation">,</span> <span class="token class-name">IHostingEnvironment</span> env<span class="token punctuation">,</span> <span class="token class-name">ILoggerFactory</span> loggerFactory<span class="token punctuation">)</span>        <span class="token punctuation">&#123;</span><span class="token range operator">..</span><span class="token punctuation">.</span>            <span class="token keyword">if</span> <span class="token punctuation">(</span>env<span class="token punctuation">.</span><span class="token function">IsDevelopment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>            <span class="token punctuation">&#123;</span>                <span class="token comment">// run webpack-dev-server for development builds using build:hotdev NPM script</span>                <span class="token comment">// NPM commands are defined in package.json</span>                app<span class="token punctuation">.</span><span class="token function">Map</span><span class="token punctuation">(</span><span class="token string">"/dist"</span><span class="token punctuation">,</span> innerApp <span class="token operator">=></span>                <span class="token punctuation">&#123;</span>                    innerApp<span class="token punctuation">.</span><span class="token function">UseSpa</span><span class="token punctuation">(</span>spa <span class="token operator">=></span>                    <span class="token punctuation">&#123;</span>                        spa<span class="token punctuation">.</span>Options<span class="token punctuation">.</span>SourcePath <span class="token operator">=</span> <span class="token string">"."</span><span class="token punctuation">;</span>                        spa<span class="token punctuation">.</span><span class="token function">UseReactDevelopmentServer</span><span class="token punctuation">(</span><span class="token named-parameter punctuation">npmScript</span><span class="token punctuation">:</span> <span class="token string">"build:hotdev"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>                    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>                <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token punctuation">&#125;</span><span class="token range operator">..</span><span class="token punctuation">.</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>What this code does, is call the NPM script <code>buid:hotdev</code>. If you’re using Vue.js, don’t worry about the React reference. It’s still just a piece of code that calls the NPM script.</p><h2 id="2-Add-NPM-scripts-that-get-called-by-NET-Core"><a href="#2-Add-NPM-scripts-that-get-called-by-NET-Core" class="headerlink" title="2. Add NPM scripts that get called by .NET Core"></a>2. Add NPM scripts that get called by .NET Core</h2><p>This should look familiar:</p><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token string">"scripts"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>  <span class="token comment">// ...</span>  <span class="token string">"build:hotdev"</span><span class="token operator">:</span> <span class="token string">"npx webpack-dev-server --open --hot --mode development"</span><span class="token punctuation">,</span>  <span class="token string">"build:live"</span><span class="token operator">:</span> <span class="token string">"npx webpack --display-error-details --mode production --env.prod"</span>  <span class="token comment">// ...</span><span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h2 id="3-Update-Webpack-configuration-with-webpack-dev-server"><a href="#3-Update-Webpack-configuration-with-webpack-dev-server" class="headerlink" title="3. Update Webpack configuration with webpack-dev-server"></a>3. Update Webpack configuration with webpack-dev-server</h2><p>Install the dependencies:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> --save-dev webpack-dev-server html-webpack-plugin html-webpack-harddisk-plugin<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>And update your Webpack configuration to look something like this:</p><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// webpack.config.js</span><span class="token comment">// ...</span><span class="token keyword">const</span> HtmlWebpackPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'html-webpack-plugin'</span><span class="token punctuation">)</span><span class="token keyword">var</span> HtmlWebpackHarddiskPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'html-webpack-harddisk-plugin'</span><span class="token punctuation">)</span>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">env</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    <span class="token keyword">const</span> isDevBuild <span class="token operator">=</span> <span class="token operator">!</span><span class="token punctuation">(</span>env <span class="token operator">&amp;&amp;</span> env<span class="token punctuation">.</span>prod<span class="token punctuation">)</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span>isDevBuild<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token comment">// don't remove - next line tricks Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer into executing</span>        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Starting the development server...\n'</span><span class="token punctuation">)</span>    <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Running production build...\n'</span><span class="token punctuation">)</span>    <span class="token punctuation">&#125;</span>    <span class="token comment">// ...</span>    <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span>        <span class="token comment">// ...</span>        devServer<span class="token operator">:</span> <span class="token punctuation">&#123;</span>            contentBase<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'./wwwroot/dist'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>            compress<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>            overlay<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>            port<span class="token operator">:</span> <span class="token number">5001</span><span class="token punctuation">,</span>            proxy<span class="token operator">:</span> <span class="token punctuation">&#123;</span>                <span class="token string">'/'</span><span class="token operator">:</span> <span class="token string">'http://localhost:5000'</span>            <span class="token punctuation">&#125;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>        <span class="token comment">// ...</span>        plugins<span class="token operator">:</span> <span class="token punctuation">[</span>            <span class="token comment">// ...</span>            <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>                inject<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>                template<span class="token operator">:</span> <span class="token string">'Views/_HtmlWebpackTemplate.cshtml'</span><span class="token punctuation">,</span>                filename<span class="token operator">:</span> <span class="token string">'../../Views/Home/Index.cshtml'</span><span class="token punctuation">,</span>                alwaysWriteToDisk<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>                minify<span class="token operator">:</span> <span class="token boolean">false</span>            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>            <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackHarddiskPlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>                <span class="token comment">// Enhances html-webpack-plugin functionality by adding the &#123;alwaysWriteToDisk: true|false&#125; option.</span>                outputPath<span class="token operator">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'wwwroot/dist/'</span><span class="token punctuation">)</span>            <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>        <span class="token punctuation">]</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">]</span><span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p><strong>Important</strong>: pay close attention to <code>console.log(&#39;Starting the development server...\n&#39;)</code>. This is the main hack that makes this method work (<a href="https://github.com/dotnet/aspnetcore/issues/12890#issuecomment-575197453">source</a>).</p><p>This code starts <code>webpack-dev-server</code> on <code>port 5001</code>. If you’re not using the default port (5000), please update this section. It also makes sure your cshtml templates get updated with the assets injected by the development server. </p><p>To make sure the cached result gets updated and recognised by .NET Core,<code>html-webpack-harddisk-plugin</code> is used. The exact configuration of the templates is out of the scope of this writeup, but feel free to get in touch if you need help!</p><h2 id="4-Configure-publishing-amp-production-builds"><a href="#4-Configure-publishing-amp-production-builds" class="headerlink" title="4. Configure publishing &amp; production builds"></a>4. Configure publishing &amp; production builds</h2><p><code>webpack-dev-server</code> is nice for development, but what about production builds? The .csproj file needs to be modified for this.</p><p>YourProject.csproj:</p><pre class="line-numbers language-xml" data-language="xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Target</span> <span class="token attr-name">Name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>PublishRunWebpack<span class="token punctuation">"</span></span> <span class="token attr-name">AfterTargets</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ComputeFilesToPublish<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>    <span class="token comment">&lt;!-- As part of publishing, ensure the JS resources are freshly built in production mode --></span><pre><code>&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Exec&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;Command&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;npm install&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Exec&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;Command&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;npm run build:live&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Include the newly-built files in the publish output --&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ItemGroup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;DistFiles&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;Include&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;wwwroot\dist\**&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ResolvedFileToPublish&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;Include&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;@(DistFiles-&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;%(FullPath)&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;Exclude&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;@(ResolvedFileToPublish)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;RelativePath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;%(DistFiles.Identity)&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;RelativePath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;CopyToPublishDirectory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;PreserveNewest&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;CopyToPublishDirectory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ResolvedFileToPublish&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ItemGroup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;</code></pre><p><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Target</span><span class="token punctuation">&gt;</span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>:hexoPostRenderEscape–&gt;</p><h2 id="Workaround-stopping-webpack-dev-server"><a href="#Workaround-stopping-webpack-dev-server" class="headerlink" title="Workaround: stopping webpack-dev-server"></a>Workaround: stopping webpack-dev-server</h2><p>Unfortunately, the <code>console.log()</code> hack in step 3. is a one-way process, meaning the webpack-dev-server will keep running until you close it manually. This means you can have conflicting servers running at the same time.</p><p>To resolve this, I’ve added a small script that gets run before the Build step. This is compatible with both Windows and Mac/Linux setups:</p><pre class="line-numbers language-xml" data-language="xml"><code class="language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Target</span> <span class="token attr-name">Name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>KillRunningNodeServer<span class="token punctuation">"</span></span> <span class="token attr-name">BeforeTargets</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Build<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Message</span> <span class="token attr-name">Importance</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>high<span class="token punctuation">"</span></span> <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Killing old Node server...<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Exec</span> <span class="token attr-name">Command</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>taskkill /f /im node.exe<span class="token punctuation">"</span></span> <span class="token attr-name">ContinueOnError</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">Condition</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">'</span>$(OS)<span class="token punctuation">'</span> == <span class="token punctuation">'</span>Windows_NT<span class="token punctuation">'</span><span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Exec</span> <span class="token attr-name">Command</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>killall node<span class="token punctuation">"</span></span> <span class="token attr-name">ContinueOnError</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span> <span class="token attr-name">Condition</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">'</span>$(OS)<span class="token punctuation">'</span> == <span class="token punctuation">'</span>Unix<span class="token punctuation">'</span><span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Target</span><span class="token punctuation">></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>Hopefull this will save you a couple of hours of puzzling and testing!</p><hr><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li><a href="https://github.com/dotnet/aspnetcore/issues/12890">[Announcement] Obsoleting Microsoft.AspNetCore.SpaServices and Microsoft.AspNetCore.NodeServices</a></li><li><a href="https://blog.bigdinosaur.org/embedding-images-in-css/">Embedding images in CSS</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/software-development/">software development</category>
      
      <category domain="https://www.stefan.lu/tag/code/">code</category>
      
      <category domain="https://www.stefan.lu/tag/web-development/">web development</category>
      
      
      <comments>https://www.stefan.lu/blog/using-webpack-with-net-core/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>How to extract vector images from an icon font</title>
      <link>https://www.stefan.lu/blog/extract-svg-icon-font/</link>
      <guid>https://www.stefan.lu/blog/extract-svg-icon-font/</guid>
      <pubDate>Mon, 15 Jun 2020 22:00:00 GMT</pubDate>
      
      <description>Writeup on how to extract images from icon fonts using CLI tools</description>
      
      
      <enclosure url="https://www.stefan.lu/header-extract-icon-font.jpg" type="image"/>
      
      
      <content:encoded><![CDATA[<p>At some point in time I found myself needing to extract a customer logo from a custom icon font. Since finding the solution required some homework, I’ll share the results here to save you some time in case you stumble upon this via a search engine.</p><a id="more"></a><h2 id="The-solution"><a href="#The-solution" class="headerlink" title="The solution"></a>The solution</h2><p>Turns out the open source font editor <a href="https://fontforge.org/en-US/">FontForge</a> is able to do exactly what we want (and more).</p><p>For this task it wasn’t my interest to learn how to use a new application, so I installed the command-line tool via Homebrew:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">brew <span class="token function">install</span> fontforge<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>Then, we can use FontForge to extract the glyphs from the font and save them as SVG images using the following command:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token comment"># e.g. for a font file named "font.ttf"</span>fontforge -lang<span class="token operator">=</span>ff -c <span class="token string">'Open(<span class="token variable">$1</span>); SelectWorthOutputting(); foreach Export("svg"); endloop;'</span> font.ttf <span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre><p><strong>Caution</strong>: this writes the images in the same directory as the font is located in, you might want to place it in a separate folder.</p><hr><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: <a href="https://www.sketchappsources.com/free-source/4480-security-icons-sketch-freebie-resource.html">24 Security Icons by Erdem Kirmitci</a></li><li><a href="https://fontforge.10959.n7.nabble.com/Saving-glyphs-as-SVG-files-via-command-line-td12726.html">Saving glyphs as SVG files via command line</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/code/">code</category>
      
      <category domain="https://www.stefan.lu/tag/web-development/">web development</category>
      
      
      <comments>https://www.stefan.lu/blog/extract-svg-icon-font/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>TIQ marketing website 2020 redesign</title>
      <link>https://www.stefan.lu/work/tiq-marketing-2020/</link>
      <guid>https://www.stefan.lu/work/tiq-marketing-2020/</guid>
      <pubDate>Tue, 05 May 2020 22:00:00 GMT</pubDate>
      
      <description>A writeup about the redesign of the TIQ marketing website in 2020.</description>
      
      
      <enclosure url="https://www.stefan.lu/header-tiq-marketing-2020.jpg" type="image"/>
      
      
      <content:encoded><![CDATA[<p>When TIQ started approximately 5 years ago, we had a very basic marketing website that grew over time. In 2017 we have done a big overhaul, but that’s already 3 years ago. But as the company grew, so did the requirements for the marketing website.</p><p>This post is a writeup about the goals, results and considerations that went into the redesign of the TIQ marketing website in 2020.</p><a id="more"></a><p><em>Note: this is the second writeup about the TIQ marketing website. In case you’re interested where we’re coming from, the previous version of the marketing website has been documented in <a href="/work/tiq-marketing/" title="my previous writeup">my previous writeup</a>.</em></p><h2 id="Goals-for-the-2020-redesign"><a href="#Goals-for-the-2020-redesign" class="headerlink" title="Goals for the 2020 redesign"></a>Goals for the 2020 redesign</h2><ul><li><strong>Implement a fresh graphic design</strong>: It’s been three years since we’ve visually upgraded the TIQ marketing website, but we’ve grown significantly as a company. A good opportunity to make sure our visual identity aligns with our current position in the market!</li><li><strong>Implement a Content Management System (CMS)</strong>: We’ve postponed using a CMS for as long as possible to keep the development fast and easy, but with frequent updates this approach no longer aligns with our marketing goals.</li><li><strong>Put all content under one roof</strong>: The blog and marketing website used to be separate locations during the startup op the company.</li><li><strong>Provide a place for premium content</strong>: Over the years we’ve gathered a lot knowledge and experience about time tracking and we offer a collection of premium content, such as whitepapers, e-books and case studies. They have grown to be the most important content we have to offer on our marketing website, so they needed a better place.</li></ul><h2 id="The-2020-graphic-design"><a href="#The-2020-graphic-design" class="headerlink" title="The 2020 graphic design"></a>The 2020 graphic design</h2><p><img src="01.jpg" alt="Homepage of the new TIQ marketing website"><br><em>The homepage of the new TIQ marketing website</em></p><p><img src="02.jpg" alt="Customer testimonials on the 2020 TIQ marketing website"><br><em>Customer testimonials have a prominent place on the homepage, right under the fold. It features a custom built slider in pure Javascript.</em></p><p><img src="03.jpg" alt="Custom features slider on the 2020 TIQ marketing website"><br><em>TIQ’s features are explained in a slideshow, again in a custom slider. All slides link to additional information to optimize clickthrough rates.</em></p><p><img src="05.jpg" alt="Blog article on the 2020 TIQ marketing website"><br><em>The blog has been integrated into the main website and the old posts have been migrated. It’s designed as a “reader view” with the focus on clean, readable typography suitable for longer texts.</em></p><p><img src="04.jpg" alt="Resources on the 2020 TIQ marketing website"><br><em>Downloadable resources are a big part of our marketing campaigns and have a clear location on the new website.</em></p><p><img src="06.jpg" alt="Resource download on the 2020 TIQ marketing website"><br><em>Download page for a selected resource.</em></p><p><img src="07.jpg" alt="Demo request form on the 2020 TIQ marketing website"><br><em>The redesigned demo request form.</em></p><h2 id="Craft-CMS-as-an-alternative-to-Wordpress"><a href="#Craft-CMS-as-an-alternative-to-Wordpress" class="headerlink" title="Craft CMS as an alternative to Wordpress"></a>Craft CMS as an alternative to Wordpress</h2><p>As I explained earlier, we decided to implement a CMS after 5 years. Now, I have plenty of experience with Wordpress and I’m not a fan. Wordpress has grown from a blog platform to a platform that does it all. But under the hood it’s still a blog platform first. In the past I usually ended up spending way too much time hacking Wordpress to get what I want. It was time to try something different.</p><p>After extensive searching, I stumbled upon Craft CMS. This offers exactly what I couldn’t get in Wordpress:</p><ul><li>“Bring your own template” platform</li><li>Well-structured back-end with as few assumptions as possible</li><li>High quality interface for creating content and management</li><li>Some basic plugins for SEO</li></ul><p>I’ve set Craft CMS up as a Docker container running on Azure with automated backups and thus far it’s holding up really well.</p><p><em>Update: I’ve written a blog post about <a href="/blog/running-craft-cms-in-docker-on-microsoft-azure/" title="Running Craft CMS in a Docker container on Microsoft Azure">Running Craft CMS in a Docker container on Microsoft Azure</a></em>.</p><h2 id="Migration-from-Google-Analytics-to-Matomo-Analytics"><a href="#Migration-from-Google-Analytics-to-Matomo-Analytics" class="headerlink" title="Migration from Google Analytics to Matomo Analytics"></a>Migration from Google Analytics to Matomo Analytics</h2><p>As part of the new website, we have also taken a good critical look at alternatives for user insights. I’ve written a separate article about this: <a href="/blog/upgrade-visitor-privacy-with-matomo-analytics/" title="Lessons learned: upgrading visitor privacy with Matomo Analytics">Lessons learned: upgrading visitor privacy with Matomo Analytics</a>.</p><h2 id="My-responsibilities"><a href="#My-responsibilities" class="headerlink" title="My responsibilities"></a>My responsibilities</h2><ul><li>Graphic design tweaks (the base design is made by my colleague <a href="https://nl.linkedin.com/in/basroodbeen">Bas Roodbeen</a>)</li><li>Web design (UI/UX)</li><li>Front-end development</li><li>Back-end development</li></ul><hr><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li><a href="https://www.tiqtime.com/">TIQ marketing website</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//work/">work</category>
      
      
      <category domain="https://www.stefan.lu/tag/software-development/">software development</category>
      
      <category domain="https://www.stefan.lu/tag/graphic-design/">graphic design</category>
      
      <category domain="https://www.stefan.lu/tag/code/">code</category>
      
      <category domain="https://www.stefan.lu/tag/web-development/">web development</category>
      
      <category domain="https://www.stefan.lu/tag/user-experience/">user experience</category>
      
      <category domain="https://www.stefan.lu/tag/legal-tech/">legal tech</category>
      
      
      <comments>https://www.stefan.lu/work/tiq-marketing-2020/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Leading Nordic law firm Roschier implements TIQ Time</title>
      <link>https://www.stefan.lu/blog/roschier-implements-tiq-time/</link>
      <guid>https://www.stefan.lu/blog/roschier-implements-tiq-time/</guid>
      <pubDate>Sun, 05 Apr 2020 22:00:00 GMT</pubDate>
      
      <description>Roschier, leading law firm in the Nordics with offices in Helsinki and Stockholm, has implemented TIQ Time to improve their time tracking</description>
      
      
      
      <content:encoded><![CDATA[<p><em>This is a copy of a <a href="https://www.tiqtime.com/blog/roschier-selected-tiq-time-capture-software">press release</a> for TIQ Time, one of the main projects I’ve been working on for several years.</em></p><p><strong>Amsterdam and Helsinki, 6 April 2020.</strong> TIQ has announced that Roschier is now working firm-wide with TIQ Time to improve its time registration. Approximately 500 staff members, of which more than 300 lawyers and practitioners, use TIQ Time as time entry solution.</p><a id="more"></a><p>Jan Willamo, Chief Digital Officer at Roschier:</p><blockquote><p>One of the main drivers to select TIQ’s best-of-breed solution was related to the uncomplicated implementation process. TIQ Time was implemented quickly without affecting our existing practice management system. Since then, time tracking has become a lot easier for our fee earners.</p></blockquote><p>The firm’s previous solution, a custom timesheet as part of the ERP system, had some shortcomings Roschier wanted to address in this project. The speed of the old application and the lack of mobile time entry capabilities caused frustration among the lawyers. The time capture functionality of TIQ Time, combined with the multilingual NarrativeBuilder, helps lawyers to construct better timesheets with less effort than before. This allows them to spend more time where it matters most, on their business and clients.</p><p>Jan Willamo, Chief Digital Officer at Roschier: </p><blockquote><p>The system has now been fully rolled-out to all fee-earners within the firm. So far, we have been hearing positive feedback from both the lawyers and the support staff. Time registration is now much more simplified, so our employees can focus on work that matters most.</p></blockquote><p>TIQ Time offers a range of time recording features, from fully automated to manual timers, supported both on desktop and mobile devices. The narrative builder ensures consistent, high-quality narratives for every time entry by capturing time spent on documents, emails, meeting, phone calls and more. Deployed as an extension to their ERP and DMS system, the software helps Roschier employees making time registration less complicated and time consuming.</p><p>Nick Schils, CEO at TIQ: </p><blockquote><p>Gaining insights into service delivery starts with taking away any friction around time entry. We are very proud to be part of Roschier’s overall IT strategy, in which they chose to implement TIQ Time ahead of the ERP migration. The result is a future-proof, accurate and more efficient way of tracking time that fits the innovative character of the firm.</p></blockquote><p>The integration with the ERP and DMS system is set up with Custodian, a dedicated integration platform as a service (iPaaS) custom-built for Nordic Professional Services Companies. The implementation is delivered by PSA Consulting, one of TIQ’s implementation partners.</p><h2 id="About-Roschier"><a href="#About-Roschier" class="headerlink" title="About Roschier"></a>About Roschier</h2><p>Roschier is one of the leading law firms in the Nordic region with offices in Helsinki and Stockholm. The firm is well-known for its excellent track record of advising on demanding international business law assignments and large-scale transactions.</p><h2 id="About-TIQ-Time"><a href="#About-TIQ-Time" class="headerlink" title="About TIQ Time"></a>About TIQ Time</h2><p>TIQ Time helps lawyers build a complete and consistent timesheet, helping firms to reduce leakage, increase their bottom-line and optimise insights and transparency in service delivery.</p><p>I’ve been involved with the design, development and management of TIQ Time since day one. My activities for TIQ Time include:</p><ul><li>product design</li><li>product development</li><li>front-end development</li><li>product management</li><li>product strategy</li></ul><p>Want to read more? Check out all related posts under <a href="/tag/legal-tech">legal tech</a>.</p><hr><h5 id="More-information"><a href="#More-information" class="headerlink" title="More information"></a>More information</h5><ul><li><a href="https://www.tiqtime.com/blog/roschier-selected-tiq-time-capture-software">Original press release by TIQ Time</a></li><li><a href="https://www.roschier.com/">Roschier</a></li><li><a href="https://www.psaconsulting.com/">PSA Consulting</a></li></ul><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Image courtesy: all images by <a href="https://www.roschier.com/">Roschier</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/legal-tech/">legal tech</category>
      
      
      <comments>https://www.stefan.lu/blog/roschier-implements-tiq-time/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Lessons learned: upgrading visitor privacy with Matomo Analytics</title>
      <link>https://www.stefan.lu/blog/upgrade-visitor-privacy-with-matomo-analytics/</link>
      <guid>https://www.stefan.lu/blog/upgrade-visitor-privacy-with-matomo-analytics/</guid>
      <pubDate>Fri, 03 Apr 2020 22:00:00 GMT</pubDate>
      
      <description>A writeup about my experience so far with Matomo Analytics, a Google Analytics alternative.</description>
      
      
      <enclosure url="https://www.stefan.lu/header-matomo.jpg" type="image"/>
      
      
      <content:encoded><![CDATA[<p>Google Analytics is hard to beat: it’s super easy to implement, it’s the market standard for analytics, it provides valuable insights and on top of that, it’s free. </p><p>That being said, Google Analytics comes with a hidden cost. Google Analytics has become ubiquitous and with that, so has Google surveillance.</p><p>For a long time, it was hard to find a good alternative to Google Analytics. But now, Matomo Analytics (formerly Piwik) deserves your serious consideration if you value your visitor’s privacy (and your own).</p><p><strong>Note</strong>: I’m not affiliated with- or paid by any of the companies discussed in this article (Matomo &amp; Google).</p><a id="more"></a><h2 id="Why-it’s-time-to-upgrade-visitor-privacy"><a href="#Why-it’s-time-to-upgrade-visitor-privacy" class="headerlink" title="Why it’s time to upgrade visitor privacy"></a>Why it’s time to upgrade visitor privacy</h2><h3 id="Google’s-market-dominance"><a href="#Google’s-market-dominance" class="headerlink" title="Google’s market dominance"></a>Google’s market dominance</h3><p>In June 2020, Google Analytics is  (<a href="https://trends.builtwith.com/analytics/Google-Analytics">BuiltWith, 2020</a>):</p><ul><li>87,47% of the top 10.000 pages use Google Analytics</li><li>87,33% of the top 100.000 pages use Google Analytics</li><li>68,76% of the top 1.000.000 pages use Google Analytics</li></ul><p>This means that all these pages let Google know you’re visiting it. And this not only applies websites. Google Analytics can also be found in mobile applications, emails, video games, desktop applications and Internet Of Things devices (<a href="https://developers.google.com/analytics/devguides/collection/">source</a>).</p><h3 id="GDPR"><a href="#GDPR" class="headerlink" title="GDPR"></a>GDPR</h3><p>In the European Union, GDPR has been implemented to protect the personal data and free movement of such data. Whether you agree with the risk of market dominance in this scenario, European law now more responsibility with regards to personal data.</p><h3 id="Being-a-good-host-means-respecting-user-privacy"><a href="#Being-a-good-host-means-respecting-user-privacy" class="headerlink" title="Being a good host means respecting user privacy"></a>Being a good host means respecting user privacy</h3><p>If you value your visitors, the least you can do is try to provide them with a safe space. If they are paying for your product, it’s your duty.</p><h2 id="Define-requirements-how-much-data-do-you-really-need"><a href="#Define-requirements-how-much-data-do-you-really-need" class="headerlink" title="Define requirements: how much data do you really need?"></a>Define requirements: how much data do you really need?</h2><p>Don’t just implement a tool, think about it for a minute:</p><ol><li>How much data does Google collect for you?</li><li>How much of that do you use?</li><li>How much data do you actually own?</li></ol><h2 id="Lessons-learned-from-switching-to-Matomo"><a href="#Lessons-learned-from-switching-to-Matomo" class="headerlink" title="Lessons learned from switching to Matomo"></a>Lessons learned from switching to Matomo</h2><h3 id="Implementation"><a href="#Implementation" class="headerlink" title="Implementation"></a>Implementation</h3><p>Basically the implementation of Matomo Analytics is very similar to Google Analytics. In both cases it’s done with a single line of code in your website or application. The only difference is that there’s two options for Matomo: 1) a self-hosted installation or 2) a Matomo Cloud installation. I would suggest to use the self-hosted option to have full control and ownership of the collected data.</p><h3 id="Benefits-of-Matomo"><a href="#Benefits-of-Matomo" class="headerlink" title="Benefits of Matomo"></a>Benefits of Matomo</h3><ul><li>You control the system, you own the data</li><li>Analytics can run on the same domain, making implementing a Content Security Policy much easier</li><li>It offers a great user experience and mobile application</li><li>Great control over data retention periods, what gets collected and how and to what degree data gets anonymized. It’s specifically geared towards GDPR compliance.</li><li>No search engine spam!</li></ul><h3 id="Downsides-of-Matomo"><a href="#Downsides-of-Matomo" class="headerlink" title="Downsides of Matomo"></a>Downsides of Matomo</h3><ul><li>It’s not free (you either pay for a server + maintenance, or a cloud subscription).</li><li>For self-hosted installations, some functionality comes at a premiums (e.g. keyword analysis, funnels, heatmaps, A/B testing, ..)</li><li>If your marketeer does most of the coding, he’ll need to learn how to code. There’s not a lot of copy-paste biolerplate code available yet.</li></ul><h2 id="Verdict-updated-August-2020"><a href="#Verdict-updated-August-2020" class="headerlink" title="Verdict (updated August 2020)"></a>Verdict (updated August 2020)</h2><p>Matomo is the best alternative to Google Analytics I’ve tried thus far and I would recommend it if you take privacy seriously. Although there are definitely differences with Google Analytics, Matomo Analytics works just as fine, or even better, to gain the insights needed from a marketing and business perspective. I’m sure the avid Google Analytics user will need some time to get used to Matomo, but the degree of customisation possible with Matomo is unparalleled.</p><p>In practice I’ve seen that having hard evidence that no data leaves your servers drastically reduces customer concerns about data processing (not only in the European Union). Even if it’s just on your marketing website, using Matomo will leave a great first impression!</p><hr><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li><a href="https://matomo.org/">Matomo Analytics</a></li><li><a href="https://trends.builtwith.com/analytics/Google-Analytics">Google Analytics Usage Statistics - BuiltWith</a></li><li><a href="https://developers.google.com/analytics/devguides/collection/">Set up Google Analytics - Google</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/code/">code</category>
      
      <category domain="https://www.stefan.lu/tag/web-development/">web development</category>
      
      <category domain="https://www.stefan.lu/tag/privacy/">privacy</category>
      
      
      <comments>https://www.stefan.lu/blog/upgrade-visitor-privacy-with-matomo-analytics/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Converting an image to a proper ICO icon using the command line</title>
      <link>https://www.stefan.lu/blog/convert-icon-to-ico/</link>
      <guid>https://www.stefan.lu/blog/convert-icon-to-ico/</guid>
      <pubDate>Fri, 14 Feb 2020 23:00:00 GMT</pubDate>
      
      <description>Writeup about converting an image file to a Windows icon using the command line.</description>
      
      
      <enclosure url="https://www.stefan.lu/header-convert-icon-ico.jpg" type="image"/>
      
      
      <content:encoded><![CDATA[<p>The ICO (.ico) icon format is a Windows icon format and as a web developer, I only see it used in the <a href="https://en.wikipedia.org/wiki/Favicon">favicon.ico</a> file. So when I was asked to export a logo in the ICO format for use in a desktop application, I had to do some homework. Since I couldn’t find it within a few minutes, here’s my contribution for anyone looking for a quick solution.</p><a id="more"></a><h2 id="The-solution"><a href="#The-solution" class="headerlink" title="The solution"></a>The solution</h2><ol><li>Make sure you export the icon at a resolution of <strong>250x250px</strong>.</li><li>We’re going to use Imagemagick for the conversion. Make sure to install it (for Mac/Homebrew users: <code>brew install imagemagick</code>).</li><li>Run this command: <code>convert -density 384 icon.svg -define icon:auto-resize icon.ico</code>  and change <strong>icon.svg</strong> and <strong>icon.ico</strong> to the desired filenames.</li></ol><p>The ICO format is an odd beast, it stores multiple images with different sizes in the same file. To check if everyting was converted correctly, run:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">identify icon.ico<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>This should output something similar to this:</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">icon.ico<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> ICO 256x256 256x256+0+0 <span class="token number">8</span>-bit sRGB <span class="token number">0</span>.010u <span class="token number">0</span>:00.006icon.ico<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> ICO 192x192 192x192+0+0 <span class="token number">8</span>-bit sRGB <span class="token number">0</span>.000u <span class="token number">0</span>:00.004icon.ico<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> ICO 128x128 128x128+0+0 <span class="token number">8</span>-bit sRGB <span class="token number">0</span>.000u <span class="token number">0</span>:00.002icon.ico<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span> ICO 96x96 96x96+0+0 <span class="token number">8</span>-bit sRGB <span class="token number">0</span>.000u <span class="token number">0</span>:00.002icon.ico<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span> ICO 64x64 64x64+0+0 <span class="token number">8</span>-bit sRGB <span class="token number">0</span>.000u <span class="token number">0</span>:00.001icon.ico<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> ICO 48x48 48x48+0+0 <span class="token number">8</span>-bit sRGB <span class="token number">0</span>.000u <span class="token number">0</span>:00.001icon.ico<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span> ICO 40x40 40x40+0+0 <span class="token number">8</span>-bit sRGB <span class="token number">0</span>.000u <span class="token number">0</span>:00.001icon.ico<span class="token punctuation">[</span><span class="token number">7</span><span class="token punctuation">]</span> ICO 32x32 32x32+0+0 <span class="token number">8</span>-bit sRGB <span class="token number">0</span>.000u <span class="token number">0</span>:00.001icon.ico<span class="token punctuation">[</span><span class="token number">8</span><span class="token punctuation">]</span> ICO 24x24 24x24+0+0 <span class="token number">8</span>-bit sRGB <span class="token number">0</span>.000u <span class="token number">0</span>:00.001icon.ico<span class="token punctuation">[</span><span class="token number">9</span><span class="token punctuation">]</span> ICO 16x16 16x16+0+0 <span class="token number">8</span>-bit sRGB 569494B <span class="token number">0</span>.000u <span class="token number">0</span>:00.001<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>This should give you a high quality desktop icon.</p><hr><h5 id="Sources"><a href="#Sources" class="headerlink" title="Sources"></a>Sources</h5><ul><li>Header image courtesy: <a href="https://www.sketchappsources.com/free-source/3903-file-icons-sketch-freebie-resource.html">Seergb’s 10 File Icons</a> and <a href="https://www.sketchappsources.com/free-source/2285-hand-drawn-vector-arrows-sketch-freebie-resource.html">Tony Thomas’s 46 Hand Drawn Arrows</a>.</li><li><a href="https://graphicdesign.stackexchange.com/questions/77359/how-to-convert-a-square-svg-to-all-size-ico">How to convert a square SVG to all-size ICO?</a></li><li><a href="https://gist.github.com/azam/3b6995a29b9f079282f3">Convert SVG to ICO using ImageMagick, with transparent background and multi-size icons</a></li></ul>]]></content:encoded>
      
      
      <category domain="https://www.stefan.lu//blog/">blog</category>
      
      
      <category domain="https://www.stefan.lu/tag/software-development/">software development</category>
      
      <category domain="https://www.stefan.lu/tag/graphic-design/">graphic design</category>
      
      <category domain="https://www.stefan.lu/tag/code/">code</category>
      
      
      <comments>https://www.stefan.lu/blog/convert-icon-to-ico/#disqus_thread</comments>
      
    </item>
    
  </channel>
</rss>
