Make all links relative

Now the abs_to_rel module is enabled, links can be made relative so they
work on the current environment.
This commit is contained in:
Oliver Davies 2025-05-29 16:42:25 +01:00
parent 0d359f81d6
commit 7a7dc297ca
349 changed files with 698 additions and 698 deletions

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>A side effect of <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/03\/04\/why-i-built-a-tool-to-generate-configuration-files\">using a tool to generate build configuration files<\/a> with templates is the consistency that it introduces.<\/p>\n\n<p>The majority of my projects use a PHP-FPM or PHP CLI container. In my Docker Compose file, the service was mostly named <code>php<\/code> but sometimes it was <code>php-fpm<\/code>. In the templated file, it's always named <code>php<\/code>.<\/p>\n\n<p>Some projects would use <code>mysql<\/code> or <code>mariadb<\/code> for the database service and <code>nginx<\/code> or <code>caddy<\/code> depending on which server was being used. These are now always <code>database<\/code> and <code>web<\/code> respectively.<\/p>\n\n<p>As well as being easier to switch between projects and not having to think about which names are used in each codebase, it's also much easier to write tools and automation when the names are consistent.<\/p>\n\n<p>For example, I'd always write a long-ish command to import a database file - reading and unzipping it, and importing it by connecting to the database running in its container. The command would essentially be the same with slight changes based on that project - such as the database service name.<\/p>\n\n<p>Now the command is the same for all projects, and I can automate it by writing a script that works on any project meaning I no longer need to write the long command at all.<\/p>\n\n ",
"value": "\n <p>A side effect of <a href=\"/daily\/2023\/03\/04\/why-i-built-a-tool-to-generate-configuration-files\">using a tool to generate build configuration files<\/a> with templates is the consistency that it introduces.<\/p>\n\n<p>The majority of my projects use a PHP-FPM or PHP CLI container. In my Docker Compose file, the service was mostly named <code>php<\/code> but sometimes it was <code>php-fpm<\/code>. In the templated file, it's always named <code>php<\/code>.<\/p>\n\n<p>Some projects would use <code>mysql<\/code> or <code>mariadb<\/code> for the database service and <code>nginx<\/code> or <code>caddy<\/code> depending on which server was being used. These are now always <code>database<\/code> and <code>web<\/code> respectively.<\/p>\n\n<p>As well as being easier to switch between projects and not having to think about which names are used in each codebase, it's also much easier to write tools and automation when the names are consistent.<\/p>\n\n<p>For example, I'd always write a long-ish command to import a database file - reading and unzipping it, and importing it by connecting to the database running in its container. The command would essentially be the same with slight changes based on that project - such as the database service name.<\/p>\n\n<p>Now the command is the same for all projects, and I can automate it by writing a script that works on any project meaning I no longer need to write the long command at all.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>A side effect of <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/03\/04\/why-i-built-a-tool-to-generate-configuration-files\">using a tool to generate build configuration files<\/a> with templates is the consistency that it introduces.<\/p>\n\n<p>The majority of my projects use a PHP-FPM or PHP CLI container. In my Docker Compose file, the service was mostly named <code>php<\/code> but sometimes it was <code>php-fpm<\/code>. In the templated file, it's always named <code>php<\/code>.<\/p>\n\n<p>Some projects would use <code>mysql<\/code> or <code>mariadb<\/code> for the database service and <code>nginx<\/code> or <code>caddy<\/code> depending on which server was being used. These are now always <code>database<\/code> and <code>web<\/code> respectively.<\/p>\n\n<p>As well as being easier to switch between projects and not having to think about which names are used in each codebase, it's also much easier to write tools and automation when the names are consistent.<\/p>\n\n<p>For example, I'd always write a long-ish command to import a database file - reading and unzipping it, and importing it by connecting to the database running in its container. The command would essentially be the same with slight changes based on that project - such as the database service name.<\/p>\n\n<p>Now the command is the same for all projects, and I can automate it by writing a script that works on any project meaning I no longer need to write the long command at all.<\/p>\n\n ",
"processed": "\n <p>A side effect of <a href=\"/daily\/2023\/03\/04\/why-i-built-a-tool-to-generate-configuration-files\">using a tool to generate build configuration files<\/a> with templates is the consistency that it introduces.<\/p>\n\n<p>The majority of my projects use a PHP-FPM or PHP CLI container. In my Docker Compose file, the service was mostly named <code>php<\/code> but sometimes it was <code>php-fpm<\/code>. In the templated file, it's always named <code>php<\/code>.<\/p>\n\n<p>Some projects would use <code>mysql<\/code> or <code>mariadb<\/code> for the database service and <code>nginx<\/code> or <code>caddy<\/code> depending on which server was being used. These are now always <code>database<\/code> and <code>web<\/code> respectively.<\/p>\n\n<p>As well as being easier to switch between projects and not having to think about which names are used in each codebase, it's also much easier to write tools and automation when the names are consistent.<\/p>\n\n<p>For example, I'd always write a long-ish command to import a database file - reading and unzipping it, and importing it by connecting to the database running in its container. The command would essentially be the same with slight changes based on that project - such as the database service name.<\/p>\n\n<p>Now the command is the same for all projects, and I can automate it by writing a script that works on any project meaning I no longer need to write the long command at all.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>A common reason why environments aren't updated and get out of sync is because it's a time-consuming or complex task.<\/p>\n\n<p>The process should be simple to run, quick, reliable and reproducible.<\/p>\n\n<p>It's the same as deploying a change to a staging or production environment.<\/p>\n\n<p>You want the same result on every time on every environment.<\/p>\n\n<p>You want every environment - including <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/12\/25\/localhost\">local development environments<\/a> to be as consistent as possible to minimise bugs and errors.<\/p>\n\n<p>To do this, I automate things to make them as simple as possible.<\/p>\n\n<p>I use <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">run files<\/a> with commands to import databases, perform updates and run pre-update and post-update tasks.<\/p>\n\n<p>I use tools like Nix and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/11\/could-nix-and-devenv-replace-docker-compose\">devenv<\/a> to create identical and reproducible environments.<\/p>\n\n<p>The simpler and quicker is it, the more it can and will be done.<\/p>\n\n<p>You can also use automation to perform long or complex tasks outside of working hours such as sanitising and importing large databases.<\/p>\n\n<p>The more you can automate, the better.<\/p>\n\n ",
"value": "\n <p>A common reason why environments aren't updated and get out of sync is because it's a time-consuming or complex task.<\/p>\n\n<p>The process should be simple to run, quick, reliable and reproducible.<\/p>\n\n<p>It's the same as deploying a change to a staging or production environment.<\/p>\n\n<p>You want the same result on every time on every environment.<\/p>\n\n<p>You want every environment - including <a href=\"/daily\/2024\/12\/25\/localhost\">local development environments<\/a> to be as consistent as possible to minimise bugs and errors.<\/p>\n\n<p>To do this, I automate things to make them as simple as possible.<\/p>\n\n<p>I use <a href=\"/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">run files<\/a> with commands to import databases, perform updates and run pre-update and post-update tasks.<\/p>\n\n<p>I use tools like Nix and <a href=\"/daily\/2024\/11\/11\/could-nix-and-devenv-replace-docker-compose\">devenv<\/a> to create identical and reproducible environments.<\/p>\n\n<p>The simpler and quicker is it, the more it can and will be done.<\/p>\n\n<p>You can also use automation to perform long or complex tasks outside of working hours such as sanitising and importing large databases.<\/p>\n\n<p>The more you can automate, the better.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>A common reason why environments aren't updated and get out of sync is because it's a time-consuming or complex task.<\/p>\n\n<p>The process should be simple to run, quick, reliable and reproducible.<\/p>\n\n<p>It's the same as deploying a change to a staging or production environment.<\/p>\n\n<p>You want the same result on every time on every environment.<\/p>\n\n<p>You want every environment - including <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/12\/25\/localhost\">local development environments<\/a> to be as consistent as possible to minimise bugs and errors.<\/p>\n\n<p>To do this, I automate things to make them as simple as possible.<\/p>\n\n<p>I use <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">run files<\/a> with commands to import databases, perform updates and run pre-update and post-update tasks.<\/p>\n\n<p>I use tools like Nix and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/11\/could-nix-and-devenv-replace-docker-compose\">devenv<\/a> to create identical and reproducible environments.<\/p>\n\n<p>The simpler and quicker is it, the more it can and will be done.<\/p>\n\n<p>You can also use automation to perform long or complex tasks outside of working hours such as sanitising and importing large databases.<\/p>\n\n<p>The more you can automate, the better.<\/p>\n\n ",
"processed": "\n <p>A common reason why environments aren't updated and get out of sync is because it's a time-consuming or complex task.<\/p>\n\n<p>The process should be simple to run, quick, reliable and reproducible.<\/p>\n\n<p>It's the same as deploying a change to a staging or production environment.<\/p>\n\n<p>You want the same result on every time on every environment.<\/p>\n\n<p>You want every environment - including <a href=\"/daily\/2024\/12\/25\/localhost\">local development environments<\/a> to be as consistent as possible to minimise bugs and errors.<\/p>\n\n<p>To do this, I automate things to make them as simple as possible.<\/p>\n\n<p>I use <a href=\"/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">run files<\/a> with commands to import databases, perform updates and run pre-update and post-update tasks.<\/p>\n\n<p>I use tools like Nix and <a href=\"/daily\/2024\/11\/11\/could-nix-and-devenv-replace-docker-compose\">devenv<\/a> to create identical and reproducible environments.<\/p>\n\n<p>The simpler and quicker is it, the more it can and will be done.<\/p>\n\n<p>You can also use automation to perform long or complex tasks outside of working hours such as sanitising and importing large databases.<\/p>\n\n<p>The more you can automate, the better.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>PHPStan is a static analysis tool for PHP.<\/p>\n\n<p>It finds potential issues in PHP code without needing to run it, so Developers can find and resolve potential issues sooner.<\/p>\n\n<p>I use it on all my projects including existing ones I've inherited.<\/p>\n\n<p>But how can you add a static analysis tool to a codebase without getting a lot of errors from the existing code?<\/p>\n\n<p>PHPStan has different levels of strictness.<\/p>\n\n<p>Level 0 is the least strict and each level adds more rules and strictness, resulting in more errors.<\/p>\n\n<p>Most of the time, people will start by running PHPStan on level 0, fixing any errors and committing the changes.<\/p>\n\n<p>Then repeat the process as many times as needed until you reach the level you want to achieve.<\/p>\n\n<p>I don't think this is the right approach.<\/p>\n\n<p>This could mean that you need to edit the same files multiple times as you work through the levels.<\/p>\n\n<p>There's also a period of time where Developers can still write suboptimal code whilst you work your way up to your desired level.<\/p>\n\n<p>Another approach is to use a feature of PHPStan called the baseline.<\/p>\n\n<p>The baseline is a way of capturing and saving all the existing errors up to the selected level so they are no longer reported.<\/p>\n\n<p>If you did this for an existing project, it would return no errors as everything would be included in the baseline.<\/p>\n\n<p>Once you decide what level you want your project to run, you can start as soon as the baseline is generated and without needing to change files multiple times.<\/p>\n\n<p>Instead of spending time working through the levels one at a time, commit some time to pruning the baseline and reducing the errors in it.<\/p>\n\n<p>This I think is a better approach and how I add PHPStan to existing codebases.<\/p>\n\n<p>To learn more about static analysis and PHPStan, listen to <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/22-dave-liddament\">episode 22 of the Beyond Blocks podcast<\/a> with Dave Liddament.<\/p>\n\n ",
"value": "\n <p>PHPStan is a static analysis tool for PHP.<\/p>\n\n<p>It finds potential issues in PHP code without needing to run it, so Developers can find and resolve potential issues sooner.<\/p>\n\n<p>I use it on all my projects including existing ones I've inherited.<\/p>\n\n<p>But how can you add a static analysis tool to a codebase without getting a lot of errors from the existing code?<\/p>\n\n<p>PHPStan has different levels of strictness.<\/p>\n\n<p>Level 0 is the least strict and each level adds more rules and strictness, resulting in more errors.<\/p>\n\n<p>Most of the time, people will start by running PHPStan on level 0, fixing any errors and committing the changes.<\/p>\n\n<p>Then repeat the process as many times as needed until you reach the level you want to achieve.<\/p>\n\n<p>I don't think this is the right approach.<\/p>\n\n<p>This could mean that you need to edit the same files multiple times as you work through the levels.<\/p>\n\n<p>There's also a period of time where Developers can still write suboptimal code whilst you work your way up to your desired level.<\/p>\n\n<p>Another approach is to use a feature of PHPStan called the baseline.<\/p>\n\n<p>The baseline is a way of capturing and saving all the existing errors up to the selected level so they are no longer reported.<\/p>\n\n<p>If you did this for an existing project, it would return no errors as everything would be included in the baseline.<\/p>\n\n<p>Once you decide what level you want your project to run, you can start as soon as the baseline is generated and without needing to change files multiple times.<\/p>\n\n<p>Instead of spending time working through the levels one at a time, commit some time to pruning the baseline and reducing the errors in it.<\/p>\n\n<p>This I think is a better approach and how I add PHPStan to existing codebases.<\/p>\n\n<p>To learn more about static analysis and PHPStan, listen to <a href=\"/podcast\/22-dave-liddament\">episode 22 of the Beyond Blocks podcast<\/a> with Dave Liddament.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>PHPStan is a static analysis tool for PHP.<\/p>\n\n<p>It finds potential issues in PHP code without needing to run it, so Developers can find and resolve potential issues sooner.<\/p>\n\n<p>I use it on all my projects including existing ones I've inherited.<\/p>\n\n<p>But how can you add a static analysis tool to a codebase without getting a lot of errors from the existing code?<\/p>\n\n<p>PHPStan has different levels of strictness.<\/p>\n\n<p>Level 0 is the least strict and each level adds more rules and strictness, resulting in more errors.<\/p>\n\n<p>Most of the time, people will start by running PHPStan on level 0, fixing any errors and committing the changes.<\/p>\n\n<p>Then repeat the process as many times as needed until you reach the level you want to achieve.<\/p>\n\n<p>I don't think this is the right approach.<\/p>\n\n<p>This could mean that you need to edit the same files multiple times as you work through the levels.<\/p>\n\n<p>There's also a period of time where Developers can still write suboptimal code whilst you work your way up to your desired level.<\/p>\n\n<p>Another approach is to use a feature of PHPStan called the baseline.<\/p>\n\n<p>The baseline is a way of capturing and saving all the existing errors up to the selected level so they are no longer reported.<\/p>\n\n<p>If you did this for an existing project, it would return no errors as everything would be included in the baseline.<\/p>\n\n<p>Once you decide what level you want your project to run, you can start as soon as the baseline is generated and without needing to change files multiple times.<\/p>\n\n<p>Instead of spending time working through the levels one at a time, commit some time to pruning the baseline and reducing the errors in it.<\/p>\n\n<p>This I think is a better approach and how I add PHPStan to existing codebases.<\/p>\n\n<p>To learn more about static analysis and PHPStan, listen to <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/22-dave-liddament\">episode 22 of the Beyond Blocks podcast<\/a> with Dave Liddament.<\/p>\n\n ",
"processed": "\n <p>PHPStan is a static analysis tool for PHP.<\/p>\n\n<p>It finds potential issues in PHP code without needing to run it, so Developers can find and resolve potential issues sooner.<\/p>\n\n<p>I use it on all my projects including existing ones I've inherited.<\/p>\n\n<p>But how can you add a static analysis tool to a codebase without getting a lot of errors from the existing code?<\/p>\n\n<p>PHPStan has different levels of strictness.<\/p>\n\n<p>Level 0 is the least strict and each level adds more rules and strictness, resulting in more errors.<\/p>\n\n<p>Most of the time, people will start by running PHPStan on level 0, fixing any errors and committing the changes.<\/p>\n\n<p>Then repeat the process as many times as needed until you reach the level you want to achieve.<\/p>\n\n<p>I don't think this is the right approach.<\/p>\n\n<p>This could mean that you need to edit the same files multiple times as you work through the levels.<\/p>\n\n<p>There's also a period of time where Developers can still write suboptimal code whilst you work your way up to your desired level.<\/p>\n\n<p>Another approach is to use a feature of PHPStan called the baseline.<\/p>\n\n<p>The baseline is a way of capturing and saving all the existing errors up to the selected level so they are no longer reported.<\/p>\n\n<p>If you did this for an existing project, it would return no errors as everything would be included in the baseline.<\/p>\n\n<p>Once you decide what level you want your project to run, you can start as soon as the baseline is generated and without needing to change files multiple times.<\/p>\n\n<p>Instead of spending time working through the levels one at a time, commit some time to pruning the baseline and reducing the errors in it.<\/p>\n\n<p>This I think is a better approach and how I add PHPStan to existing codebases.<\/p>\n\n<p>To learn more about static analysis and PHPStan, listen to <a href=\"/podcast\/22-dave-liddament\">episode 22 of the Beyond Blocks podcast<\/a> with Dave Liddament.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>When reviewing a pull or merge request, tools like GitHub and GitHub offer the option to squash the commits before merging.<\/p>\n\n<p>If the request had twenty commits, they'd be combined into a single commit before being merged.<\/p>\n\n<p>But should you do it?<\/p>\n\n<p>The answer will be \"it depends\" based on the project or team, but I'm personally not a fan of squashing commits.<\/p>\n\n<p>Even though I commit small changes often, I put quite a bit of effort into <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/01\/24\/small-commits-and-good-commit-messges\">crafting commits and writing detailed commit messages<\/a> that capture the reason for each change. If the commits are squashed, either the messages will be combined into one extra-long commit message or I've seen them be deleted completely.<\/p>\n\n<p>One large commit message would be very difficult to read and connect specific messages with their changes, and deleting the commit body would lose the history completely and waste the time it took to write the messages and craft the commits. It may be available within the pull or merge request page but there's no guarantee that you'll continue to use the same repository hosting service in the future.<\/p>\n\n<p>One large commit would also be difficult to debug if there was an error. If the whole feature was added in a single commit, tools like <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/01\/23\/debugging-with-git-bisect\">git bisect<\/a> would no longer work and a single commit couldn't be simply reverted if it contained a bug.<\/p>\n\n<p>I prefer to keep the original small commits and instead prefer to use rebasing and only fast-forward merges to avoid merge commits and keep a simple, linear history in my Git log, and be able to easily read, find and, if needed, fix the code that's been committed.<\/p>\n\n ",
"value": "\n <p>When reviewing a pull or merge request, tools like GitHub and GitHub offer the option to squash the commits before merging.<\/p>\n\n<p>If the request had twenty commits, they'd be combined into a single commit before being merged.<\/p>\n\n<p>But should you do it?<\/p>\n\n<p>The answer will be \"it depends\" based on the project or team, but I'm personally not a fan of squashing commits.<\/p>\n\n<p>Even though I commit small changes often, I put quite a bit of effort into <a href=\"/daily\/2023\/01\/24\/small-commits-and-good-commit-messges\">crafting commits and writing detailed commit messages<\/a> that capture the reason for each change. If the commits are squashed, either the messages will be combined into one extra-long commit message or I've seen them be deleted completely.<\/p>\n\n<p>One large commit message would be very difficult to read and connect specific messages with their changes, and deleting the commit body would lose the history completely and waste the time it took to write the messages and craft the commits. It may be available within the pull or merge request page but there's no guarantee that you'll continue to use the same repository hosting service in the future.<\/p>\n\n<p>One large commit would also be difficult to debug if there was an error. If the whole feature was added in a single commit, tools like <a href=\"/daily\/2023\/01\/23\/debugging-with-git-bisect\">git bisect<\/a> would no longer work and a single commit couldn't be simply reverted if it contained a bug.<\/p>\n\n<p>I prefer to keep the original small commits and instead prefer to use rebasing and only fast-forward merges to avoid merge commits and keep a simple, linear history in my Git log, and be able to easily read, find and, if needed, fix the code that's been committed.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>When reviewing a pull or merge request, tools like GitHub and GitHub offer the option to squash the commits before merging.<\/p>\n\n<p>If the request had twenty commits, they'd be combined into a single commit before being merged.<\/p>\n\n<p>But should you do it?<\/p>\n\n<p>The answer will be \"it depends\" based on the project or team, but I'm personally not a fan of squashing commits.<\/p>\n\n<p>Even though I commit small changes often, I put quite a bit of effort into <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/01\/24\/small-commits-and-good-commit-messges\">crafting commits and writing detailed commit messages<\/a> that capture the reason for each change. If the commits are squashed, either the messages will be combined into one extra-long commit message or I've seen them be deleted completely.<\/p>\n\n<p>One large commit message would be very difficult to read and connect specific messages with their changes, and deleting the commit body would lose the history completely and waste the time it took to write the messages and craft the commits. It may be available within the pull or merge request page but there's no guarantee that you'll continue to use the same repository hosting service in the future.<\/p>\n\n<p>One large commit would also be difficult to debug if there was an error. If the whole feature was added in a single commit, tools like <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/01\/23\/debugging-with-git-bisect\">git bisect<\/a> would no longer work and a single commit couldn't be simply reverted if it contained a bug.<\/p>\n\n<p>I prefer to keep the original small commits and instead prefer to use rebasing and only fast-forward merges to avoid merge commits and keep a simple, linear history in my Git log, and be able to easily read, find and, if needed, fix the code that's been committed.<\/p>\n\n ",
"processed": "\n <p>When reviewing a pull or merge request, tools like GitHub and GitHub offer the option to squash the commits before merging.<\/p>\n\n<p>If the request had twenty commits, they'd be combined into a single commit before being merged.<\/p>\n\n<p>But should you do it?<\/p>\n\n<p>The answer will be \"it depends\" based on the project or team, but I'm personally not a fan of squashing commits.<\/p>\n\n<p>Even though I commit small changes often, I put quite a bit of effort into <a href=\"/daily\/2023\/01\/24\/small-commits-and-good-commit-messges\">crafting commits and writing detailed commit messages<\/a> that capture the reason for each change. If the commits are squashed, either the messages will be combined into one extra-long commit message or I've seen them be deleted completely.<\/p>\n\n<p>One large commit message would be very difficult to read and connect specific messages with their changes, and deleting the commit body would lose the history completely and waste the time it took to write the messages and craft the commits. It may be available within the pull or merge request page but there's no guarantee that you'll continue to use the same repository hosting service in the future.<\/p>\n\n<p>One large commit would also be difficult to debug if there was an error. If the whole feature was added in a single commit, tools like <a href=\"/daily\/2023\/01\/23\/debugging-with-git-bisect\">git bisect<\/a> would no longer work and a single commit couldn't be simply reverted if it contained a bug.<\/p>\n\n<p>I prefer to keep the original small commits and instead prefer to use rebasing and only fast-forward merges to avoid merge commits and keep a simple, linear history in my Git log, and be able to easily read, find and, if needed, fix the code that's been committed.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/11\/03\/why-your-company-should-contribute-to-open-source-software\">Yesterday's email<\/a> explained why your company should contribute to open-source software, but why should you contribute as an individual?<\/p>\n\n<p>Most of the same reasons apply, such as gaining experience and improved knowledge from contributing.<\/p>\n\n<p>As an individual, you can build your own reputation and personal brand.<\/p>\n\n<p>You'll get exposure from contributions and involvement with initiatives, such as the Drupal admin UI improvements and other core initiatives, which look great on your CV and LinkedIn profile.<\/p>\n\n<p>This could lead to better career opportunities and potential projects.<\/p>\n\n<p>I've had paid development work directly from my open-source code contributions, as well as public speaking and event organising, so I can vouch for this.<\/p>\n\n<p>Like companies, if you make money from open-source software - either a salary or from paid projects or courses - it's in your interest to contribute so the software you use is maintained and improved so it's the best it can be.<\/p>\n\n ",
"value": "\n <p><a href=\"/daily\/2023\/11\/03\/why-your-company-should-contribute-to-open-source-software\">Yesterday's email<\/a> explained why your company should contribute to open-source software, but why should you contribute as an individual?<\/p>\n\n<p>Most of the same reasons apply, such as gaining experience and improved knowledge from contributing.<\/p>\n\n<p>As an individual, you can build your own reputation and personal brand.<\/p>\n\n<p>You'll get exposure from contributions and involvement with initiatives, such as the Drupal admin UI improvements and other core initiatives, which look great on your CV and LinkedIn profile.<\/p>\n\n<p>This could lead to better career opportunities and potential projects.<\/p>\n\n<p>I've had paid development work directly from my open-source code contributions, as well as public speaking and event organising, so I can vouch for this.<\/p>\n\n<p>Like companies, if you make money from open-source software - either a salary or from paid projects or courses - it's in your interest to contribute so the software you use is maintained and improved so it's the best it can be.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/11\/03\/why-your-company-should-contribute-to-open-source-software\">Yesterday's email<\/a> explained why your company should contribute to open-source software, but why should you contribute as an individual?<\/p>\n\n<p>Most of the same reasons apply, such as gaining experience and improved knowledge from contributing.<\/p>\n\n<p>As an individual, you can build your own reputation and personal brand.<\/p>\n\n<p>You'll get exposure from contributions and involvement with initiatives, such as the Drupal admin UI improvements and other core initiatives, which look great on your CV and LinkedIn profile.<\/p>\n\n<p>This could lead to better career opportunities and potential projects.<\/p>\n\n<p>I've had paid development work directly from my open-source code contributions, as well as public speaking and event organising, so I can vouch for this.<\/p>\n\n<p>Like companies, if you make money from open-source software - either a salary or from paid projects or courses - it's in your interest to contribute so the software you use is maintained and improved so it's the best it can be.<\/p>\n\n ",
"processed": "\n <p><a href=\"/daily\/2023\/11\/03\/why-your-company-should-contribute-to-open-source-software\">Yesterday's email<\/a> explained why your company should contribute to open-source software, but why should you contribute as an individual?<\/p>\n\n<p>Most of the same reasons apply, such as gaining experience and improved knowledge from contributing.<\/p>\n\n<p>As an individual, you can build your own reputation and personal brand.<\/p>\n\n<p>You'll get exposure from contributions and involvement with initiatives, such as the Drupal admin UI improvements and other core initiatives, which look great on your CV and LinkedIn profile.<\/p>\n\n<p>This could lead to better career opportunities and potential projects.<\/p>\n\n<p>I've had paid development work directly from my open-source code contributions, as well as public speaking and event organising, so I can vouch for this.<\/p>\n\n<p>Like companies, if you make money from open-source software - either a salary or from paid projects or courses - it's in your interest to contribute so the software you use is maintained and improved so it's the best it can be.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Does your team have a \"No deploy Friday\" policy?<\/p>\n\n<p>What about not deploying after a certain time in the afternoon?<\/p>\n\n<p>These approaches are attempts to minimise risk when deploying.<\/p>\n\n<p>If there is an issue, will someone be available during the evening or weekend to resolve it?<\/p>\n\n<p>To me, this indicates the deployment process is too complicated, possibly due to a lack of automation, or deployments aren't happening frequently enough.<\/p>\n\n<p>Having a <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/01\/30\/gatekeeper\">robust and passing CI pipeline<\/a> that runs automated checks and tests is crucial to know the code is deployable.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/09\/28\/feature-flags-enable-continuous-integration\">Feature flags are a great way<\/a> to separate deploying code from releasing changes to users, which means you don't need to avoid pushing some code until the change is complete. It can be done incrementally and released over several deployments.<\/p>\n\n<p>Too much time between deployments is a smell.<\/p>\n\n<p>The more time there is between a deployment and the larger the changeset, the riskier the deployment will be.<\/p>\n\n<p>There is more to go wrong and it'll be harder to diagnose and resolve any issues.<\/p>\n\n<p>I always advocate for many smaller releases than larger less frequent ones.<\/p>\n\n<p>Ideally, a production release every day - even if the changes are small or everything is hidden behind feature flags.<\/p>\n\n<p>Deploying on Friday is easy if you last deployed on Thursday.<\/p>\n\n ",
"value": "\n <p>Does your team have a \"No deploy Friday\" policy?<\/p>\n\n<p>What about not deploying after a certain time in the afternoon?<\/p>\n\n<p>These approaches are attempts to minimise risk when deploying.<\/p>\n\n<p>If there is an issue, will someone be available during the evening or weekend to resolve it?<\/p>\n\n<p>To me, this indicates the deployment process is too complicated, possibly due to a lack of automation, or deployments aren't happening frequently enough.<\/p>\n\n<p>Having a <a href=\"/daily\/2025\/01\/30\/gatekeeper\">robust and passing CI pipeline<\/a> that runs automated checks and tests is crucial to know the code is deployable.<\/p>\n\n<p><a href=\"/daily\/2023\/09\/28\/feature-flags-enable-continuous-integration\">Feature flags are a great way<\/a> to separate deploying code from releasing changes to users, which means you don't need to avoid pushing some code until the change is complete. It can be done incrementally and released over several deployments.<\/p>\n\n<p>Too much time between deployments is a smell.<\/p>\n\n<p>The more time there is between a deployment and the larger the changeset, the riskier the deployment will be.<\/p>\n\n<p>There is more to go wrong and it'll be harder to diagnose and resolve any issues.<\/p>\n\n<p>I always advocate for many smaller releases than larger less frequent ones.<\/p>\n\n<p>Ideally, a production release every day - even if the changes are small or everything is hidden behind feature flags.<\/p>\n\n<p>Deploying on Friday is easy if you last deployed on Thursday.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Does your team have a \"No deploy Friday\" policy?<\/p>\n\n<p>What about not deploying after a certain time in the afternoon?<\/p>\n\n<p>These approaches are attempts to minimise risk when deploying.<\/p>\n\n<p>If there is an issue, will someone be available during the evening or weekend to resolve it?<\/p>\n\n<p>To me, this indicates the deployment process is too complicated, possibly due to a lack of automation, or deployments aren't happening frequently enough.<\/p>\n\n<p>Having a <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/01\/30\/gatekeeper\">robust and passing CI pipeline<\/a> that runs automated checks and tests is crucial to know the code is deployable.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/09\/28\/feature-flags-enable-continuous-integration\">Feature flags are a great way<\/a> to separate deploying code from releasing changes to users, which means you don't need to avoid pushing some code until the change is complete. It can be done incrementally and released over several deployments.<\/p>\n\n<p>Too much time between deployments is a smell.<\/p>\n\n<p>The more time there is between a deployment and the larger the changeset, the riskier the deployment will be.<\/p>\n\n<p>There is more to go wrong and it'll be harder to diagnose and resolve any issues.<\/p>\n\n<p>I always advocate for many smaller releases than larger less frequent ones.<\/p>\n\n<p>Ideally, a production release every day - even if the changes are small or everything is hidden behind feature flags.<\/p>\n\n<p>Deploying on Friday is easy if you last deployed on Thursday.<\/p>\n\n ",
"processed": "\n <p>Does your team have a \"No deploy Friday\" policy?<\/p>\n\n<p>What about not deploying after a certain time in the afternoon?<\/p>\n\n<p>These approaches are attempts to minimise risk when deploying.<\/p>\n\n<p>If there is an issue, will someone be available during the evening or weekend to resolve it?<\/p>\n\n<p>To me, this indicates the deployment process is too complicated, possibly due to a lack of automation, or deployments aren't happening frequently enough.<\/p>\n\n<p>Having a <a href=\"/daily\/2025\/01\/30\/gatekeeper\">robust and passing CI pipeline<\/a> that runs automated checks and tests is crucial to know the code is deployable.<\/p>\n\n<p><a href=\"/daily\/2023\/09\/28\/feature-flags-enable-continuous-integration\">Feature flags are a great way<\/a> to separate deploying code from releasing changes to users, which means you don't need to avoid pushing some code until the change is complete. It can be done incrementally and released over several deployments.<\/p>\n\n<p>Too much time between deployments is a smell.<\/p>\n\n<p>The more time there is between a deployment and the larger the changeset, the riskier the deployment will be.<\/p>\n\n<p>There is more to go wrong and it'll be harder to diagnose and resolve any issues.<\/p>\n\n<p>I always advocate for many smaller releases than larger less frequent ones.<\/p>\n\n<p>Ideally, a production release every day - even if the changes are small or everything is hidden behind feature flags.<\/p>\n\n<p>Deploying on Friday is easy if you last deployed on Thursday.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/01\/13\/patches\">Applying patch files<\/a> is a common way to customise and extend open source software, and how we used to submit changes to Drupal before issue forks and merge requests were added to Drupal.org.<\/p>\n\n<p>Some software, such as dwm and st from suckless.org are released as minimal versions that you patch to add features to.<\/p>\n\n<p>If you find a line of code that you want to add, edit or delete, a patch file describes the changes so you can re-apply them whenever the source file changes.<\/p>\n\n<p>Patching offers unlimited customisation and flexibility.<\/p>\n\n<p>Whatever changes you want to make, you can.<\/p>\n\n<p>The downside is you need to maintain any patches you've written.<\/p>\n\n<p>If a change is made that causes your patch to no longer apply, you'll need to update the patch.<\/p>\n\n<p>There are some patches I commonly apply to Drupal projects, but I'll try to either contribute the changes back to the Drupal so I no longer need the patch or make the change in a custom module.<\/p>\n\n<p>Sometimes, though, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/01\/14\/patching-drupal\">patching is the only option<\/a>.<\/p>\n\n ",
"value": "\n <p><a href=\"/daily\/2025\/01\/13\/patches\">Applying patch files<\/a> is a common way to customise and extend open source software, and how we used to submit changes to Drupal before issue forks and merge requests were added to Drupal.org.<\/p>\n\n<p>Some software, such as dwm and st from suckless.org are released as minimal versions that you patch to add features to.<\/p>\n\n<p>If you find a line of code that you want to add, edit or delete, a patch file describes the changes so you can re-apply them whenever the source file changes.<\/p>\n\n<p>Patching offers unlimited customisation and flexibility.<\/p>\n\n<p>Whatever changes you want to make, you can.<\/p>\n\n<p>The downside is you need to maintain any patches you've written.<\/p>\n\n<p>If a change is made that causes your patch to no longer apply, you'll need to update the patch.<\/p>\n\n<p>There are some patches I commonly apply to Drupal projects, but I'll try to either contribute the changes back to the Drupal so I no longer need the patch or make the change in a custom module.<\/p>\n\n<p>Sometimes, though, <a href=\"/daily\/2025\/01\/14\/patching-drupal\">patching is the only option<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/01\/13\/patches\">Applying patch files<\/a> is a common way to customise and extend open source software, and how we used to submit changes to Drupal before issue forks and merge requests were added to Drupal.org.<\/p>\n\n<p>Some software, such as dwm and st from suckless.org are released as minimal versions that you patch to add features to.<\/p>\n\n<p>If you find a line of code that you want to add, edit or delete, a patch file describes the changes so you can re-apply them whenever the source file changes.<\/p>\n\n<p>Patching offers unlimited customisation and flexibility.<\/p>\n\n<p>Whatever changes you want to make, you can.<\/p>\n\n<p>The downside is you need to maintain any patches you've written.<\/p>\n\n<p>If a change is made that causes your patch to no longer apply, you'll need to update the patch.<\/p>\n\n<p>There are some patches I commonly apply to Drupal projects, but I'll try to either contribute the changes back to the Drupal so I no longer need the patch or make the change in a custom module.<\/p>\n\n<p>Sometimes, though, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/01\/14\/patching-drupal\">patching is the only option<\/a>.<\/p>\n\n ",
"processed": "\n <p><a href=\"/daily\/2025\/01\/13\/patches\">Applying patch files<\/a> is a common way to customise and extend open source software, and how we used to submit changes to Drupal before issue forks and merge requests were added to Drupal.org.<\/p>\n\n<p>Some software, such as dwm and st from suckless.org are released as minimal versions that you patch to add features to.<\/p>\n\n<p>If you find a line of code that you want to add, edit or delete, a patch file describes the changes so you can re-apply them whenever the source file changes.<\/p>\n\n<p>Patching offers unlimited customisation and flexibility.<\/p>\n\n<p>Whatever changes you want to make, you can.<\/p>\n\n<p>The downside is you need to maintain any patches you've written.<\/p>\n\n<p>If a change is made that causes your patch to no longer apply, you'll need to update the patch.<\/p>\n\n<p>There are some patches I commonly apply to Drupal projects, but I'll try to either contribute the changes back to the Drupal so I no longer need the patch or make the change in a custom module.<\/p>\n\n<p>Sometimes, though, <a href=\"/daily\/2025\/01\/14\/patching-drupal\">patching is the only option<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>My website is built with Sculpin - a static site generator written in PHP.<\/p>\n\n<p>It uses a some of the same Symfony components as Drupal, uses Twig for templating and YAML for configuration, and has similar features like content types and taxonomies for structuring content.<\/p>\n\n<p>When I first created my website it was on Drupal 6 and upgraded to Drupal 7 before I started to take an interest in static site generators and later using Jekyll, Sculpin and Astro (and Sculpin, again).<\/p>\n\n<p>I enjoyed learning Sculpin and took it as an opportunity to learn Twig before Drupal 8, which I spoke about in <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/test-drive-twig-with-sculpin\">the first Sculpin talk I gave<\/a>, at DrupalCamp North in July 2015.<\/p>\n\n<p>I had three Git repositories, the current Sculpin one, the Astro version, and the original Sculpin version with its first commit in March 2015 - a few months before DrupalCamp North.<\/p>\n\n<p>Static site generators keep the files in text files intead of a database, so I was wondering if it was possible to merge the repositories together and combine the information whilst keeping the same commit history so existing tags and contribtions would still apply to the original commits.<\/p>\n\n<p>In short, I was able to do it by adding the old repositories as additional remotes and using the <code>--allow-unrelated-histories<\/code> <a href=\"https:\/\/git-scm.com\/docs\/git-merge#Documentation\/git-merge.txt---allow-unrelated-histories\">option for git merge<\/a>.<\/p>\n\n<p>After fixing some minor merge conflicts, everything was merged successfully and I have [one repository containing 5,272 all commits][2], going back to 2015.<\/p>\n\n<p>This makes it older than <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/08\/08\/8-years-of-dotfiles\">my dotfiles repository<\/a>, which I started in July 2015.<\/p>\n\n<p>Similar to <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/07\/31\/why-i-use-linux\">why I use Linux<\/a>, I believe in owning your own content rather than relying on third-party platforms, so having all my content and history in one repository is great.<\/p>\n\n<p>And I learned something new about Git at the same time.<\/p>\n\n ",
"value": "\n <p>My website is built with Sculpin - a static site generator written in PHP.<\/p>\n\n<p>It uses a some of the same Symfony components as Drupal, uses Twig for templating and YAML for configuration, and has similar features like content types and taxonomies for structuring content.<\/p>\n\n<p>When I first created my website it was on Drupal 6 and upgraded to Drupal 7 before I started to take an interest in static site generators and later using Jekyll, Sculpin and Astro (and Sculpin, again).<\/p>\n\n<p>I enjoyed learning Sculpin and took it as an opportunity to learn Twig before Drupal 8, which I spoke about in <a href=\"/presentations\/test-drive-twig-with-sculpin\">the first Sculpin talk I gave<\/a>, at DrupalCamp North in July 2015.<\/p>\n\n<p>I had three Git repositories, the current Sculpin one, the Astro version, and the original Sculpin version with its first commit in March 2015 - a few months before DrupalCamp North.<\/p>\n\n<p>Static site generators keep the files in text files intead of a database, so I was wondering if it was possible to merge the repositories together and combine the information whilst keeping the same commit history so existing tags and contribtions would still apply to the original commits.<\/p>\n\n<p>In short, I was able to do it by adding the old repositories as additional remotes and using the <code>--allow-unrelated-histories<\/code> <a href=\"https:\/\/git-scm.com\/docs\/git-merge#Documentation\/git-merge.txt---allow-unrelated-histories\">option for git merge<\/a>.<\/p>\n\n<p>After fixing some minor merge conflicts, everything was merged successfully and I have [one repository containing 5,272 all commits][2], going back to 2015.<\/p>\n\n<p>This makes it older than <a href=\"/daily\/2023\/08\/08\/8-years-of-dotfiles\">my dotfiles repository<\/a>, which I started in July 2015.<\/p>\n\n<p>Similar to <a href=\"/daily\/2024\/07\/31\/why-i-use-linux\">why I use Linux<\/a>, I believe in owning your own content rather than relying on third-party platforms, so having all my content and history in one repository is great.<\/p>\n\n<p>And I learned something new about Git at the same time.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>My website is built with Sculpin - a static site generator written in PHP.<\/p>\n\n<p>It uses a some of the same Symfony components as Drupal, uses Twig for templating and YAML for configuration, and has similar features like content types and taxonomies for structuring content.<\/p>\n\n<p>When I first created my website it was on Drupal 6 and upgraded to Drupal 7 before I started to take an interest in static site generators and later using Jekyll, Sculpin and Astro (and Sculpin, again).<\/p>\n\n<p>I enjoyed learning Sculpin and took it as an opportunity to learn Twig before Drupal 8, which I spoke about in <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/test-drive-twig-with-sculpin\">the first Sculpin talk I gave<\/a>, at DrupalCamp North in July 2015.<\/p>\n\n<p>I had three Git repositories, the current Sculpin one, the Astro version, and the original Sculpin version with its first commit in March 2015 - a few months before DrupalCamp North.<\/p>\n\n<p>Static site generators keep the files in text files intead of a database, so I was wondering if it was possible to merge the repositories together and combine the information whilst keeping the same commit history so existing tags and contribtions would still apply to the original commits.<\/p>\n\n<p>In short, I was able to do it by adding the old repositories as additional remotes and using the <code>--allow-unrelated-histories<\/code> <a href=\"https:\/\/git-scm.com\/docs\/git-merge#Documentation\/git-merge.txt---allow-unrelated-histories\">option for git merge<\/a>.<\/p>\n\n<p>After fixing some minor merge conflicts, everything was merged successfully and I have [one repository containing 5,272 all commits][2], going back to 2015.<\/p>\n\n<p>This makes it older than <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/08\/08\/8-years-of-dotfiles\">my dotfiles repository<\/a>, which I started in July 2015.<\/p>\n\n<p>Similar to <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/07\/31\/why-i-use-linux\">why I use Linux<\/a>, I believe in owning your own content rather than relying on third-party platforms, so having all my content and history in one repository is great.<\/p>\n\n<p>And I learned something new about Git at the same time.<\/p>\n\n ",
"processed": "\n <p>My website is built with Sculpin - a static site generator written in PHP.<\/p>\n\n<p>It uses a some of the same Symfony components as Drupal, uses Twig for templating and YAML for configuration, and has similar features like content types and taxonomies for structuring content.<\/p>\n\n<p>When I first created my website it was on Drupal 6 and upgraded to Drupal 7 before I started to take an interest in static site generators and later using Jekyll, Sculpin and Astro (and Sculpin, again).<\/p>\n\n<p>I enjoyed learning Sculpin and took it as an opportunity to learn Twig before Drupal 8, which I spoke about in <a href=\"/presentations\/test-drive-twig-with-sculpin\">the first Sculpin talk I gave<\/a>, at DrupalCamp North in July 2015.<\/p>\n\n<p>I had three Git repositories, the current Sculpin one, the Astro version, and the original Sculpin version with its first commit in March 2015 - a few months before DrupalCamp North.<\/p>\n\n<p>Static site generators keep the files in text files intead of a database, so I was wondering if it was possible to merge the repositories together and combine the information whilst keeping the same commit history so existing tags and contribtions would still apply to the original commits.<\/p>\n\n<p>In short, I was able to do it by adding the old repositories as additional remotes and using the <code>--allow-unrelated-histories<\/code> <a href=\"https:\/\/git-scm.com\/docs\/git-merge#Documentation\/git-merge.txt---allow-unrelated-histories\">option for git merge<\/a>.<\/p>\n\n<p>After fixing some minor merge conflicts, everything was merged successfully and I have [one repository containing 5,272 all commits][2], going back to 2015.<\/p>\n\n<p>This makes it older than <a href=\"/daily\/2023\/08\/08\/8-years-of-dotfiles\">my dotfiles repository<\/a>, which I started in July 2015.<\/p>\n\n<p>Similar to <a href=\"/daily\/2024\/07\/31\/why-i-use-linux\">why I use Linux<\/a>, I believe in owning your own content rather than relying on third-party platforms, so having all my content and history in one repository is great.<\/p>\n\n<p>And I learned something new about Git at the same time.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/2-alternate-realities\">This week's episode<\/a> of the Beyond Blocks podcast is live, where I speak with Panagiotis Moutsopoulos (vensires on Drupal.org) - Drupal Backend Developer at E-Sepia.<\/p>\n\n<p>We discuss his first time DrupalCon and, more specifically, his session \"Drupal's Alternate Realities\" - a \"Birds of a Feather\" (BoF) session presenting some history, but mainly the different ways to tackle a problem in Drupal using different methodologies.<\/p>\n\n ",
"value": "\n <p><a href=\"/podcast\/2-alternate-realities\">This week's episode<\/a> of the Beyond Blocks podcast is live, where I speak with Panagiotis Moutsopoulos (vensires on Drupal.org) - Drupal Backend Developer at E-Sepia.<\/p>\n\n<p>We discuss his first time DrupalCon and, more specifically, his session \"Drupal's Alternate Realities\" - a \"Birds of a Feather\" (BoF) session presenting some history, but mainly the different ways to tackle a problem in Drupal using different methodologies.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/2-alternate-realities\">This week's episode<\/a> of the Beyond Blocks podcast is live, where I speak with Panagiotis Moutsopoulos (vensires on Drupal.org) - Drupal Backend Developer at E-Sepia.<\/p>\n\n<p>We discuss his first time DrupalCon and, more specifically, his session \"Drupal's Alternate Realities\" - a \"Birds of a Feather\" (BoF) session presenting some history, but mainly the different ways to tackle a problem in Drupal using different methodologies.<\/p>\n\n ",
"processed": "\n <p><a href=\"/podcast\/2-alternate-realities\">This week's episode<\/a> of the Beyond Blocks podcast is live, where I speak with Panagiotis Moutsopoulos (vensires on Drupal.org) - Drupal Backend Developer at E-Sepia.<\/p>\n\n<p>We discuss his first time DrupalCon and, more specifically, his session \"Drupal's Alternate Realities\" - a \"Birds of a Feather\" (BoF) session presenting some history, but mainly the different ways to tackle a problem in Drupal using different methodologies.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>As well as <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/27\/nix-as-an-operating-system\">my laptop configuration<\/a>, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/30\/using-nix-for-local-application-development\">local development environments<\/a> and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/28\/running-nixos-in-the-cloud\">production server<\/a>, I've also been using Nix for something else recently.<\/p>\n\n<p>Setting up and configuring a Homelab on an old laptop.<\/p>\n\n<p>I've been able to install and configure services like Jellyfin for playing video files, Immich for photo hosting and management, Gitea as my own Git server, Vaultwarden for securely storing my passwords and Traefik as a reverse proxy.<\/p>\n\n<p>Each of these was very easy to configure with only a few lines of the Nix language and avoided a heavy use of Docker which seems common in most Homelab setups.<\/p>\n\n<p>Next, I'd like to add home automation with Home Assistant and explore running a local DNS server within my network.<\/p>\n\n<p>I'm looking forward to these, and seeing what else I can add to this setup using Nix and NixOS.<\/p>\n\n ",
"value": "\n <p>As well as <a href=\"/daily\/2024\/11\/27\/nix-as-an-operating-system\">my laptop configuration<\/a>, <a href=\"/daily\/2024\/11\/30\/using-nix-for-local-application-development\">local development environments<\/a> and <a href=\"/daily\/2024\/11\/28\/running-nixos-in-the-cloud\">production server<\/a>, I've also been using Nix for something else recently.<\/p>\n\n<p>Setting up and configuring a Homelab on an old laptop.<\/p>\n\n<p>I've been able to install and configure services like Jellyfin for playing video files, Immich for photo hosting and management, Gitea as my own Git server, Vaultwarden for securely storing my passwords and Traefik as a reverse proxy.<\/p>\n\n<p>Each of these was very easy to configure with only a few lines of the Nix language and avoided a heavy use of Docker which seems common in most Homelab setups.<\/p>\n\n<p>Next, I'd like to add home automation with Home Assistant and explore running a local DNS server within my network.<\/p>\n\n<p>I'm looking forward to these, and seeing what else I can add to this setup using Nix and NixOS.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>As well as <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/27\/nix-as-an-operating-system\">my laptop configuration<\/a>, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/30\/using-nix-for-local-application-development\">local development environments<\/a> and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/28\/running-nixos-in-the-cloud\">production server<\/a>, I've also been using Nix for something else recently.<\/p>\n\n<p>Setting up and configuring a Homelab on an old laptop.<\/p>\n\n<p>I've been able to install and configure services like Jellyfin for playing video files, Immich for photo hosting and management, Gitea as my own Git server, Vaultwarden for securely storing my passwords and Traefik as a reverse proxy.<\/p>\n\n<p>Each of these was very easy to configure with only a few lines of the Nix language and avoided a heavy use of Docker which seems common in most Homelab setups.<\/p>\n\n<p>Next, I'd like to add home automation with Home Assistant and explore running a local DNS server within my network.<\/p>\n\n<p>I'm looking forward to these, and seeing what else I can add to this setup using Nix and NixOS.<\/p>\n\n ",
"processed": "\n <p>As well as <a href=\"/daily\/2024\/11\/27\/nix-as-an-operating-system\">my laptop configuration<\/a>, <a href=\"/daily\/2024\/11\/30\/using-nix-for-local-application-development\">local development environments<\/a> and <a href=\"/daily\/2024\/11\/28\/running-nixos-in-the-cloud\">production server<\/a>, I've also been using Nix for something else recently.<\/p>\n\n<p>Setting up and configuring a Homelab on an old laptop.<\/p>\n\n<p>I've been able to install and configure services like Jellyfin for playing video files, Immich for photo hosting and management, Gitea as my own Git server, Vaultwarden for securely storing my passwords and Traefik as a reverse proxy.<\/p>\n\n<p>Each of these was very easy to configure with only a few lines of the Nix language and avoided a heavy use of Docker which seems common in most Homelab setups.<\/p>\n\n<p>Next, I'd like to add home automation with Home Assistant and explore running a local DNS server within my network.<\/p>\n\n<p>I'm looking forward to these, and seeing what else I can add to this setup using Nix and NixOS.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>This week on the <a href=\"https:\/\/www.oliverdavies.uk\/podcast\">Beyond Blocks podcast<\/a>, I'm joined by Dan Leech - a PHP Developer and open-source project creator.<\/p>\n\n<p>He and I recently gave talks at the PHP South West meetup, where Dan introduced a new project - PHP-TUI - for building terminal user interfaces (TUIs) with PHP.<\/p>\n\n<p>I use one of Dan's other open-source projects - Phpactor - within Neovim, and he also presented at PHP South Wales about PHPBench, so it was great to discuss and learn more about these in this episode.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/6-dan-leech-php-tui\">Listen to the episode now<\/a>, and I'll be back with more in the New Year.<\/p>\n\n ",
"value": "\n <p>This week on the <a href=\"/podcast\">Beyond Blocks podcast<\/a>, I'm joined by Dan Leech - a PHP Developer and open-source project creator.<\/p>\n\n<p>He and I recently gave talks at the PHP South West meetup, where Dan introduced a new project - PHP-TUI - for building terminal user interfaces (TUIs) with PHP.<\/p>\n\n<p>I use one of Dan's other open-source projects - Phpactor - within Neovim, and he also presented at PHP South Wales about PHPBench, so it was great to discuss and learn more about these in this episode.<\/p>\n\n<p><a href=\"/podcast\/6-dan-leech-php-tui\">Listen to the episode now<\/a>, and I'll be back with more in the New Year.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>This week on the <a href=\"https:\/\/www.oliverdavies.uk\/podcast\">Beyond Blocks podcast<\/a>, I'm joined by Dan Leech - a PHP Developer and open-source project creator.<\/p>\n\n<p>He and I recently gave talks at the PHP South West meetup, where Dan introduced a new project - PHP-TUI - for building terminal user interfaces (TUIs) with PHP.<\/p>\n\n<p>I use one of Dan's other open-source projects - Phpactor - within Neovim, and he also presented at PHP South Wales about PHPBench, so it was great to discuss and learn more about these in this episode.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/6-dan-leech-php-tui\">Listen to the episode now<\/a>, and I'll be back with more in the New Year.<\/p>\n\n ",
"processed": "\n <p>This week on the <a href=\"/podcast\">Beyond Blocks podcast<\/a>, I'm joined by Dan Leech - a PHP Developer and open-source project creator.<\/p>\n\n<p>He and I recently gave talks at the PHP South West meetup, where Dan introduced a new project - PHP-TUI - for building terminal user interfaces (TUIs) with PHP.<\/p>\n\n<p>I use one of Dan's other open-source projects - Phpactor - within Neovim, and he also presented at PHP South Wales about PHPBench, so it was great to discuss and learn more about these in this episode.<\/p>\n\n<p><a href=\"/podcast\/6-dan-leech-php-tui\">Listen to the episode now<\/a>, and I'll be back with more in the New Year.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>I've noticed a lot of Developers recently adopting SQLite for their database and I wonder why this is.<\/p>\n\n<p>Laravel changed their default database to SQLite for local development.<\/p>\n\n<p>It simplifies the development environment as there's no need for a separate database like MySQL or MariaDB but, if you'll be using one of those in production, won't that cause more issues when you migrate your local application?<\/p>\n\n<p>Drupal supports using SQLite, but, other than for <a href=\"https:\/\/www.oliverdavies.uk\/atdc\">my automated testing course<\/a>, or when running automated tests, I've always used a MySQL or MariaDB database.<\/p>\n\n<p>Maybe this is something to keep an eye on and potentially use more for some scenarios in the future.<\/p>\n\n ",
"value": "\n <p>I've noticed a lot of Developers recently adopting SQLite for their database and I wonder why this is.<\/p>\n\n<p>Laravel changed their default database to SQLite for local development.<\/p>\n\n<p>It simplifies the development environment as there's no need for a separate database like MySQL or MariaDB but, if you'll be using one of those in production, won't that cause more issues when you migrate your local application?<\/p>\n\n<p>Drupal supports using SQLite, but, other than for <a href=\"/atdc\">my automated testing course<\/a>, or when running automated tests, I've always used a MySQL or MariaDB database.<\/p>\n\n<p>Maybe this is something to keep an eye on and potentially use more for some scenarios in the future.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>I've noticed a lot of Developers recently adopting SQLite for their database and I wonder why this is.<\/p>\n\n<p>Laravel changed their default database to SQLite for local development.<\/p>\n\n<p>It simplifies the development environment as there's no need for a separate database like MySQL or MariaDB but, if you'll be using one of those in production, won't that cause more issues when you migrate your local application?<\/p>\n\n<p>Drupal supports using SQLite, but, other than for <a href=\"https:\/\/www.oliverdavies.uk\/atdc\">my automated testing course<\/a>, or when running automated tests, I've always used a MySQL or MariaDB database.<\/p>\n\n<p>Maybe this is something to keep an eye on and potentially use more for some scenarios in the future.<\/p>\n\n ",
"processed": "\n <p>I've noticed a lot of Developers recently adopting SQLite for their database and I wonder why this is.<\/p>\n\n<p>Laravel changed their default database to SQLite for local development.<\/p>\n\n<p>It simplifies the development environment as there's no need for a separate database like MySQL or MariaDB but, if you'll be using one of those in production, won't that cause more issues when you migrate your local application?<\/p>\n\n<p>Drupal supports using SQLite, but, other than for <a href=\"/atdc\">my automated testing course<\/a>, or when running automated tests, I've always used a MySQL or MariaDB database.<\/p>\n\n<p>Maybe this is something to keep an eye on and potentially use more for some scenarios in the future.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>As well as <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/06\/03\/writing-comments-first\">writing comments first<\/a>, when writing tests, I sometimes like to write my tests backwards and start by writing the assertions first.<\/p>\n\n<p>I know what I want to assert in the test, so it's an easy place to start.<\/p>\n\n<p>I'll run it, see the error, fix it and continue working backwards.<\/p>\n\n<p>For example, I could start with this:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>This test will fail when I run it, but it makes me think about what I need to do to fix the error and how to do so in the best way.<\/p>\n\n<p>In this case, I need to make a request to the page that should render the text:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n $this-&gt;drupalGet('\/blog');\n\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>This will still fail, as I also need to create the required posts:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n PostBuilder::create()-&gt;setTitle('Post one')-&gt;getPost();\n PostBuilder::create()-&gt;setTitle('Post two')-&gt;getPost();\n\n $this-&gt;createNode([\n 'title' =&gt; 'This is not a post',\n 'type' =&gt; 'page',\n ]);\n\n $this-&gt;drupalGet('\/blog');\n\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>Now the test passes.<\/p>\n\n<p>Doing test-driven development keeps my code clean and minimal, and I find this approach keeps my test clean, too.<\/p>\n\n ",
"value": "\n <p>As well as <a href=\"/daily\/2024\/06\/03\/writing-comments-first\">writing comments first<\/a>, when writing tests, I sometimes like to write my tests backwards and start by writing the assertions first.<\/p>\n\n<p>I know what I want to assert in the test, so it's an easy place to start.<\/p>\n\n<p>I'll run it, see the error, fix it and continue working backwards.<\/p>\n\n<p>For example, I could start with this:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>This test will fail when I run it, but it makes me think about what I need to do to fix the error and how to do so in the best way.<\/p>\n\n<p>In this case, I need to make a request to the page that should render the text:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n $this-&gt;drupalGet('\/blog');\n\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>This will still fail, as I also need to create the required posts:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n PostBuilder::create()-&gt;setTitle('Post one')-&gt;getPost();\n PostBuilder::create()-&gt;setTitle('Post two')-&gt;getPost();\n\n $this-&gt;createNode([\n 'title' =&gt; 'This is not a post',\n 'type' =&gt; 'page',\n ]);\n\n $this-&gt;drupalGet('\/blog');\n\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>Now the test passes.<\/p>\n\n<p>Doing test-driven development keeps my code clean and minimal, and I find this approach keeps my test clean, too.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>As well as <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/06\/03\/writing-comments-first\">writing comments first<\/a>, when writing tests, I sometimes like to write my tests backwards and start by writing the assertions first.<\/p>\n\n<p>I know what I want to assert in the test, so it's an easy place to start.<\/p>\n\n<p>I'll run it, see the error, fix it and continue working backwards.<\/p>\n\n<p>For example, I could start with this:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>This test will fail when I run it, but it makes me think about what I need to do to fix the error and how to do so in the best way.<\/p>\n\n<p>In this case, I need to make a request to the page that should render the text:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n $this-&gt;drupalGet('\/blog');\n\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>This will still fail, as I also need to create the required posts:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n PostBuilder::create()-&gt;setTitle('Post one')-&gt;getPost();\n PostBuilder::create()-&gt;setTitle('Post two')-&gt;getPost();\n\n $this-&gt;createNode([\n 'title' =&gt; 'This is not a post',\n 'type' =&gt; 'page',\n ]);\n\n $this-&gt;drupalGet('\/blog');\n\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>Now the test passes.<\/p>\n\n<p>Doing test-driven development keeps my code clean and minimal, and I find this approach keeps my test clean, too.<\/p>\n\n ",
"processed": "\n <p>As well as <a href=\"/daily\/2024\/06\/03\/writing-comments-first\">writing comments first<\/a>, when writing tests, I sometimes like to write my tests backwards and start by writing the assertions first.<\/p>\n\n<p>I know what I want to assert in the test, so it's an easy place to start.<\/p>\n\n<p>I'll run it, see the error, fix it and continue working backwards.<\/p>\n\n<p>For example, I could start with this:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>This test will fail when I run it, but it makes me think about what I need to do to fix the error and how to do so in the best way.<\/p>\n\n<p>In this case, I need to make a request to the page that should render the text:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n $this-&gt;drupalGet('\/blog');\n\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>This will still fail, as I also need to create the required posts:<\/p>\n\n<pre><code class=\"php\">public function testOnlyPostNodesAreShown(): void {\n PostBuilder::create()-&gt;setTitle('Post one')-&gt;getPost();\n PostBuilder::create()-&gt;setTitle('Post two')-&gt;getPost();\n\n $this-&gt;createNode([\n 'title' =&gt; 'This is not a post',\n 'type' =&gt; 'page',\n ]);\n\n $this-&gt;drupalGet('\/blog');\n\n $assert = $this-&gt;assertSession();\n $assert-&gt;pageTextContains('Post one');\n $assert-&gt;pageTextContains('Post two');\n $assert-&gt;pageTextNotContains('This is not a post');\n}\n<\/code><\/pre>\n\n<p>Now the test passes.<\/p>\n\n<p>Doing test-driven development keeps my code clean and minimal, and I find this approach keeps my test clean, too.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>It's shown in the examples of the <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/11\/24\/are-conventional-commits-worth-it\">conventional commits specification<\/a> as part of the optional footer data.<\/p>\n\n<p>But is it useful?<\/p>\n\n<p>It can be if your issue tracker is linked to your Git repository and you can click the issue ID in a commit message and see the issue.<\/p>\n\n<p>But, how often do teams change issue-tracking software or the project is passed to a different company that uses a different issue tracker?<\/p>\n\n<p>That makes the issue IDs that reference the old IDs useless as no one has access to the issues it references.<\/p>\n\n<p>I'd recommend putting as much information in the commit message itself and not relying on it being in an external source, like an issue tracker.<\/p>\n\n<p>The Git log and commit messages will remain even if a different issue tracker is used, or a different team starts working on the project, and that additional information isn't lost.<\/p>\n\n<p>I'm not against putting the issue ID in the commit message but don't do it instead of writing a descriptive commit message.<\/p>\n\n ",
"value": "\n <p>It's shown in the examples of the <a href=\"/daily\/2023\/11\/24\/are-conventional-commits-worth-it\">conventional commits specification<\/a> as part of the optional footer data.<\/p>\n\n<p>But is it useful?<\/p>\n\n<p>It can be if your issue tracker is linked to your Git repository and you can click the issue ID in a commit message and see the issue.<\/p>\n\n<p>But, how often do teams change issue-tracking software or the project is passed to a different company that uses a different issue tracker?<\/p>\n\n<p>That makes the issue IDs that reference the old IDs useless as no one has access to the issues it references.<\/p>\n\n<p>I'd recommend putting as much information in the commit message itself and not relying on it being in an external source, like an issue tracker.<\/p>\n\n<p>The Git log and commit messages will remain even if a different issue tracker is used, or a different team starts working on the project, and that additional information isn't lost.<\/p>\n\n<p>I'm not against putting the issue ID in the commit message but don't do it instead of writing a descriptive commit message.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>It's shown in the examples of the <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/11\/24\/are-conventional-commits-worth-it\">conventional commits specification<\/a> as part of the optional footer data.<\/p>\n\n<p>But is it useful?<\/p>\n\n<p>It can be if your issue tracker is linked to your Git repository and you can click the issue ID in a commit message and see the issue.<\/p>\n\n<p>But, how often do teams change issue-tracking software or the project is passed to a different company that uses a different issue tracker?<\/p>\n\n<p>That makes the issue IDs that reference the old IDs useless as no one has access to the issues it references.<\/p>\n\n<p>I'd recommend putting as much information in the commit message itself and not relying on it being in an external source, like an issue tracker.<\/p>\n\n<p>The Git log and commit messages will remain even if a different issue tracker is used, or a different team starts working on the project, and that additional information isn't lost.<\/p>\n\n<p>I'm not against putting the issue ID in the commit message but don't do it instead of writing a descriptive commit message.<\/p>\n\n ",
"processed": "\n <p>It's shown in the examples of the <a href=\"/daily\/2023\/11\/24\/are-conventional-commits-worth-it\">conventional commits specification<\/a> as part of the optional footer data.<\/p>\n\n<p>But is it useful?<\/p>\n\n<p>It can be if your issue tracker is linked to your Git repository and you can click the issue ID in a commit message and see the issue.<\/p>\n\n<p>But, how often do teams change issue-tracking software or the project is passed to a different company that uses a different issue tracker?<\/p>\n\n<p>That makes the issue IDs that reference the old IDs useless as no one has access to the issues it references.<\/p>\n\n<p>I'd recommend putting as much information in the commit message itself and not relying on it being in an external source, like an issue tracker.<\/p>\n\n<p>The Git log and commit messages will remain even if a different issue tracker is used, or a different team starts working on the project, and that additional information isn't lost.<\/p>\n\n<p>I'm not against putting the issue ID in the commit message but don't do it instead of writing a descriptive commit message.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>I took a bit of time off from these emails whilst I was preparing for the first PHP Stoke event which happened last week in Stoke-on-Trent.<\/p>\n\n<p>It was a great event with around 35 attendees and two other speakers as well as myself.<\/p>\n\n<p>The <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/things-you-should-know-about-php\">latest version of my slides are online<\/a> as well <a href=\"https:\/\/www.oliverdavies.uk\/things-about-php\">some updated resources<\/a>.<\/p>\n\n<p>My next talk will be at the Norfolk Developers conference next month where I'll be presenting an updated version of <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/taking-flight-with-tailwind-css\">Taking Flight with Tailwind CSS<\/a>.<\/p>\n\n<p>If you have a topic idea for a talk or would like me to speak at your meetup or conference, please get in touch.<\/p>\n\n ",
"value": "\n <p>I took a bit of time off from these emails whilst I was preparing for the first PHP Stoke event which happened last week in Stoke-on-Trent.<\/p>\n\n<p>It was a great event with around 35 attendees and two other speakers as well as myself.<\/p>\n\n<p>The <a href=\"/presentations\/things-you-should-know-about-php\">latest version of my slides are online<\/a> as well <a href=\"/things-about-php\">some updated resources<\/a>.<\/p>\n\n<p>My next talk will be at the Norfolk Developers conference next month where I'll be presenting an updated version of <a href=\"/presentations\/taking-flight-with-tailwind-css\">Taking Flight with Tailwind CSS<\/a>.<\/p>\n\n<p>If you have a topic idea for a talk or would like me to speak at your meetup or conference, please get in touch.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>I took a bit of time off from these emails whilst I was preparing for the first PHP Stoke event which happened last week in Stoke-on-Trent.<\/p>\n\n<p>It was a great event with around 35 attendees and two other speakers as well as myself.<\/p>\n\n<p>The <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/things-you-should-know-about-php\">latest version of my slides are online<\/a> as well <a href=\"https:\/\/www.oliverdavies.uk\/things-about-php\">some updated resources<\/a>.<\/p>\n\n<p>My next talk will be at the Norfolk Developers conference next month where I'll be presenting an updated version of <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/taking-flight-with-tailwind-css\">Taking Flight with Tailwind CSS<\/a>.<\/p>\n\n<p>If you have a topic idea for a talk or would like me to speak at your meetup or conference, please get in touch.<\/p>\n\n ",
"processed": "\n <p>I took a bit of time off from these emails whilst I was preparing for the first PHP Stoke event which happened last week in Stoke-on-Trent.<\/p>\n\n<p>It was a great event with around 35 attendees and two other speakers as well as myself.<\/p>\n\n<p>The <a href=\"/presentations\/things-you-should-know-about-php\">latest version of my slides are online<\/a> as well <a href=\"/things-about-php\">some updated resources<\/a>.<\/p>\n\n<p>My next talk will be at the Norfolk Developers conference next month where I'll be presenting an updated version of <a href=\"/presentations\/taking-flight-with-tailwind-css\">Taking Flight with Tailwind CSS<\/a>.<\/p>\n\n<p>If you have a topic idea for a talk or would like me to speak at your meetup or conference, please get in touch.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>I've been using Drupal since 2008 and built the first version of my website with Drupal 6 before updating it to Drupal 7.<\/p>\n\n<p>Around that time, I discovered static site generators and built the next version of my website with Jekyll.<\/p>\n\n<p>I liked how I could write content in simple plain files, export them to HTML and upload them to a server.<\/p>\n\n<p>Static websites are fast and secure.<\/p>\n\n<p>There was no need for PHP or a database. Just a simple web server like Apache or Nginx that can serve static files.<\/p>\n\n<p>I later switched to Sculpin, a static site generator written with PHP, which has a lot of similarities with Drupal.<\/p>\n\n<p>But what if you want the power of Drupal with the benefits of a static website?<\/p>\n\n<p><a href=\"https:\/\/www.drupal.org\/project\/tome\">Tome<\/a> is a module that turns Drupal into a static site generator.<\/p>\n\n<p>Drupal works the same locally with access to all the usual core functionality and contrib modules and themes from Drupal.org, but you export everything to static files - the same as using Jekyll or Sculpin.<\/p>\n\n<p>Sam Mortenson, the creator of the Tome module discussed it on <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/19-sam-mortenson\">our episode of the Beyond Blocks podcast<\/a> where we also talked about single file components.<\/p>\n\n<p>If you want the power of a flexible content management system and the performance and security benefits of a static website, Tome gives you the best of both worlds.<\/p>\n\n ",
"value": "\n <p>I've been using Drupal since 2008 and built the first version of my website with Drupal 6 before updating it to Drupal 7.<\/p>\n\n<p>Around that time, I discovered static site generators and built the next version of my website with Jekyll.<\/p>\n\n<p>I liked how I could write content in simple plain files, export them to HTML and upload them to a server.<\/p>\n\n<p>Static websites are fast and secure.<\/p>\n\n<p>There was no need for PHP or a database. Just a simple web server like Apache or Nginx that can serve static files.<\/p>\n\n<p>I later switched to Sculpin, a static site generator written with PHP, which has a lot of similarities with Drupal.<\/p>\n\n<p>But what if you want the power of Drupal with the benefits of a static website?<\/p>\n\n<p><a href=\"https:\/\/www.drupal.org\/project\/tome\">Tome<\/a> is a module that turns Drupal into a static site generator.<\/p>\n\n<p>Drupal works the same locally with access to all the usual core functionality and contrib modules and themes from Drupal.org, but you export everything to static files - the same as using Jekyll or Sculpin.<\/p>\n\n<p>Sam Mortenson, the creator of the Tome module discussed it on <a href=\"/podcast\/19-sam-mortenson\">our episode of the Beyond Blocks podcast<\/a> where we also talked about single file components.<\/p>\n\n<p>If you want the power of a flexible content management system and the performance and security benefits of a static website, Tome gives you the best of both worlds.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>I've been using Drupal since 2008 and built the first version of my website with Drupal 6 before updating it to Drupal 7.<\/p>\n\n<p>Around that time, I discovered static site generators and built the next version of my website with Jekyll.<\/p>\n\n<p>I liked how I could write content in simple plain files, export them to HTML and upload them to a server.<\/p>\n\n<p>Static websites are fast and secure.<\/p>\n\n<p>There was no need for PHP or a database. Just a simple web server like Apache or Nginx that can serve static files.<\/p>\n\n<p>I later switched to Sculpin, a static site generator written with PHP, which has a lot of similarities with Drupal.<\/p>\n\n<p>But what if you want the power of Drupal with the benefits of a static website?<\/p>\n\n<p><a href=\"https:\/\/www.drupal.org\/project\/tome\">Tome<\/a> is a module that turns Drupal into a static site generator.<\/p>\n\n<p>Drupal works the same locally with access to all the usual core functionality and contrib modules and themes from Drupal.org, but you export everything to static files - the same as using Jekyll or Sculpin.<\/p>\n\n<p>Sam Mortenson, the creator of the Tome module discussed it on <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/19-sam-mortenson\">our episode of the Beyond Blocks podcast<\/a> where we also talked about single file components.<\/p>\n\n<p>If you want the power of a flexible content management system and the performance and security benefits of a static website, Tome gives you the best of both worlds.<\/p>\n\n ",
"processed": "\n <p>I've been using Drupal since 2008 and built the first version of my website with Drupal 6 before updating it to Drupal 7.<\/p>\n\n<p>Around that time, I discovered static site generators and built the next version of my website with Jekyll.<\/p>\n\n<p>I liked how I could write content in simple plain files, export them to HTML and upload them to a server.<\/p>\n\n<p>Static websites are fast and secure.<\/p>\n\n<p>There was no need for PHP or a database. Just a simple web server like Apache or Nginx that can serve static files.<\/p>\n\n<p>I later switched to Sculpin, a static site generator written with PHP, which has a lot of similarities with Drupal.<\/p>\n\n<p>But what if you want the power of Drupal with the benefits of a static website?<\/p>\n\n<p><a href=\"https:\/\/www.drupal.org\/project\/tome\">Tome<\/a> is a module that turns Drupal into a static site generator.<\/p>\n\n<p>Drupal works the same locally with access to all the usual core functionality and contrib modules and themes from Drupal.org, but you export everything to static files - the same as using Jekyll or Sculpin.<\/p>\n\n<p>Sam Mortenson, the creator of the Tome module discussed it on <a href=\"/podcast\/19-sam-mortenson\">our episode of the Beyond Blocks podcast<\/a> where we also talked about single file components.<\/p>\n\n<p>If you want the power of a flexible content management system and the performance and security benefits of a static website, Tome gives you the best of both worlds.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Yesterday I replied to <a href=\"https:\/\/x.com\/ianmiell\/status\/1304103008242991111\">a post on X<\/a>:<\/p>\n\n<blockquote>\n <p>I have worked on many teams that use CI tooling and call their process CI, but I have never seen CI actually done as defined on Wikipedia:<\/p>\n \n <p>\"CI is the practice of merging all developers' working copies to a shared mainline several times a day\"<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/blog\/continuous-integration-vs-continuous-integration\">I've written about this before<\/a> and I think the term CI or CI\/CD is one of the most misused or misleading in software development.<\/p>\n\n<p>CI, or continuous integration, is, as the post days, the process of everyone merging their changes at least once, or usually several, times a day.<\/p>\n\n<p>It isn't something that is configured or created - it's a process.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>You can do CI without a CI pipeline and vice versa.<\/p>\n\n<p>You can have a CI pipeline but not do continuous delivery or deployment.<\/p>\n\n<p>What most people think of as CI or CI\/CD is a set of automated checks that run when code is updated - usually on a feature or topic branch.<\/p>\n\n<p>Whilst important, it's not \"CI\".<\/p>\n\n ",
"value": "\n <p>Yesterday I replied to <a href=\"https:\/\/x.com\/ianmiell\/status\/1304103008242991111\">a post on X<\/a>:<\/p>\n\n<blockquote>\n <p>I have worked on many teams that use CI tooling and call their process CI, but I have never seen CI actually done as defined on Wikipedia:<\/p>\n \n <p>\"CI is the practice of merging all developers' working copies to a shared mainline several times a day\"<\/p>\n<\/blockquote>\n\n<p><a href=\"/blog\/continuous-integration-vs-continuous-integration\">I've written about this before<\/a> and I think the term CI or CI\/CD is one of the most misused or misleading in software development.<\/p>\n\n<p>CI, or continuous integration, is, as the post days, the process of everyone merging their changes at least once, or usually several, times a day.<\/p>\n\n<p>It isn't something that is configured or created - it's a process.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>You can do CI without a CI pipeline and vice versa.<\/p>\n\n<p>You can have a CI pipeline but not do continuous delivery or deployment.<\/p>\n\n<p>What most people think of as CI or CI\/CD is a set of automated checks that run when code is updated - usually on a feature or topic branch.<\/p>\n\n<p>Whilst important, it's not \"CI\".<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Yesterday I replied to <a href=\"https:\/\/x.com\/ianmiell\/status\/1304103008242991111\">a post on X<\/a>:<\/p>\n\n<blockquote>\n <p>I have worked on many teams that use CI tooling and call their process CI, but I have never seen CI actually done as defined on Wikipedia:<\/p>\n \n <p>\"CI is the practice of merging all developers' working copies to a shared mainline several times a day\"<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/blog\/continuous-integration-vs-continuous-integration\">I've written about this before<\/a> and I think the term CI or CI\/CD is one of the most misused or misleading in software development.<\/p>\n\n<p>CI, or continuous integration, is, as the post days, the process of everyone merging their changes at least once, or usually several, times a day.<\/p>\n\n<p>It isn't something that is configured or created - it's a process.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>You can do CI without a CI pipeline and vice versa.<\/p>\n\n<p>You can have a CI pipeline but not do continuous delivery or deployment.<\/p>\n\n<p>What most people think of as CI or CI\/CD is a set of automated checks that run when code is updated - usually on a feature or topic branch.<\/p>\n\n<p>Whilst important, it's not \"CI\".<\/p>\n\n ",
"processed": "\n <p>Yesterday I replied to <a href=\"https:\/\/x.com\/ianmiell\/status\/1304103008242991111\">a post on X<\/a>:<\/p>\n\n<blockquote>\n <p>I have worked on many teams that use CI tooling and call their process CI, but I have never seen CI actually done as defined on Wikipedia:<\/p>\n \n <p>\"CI is the practice of merging all developers' working copies to a shared mainline several times a day\"<\/p>\n<\/blockquote>\n\n<p><a href=\"/blog\/continuous-integration-vs-continuous-integration\">I've written about this before<\/a> and I think the term CI or CI\/CD is one of the most misused or misleading in software development.<\/p>\n\n<p>CI, or continuous integration, is, as the post days, the process of everyone merging their changes at least once, or usually several, times a day.<\/p>\n\n<p>It isn't something that is configured or created - it's a process.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>You can do CI without a CI pipeline and vice versa.<\/p>\n\n<p>You can have a CI pipeline but not do continuous delivery or deployment.<\/p>\n\n<p>What most people think of as CI or CI\/CD is a set of automated checks that run when code is updated - usually on a feature or topic branch.<\/p>\n\n<p>Whilst important, it's not \"CI\".<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Last Friday and Saturday, I was happy to attend and present two sessions at DrupalCamp Ghent in Belgium.<\/p>\n\n<p>I was able to present talks on automated testing and Tailwind CSS, which were my 99th and 100th talks, respectively!<\/p>\n\n<p>The sessions were streamed live, or the slides and previous recordings <a href=\"https:\/\/www.oliverdavies.uk\/dcg\">are on my website<\/a>.<\/p>\n\n<p>It was a great event and it's always nice to see and meet new people within the Drupal community, to see new places and share knowledge by giving presentations.<\/p>\n\n<p>Reply and let me know if you have any feedback on the sessions or if you'd like me to present a talk or workshop at your event.<\/p>\n\n ",
"value": "\n <p>Last Friday and Saturday, I was happy to attend and present two sessions at DrupalCamp Ghent in Belgium.<\/p>\n\n<p>I was able to present talks on automated testing and Tailwind CSS, which were my 99th and 100th talks, respectively!<\/p>\n\n<p>The sessions were streamed live, or the slides and previous recordings <a href=\"/dcg\">are on my website<\/a>.<\/p>\n\n<p>It was a great event and it's always nice to see and meet new people within the Drupal community, to see new places and share knowledge by giving presentations.<\/p>\n\n<p>Reply and let me know if you have any feedback on the sessions or if you'd like me to present a talk or workshop at your event.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Last Friday and Saturday, I was happy to attend and present two sessions at DrupalCamp Ghent in Belgium.<\/p>\n\n<p>I was able to present talks on automated testing and Tailwind CSS, which were my 99th and 100th talks, respectively!<\/p>\n\n<p>The sessions were streamed live, or the slides and previous recordings <a href=\"https:\/\/www.oliverdavies.uk\/dcg\">are on my website<\/a>.<\/p>\n\n<p>It was a great event and it's always nice to see and meet new people within the Drupal community, to see new places and share knowledge by giving presentations.<\/p>\n\n<p>Reply and let me know if you have any feedback on the sessions or if you'd like me to present a talk or workshop at your event.<\/p>\n\n ",
"processed": "\n <p>Last Friday and Saturday, I was happy to attend and present two sessions at DrupalCamp Ghent in Belgium.<\/p>\n\n<p>I was able to present talks on automated testing and Tailwind CSS, which were my 99th and 100th talks, respectively!<\/p>\n\n<p>The sessions were streamed live, or the slides and previous recordings <a href=\"/dcg\">are on my website<\/a>.<\/p>\n\n<p>It was a great event and it's always nice to see and meet new people within the Drupal community, to see new places and share knowledge by giving presentations.<\/p>\n\n<p>Reply and let me know if you have any feedback on the sessions or if you'd like me to present a talk or workshop at your event.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>If <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/18\/conflicts\">feature branches cause conflicts<\/a>, what is the alternative?<\/p>\n\n<p>Don't branch.<\/p>\n\n<p>Keep all changes on a single branch and avoid merge conflicts between branches by not having branches.<\/p>\n\n<p>But how can you avoid releasing changes before they are ready?<\/p>\n\n<p>You can have a local branch with your changes that you don't push and rebase locally, but then <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/17\/ci-cd\">you're not doing continuous integration<\/a> and you're just as likely to get conflicts and have incompatible code.<\/p>\n\n<p>One of the main benefits of trunk-based development, where everything is on a single branch, is that everyone's work always works together.<\/p>\n\n<p>The better option is to use feature toggles (aka feature flags).<\/p>\n\n<p>Wrapping code in feature toggles separates deploying the code from releasing the feature.<\/p>\n\n<p>The code can be released, but the feature isn't active until the toggle is enabled.<\/p>\n\n<p>This means everyone can work on the same branch and continuously deploy changes whilst being selective about the features that are visible to the end users.<\/p>\n\n<p>If you have multiple environments, the same code can be used with different toggles enabled to allow for testing different features.<\/p>\n\n<p>Then, once the feature is ready to be enabled, there is no deployment needed.<\/p>\n\n<p>The code is already there - it just needs to be enabled.<\/p>\n\n<p>For Drupal, there is a <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle\">Feature Toggle module<\/a> and <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle_twig\">an extension that I wrote<\/a> that make it easy to use and manage feature toggles by just logging into the admin UI and selecting the active toggles you want.<\/p>\n\n<p>And, if an issue is discovered, it can also be easily disabled <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/19\/back-or-forward\">without needing to roll back to the previous version<\/a>.<\/p>\n\n ",
"value": "\n <p>If <a href=\"/daily\/2025\/02\/18\/conflicts\">feature branches cause conflicts<\/a>, what is the alternative?<\/p>\n\n<p>Don't branch.<\/p>\n\n<p>Keep all changes on a single branch and avoid merge conflicts between branches by not having branches.<\/p>\n\n<p>But how can you avoid releasing changes before they are ready?<\/p>\n\n<p>You can have a local branch with your changes that you don't push and rebase locally, but then <a href=\"/daily\/2025\/02\/17\/ci-cd\">you're not doing continuous integration<\/a> and you're just as likely to get conflicts and have incompatible code.<\/p>\n\n<p>One of the main benefits of trunk-based development, where everything is on a single branch, is that everyone's work always works together.<\/p>\n\n<p>The better option is to use feature toggles (aka feature flags).<\/p>\n\n<p>Wrapping code in feature toggles separates deploying the code from releasing the feature.<\/p>\n\n<p>The code can be released, but the feature isn't active until the toggle is enabled.<\/p>\n\n<p>This means everyone can work on the same branch and continuously deploy changes whilst being selective about the features that are visible to the end users.<\/p>\n\n<p>If you have multiple environments, the same code can be used with different toggles enabled to allow for testing different features.<\/p>\n\n<p>Then, once the feature is ready to be enabled, there is no deployment needed.<\/p>\n\n<p>The code is already there - it just needs to be enabled.<\/p>\n\n<p>For Drupal, there is a <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle\">Feature Toggle module<\/a> and <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle_twig\">an extension that I wrote<\/a> that make it easy to use and manage feature toggles by just logging into the admin UI and selecting the active toggles you want.<\/p>\n\n<p>And, if an issue is discovered, it can also be easily disabled <a href=\"/daily\/2025\/02\/19\/back-or-forward\">without needing to roll back to the previous version<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>If <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/18\/conflicts\">feature branches cause conflicts<\/a>, what is the alternative?<\/p>\n\n<p>Don't branch.<\/p>\n\n<p>Keep all changes on a single branch and avoid merge conflicts between branches by not having branches.<\/p>\n\n<p>But how can you avoid releasing changes before they are ready?<\/p>\n\n<p>You can have a local branch with your changes that you don't push and rebase locally, but then <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/17\/ci-cd\">you're not doing continuous integration<\/a> and you're just as likely to get conflicts and have incompatible code.<\/p>\n\n<p>One of the main benefits of trunk-based development, where everything is on a single branch, is that everyone's work always works together.<\/p>\n\n<p>The better option is to use feature toggles (aka feature flags).<\/p>\n\n<p>Wrapping code in feature toggles separates deploying the code from releasing the feature.<\/p>\n\n<p>The code can be released, but the feature isn't active until the toggle is enabled.<\/p>\n\n<p>This means everyone can work on the same branch and continuously deploy changes whilst being selective about the features that are visible to the end users.<\/p>\n\n<p>If you have multiple environments, the same code can be used with different toggles enabled to allow for testing different features.<\/p>\n\n<p>Then, once the feature is ready to be enabled, there is no deployment needed.<\/p>\n\n<p>The code is already there - it just needs to be enabled.<\/p>\n\n<p>For Drupal, there is a <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle\">Feature Toggle module<\/a> and <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle_twig\">an extension that I wrote<\/a> that make it easy to use and manage feature toggles by just logging into the admin UI and selecting the active toggles you want.<\/p>\n\n<p>And, if an issue is discovered, it can also be easily disabled <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/19\/back-or-forward\">without needing to roll back to the previous version<\/a>.<\/p>\n\n ",
"processed": "\n <p>If <a href=\"/daily\/2025\/02\/18\/conflicts\">feature branches cause conflicts<\/a>, what is the alternative?<\/p>\n\n<p>Don't branch.<\/p>\n\n<p>Keep all changes on a single branch and avoid merge conflicts between branches by not having branches.<\/p>\n\n<p>But how can you avoid releasing changes before they are ready?<\/p>\n\n<p>You can have a local branch with your changes that you don't push and rebase locally, but then <a href=\"/daily\/2025\/02\/17\/ci-cd\">you're not doing continuous integration<\/a> and you're just as likely to get conflicts and have incompatible code.<\/p>\n\n<p>One of the main benefits of trunk-based development, where everything is on a single branch, is that everyone's work always works together.<\/p>\n\n<p>The better option is to use feature toggles (aka feature flags).<\/p>\n\n<p>Wrapping code in feature toggles separates deploying the code from releasing the feature.<\/p>\n\n<p>The code can be released, but the feature isn't active until the toggle is enabled.<\/p>\n\n<p>This means everyone can work on the same branch and continuously deploy changes whilst being selective about the features that are visible to the end users.<\/p>\n\n<p>If you have multiple environments, the same code can be used with different toggles enabled to allow for testing different features.<\/p>\n\n<p>Then, once the feature is ready to be enabled, there is no deployment needed.<\/p>\n\n<p>The code is already there - it just needs to be enabled.<\/p>\n\n<p>For Drupal, there is a <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle\">Feature Toggle module<\/a> and <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle_twig\">an extension that I wrote<\/a> that make it easy to use and manage feature toggles by just logging into the admin UI and selecting the active toggles you want.<\/p>\n\n<p>And, if an issue is discovered, it can also be easily disabled <a href=\"/daily\/2025\/02\/19\/back-or-forward\">without needing to roll back to the previous version<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Instead of <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/31\/putting-glue-on-pizza\">using AI to autocomplete code<\/a> or <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/10\/08\/ai-in-drupal\">perform tasks within your Drupal website<\/a>, I've seen people using AI as a virtual pair programming partner.<\/p>\n\n<p>Similar to using a search engine or finding results on websites like Stack Overflow, but also being able to ask follow-up questions and for clarification as part of a conversation.<\/p>\n\n<p>You're still relying on its answers and advice to be correct, but using AI as a learning tool seems like a sensible approach if you don't have a non-AI pairing partner available.<\/p>\n\n<p>Just make sure to validate and verify whatever it gives you.<\/p>\n\n<p>Once you've committed it, you're responsible for it.<\/p>\n\n ",
"value": "\n <p>Instead of <a href=\"/daily\/2024\/05\/31\/putting-glue-on-pizza\">using AI to autocomplete code<\/a> or <a href=\"/daily\/2024\/10\/08\/ai-in-drupal\">perform tasks within your Drupal website<\/a>, I've seen people using AI as a virtual pair programming partner.<\/p>\n\n<p>Similar to using a search engine or finding results on websites like Stack Overflow, but also being able to ask follow-up questions and for clarification as part of a conversation.<\/p>\n\n<p>You're still relying on its answers and advice to be correct, but using AI as a learning tool seems like a sensible approach if you don't have a non-AI pairing partner available.<\/p>\n\n<p>Just make sure to validate and verify whatever it gives you.<\/p>\n\n<p>Once you've committed it, you're responsible for it.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Instead of <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/31\/putting-glue-on-pizza\">using AI to autocomplete code<\/a> or <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/10\/08\/ai-in-drupal\">perform tasks within your Drupal website<\/a>, I've seen people using AI as a virtual pair programming partner.<\/p>\n\n<p>Similar to using a search engine or finding results on websites like Stack Overflow, but also being able to ask follow-up questions and for clarification as part of a conversation.<\/p>\n\n<p>You're still relying on its answers and advice to be correct, but using AI as a learning tool seems like a sensible approach if you don't have a non-AI pairing partner available.<\/p>\n\n<p>Just make sure to validate and verify whatever it gives you.<\/p>\n\n<p>Once you've committed it, you're responsible for it.<\/p>\n\n ",
"processed": "\n <p>Instead of <a href=\"/daily\/2024\/05\/31\/putting-glue-on-pizza\">using AI to autocomplete code<\/a> or <a href=\"/daily\/2024\/10\/08\/ai-in-drupal\">perform tasks within your Drupal website<\/a>, I've seen people using AI as a virtual pair programming partner.<\/p>\n\n<p>Similar to using a search engine or finding results on websites like Stack Overflow, but also being able to ask follow-up questions and for clarification as part of a conversation.<\/p>\n\n<p>You're still relying on its answers and advice to be correct, but using AI as a learning tool seems like a sensible approach if you don't have a non-AI pairing partner available.<\/p>\n\n<p>Just make sure to validate and verify whatever it gives you.<\/p>\n\n<p>Once you've committed it, you're responsible for it.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>I've recently decided I'm going to open source <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/building-build-configs\">Build Configs tool<\/a> that I use to generate build configuration files for Drupal, Sculpin and Fractal projects.<\/p>\n\n<p>Inspired by <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/working-with-workspace\">Workspace<\/a> and others, and based on previous versions of similar tools - most recently by <a href=\"https:\/\/github.com\/ALT-F4-LLC\/build-configs\">TheAltF4Stream's project with the same name<\/a> (which is written in Rust and supports different template types) - I've been using this tool to manage configuration files for various personal, client and open-source projects.<\/p>\n\n<p>Before I open-source it, there are some changes I'd like to make, such as renaming some template types and updating the format and keys within the configuration file.<\/p>\n\n<p>Changes to the configuration file would be a breaking change and, whilst it's only me using it, I want my other projects to keep working and for me to continue supporting the prior versions - at least for now, so I want to make sure any changes are backward compatible.<\/p>\n\n<h2 id=\"how-it-works\">How it works<\/h2>\n\n<p>There are four steps performed when generating files for a project:<\/p>\n\n<ul>\n<li>Create a final configuration object from the project's configuration file as well as any defaults.<\/li>\n<li>Validate the final configuration.<\/li>\n<li>Create a list of files to generate.<\/li>\n<li>Generate the files.<\/li>\n<\/ul>\n\n<p>If I change <code>sculpin<\/code> to <code>sculpin-site<\/code> in a configuration file, for example, it will fail the validation step.<\/p>\n\n<p>But, I have an opportunity within the first step to perform any normalisation that's needed and to provide a compatibility layer - such as changing <code>sculpin-site<\/code>, which is an invalid value, to <code>sculpin<\/code>.<\/p>\n\n<p>I also renamed <code>symfony<\/code> to <code>symfony-cli<\/code> by performing the same step.<\/p>\n\n<p>This means the validation step will receive valid data that it can use and the new changes have been encapsulated within a single step of the process. I haven't needed to change any code elsewhere.<\/p>\n\n<p>I can also add deprecation warnings if legacy values are used.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Similar to feature flags, this is temporary code that will later be removed when I'm ready to remove the compatibility layer, similar to how <code>drupal_set_message()<\/code> was deprecated and changed to use the <code>Messenger<\/code> service before being removed in Drupal 9.<\/p>\n\n<p>In the future, I can refactor the internal logic to use a different approach and when I'm ready, eventually remove the compatibility layer and tag a new major version with the breaking changes.<\/p>\n\n ",
"value": "\n <p>I've recently decided I'm going to open source <a href=\"/presentations\/building-build-configs\">Build Configs tool<\/a> that I use to generate build configuration files for Drupal, Sculpin and Fractal projects.<\/p>\n\n<p>Inspired by <a href=\"/presentations\/working-with-workspace\">Workspace<\/a> and others, and based on previous versions of similar tools - most recently by <a href=\"https:\/\/github.com\/ALT-F4-LLC\/build-configs\">TheAltF4Stream's project with the same name<\/a> (which is written in Rust and supports different template types) - I've been using this tool to manage configuration files for various personal, client and open-source projects.<\/p>\n\n<p>Before I open-source it, there are some changes I'd like to make, such as renaming some template types and updating the format and keys within the configuration file.<\/p>\n\n<p>Changes to the configuration file would be a breaking change and, whilst it's only me using it, I want my other projects to keep working and for me to continue supporting the prior versions - at least for now, so I want to make sure any changes are backward compatible.<\/p>\n\n<h2 id=\"how-it-works\">How it works<\/h2>\n\n<p>There are four steps performed when generating files for a project:<\/p>\n\n<ul>\n<li>Create a final configuration object from the project's configuration file as well as any defaults.<\/li>\n<li>Validate the final configuration.<\/li>\n<li>Create a list of files to generate.<\/li>\n<li>Generate the files.<\/li>\n<\/ul>\n\n<p>If I change <code>sculpin<\/code> to <code>sculpin-site<\/code> in a configuration file, for example, it will fail the validation step.<\/p>\n\n<p>But, I have an opportunity within the first step to perform any normalisation that's needed and to provide a compatibility layer - such as changing <code>sculpin-site<\/code>, which is an invalid value, to <code>sculpin<\/code>.<\/p>\n\n<p>I also renamed <code>symfony<\/code> to <code>symfony-cli<\/code> by performing the same step.<\/p>\n\n<p>This means the validation step will receive valid data that it can use and the new changes have been encapsulated within a single step of the process. I haven't needed to change any code elsewhere.<\/p>\n\n<p>I can also add deprecation warnings if legacy values are used.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Similar to feature flags, this is temporary code that will later be removed when I'm ready to remove the compatibility layer, similar to how <code>drupal_set_message()<\/code> was deprecated and changed to use the <code>Messenger<\/code> service before being removed in Drupal 9.<\/p>\n\n<p>In the future, I can refactor the internal logic to use a different approach and when I'm ready, eventually remove the compatibility layer and tag a new major version with the breaking changes.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>I've recently decided I'm going to open source <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/building-build-configs\">Build Configs tool<\/a> that I use to generate build configuration files for Drupal, Sculpin and Fractal projects.<\/p>\n\n<p>Inspired by <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/working-with-workspace\">Workspace<\/a> and others, and based on previous versions of similar tools - most recently by <a href=\"https:\/\/github.com\/ALT-F4-LLC\/build-configs\">TheAltF4Stream's project with the same name<\/a> (which is written in Rust and supports different template types) - I've been using this tool to manage configuration files for various personal, client and open-source projects.<\/p>\n\n<p>Before I open-source it, there are some changes I'd like to make, such as renaming some template types and updating the format and keys within the configuration file.<\/p>\n\n<p>Changes to the configuration file would be a breaking change and, whilst it's only me using it, I want my other projects to keep working and for me to continue supporting the prior versions - at least for now, so I want to make sure any changes are backward compatible.<\/p>\n\n<h2 id=\"how-it-works\">How it works<\/h2>\n\n<p>There are four steps performed when generating files for a project:<\/p>\n\n<ul>\n<li>Create a final configuration object from the project's configuration file as well as any defaults.<\/li>\n<li>Validate the final configuration.<\/li>\n<li>Create a list of files to generate.<\/li>\n<li>Generate the files.<\/li>\n<\/ul>\n\n<p>If I change <code>sculpin<\/code> to <code>sculpin-site<\/code> in a configuration file, for example, it will fail the validation step.<\/p>\n\n<p>But, I have an opportunity within the first step to perform any normalisation that's needed and to provide a compatibility layer - such as changing <code>sculpin-site<\/code>, which is an invalid value, to <code>sculpin<\/code>.<\/p>\n\n<p>I also renamed <code>symfony<\/code> to <code>symfony-cli<\/code> by performing the same step.<\/p>\n\n<p>This means the validation step will receive valid data that it can use and the new changes have been encapsulated within a single step of the process. I haven't needed to change any code elsewhere.<\/p>\n\n<p>I can also add deprecation warnings if legacy values are used.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Similar to feature flags, this is temporary code that will later be removed when I'm ready to remove the compatibility layer, similar to how <code>drupal_set_message()<\/code> was deprecated and changed to use the <code>Messenger<\/code> service before being removed in Drupal 9.<\/p>\n\n<p>In the future, I can refactor the internal logic to use a different approach and when I'm ready, eventually remove the compatibility layer and tag a new major version with the breaking changes.<\/p>\n\n ",
"processed": "\n <p>I've recently decided I'm going to open source <a href=\"/presentations\/building-build-configs\">Build Configs tool<\/a> that I use to generate build configuration files for Drupal, Sculpin and Fractal projects.<\/p>\n\n<p>Inspired by <a href=\"/presentations\/working-with-workspace\">Workspace<\/a> and others, and based on previous versions of similar tools - most recently by <a href=\"https:\/\/github.com\/ALT-F4-LLC\/build-configs\">TheAltF4Stream's project with the same name<\/a> (which is written in Rust and supports different template types) - I've been using this tool to manage configuration files for various personal, client and open-source projects.<\/p>\n\n<p>Before I open-source it, there are some changes I'd like to make, such as renaming some template types and updating the format and keys within the configuration file.<\/p>\n\n<p>Changes to the configuration file would be a breaking change and, whilst it's only me using it, I want my other projects to keep working and for me to continue supporting the prior versions - at least for now, so I want to make sure any changes are backward compatible.<\/p>\n\n<h2 id=\"how-it-works\">How it works<\/h2>\n\n<p>There are four steps performed when generating files for a project:<\/p>\n\n<ul>\n<li>Create a final configuration object from the project's configuration file as well as any defaults.<\/li>\n<li>Validate the final configuration.<\/li>\n<li>Create a list of files to generate.<\/li>\n<li>Generate the files.<\/li>\n<\/ul>\n\n<p>If I change <code>sculpin<\/code> to <code>sculpin-site<\/code> in a configuration file, for example, it will fail the validation step.<\/p>\n\n<p>But, I have an opportunity within the first step to perform any normalisation that's needed and to provide a compatibility layer - such as changing <code>sculpin-site<\/code>, which is an invalid value, to <code>sculpin<\/code>.<\/p>\n\n<p>I also renamed <code>symfony<\/code> to <code>symfony-cli<\/code> by performing the same step.<\/p>\n\n<p>This means the validation step will receive valid data that it can use and the new changes have been encapsulated within a single step of the process. I haven't needed to change any code elsewhere.<\/p>\n\n<p>I can also add deprecation warnings if legacy values are used.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Similar to feature flags, this is temporary code that will later be removed when I'm ready to remove the compatibility layer, similar to how <code>drupal_set_message()<\/code> was deprecated and changed to use the <code>Messenger<\/code> service before being removed in Drupal 9.<\/p>\n\n<p>In the future, I can refactor the internal logic to use a different approach and when I'm ready, eventually remove the compatibility layer and tag a new major version with the breaking changes.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>A common misunderstanding for new Developers is that Git and GitHub are the same thing, but they aren't.<\/p>\n\n<p>Git is decentralised, so doesn't rely on using external repositories on services like GitHub, GitLab or Bitbucket.<\/p>\n\n<p>You can run <code>git init<\/code> and use it locally without pushing to any remote services.<\/p>\n\n<p>These services also add extra terminology, such as forks, syncing and pull or merge requests which aren't part of Git itself.<\/p>\n\n<p>This can cause confusion, which is why <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/23\/git-gui-command-line\">I think it's important to learn Git itself<\/a> instead of relying on external services or desktop apps.<\/p>\n\n<p>And, if you're going to use a remote repository, consider something like Gitea, which you can host yourself and keep control of your data.<\/p>\n\n ",
"value": "\n <p>A common misunderstanding for new Developers is that Git and GitHub are the same thing, but they aren't.<\/p>\n\n<p>Git is decentralised, so doesn't rely on using external repositories on services like GitHub, GitLab or Bitbucket.<\/p>\n\n<p>You can run <code>git init<\/code> and use it locally without pushing to any remote services.<\/p>\n\n<p>These services also add extra terminology, such as forks, syncing and pull or merge requests which aren't part of Git itself.<\/p>\n\n<p>This can cause confusion, which is why <a href=\"/daily\/2022\/08\/23\/git-gui-command-line\">I think it's important to learn Git itself<\/a> instead of relying on external services or desktop apps.<\/p>\n\n<p>And, if you're going to use a remote repository, consider something like Gitea, which you can host yourself and keep control of your data.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>A common misunderstanding for new Developers is that Git and GitHub are the same thing, but they aren't.<\/p>\n\n<p>Git is decentralised, so doesn't rely on using external repositories on services like GitHub, GitLab or Bitbucket.<\/p>\n\n<p>You can run <code>git init<\/code> and use it locally without pushing to any remote services.<\/p>\n\n<p>These services also add extra terminology, such as forks, syncing and pull or merge requests which aren't part of Git itself.<\/p>\n\n<p>This can cause confusion, which is why <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/23\/git-gui-command-line\">I think it's important to learn Git itself<\/a> instead of relying on external services or desktop apps.<\/p>\n\n<p>And, if you're going to use a remote repository, consider something like Gitea, which you can host yourself and keep control of your data.<\/p>\n\n ",
"processed": "\n <p>A common misunderstanding for new Developers is that Git and GitHub are the same thing, but they aren't.<\/p>\n\n<p>Git is decentralised, so doesn't rely on using external repositories on services like GitHub, GitLab or Bitbucket.<\/p>\n\n<p>You can run <code>git init<\/code> and use it locally without pushing to any remote services.<\/p>\n\n<p>These services also add extra terminology, such as forks, syncing and pull or merge requests which aren't part of Git itself.<\/p>\n\n<p>This can cause confusion, which is why <a href=\"/daily\/2022\/08\/23\/git-gui-command-line\">I think it's important to learn Git itself<\/a> instead of relying on external services or desktop apps.<\/p>\n\n<p>And, if you're going to use a remote repository, consider something like Gitea, which you can host yourself and keep control of your data.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Before adding a new feature or change to a codebase, ask if it's really needed and consider its long-term implications.<\/p>\n\n<p>Code is easy to write, but needs to be maintained as newer language or framework features are added or have breaking changes.<\/p>\n\n<p>Something I've added recently to Build Configs was an option to use an <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/01\/27\/gitignore-inclusive-or-exclusive\">inclusive or exclusive .gitignore file<\/a>.<\/p>\n\n<p>Whilst it's only adding an if condition based on a value, it adds a separate path in my code and both need to be maintained.<\/p>\n\n<p>I've been thinking of adding <code>just<\/code> again to some projects instead of a <code>run<\/code> file, which would add separate files that need to be maintained and kept up-to-date with each other so both offer the same features.<\/p>\n\n<p>Is this something I want to maintain going forward? Does it add enough value to justify its maintenance?<\/p>\n\n<p>Different to a feature flag, which usually has a known lifespan, this could need be maintained for the whole lifespan of the application.<\/p>\n\n<p>On a client project, this could be having two sets of buttons with rounded and square corners.<\/p>\n\n<p>Do we need both?<\/p>\n\n<p>It could be the positioning of a title in a header. Fewer options mean there is less code to write and maintain.<\/p>\n\n<p>In a Drupal project, each choice could mean adding a different field, taxonomy term, or content or block type to achieve the desired result.<\/p>\n\n<p>The more we can achieve with fewer options means the application will be easier to maintain and work on in the future.<\/p>\n\n ",
"value": "\n <p>Before adding a new feature or change to a codebase, ask if it's really needed and consider its long-term implications.<\/p>\n\n<p>Code is easy to write, but needs to be maintained as newer language or framework features are added or have breaking changes.<\/p>\n\n<p>Something I've added recently to Build Configs was an option to use an <a href=\"/daily\/2024\/01\/27\/gitignore-inclusive-or-exclusive\">inclusive or exclusive .gitignore file<\/a>.<\/p>\n\n<p>Whilst it's only adding an if condition based on a value, it adds a separate path in my code and both need to be maintained.<\/p>\n\n<p>I've been thinking of adding <code>just<\/code> again to some projects instead of a <code>run<\/code> file, which would add separate files that need to be maintained and kept up-to-date with each other so both offer the same features.<\/p>\n\n<p>Is this something I want to maintain going forward? Does it add enough value to justify its maintenance?<\/p>\n\n<p>Different to a feature flag, which usually has a known lifespan, this could need be maintained for the whole lifespan of the application.<\/p>\n\n<p>On a client project, this could be having two sets of buttons with rounded and square corners.<\/p>\n\n<p>Do we need both?<\/p>\n\n<p>It could be the positioning of a title in a header. Fewer options mean there is less code to write and maintain.<\/p>\n\n<p>In a Drupal project, each choice could mean adding a different field, taxonomy term, or content or block type to achieve the desired result.<\/p>\n\n<p>The more we can achieve with fewer options means the application will be easier to maintain and work on in the future.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Before adding a new feature or change to a codebase, ask if it's really needed and consider its long-term implications.<\/p>\n\n<p>Code is easy to write, but needs to be maintained as newer language or framework features are added or have breaking changes.<\/p>\n\n<p>Something I've added recently to Build Configs was an option to use an <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/01\/27\/gitignore-inclusive-or-exclusive\">inclusive or exclusive .gitignore file<\/a>.<\/p>\n\n<p>Whilst it's only adding an if condition based on a value, it adds a separate path in my code and both need to be maintained.<\/p>\n\n<p>I've been thinking of adding <code>just<\/code> again to some projects instead of a <code>run<\/code> file, which would add separate files that need to be maintained and kept up-to-date with each other so both offer the same features.<\/p>\n\n<p>Is this something I want to maintain going forward? Does it add enough value to justify its maintenance?<\/p>\n\n<p>Different to a feature flag, which usually has a known lifespan, this could need be maintained for the whole lifespan of the application.<\/p>\n\n<p>On a client project, this could be having two sets of buttons with rounded and square corners.<\/p>\n\n<p>Do we need both?<\/p>\n\n<p>It could be the positioning of a title in a header. Fewer options mean there is less code to write and maintain.<\/p>\n\n<p>In a Drupal project, each choice could mean adding a different field, taxonomy term, or content or block type to achieve the desired result.<\/p>\n\n<p>The more we can achieve with fewer options means the application will be easier to maintain and work on in the future.<\/p>\n\n ",
"processed": "\n <p>Before adding a new feature or change to a codebase, ask if it's really needed and consider its long-term implications.<\/p>\n\n<p>Code is easy to write, but needs to be maintained as newer language or framework features are added or have breaking changes.<\/p>\n\n<p>Something I've added recently to Build Configs was an option to use an <a href=\"/daily\/2024\/01\/27\/gitignore-inclusive-or-exclusive\">inclusive or exclusive .gitignore file<\/a>.<\/p>\n\n<p>Whilst it's only adding an if condition based on a value, it adds a separate path in my code and both need to be maintained.<\/p>\n\n<p>I've been thinking of adding <code>just<\/code> again to some projects instead of a <code>run<\/code> file, which would add separate files that need to be maintained and kept up-to-date with each other so both offer the same features.<\/p>\n\n<p>Is this something I want to maintain going forward? Does it add enough value to justify its maintenance?<\/p>\n\n<p>Different to a feature flag, which usually has a known lifespan, this could need be maintained for the whole lifespan of the application.<\/p>\n\n<p>On a client project, this could be having two sets of buttons with rounded and square corners.<\/p>\n\n<p>Do we need both?<\/p>\n\n<p>It could be the positioning of a title in a header. Fewer options mean there is less code to write and maintain.<\/p>\n\n<p>In a Drupal project, each choice could mean adding a different field, taxonomy term, or content or block type to achieve the desired result.<\/p>\n\n<p>The more we can achieve with fewer options means the application will be easier to maintain and work on in the future.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>I recently had <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/27-drupalisms\">my first podcast episode with two guests<\/a>, where I discussed Drupal terminology and Drupalisms with Emma Horrell and Luke McCormick.<\/p>\n\n<p>It was a great episode, but there was something I needed to do before I could release it.<\/p>\n\n<p>Before I could release the episode, I needed to update my website to show both guest names.<\/p>\n\n<p>The other 26 episodes only had a single guest per episode, and my podcast pages were built to only show the first guest name.<\/p>\n\n<p>When building the pages for the <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/1-retrofit\">first episode with Matt Glaman<\/a>, I only needed to show a single guest name.<\/p>\n\n<p>There was no need to show multiple guest names until I had an episode with multiple guests.<\/p>\n\n<p>I wrote the simplest code to achieve the requirements I had at the time.<\/p>\n\n<p>If I wrote for two guests but never had an episode with two guests, my website would be bloated and have functionality that wasn't needed or used.<\/p>\n\n<p>Now my requirements have changed.<\/p>\n\n<p>I can have an episode with one or two guests, but not three or more guests.<\/p>\n\n<p>If I have an episode with more than two guests, I'll write that functionality then.<\/p>\n\n<p>But not before.<\/p>\n\n ",
"value": "\n <p>I recently had <a href=\"/podcast\/27-drupalisms\">my first podcast episode with two guests<\/a>, where I discussed Drupal terminology and Drupalisms with Emma Horrell and Luke McCormick.<\/p>\n\n<p>It was a great episode, but there was something I needed to do before I could release it.<\/p>\n\n<p>Before I could release the episode, I needed to update my website to show both guest names.<\/p>\n\n<p>The other 26 episodes only had a single guest per episode, and my podcast pages were built to only show the first guest name.<\/p>\n\n<p>When building the pages for the <a href=\"/podcast\/1-retrofit\">first episode with Matt Glaman<\/a>, I only needed to show a single guest name.<\/p>\n\n<p>There was no need to show multiple guest names until I had an episode with multiple guests.<\/p>\n\n<p>I wrote the simplest code to achieve the requirements I had at the time.<\/p>\n\n<p>If I wrote for two guests but never had an episode with two guests, my website would be bloated and have functionality that wasn't needed or used.<\/p>\n\n<p>Now my requirements have changed.<\/p>\n\n<p>I can have an episode with one or two guests, but not three or more guests.<\/p>\n\n<p>If I have an episode with more than two guests, I'll write that functionality then.<\/p>\n\n<p>But not before.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>I recently had <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/27-drupalisms\">my first podcast episode with two guests<\/a>, where I discussed Drupal terminology and Drupalisms with Emma Horrell and Luke McCormick.<\/p>\n\n<p>It was a great episode, but there was something I needed to do before I could release it.<\/p>\n\n<p>Before I could release the episode, I needed to update my website to show both guest names.<\/p>\n\n<p>The other 26 episodes only had a single guest per episode, and my podcast pages were built to only show the first guest name.<\/p>\n\n<p>When building the pages for the <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/1-retrofit\">first episode with Matt Glaman<\/a>, I only needed to show a single guest name.<\/p>\n\n<p>There was no need to show multiple guest names until I had an episode with multiple guests.<\/p>\n\n<p>I wrote the simplest code to achieve the requirements I had at the time.<\/p>\n\n<p>If I wrote for two guests but never had an episode with two guests, my website would be bloated and have functionality that wasn't needed or used.<\/p>\n\n<p>Now my requirements have changed.<\/p>\n\n<p>I can have an episode with one or two guests, but not three or more guests.<\/p>\n\n<p>If I have an episode with more than two guests, I'll write that functionality then.<\/p>\n\n<p>But not before.<\/p>\n\n ",
"processed": "\n <p>I recently had <a href=\"/podcast\/27-drupalisms\">my first podcast episode with two guests<\/a>, where I discussed Drupal terminology and Drupalisms with Emma Horrell and Luke McCormick.<\/p>\n\n<p>It was a great episode, but there was something I needed to do before I could release it.<\/p>\n\n<p>Before I could release the episode, I needed to update my website to show both guest names.<\/p>\n\n<p>The other 26 episodes only had a single guest per episode, and my podcast pages were built to only show the first guest name.<\/p>\n\n<p>When building the pages for the <a href=\"/podcast\/1-retrofit\">first episode with Matt Glaman<\/a>, I only needed to show a single guest name.<\/p>\n\n<p>There was no need to show multiple guest names until I had an episode with multiple guests.<\/p>\n\n<p>I wrote the simplest code to achieve the requirements I had at the time.<\/p>\n\n<p>If I wrote for two guests but never had an episode with two guests, my website would be bloated and have functionality that wasn't needed or used.<\/p>\n\n<p>Now my requirements have changed.<\/p>\n\n<p>I can have an episode with one or two guests, but not three or more guests.<\/p>\n\n<p>If I have an episode with more than two guests, I'll write that functionality then.<\/p>\n\n<p>But not before.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Last week, I asked <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/15\/should-you-include-issue-ids-in-your-commit-messages\">whether you should include issue IDs in commit messages<\/a>.<\/p>\n\n<p>Another thing I like to reference in a commit message is the commit ID (or SHA) of a related commit.<\/p>\n\n<p>For example, when I run <code>git log<\/code> in my website repository, I see commits like this:<\/p>\n\n<pre><code class=\"plain\">commit 0c91825c16217d0fe7eff4ea100a67550051c4a9\nAuthor: Oliver Davies &lt;oliver@oliverdavies.dev&gt;\nDate: Sat May 11 15:32:07 2024 +0200\n\n Create a cached talk counter\n\n Create a cached version of the talk counter service that returns a\n cached result of the talk count for that day.\n\n This uses the Decorator design pattern to decorate the existing\n `TalkCounter` service and works as they both implement the same\n `TalkCounterInterface`.\n<\/code><\/pre>\n\n<p>The sha for this commit is <code>0c91825c16217d0fe7eff4ea100a67550051c4a9<\/code>.<\/p>\n\n<p>If I was to make another commit that was related to this one, I can include this commit sha in my new commit message.<\/p>\n\n<p>I also don't need to include the entire thing - only enough for it to be unique (usually five or six characters).<\/p>\n\n<p>Once pushed, the commit IDs should never change, so this will be a permanent reference to the first commit.<\/p>\n\n<p>Helpfully, websites like GitHub, GitLab and Bitbucket will identify it as a commit sha and make it clickable so you can easily navigate to the referenced commit.<\/p>\n\n ",
"value": "\n <p>Last week, I asked <a href=\"/daily\/2024\/05\/15\/should-you-include-issue-ids-in-your-commit-messages\">whether you should include issue IDs in commit messages<\/a>.<\/p>\n\n<p>Another thing I like to reference in a commit message is the commit ID (or SHA) of a related commit.<\/p>\n\n<p>For example, when I run <code>git log<\/code> in my website repository, I see commits like this:<\/p>\n\n<pre><code class=\"plain\">commit 0c91825c16217d0fe7eff4ea100a67550051c4a9\nAuthor: Oliver Davies &lt;oliver@oliverdavies.dev&gt;\nDate: Sat May 11 15:32:07 2024 +0200\n\n Create a cached talk counter\n\n Create a cached version of the talk counter service that returns a\n cached result of the talk count for that day.\n\n This uses the Decorator design pattern to decorate the existing\n `TalkCounter` service and works as they both implement the same\n `TalkCounterInterface`.\n<\/code><\/pre>\n\n<p>The sha for this commit is <code>0c91825c16217d0fe7eff4ea100a67550051c4a9<\/code>.<\/p>\n\n<p>If I was to make another commit that was related to this one, I can include this commit sha in my new commit message.<\/p>\n\n<p>I also don't need to include the entire thing - only enough for it to be unique (usually five or six characters).<\/p>\n\n<p>Once pushed, the commit IDs should never change, so this will be a permanent reference to the first commit.<\/p>\n\n<p>Helpfully, websites like GitHub, GitLab and Bitbucket will identify it as a commit sha and make it clickable so you can easily navigate to the referenced commit.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Last week, I asked <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/15\/should-you-include-issue-ids-in-your-commit-messages\">whether you should include issue IDs in commit messages<\/a>.<\/p>\n\n<p>Another thing I like to reference in a commit message is the commit ID (or SHA) of a related commit.<\/p>\n\n<p>For example, when I run <code>git log<\/code> in my website repository, I see commits like this:<\/p>\n\n<pre><code class=\"plain\">commit 0c91825c16217d0fe7eff4ea100a67550051c4a9\nAuthor: Oliver Davies &lt;oliver@oliverdavies.dev&gt;\nDate: Sat May 11 15:32:07 2024 +0200\n\n Create a cached talk counter\n\n Create a cached version of the talk counter service that returns a\n cached result of the talk count for that day.\n\n This uses the Decorator design pattern to decorate the existing\n `TalkCounter` service and works as they both implement the same\n `TalkCounterInterface`.\n<\/code><\/pre>\n\n<p>The sha for this commit is <code>0c91825c16217d0fe7eff4ea100a67550051c4a9<\/code>.<\/p>\n\n<p>If I was to make another commit that was related to this one, I can include this commit sha in my new commit message.<\/p>\n\n<p>I also don't need to include the entire thing - only enough for it to be unique (usually five or six characters).<\/p>\n\n<p>Once pushed, the commit IDs should never change, so this will be a permanent reference to the first commit.<\/p>\n\n<p>Helpfully, websites like GitHub, GitLab and Bitbucket will identify it as a commit sha and make it clickable so you can easily navigate to the referenced commit.<\/p>\n\n ",
"processed": "\n <p>Last week, I asked <a href=\"/daily\/2024\/05\/15\/should-you-include-issue-ids-in-your-commit-messages\">whether you should include issue IDs in commit messages<\/a>.<\/p>\n\n<p>Another thing I like to reference in a commit message is the commit ID (or SHA) of a related commit.<\/p>\n\n<p>For example, when I run <code>git log<\/code> in my website repository, I see commits like this:<\/p>\n\n<pre><code class=\"plain\">commit 0c91825c16217d0fe7eff4ea100a67550051c4a9\nAuthor: Oliver Davies &lt;oliver@oliverdavies.dev&gt;\nDate: Sat May 11 15:32:07 2024 +0200\n\n Create a cached talk counter\n\n Create a cached version of the talk counter service that returns a\n cached result of the talk count for that day.\n\n This uses the Decorator design pattern to decorate the existing\n `TalkCounter` service and works as they both implement the same\n `TalkCounterInterface`.\n<\/code><\/pre>\n\n<p>The sha for this commit is <code>0c91825c16217d0fe7eff4ea100a67550051c4a9<\/code>.<\/p>\n\n<p>If I was to make another commit that was related to this one, I can include this commit sha in my new commit message.<\/p>\n\n<p>I also don't need to include the entire thing - only enough for it to be unique (usually five or six characters).<\/p>\n\n<p>Once pushed, the commit IDs should never change, so this will be a permanent reference to the first commit.<\/p>\n\n<p>Helpfully, websites like GitHub, GitLab and Bitbucket will identify it as a commit sha and make it clickable so you can easily navigate to the referenced commit.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Note: The numbers within this post are taken from my <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/tdd-test-driven-drupal\">Test-Driven Drupal talk<\/a>, in which I also talk about this.<\/p>\n\n<p>My first commit to the 7.x-1.x branch of the Override Node Options module was in March 2012. According to Drupal.org, the module was used on 9,212 websites then.<\/p>\n\n<p>As well as the 7.x-1.x branch, there's the 8.x-2.x branch which supports Drupal 9 and 10, and previously Drupal 8.<\/p>\n\n<p>The most recent statistics show the module is currently used on 34,981 websites and is consistently around 35,000.<\/p>\n\n<h2 id=\"what-does-that-mean%3F\">What does that mean?<\/h2>\n\n<p>The module is considered feature complete, but I'm not ruling out any new additions.<\/p>\n\n<p>The main thing is ensuring that any changes don't break 35,000 websites!<\/p>\n\n<p>I do this by relying on the module's automated test suite and ensuring that tests are added for any features or bugs and that the tests are passing before any new release.<\/p>\n\n<h2 id=\"this-has-worked-well\">This has worked well<\/h2>\n\n<p>A few years ago, I committed a feature request to both versions. While it didn't include additional tests, I verified the existing functionality worked after resolving a large merge conflict by ensuring the original tests passed.<\/p>\n\n<p>More recently, a colleague and I refactored the module and split each override into its own class, making adding and maintaining overrides easier.<\/p>\n\n<p>Because the tests were still passing, we knew our refactor was successful and not causing regressions.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Having automated tests and ensuring they're always passing has allowed me to add features and refactor code that I wouldn't have done or had the confidence to do otherwise.<\/p>\n\n<p>It's great to have a popular module, but on the other hand, I don't want to break 35,000 websites which makes the tests invaluable.<\/p>\n\n ",
"value": "\n <p>Note: The numbers within this post are taken from my <a href=\"/presentations\/tdd-test-driven-drupal\">Test-Driven Drupal talk<\/a>, in which I also talk about this.<\/p>\n\n<p>My first commit to the 7.x-1.x branch of the Override Node Options module was in March 2012. According to Drupal.org, the module was used on 9,212 websites then.<\/p>\n\n<p>As well as the 7.x-1.x branch, there's the 8.x-2.x branch which supports Drupal 9 and 10, and previously Drupal 8.<\/p>\n\n<p>The most recent statistics show the module is currently used on 34,981 websites and is consistently around 35,000.<\/p>\n\n<h2 id=\"what-does-that-mean%3F\">What does that mean?<\/h2>\n\n<p>The module is considered feature complete, but I'm not ruling out any new additions.<\/p>\n\n<p>The main thing is ensuring that any changes don't break 35,000 websites!<\/p>\n\n<p>I do this by relying on the module's automated test suite and ensuring that tests are added for any features or bugs and that the tests are passing before any new release.<\/p>\n\n<h2 id=\"this-has-worked-well\">This has worked well<\/h2>\n\n<p>A few years ago, I committed a feature request to both versions. While it didn't include additional tests, I verified the existing functionality worked after resolving a large merge conflict by ensuring the original tests passed.<\/p>\n\n<p>More recently, a colleague and I refactored the module and split each override into its own class, making adding and maintaining overrides easier.<\/p>\n\n<p>Because the tests were still passing, we knew our refactor was successful and not causing regressions.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Having automated tests and ensuring they're always passing has allowed me to add features and refactor code that I wouldn't have done or had the confidence to do otherwise.<\/p>\n\n<p>It's great to have a popular module, but on the other hand, I don't want to break 35,000 websites which makes the tests invaluable.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Note: The numbers within this post are taken from my <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/tdd-test-driven-drupal\">Test-Driven Drupal talk<\/a>, in which I also talk about this.<\/p>\n\n<p>My first commit to the 7.x-1.x branch of the Override Node Options module was in March 2012. According to Drupal.org, the module was used on 9,212 websites then.<\/p>\n\n<p>As well as the 7.x-1.x branch, there's the 8.x-2.x branch which supports Drupal 9 and 10, and previously Drupal 8.<\/p>\n\n<p>The most recent statistics show the module is currently used on 34,981 websites and is consistently around 35,000.<\/p>\n\n<h2 id=\"what-does-that-mean%3F\">What does that mean?<\/h2>\n\n<p>The module is considered feature complete, but I'm not ruling out any new additions.<\/p>\n\n<p>The main thing is ensuring that any changes don't break 35,000 websites!<\/p>\n\n<p>I do this by relying on the module's automated test suite and ensuring that tests are added for any features or bugs and that the tests are passing before any new release.<\/p>\n\n<h2 id=\"this-has-worked-well\">This has worked well<\/h2>\n\n<p>A few years ago, I committed a feature request to both versions. While it didn't include additional tests, I verified the existing functionality worked after resolving a large merge conflict by ensuring the original tests passed.<\/p>\n\n<p>More recently, a colleague and I refactored the module and split each override into its own class, making adding and maintaining overrides easier.<\/p>\n\n<p>Because the tests were still passing, we knew our refactor was successful and not causing regressions.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Having automated tests and ensuring they're always passing has allowed me to add features and refactor code that I wouldn't have done or had the confidence to do otherwise.<\/p>\n\n<p>It's great to have a popular module, but on the other hand, I don't want to break 35,000 websites which makes the tests invaluable.<\/p>\n\n ",
"processed": "\n <p>Note: The numbers within this post are taken from my <a href=\"/presentations\/tdd-test-driven-drupal\">Test-Driven Drupal talk<\/a>, in which I also talk about this.<\/p>\n\n<p>My first commit to the 7.x-1.x branch of the Override Node Options module was in March 2012. According to Drupal.org, the module was used on 9,212 websites then.<\/p>\n\n<p>As well as the 7.x-1.x branch, there's the 8.x-2.x branch which supports Drupal 9 and 10, and previously Drupal 8.<\/p>\n\n<p>The most recent statistics show the module is currently used on 34,981 websites and is consistently around 35,000.<\/p>\n\n<h2 id=\"what-does-that-mean%3F\">What does that mean?<\/h2>\n\n<p>The module is considered feature complete, but I'm not ruling out any new additions.<\/p>\n\n<p>The main thing is ensuring that any changes don't break 35,000 websites!<\/p>\n\n<p>I do this by relying on the module's automated test suite and ensuring that tests are added for any features or bugs and that the tests are passing before any new release.<\/p>\n\n<h2 id=\"this-has-worked-well\">This has worked well<\/h2>\n\n<p>A few years ago, I committed a feature request to both versions. While it didn't include additional tests, I verified the existing functionality worked after resolving a large merge conflict by ensuring the original tests passed.<\/p>\n\n<p>More recently, a colleague and I refactored the module and split each override into its own class, making adding and maintaining overrides easier.<\/p>\n\n<p>Because the tests were still passing, we knew our refactor was successful and not causing regressions.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Having automated tests and ensuring they're always passing has allowed me to add features and refactor code that I wouldn't have done or had the confidence to do otherwise.<\/p>\n\n<p>It's great to have a popular module, but on the other hand, I don't want to break 35,000 websites which makes the tests invaluable.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/01\/02\/dont-use-arbitrary-values-in-tailwind-css\">I generally don't use aritrary classes with Tailwind CSS<\/a>.<\/p>\n\n<p>But, they are powerful, and I do use them in some situations.<\/p>\n\n<p>A few months ago, <a href=\"https:\/\/x.com\/opdavies\/status\/1755332703308652730\">I posted a screenshot of a timeline component<\/a> I've built for a client project.<\/p>\n\n<p>Today, I needed to fix an issue with the first and last \"paths\" as they were stretching further than they should.<\/p>\n\n<p>This is the class I added to fix the problem:<\/p>\n\n<blockquote>\n <p>mr-[calc(50%<em>-_calc(var(--path-width)<\/em>\/_2))]<\/p>\n<\/blockquote>\n\n<p>It adds an arbitrary amount of right margin, which is 50% of the container minus half of the path width, which is the <code>--path-width<\/code> variable.<\/p>\n\n<p>This class uses the <code>calc<\/code> function as well as <code>var<\/code> to determine the correct margin to apply, whilst keeping the code adaptable in case the path width changes.<\/p>\n\n<p>And, as this is a value that's only used in this component, there's no benefit to writing this in a stylesheet - making an arbitrary value was a good option.<\/p>\n\n ",
"value": "\n <p><a href=\"/daily\/2023\/01\/02\/dont-use-arbitrary-values-in-tailwind-css\">I generally don't use aritrary classes with Tailwind CSS<\/a>.<\/p>\n\n<p>But, they are powerful, and I do use them in some situations.<\/p>\n\n<p>A few months ago, <a href=\"https:\/\/x.com\/opdavies\/status\/1755332703308652730\">I posted a screenshot of a timeline component<\/a> I've built for a client project.<\/p>\n\n<p>Today, I needed to fix an issue with the first and last \"paths\" as they were stretching further than they should.<\/p>\n\n<p>This is the class I added to fix the problem:<\/p>\n\n<blockquote>\n <p>mr-[calc(50%<em>-_calc(var(--path-width)<\/em>\/_2))]<\/p>\n<\/blockquote>\n\n<p>It adds an arbitrary amount of right margin, which is 50% of the container minus half of the path width, which is the <code>--path-width<\/code> variable.<\/p>\n\n<p>This class uses the <code>calc<\/code> function as well as <code>var<\/code> to determine the correct margin to apply, whilst keeping the code adaptable in case the path width changes.<\/p>\n\n<p>And, as this is a value that's only used in this component, there's no benefit to writing this in a stylesheet - making an arbitrary value was a good option.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/01\/02\/dont-use-arbitrary-values-in-tailwind-css\">I generally don't use aritrary classes with Tailwind CSS<\/a>.<\/p>\n\n<p>But, they are powerful, and I do use them in some situations.<\/p>\n\n<p>A few months ago, <a href=\"https:\/\/x.com\/opdavies\/status\/1755332703308652730\">I posted a screenshot of a timeline component<\/a> I've built for a client project.<\/p>\n\n<p>Today, I needed to fix an issue with the first and last \"paths\" as they were stretching further than they should.<\/p>\n\n<p>This is the class I added to fix the problem:<\/p>\n\n<blockquote>\n <p>mr-[calc(50%<em>-_calc(var(--path-width)<\/em>\/_2))]<\/p>\n<\/blockquote>\n\n<p>It adds an arbitrary amount of right margin, which is 50% of the container minus half of the path width, which is the <code>--path-width<\/code> variable.<\/p>\n\n<p>This class uses the <code>calc<\/code> function as well as <code>var<\/code> to determine the correct margin to apply, whilst keeping the code adaptable in case the path width changes.<\/p>\n\n<p>And, as this is a value that's only used in this component, there's no benefit to writing this in a stylesheet - making an arbitrary value was a good option.<\/p>\n\n ",
"processed": "\n <p><a href=\"/daily\/2023\/01\/02\/dont-use-arbitrary-values-in-tailwind-css\">I generally don't use aritrary classes with Tailwind CSS<\/a>.<\/p>\n\n<p>But, they are powerful, and I do use them in some situations.<\/p>\n\n<p>A few months ago, <a href=\"https:\/\/x.com\/opdavies\/status\/1755332703308652730\">I posted a screenshot of a timeline component<\/a> I've built for a client project.<\/p>\n\n<p>Today, I needed to fix an issue with the first and last \"paths\" as they were stretching further than they should.<\/p>\n\n<p>This is the class I added to fix the problem:<\/p>\n\n<blockquote>\n <p>mr-[calc(50%<em>-_calc(var(--path-width)<\/em>\/_2))]<\/p>\n<\/blockquote>\n\n<p>It adds an arbitrary amount of right margin, which is 50% of the container minus half of the path width, which is the <code>--path-width<\/code> variable.<\/p>\n\n<p>This class uses the <code>calc<\/code> function as well as <code>var<\/code> to determine the correct margin to apply, whilst keeping the code adaptable in case the path width changes.<\/p>\n\n<p>And, as this is a value that's only used in this component, there's no benefit to writing this in a stylesheet - making an arbitrary value was a good option.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>A few years ago, decoupled or headless Drupal - where Drupal is used as an API with a separate front-end - was very popular with some large Drupal agencies and clients using it.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/talks\/decoupling-drupal-vuejs\">I gave a conference talk<\/a> about how to use Drupal as a backend application for a Vue.js frontend.<\/p>\n\n<p>Recently, though, I haven't heard much about it.<\/p>\n\n<p>Some previous advocates have moved back to the more traditional approach.<\/p>\n\n<p>Interestingly, though, I did hear quite a bit about it at DrupalCon and about Drupal and Next.js in particular.<\/p>\n\n<p>I want to try using Drupal with Astro in the future and see what the landscape is like now.<\/p>\n\n<h2 id=\"what-about-you%3F\">What about you?<\/h2>\n\n<p>Do you use Drupal in a decoupled or headless way? If so, what do you use for the frontend?<\/p>\n\n<p>If not, or if you've moved back to a more traditional approach, why?<\/p>\n\n<p>Reply and let me know.<\/p>\n\n ",
"value": "\n <p>A few years ago, decoupled or headless Drupal - where Drupal is used as an API with a separate front-end - was very popular with some large Drupal agencies and clients using it.<\/p>\n\n<p><a href=\"/talks\/decoupling-drupal-vuejs\">I gave a conference talk<\/a> about how to use Drupal as a backend application for a Vue.js frontend.<\/p>\n\n<p>Recently, though, I haven't heard much about it.<\/p>\n\n<p>Some previous advocates have moved back to the more traditional approach.<\/p>\n\n<p>Interestingly, though, I did hear quite a bit about it at DrupalCon and about Drupal and Next.js in particular.<\/p>\n\n<p>I want to try using Drupal with Astro in the future and see what the landscape is like now.<\/p>\n\n<h2 id=\"what-about-you%3F\">What about you?<\/h2>\n\n<p>Do you use Drupal in a decoupled or headless way? If so, what do you use for the frontend?<\/p>\n\n<p>If not, or if you've moved back to a more traditional approach, why?<\/p>\n\n<p>Reply and let me know.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>A few years ago, decoupled or headless Drupal - where Drupal is used as an API with a separate front-end - was very popular with some large Drupal agencies and clients using it.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/talks\/decoupling-drupal-vuejs\">I gave a conference talk<\/a> about how to use Drupal as a backend application for a Vue.js frontend.<\/p>\n\n<p>Recently, though, I haven't heard much about it.<\/p>\n\n<p>Some previous advocates have moved back to the more traditional approach.<\/p>\n\n<p>Interestingly, though, I did hear quite a bit about it at DrupalCon and about Drupal and Next.js in particular.<\/p>\n\n<p>I want to try using Drupal with Astro in the future and see what the landscape is like now.<\/p>\n\n<h2 id=\"what-about-you%3F\">What about you?<\/h2>\n\n<p>Do you use Drupal in a decoupled or headless way? If so, what do you use for the frontend?<\/p>\n\n<p>If not, or if you've moved back to a more traditional approach, why?<\/p>\n\n<p>Reply and let me know.<\/p>\n\n ",
"processed": "\n <p>A few years ago, decoupled or headless Drupal - where Drupal is used as an API with a separate front-end - was very popular with some large Drupal agencies and clients using it.<\/p>\n\n<p><a href=\"/talks\/decoupling-drupal-vuejs\">I gave a conference talk<\/a> about how to use Drupal as a backend application for a Vue.js frontend.<\/p>\n\n<p>Recently, though, I haven't heard much about it.<\/p>\n\n<p>Some previous advocates have moved back to the more traditional approach.<\/p>\n\n<p>Interestingly, though, I did hear quite a bit about it at DrupalCon and about Drupal and Next.js in particular.<\/p>\n\n<p>I want to try using Drupal with Astro in the future and see what the landscape is like now.<\/p>\n\n<h2 id=\"what-about-you%3F\">What about you?<\/h2>\n\n<p>Do you use Drupal in a decoupled or headless way? If so, what do you use for the frontend?<\/p>\n\n<p>If not, or if you've moved back to a more traditional approach, why?<\/p>\n\n<p>Reply and let me know.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>In the most recent episode of the Beyond Blocks podcast, I spoke with J\u00fcrgen Haas about Drupal's ECA module.<\/p>\n\n<p>ECA stands for Events, Conditions and Actions and is a module I was aware of, but haven't used before - so I was great to learn more about it.<\/p>\n\n<p>I also got to meet J\u00fcrgen at DrupalCon in Barcelona, as well as several other podcast guests, which was fantastic.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/23-jurgen-haas-eca\">Listen to the episode now<\/a>.<\/p>\n\n<p>If you'd like to be a guest on the podcast or want to suggest a topic, reply and let me know!<\/p>\n\n ",
"value": "\n <p>In the most recent episode of the Beyond Blocks podcast, I spoke with J\u00fcrgen Haas about Drupal's ECA module.<\/p>\n\n<p>ECA stands for Events, Conditions and Actions and is a module I was aware of, but haven't used before - so I was great to learn more about it.<\/p>\n\n<p>I also got to meet J\u00fcrgen at DrupalCon in Barcelona, as well as several other podcast guests, which was fantastic.<\/p>\n\n<p><a href=\"/podcast\/23-jurgen-haas-eca\">Listen to the episode now<\/a>.<\/p>\n\n<p>If you'd like to be a guest on the podcast or want to suggest a topic, reply and let me know!<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>In the most recent episode of the Beyond Blocks podcast, I spoke with J\u00fcrgen Haas about Drupal's ECA module.<\/p>\n\n<p>ECA stands for Events, Conditions and Actions and is a module I was aware of, but haven't used before - so I was great to learn more about it.<\/p>\n\n<p>I also got to meet J\u00fcrgen at DrupalCon in Barcelona, as well as several other podcast guests, which was fantastic.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/23-jurgen-haas-eca\">Listen to the episode now<\/a>.<\/p>\n\n<p>If you'd like to be a guest on the podcast or want to suggest a topic, reply and let me know!<\/p>\n\n ",
"processed": "\n <p>In the most recent episode of the Beyond Blocks podcast, I spoke with J\u00fcrgen Haas about Drupal's ECA module.<\/p>\n\n<p>ECA stands for Events, Conditions and Actions and is a module I was aware of, but haven't used before - so I was great to learn more about it.<\/p>\n\n<p>I also got to meet J\u00fcrgen at DrupalCon in Barcelona, as well as several other podcast guests, which was fantastic.<\/p>\n\n<p><a href=\"/podcast\/23-jurgen-haas-eca\">Listen to the episode now<\/a>.<\/p>\n\n<p>If you'd like to be a guest on the podcast or want to suggest a topic, reply and let me know!<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Yesterday, I wanted to make a breaking change to my <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/03\/04\/why-i-built-a-tool-to-generate-configuration-files\">build-configs project<\/a> - changing the default database credentials that are used by Docker Compose.<\/p>\n\n<p>As I have several projects based on generated files by the tool, changing the values could cause issues in those projects in the future and this is something that I wanted to avoid.<\/p>\n\n<h2 id=\"what-did-i-do%3F\">What did I do?<\/h2>\n\n<p>To avoid this issue and needing to update all of my projects at once, I added a feature flag to the <code>build.yaml<\/code> file so I can opt-in to this feature on a per-project basis.<\/p>\n\n<p>If a project, like my <a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal\">Drupal<\/a> and <a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal-localgov\">LocalGov Drupal<\/a> Docker examples, are opted in, its files will get the new credentials. If not, it will continue to use the original ones.<\/p>\n\n<p><a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal\/commit\/3f496168d5c32f9706970519023b431ee02c4b19\">In this commit<\/a>, you'll see where I enabled the feature flag and committed the resulting change.<\/p>\n\n<h2 id=\"what-does-this-achieve%3F\">What does this achieve?<\/h2>\n\n<p>I can continue to work on existing projects without them breaking, and migrate projects one at a time by using the feature flag instead of needing to do them all once.<\/p>\n\n<p>Once all active projects have been migrated or completed, the feature flag can be removed and I can refactor and simplify the code - removing the feature flag and the legacy values.<\/p>\n\n ",
"value": "\n <p>Yesterday, I wanted to make a breaking change to my <a href=\"/daily\/2023\/03\/04\/why-i-built-a-tool-to-generate-configuration-files\">build-configs project<\/a> - changing the default database credentials that are used by Docker Compose.<\/p>\n\n<p>As I have several projects based on generated files by the tool, changing the values could cause issues in those projects in the future and this is something that I wanted to avoid.<\/p>\n\n<h2 id=\"what-did-i-do%3F\">What did I do?<\/h2>\n\n<p>To avoid this issue and needing to update all of my projects at once, I added a feature flag to the <code>build.yaml<\/code> file so I can opt-in to this feature on a per-project basis.<\/p>\n\n<p>If a project, like my <a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal\">Drupal<\/a> and <a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal-localgov\">LocalGov Drupal<\/a> Docker examples, are opted in, its files will get the new credentials. If not, it will continue to use the original ones.<\/p>\n\n<p><a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal\/commit\/3f496168d5c32f9706970519023b431ee02c4b19\">In this commit<\/a>, you'll see where I enabled the feature flag and committed the resulting change.<\/p>\n\n<h2 id=\"what-does-this-achieve%3F\">What does this achieve?<\/h2>\n\n<p>I can continue to work on existing projects without them breaking, and migrate projects one at a time by using the feature flag instead of needing to do them all once.<\/p>\n\n<p>Once all active projects have been migrated or completed, the feature flag can be removed and I can refactor and simplify the code - removing the feature flag and the legacy values.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Yesterday, I wanted to make a breaking change to my <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/03\/04\/why-i-built-a-tool-to-generate-configuration-files\">build-configs project<\/a> - changing the default database credentials that are used by Docker Compose.<\/p>\n\n<p>As I have several projects based on generated files by the tool, changing the values could cause issues in those projects in the future and this is something that I wanted to avoid.<\/p>\n\n<h2 id=\"what-did-i-do%3F\">What did I do?<\/h2>\n\n<p>To avoid this issue and needing to update all of my projects at once, I added a feature flag to the <code>build.yaml<\/code> file so I can opt-in to this feature on a per-project basis.<\/p>\n\n<p>If a project, like my <a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal\">Drupal<\/a> and <a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal-localgov\">LocalGov Drupal<\/a> Docker examples, are opted in, its files will get the new credentials. If not, it will continue to use the original ones.<\/p>\n\n<p><a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal\/commit\/3f496168d5c32f9706970519023b431ee02c4b19\">In this commit<\/a>, you'll see where I enabled the feature flag and committed the resulting change.<\/p>\n\n<h2 id=\"what-does-this-achieve%3F\">What does this achieve?<\/h2>\n\n<p>I can continue to work on existing projects without them breaking, and migrate projects one at a time by using the feature flag instead of needing to do them all once.<\/p>\n\n<p>Once all active projects have been migrated or completed, the feature flag can be removed and I can refactor and simplify the code - removing the feature flag and the legacy values.<\/p>\n\n ",
"processed": "\n <p>Yesterday, I wanted to make a breaking change to my <a href=\"/daily\/2023\/03\/04\/why-i-built-a-tool-to-generate-configuration-files\">build-configs project<\/a> - changing the default database credentials that are used by Docker Compose.<\/p>\n\n<p>As I have several projects based on generated files by the tool, changing the values could cause issues in those projects in the future and this is something that I wanted to avoid.<\/p>\n\n<h2 id=\"what-did-i-do%3F\">What did I do?<\/h2>\n\n<p>To avoid this issue and needing to update all of my projects at once, I added a feature flag to the <code>build.yaml<\/code> file so I can opt-in to this feature on a per-project basis.<\/p>\n\n<p>If a project, like my <a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal\">Drupal<\/a> and <a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal-localgov\">LocalGov Drupal<\/a> Docker examples, are opted in, its files will get the new credentials. If not, it will continue to use the original ones.<\/p>\n\n<p><a href=\"https:\/\/github.com\/opdavies\/docker-example-drupal\/commit\/3f496168d5c32f9706970519023b431ee02c4b19\">In this commit<\/a>, you'll see where I enabled the feature flag and committed the resulting change.<\/p>\n\n<h2 id=\"what-does-this-achieve%3F\">What does this achieve?<\/h2>\n\n<p>I can continue to work on existing projects without them breaking, and migrate projects one at a time by using the feature flag instead of needing to do them all once.<\/p>\n\n<p>Once all active projects have been migrated or completed, the feature flag can be removed and I can refactor and simplify the code - removing the feature flag and the legacy values.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>After my Beyond Blocks episode with Mark Conroy, I've spent some time this week experimenting with web components.<\/p>\n\n<p>The team and I are building a new design system in Fractal and, as Drupal is our main application, we're using Twig as our templating language within Fractal so the changes are easier to port between systems.<\/p>\n\n<p>Web components are agnostic, so they work within different languages and frameworks.<\/p>\n\n<p>We also use other technologies, such as Vue.js, and third-party suppliers, so having an agnostic web component would reduce the time and effort needed to implement the design system across different technologies and applications.<\/p>\n\n<p>If we can make self-contained web components that include their own styling and behaviour, that also improves re-usability and reduces the maintenance overhead as there would be one canonical version for everyone to use - not just a reference implementation everyone would need to recreate.<\/p>\n\n<p>After this spike, I'm intrigued to see how we could use web components and what potential issues we can solve with them whilst reducing our implementation and maintenance efforts.<\/p>\n\n<p>Are you interested in web components, too? <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/11-mark-conroy\">Listen to the podcast episode with Mark Conroy<\/a>.<\/p>\n\n ",
"value": "\n <p>After my Beyond Blocks episode with Mark Conroy, I've spent some time this week experimenting with web components.<\/p>\n\n<p>The team and I are building a new design system in Fractal and, as Drupal is our main application, we're using Twig as our templating language within Fractal so the changes are easier to port between systems.<\/p>\n\n<p>Web components are agnostic, so they work within different languages and frameworks.<\/p>\n\n<p>We also use other technologies, such as Vue.js, and third-party suppliers, so having an agnostic web component would reduce the time and effort needed to implement the design system across different technologies and applications.<\/p>\n\n<p>If we can make self-contained web components that include their own styling and behaviour, that also improves re-usability and reduces the maintenance overhead as there would be one canonical version for everyone to use - not just a reference implementation everyone would need to recreate.<\/p>\n\n<p>After this spike, I'm intrigued to see how we could use web components and what potential issues we can solve with them whilst reducing our implementation and maintenance efforts.<\/p>\n\n<p>Are you interested in web components, too? <a href=\"/podcast\/11-mark-conroy\">Listen to the podcast episode with Mark Conroy<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>After my Beyond Blocks episode with Mark Conroy, I've spent some time this week experimenting with web components.<\/p>\n\n<p>The team and I are building a new design system in Fractal and, as Drupal is our main application, we're using Twig as our templating language within Fractal so the changes are easier to port between systems.<\/p>\n\n<p>Web components are agnostic, so they work within different languages and frameworks.<\/p>\n\n<p>We also use other technologies, such as Vue.js, and third-party suppliers, so having an agnostic web component would reduce the time and effort needed to implement the design system across different technologies and applications.<\/p>\n\n<p>If we can make self-contained web components that include their own styling and behaviour, that also improves re-usability and reduces the maintenance overhead as there would be one canonical version for everyone to use - not just a reference implementation everyone would need to recreate.<\/p>\n\n<p>After this spike, I'm intrigued to see how we could use web components and what potential issues we can solve with them whilst reducing our implementation and maintenance efforts.<\/p>\n\n<p>Are you interested in web components, too? <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/11-mark-conroy\">Listen to the podcast episode with Mark Conroy<\/a>.<\/p>\n\n ",
"processed": "\n <p>After my Beyond Blocks episode with Mark Conroy, I've spent some time this week experimenting with web components.<\/p>\n\n<p>The team and I are building a new design system in Fractal and, as Drupal is our main application, we're using Twig as our templating language within Fractal so the changes are easier to port between systems.<\/p>\n\n<p>Web components are agnostic, so they work within different languages and frameworks.<\/p>\n\n<p>We also use other technologies, such as Vue.js, and third-party suppliers, so having an agnostic web component would reduce the time and effort needed to implement the design system across different technologies and applications.<\/p>\n\n<p>If we can make self-contained web components that include their own styling and behaviour, that also improves re-usability and reduces the maintenance overhead as there would be one canonical version for everyone to use - not just a reference implementation everyone would need to recreate.<\/p>\n\n<p>After this spike, I'm intrigued to see how we could use web components and what potential issues we can solve with them whilst reducing our implementation and maintenance efforts.<\/p>\n\n<p>Are you interested in web components, too? <a href=\"/podcast\/11-mark-conroy\">Listen to the podcast episode with Mark Conroy<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>As well as <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/04\/05\/strategies\">working with different versions of an API<\/a>, I was able to use the same technique I wrote about yesterday to easily add a cacheable version of the API client.<\/p>\n\n<p>As they all implement the same <code>ApiClientInterface<\/code>, I can inject and decorate a client with another client, making one solely responsible for caching the result from the API whilst keeping the API interaction logic separate (aka <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/12\/08\/the-decorator-design-pattern\">the Decorator design pattern<\/a>).<\/p>\n\n<p>Here's an example based on the code I wrote:<\/p>\n\n<pre><code class=\"php\">final class CacheableApiClient implements ApiClientInterface {\n\n \/**\n * The cache duration in seconds.\n *\/\n private const CACHE_DURATION = 3600;\n\n public function __construct(\n private readonly ApiClientInterface $client,\n private readonly TimeInterface $time,\n private readonly CacheBackendInterface $cache,\n ) {\n }\n\n public function getResults(): Collection {\n $key = $this-&gt;getCacheKey();\n\n $cache = $this-&gt;cache-&gt;get($key);\n\n if ($cache !== FALSE) {\n return $cache-&gt;data;\n }\n\n $result = $this-&gt;client-&gt;getResults();\n\n $this-&gt;cache-&gt;set(\n cid: $key,\n data: $result,\n expire: $this-&gt;time-&gt;getRequestTime() + self::CACHE_DURATION,\n );\n\n return $result;\n }\n\n}\n<\/code><\/pre>\n\n<p>Nothing in this instance is specific to either version of the API.<\/p>\n\n<p>This client is only concerned with retrieving and saving cache data, and delegating any other logic to the original version.<\/p>\n\n<p>With this approach, I can switch between <code>V1ApiClient<\/code>, <code>V2ApiClient<\/code> or any other version with the same methods without having to reimplement caching as that's handled within the <code>CacheableApiClient<\/code>.<\/p>\n\n<p>But what if I don't want to interact with the API at all?<\/p>\n\n<p>For local development, I have a <code>FakeApiClient<\/code> that returns a static response that I can work with.<\/p>\n\n<p>The possibilities are endless.<\/p>\n\n ",
"value": "\n <p>As well as <a href=\"/daily\/2025\/04\/05\/strategies\">working with different versions of an API<\/a>, I was able to use the same technique I wrote about yesterday to easily add a cacheable version of the API client.<\/p>\n\n<p>As they all implement the same <code>ApiClientInterface<\/code>, I can inject and decorate a client with another client, making one solely responsible for caching the result from the API whilst keeping the API interaction logic separate (aka <a href=\"/daily\/2022\/12\/08\/the-decorator-design-pattern\">the Decorator design pattern<\/a>).<\/p>\n\n<p>Here's an example based on the code I wrote:<\/p>\n\n<pre><code class=\"php\">final class CacheableApiClient implements ApiClientInterface {\n\n \/**\n * The cache duration in seconds.\n *\/\n private const CACHE_DURATION = 3600;\n\n public function __construct(\n private readonly ApiClientInterface $client,\n private readonly TimeInterface $time,\n private readonly CacheBackendInterface $cache,\n ) {\n }\n\n public function getResults(): Collection {\n $key = $this-&gt;getCacheKey();\n\n $cache = $this-&gt;cache-&gt;get($key);\n\n if ($cache !== FALSE) {\n return $cache-&gt;data;\n }\n\n $result = $this-&gt;client-&gt;getResults();\n\n $this-&gt;cache-&gt;set(\n cid: $key,\n data: $result,\n expire: $this-&gt;time-&gt;getRequestTime() + self::CACHE_DURATION,\n );\n\n return $result;\n }\n\n}\n<\/code><\/pre>\n\n<p>Nothing in this instance is specific to either version of the API.<\/p>\n\n<p>This client is only concerned with retrieving and saving cache data, and delegating any other logic to the original version.<\/p>\n\n<p>With this approach, I can switch between <code>V1ApiClient<\/code>, <code>V2ApiClient<\/code> or any other version with the same methods without having to reimplement caching as that's handled within the <code>CacheableApiClient<\/code>.<\/p>\n\n<p>But what if I don't want to interact with the API at all?<\/p>\n\n<p>For local development, I have a <code>FakeApiClient<\/code> that returns a static response that I can work with.<\/p>\n\n<p>The possibilities are endless.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>As well as <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/04\/05\/strategies\">working with different versions of an API<\/a>, I was able to use the same technique I wrote about yesterday to easily add a cacheable version of the API client.<\/p>\n\n<p>As they all implement the same <code>ApiClientInterface<\/code>, I can inject and decorate a client with another client, making one solely responsible for caching the result from the API whilst keeping the API interaction logic separate (aka <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/12\/08\/the-decorator-design-pattern\">the Decorator design pattern<\/a>).<\/p>\n\n<p>Here's an example based on the code I wrote:<\/p>\n\n<pre><code class=\"php\">final class CacheableApiClient implements ApiClientInterface {\n\n \/**\n * The cache duration in seconds.\n *\/\n private const CACHE_DURATION = 3600;\n\n public function __construct(\n private readonly ApiClientInterface $client,\n private readonly TimeInterface $time,\n private readonly CacheBackendInterface $cache,\n ) {\n }\n\n public function getResults(): Collection {\n $key = $this-&gt;getCacheKey();\n\n $cache = $this-&gt;cache-&gt;get($key);\n\n if ($cache !== FALSE) {\n return $cache-&gt;data;\n }\n\n $result = $this-&gt;client-&gt;getResults();\n\n $this-&gt;cache-&gt;set(\n cid: $key,\n data: $result,\n expire: $this-&gt;time-&gt;getRequestTime() + self::CACHE_DURATION,\n );\n\n return $result;\n }\n\n}\n<\/code><\/pre>\n\n<p>Nothing in this instance is specific to either version of the API.<\/p>\n\n<p>This client is only concerned with retrieving and saving cache data, and delegating any other logic to the original version.<\/p>\n\n<p>With this approach, I can switch between <code>V1ApiClient<\/code>, <code>V2ApiClient<\/code> or any other version with the same methods without having to reimplement caching as that's handled within the <code>CacheableApiClient<\/code>.<\/p>\n\n<p>But what if I don't want to interact with the API at all?<\/p>\n\n<p>For local development, I have a <code>FakeApiClient<\/code> that returns a static response that I can work with.<\/p>\n\n<p>The possibilities are endless.<\/p>\n\n ",
"processed": "\n <p>As well as <a href=\"/daily\/2025\/04\/05\/strategies\">working with different versions of an API<\/a>, I was able to use the same technique I wrote about yesterday to easily add a cacheable version of the API client.<\/p>\n\n<p>As they all implement the same <code>ApiClientInterface<\/code>, I can inject and decorate a client with another client, making one solely responsible for caching the result from the API whilst keeping the API interaction logic separate (aka <a href=\"/daily\/2022\/12\/08\/the-decorator-design-pattern\">the Decorator design pattern<\/a>).<\/p>\n\n<p>Here's an example based on the code I wrote:<\/p>\n\n<pre><code class=\"php\">final class CacheableApiClient implements ApiClientInterface {\n\n \/**\n * The cache duration in seconds.\n *\/\n private const CACHE_DURATION = 3600;\n\n public function __construct(\n private readonly ApiClientInterface $client,\n private readonly TimeInterface $time,\n private readonly CacheBackendInterface $cache,\n ) {\n }\n\n public function getResults(): Collection {\n $key = $this-&gt;getCacheKey();\n\n $cache = $this-&gt;cache-&gt;get($key);\n\n if ($cache !== FALSE) {\n return $cache-&gt;data;\n }\n\n $result = $this-&gt;client-&gt;getResults();\n\n $this-&gt;cache-&gt;set(\n cid: $key,\n data: $result,\n expire: $this-&gt;time-&gt;getRequestTime() + self::CACHE_DURATION,\n );\n\n return $result;\n }\n\n}\n<\/code><\/pre>\n\n<p>Nothing in this instance is specific to either version of the API.<\/p>\n\n<p>This client is only concerned with retrieving and saving cache data, and delegating any other logic to the original version.<\/p>\n\n<p>With this approach, I can switch between <code>V1ApiClient<\/code>, <code>V2ApiClient<\/code> or any other version with the same methods without having to reimplement caching as that's handled within the <code>CacheableApiClient<\/code>.<\/p>\n\n<p>But what if I don't want to interact with the API at all?<\/p>\n\n<p>For local development, I have a <code>FakeApiClient<\/code> that returns a static response that I can work with.<\/p>\n\n<p>The possibilities are endless.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>As I've added software to my NixOS homelab server, I've found some things that aren't yet available in the nixpkgs repository.<\/p>\n\n<p>A common approach seems to be to use Docker and Docker Compose to run things in containers, especially ones that need multiple services like a web server, a database and a cache or proxy.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/12\/09\/drupal-devenv\">I've moved my development projects from Docker to devenv<\/a>, but I still have Docker installed and available.<\/p>\n\n<p>I knew it was easy to create a container image from a Nix-based setup, but the opposite is also true.<\/p>\n\n<p>It's very easy to run containers within NixOS.<\/p>\n\n<p>For example, here's <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/8cdc6a511dab5a31b1bc0a90bcdcf361043498e7\/nix\/modules\/nixos\/features\/homelab\/tubearchivist-container.nix\">how I've configured Tube Archivist<\/a>.<\/p>\n\n<p>This was created using a tool called <code>compose2nix<\/code>, but I've seen simpler examples for other services.<\/p>\n\n<p>This made it easy to take a Docker Compose file and convert it to a Docker or Podman container.<\/p>\n\n<p>My preference is to use NixOS services if they exist, but it's great to be able to do this as an alternative when needed.<\/p>\n\n ",
"value": "\n <p>As I've added software to my NixOS homelab server, I've found some things that aren't yet available in the nixpkgs repository.<\/p>\n\n<p>A common approach seems to be to use Docker and Docker Compose to run things in containers, especially ones that need multiple services like a web server, a database and a cache or proxy.<\/p>\n\n<p><a href=\"/daily\/2024\/12\/09\/drupal-devenv\">I've moved my development projects from Docker to devenv<\/a>, but I still have Docker installed and available.<\/p>\n\n<p>I knew it was easy to create a container image from a Nix-based setup, but the opposite is also true.<\/p>\n\n<p>It's very easy to run containers within NixOS.<\/p>\n\n<p>For example, here's <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/8cdc6a511dab5a31b1bc0a90bcdcf361043498e7\/nix\/modules\/nixos\/features\/homelab\/tubearchivist-container.nix\">how I've configured Tube Archivist<\/a>.<\/p>\n\n<p>This was created using a tool called <code>compose2nix<\/code>, but I've seen simpler examples for other services.<\/p>\n\n<p>This made it easy to take a Docker Compose file and convert it to a Docker or Podman container.<\/p>\n\n<p>My preference is to use NixOS services if they exist, but it's great to be able to do this as an alternative when needed.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>As I've added software to my NixOS homelab server, I've found some things that aren't yet available in the nixpkgs repository.<\/p>\n\n<p>A common approach seems to be to use Docker and Docker Compose to run things in containers, especially ones that need multiple services like a web server, a database and a cache or proxy.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/12\/09\/drupal-devenv\">I've moved my development projects from Docker to devenv<\/a>, but I still have Docker installed and available.<\/p>\n\n<p>I knew it was easy to create a container image from a Nix-based setup, but the opposite is also true.<\/p>\n\n<p>It's very easy to run containers within NixOS.<\/p>\n\n<p>For example, here's <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/8cdc6a511dab5a31b1bc0a90bcdcf361043498e7\/nix\/modules\/nixos\/features\/homelab\/tubearchivist-container.nix\">how I've configured Tube Archivist<\/a>.<\/p>\n\n<p>This was created using a tool called <code>compose2nix<\/code>, but I've seen simpler examples for other services.<\/p>\n\n<p>This made it easy to take a Docker Compose file and convert it to a Docker or Podman container.<\/p>\n\n<p>My preference is to use NixOS services if they exist, but it's great to be able to do this as an alternative when needed.<\/p>\n\n ",
"processed": "\n <p>As I've added software to my NixOS homelab server, I've found some things that aren't yet available in the nixpkgs repository.<\/p>\n\n<p>A common approach seems to be to use Docker and Docker Compose to run things in containers, especially ones that need multiple services like a web server, a database and a cache or proxy.<\/p>\n\n<p><a href=\"/daily\/2024\/12\/09\/drupal-devenv\">I've moved my development projects from Docker to devenv<\/a>, but I still have Docker installed and available.<\/p>\n\n<p>I knew it was easy to create a container image from a Nix-based setup, but the opposite is also true.<\/p>\n\n<p>It's very easy to run containers within NixOS.<\/p>\n\n<p>For example, here's <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/8cdc6a511dab5a31b1bc0a90bcdcf361043498e7\/nix\/modules\/nixos\/features\/homelab\/tubearchivist-container.nix\">how I've configured Tube Archivist<\/a>.<\/p>\n\n<p>This was created using a tool called <code>compose2nix<\/code>, but I've seen simpler examples for other services.<\/p>\n\n<p>This made it easy to take a Docker Compose file and convert it to a Docker or Podman container.<\/p>\n\n<p>My preference is to use NixOS services if they exist, but it's great to be able to do this as an alternative when needed.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>When I speak to people about automated testing or hear others speak about it, it's often confused with unit testing.<\/p>\n\n<p>Drupal and many other projects use PHPUnit. Its website describes PHPUnit as \"a programmer-oriented testing framework for PHP\", whereas Wikipedia explicitly says \"PHPUnit is a unit testing framework\".<\/p>\n\n<p>But automated testing includes much more.<\/p>\n\n<h2 id=\"other-types-of-tests\">Other types of tests<\/h2>\n\n<p>In Drupal, whilst there are unit tests, PHPUnit also does feature (aka functional or browser) testing, where it can make an HTTP request to an endpoint and perform assertions on the response's status code and the returned text. This is great for checking if a page exists at a certain path, whether the correct users can access it and whether it contains the expected text. This isn't something that can be done with a unit test.<\/p>\n\n<p>There are also integration (aka kernel) tests which don't access the browser but have access to Drupal's service container to interact with its services and can save and retrieve values from the database. Again, this isn't available in a unit test which relies heavily on mocking.<\/p>\n\n<h2 id=\"what-else-is-there%3F\">What else is there?<\/h2>\n\n<p>In Drupal, I've also used Behat - a behaviour-driven development testing framework that allows writing tests in a plain English syntax called Gherkin instead of PHP.<\/p>\n\n<p>Pest PHP has an architecture plugin.<\/p>\n\n<p>There are dedicated front-end testing frameworks like Cypress for UI testing.<\/p>\n\n<p>Other quality tools like static analysis can also be considered testing tools.<\/p>\n\n<h2 id=\"want-to-learn-more%3F\">Want to learn more?<\/h2>\n\n<p>If you want to learn more about automated testing in Drupal, <a href=\"https:\/\/www.oliverdavies.uk\/talks\/tdd-test-driven-drupal\">I have a talk about that<\/a>.<\/p>\n\n ",
"value": "\n <p>When I speak to people about automated testing or hear others speak about it, it's often confused with unit testing.<\/p>\n\n<p>Drupal and many other projects use PHPUnit. Its website describes PHPUnit as \"a programmer-oriented testing framework for PHP\", whereas Wikipedia explicitly says \"PHPUnit is a unit testing framework\".<\/p>\n\n<p>But automated testing includes much more.<\/p>\n\n<h2 id=\"other-types-of-tests\">Other types of tests<\/h2>\n\n<p>In Drupal, whilst there are unit tests, PHPUnit also does feature (aka functional or browser) testing, where it can make an HTTP request to an endpoint and perform assertions on the response's status code and the returned text. This is great for checking if a page exists at a certain path, whether the correct users can access it and whether it contains the expected text. This isn't something that can be done with a unit test.<\/p>\n\n<p>There are also integration (aka kernel) tests which don't access the browser but have access to Drupal's service container to interact with its services and can save and retrieve values from the database. Again, this isn't available in a unit test which relies heavily on mocking.<\/p>\n\n<h2 id=\"what-else-is-there%3F\">What else is there?<\/h2>\n\n<p>In Drupal, I've also used Behat - a behaviour-driven development testing framework that allows writing tests in a plain English syntax called Gherkin instead of PHP.<\/p>\n\n<p>Pest PHP has an architecture plugin.<\/p>\n\n<p>There are dedicated front-end testing frameworks like Cypress for UI testing.<\/p>\n\n<p>Other quality tools like static analysis can also be considered testing tools.<\/p>\n\n<h2 id=\"want-to-learn-more%3F\">Want to learn more?<\/h2>\n\n<p>If you want to learn more about automated testing in Drupal, <a href=\"/talks\/tdd-test-driven-drupal\">I have a talk about that<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>When I speak to people about automated testing or hear others speak about it, it's often confused with unit testing.<\/p>\n\n<p>Drupal and many other projects use PHPUnit. Its website describes PHPUnit as \"a programmer-oriented testing framework for PHP\", whereas Wikipedia explicitly says \"PHPUnit is a unit testing framework\".<\/p>\n\n<p>But automated testing includes much more.<\/p>\n\n<h2 id=\"other-types-of-tests\">Other types of tests<\/h2>\n\n<p>In Drupal, whilst there are unit tests, PHPUnit also does feature (aka functional or browser) testing, where it can make an HTTP request to an endpoint and perform assertions on the response's status code and the returned text. This is great for checking if a page exists at a certain path, whether the correct users can access it and whether it contains the expected text. This isn't something that can be done with a unit test.<\/p>\n\n<p>There are also integration (aka kernel) tests which don't access the browser but have access to Drupal's service container to interact with its services and can save and retrieve values from the database. Again, this isn't available in a unit test which relies heavily on mocking.<\/p>\n\n<h2 id=\"what-else-is-there%3F\">What else is there?<\/h2>\n\n<p>In Drupal, I've also used Behat - a behaviour-driven development testing framework that allows writing tests in a plain English syntax called Gherkin instead of PHP.<\/p>\n\n<p>Pest PHP has an architecture plugin.<\/p>\n\n<p>There are dedicated front-end testing frameworks like Cypress for UI testing.<\/p>\n\n<p>Other quality tools like static analysis can also be considered testing tools.<\/p>\n\n<h2 id=\"want-to-learn-more%3F\">Want to learn more?<\/h2>\n\n<p>If you want to learn more about automated testing in Drupal, <a href=\"https:\/\/www.oliverdavies.uk\/talks\/tdd-test-driven-drupal\">I have a talk about that<\/a>.<\/p>\n\n ",
"processed": "\n <p>When I speak to people about automated testing or hear others speak about it, it's often confused with unit testing.<\/p>\n\n<p>Drupal and many other projects use PHPUnit. Its website describes PHPUnit as \"a programmer-oriented testing framework for PHP\", whereas Wikipedia explicitly says \"PHPUnit is a unit testing framework\".<\/p>\n\n<p>But automated testing includes much more.<\/p>\n\n<h2 id=\"other-types-of-tests\">Other types of tests<\/h2>\n\n<p>In Drupal, whilst there are unit tests, PHPUnit also does feature (aka functional or browser) testing, where it can make an HTTP request to an endpoint and perform assertions on the response's status code and the returned text. This is great for checking if a page exists at a certain path, whether the correct users can access it and whether it contains the expected text. This isn't something that can be done with a unit test.<\/p>\n\n<p>There are also integration (aka kernel) tests which don't access the browser but have access to Drupal's service container to interact with its services and can save and retrieve values from the database. Again, this isn't available in a unit test which relies heavily on mocking.<\/p>\n\n<h2 id=\"what-else-is-there%3F\">What else is there?<\/h2>\n\n<p>In Drupal, I've also used Behat - a behaviour-driven development testing framework that allows writing tests in a plain English syntax called Gherkin instead of PHP.<\/p>\n\n<p>Pest PHP has an architecture plugin.<\/p>\n\n<p>There are dedicated front-end testing frameworks like Cypress for UI testing.<\/p>\n\n<p>Other quality tools like static analysis can also be considered testing tools.<\/p>\n\n<h2 id=\"want-to-learn-more%3F\">Want to learn more?<\/h2>\n\n<p>If you want to learn more about automated testing in Drupal, <a href=\"/talks\/tdd-test-driven-drupal\">I have a talk about that<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>When looking at some websites, you can tell that it was built using a certain CSS framework.<\/p>\n\n<p>Whether it's using a standard component like a navbar or card, or it's using the default colour palette, you can confidently know that website uses ___.<\/p>\n\n<p>As Tailwind includes no components (other than the <code>container<\/code>) and only has low-level utility classes for things like spacing and colours (amongst many other things), you can build radically different-looking websites with the same classes.<\/p>\n\n<p>There are some <a href=\"https:\/\/www.oliverdavies.uk\/blog\/uis-ive-rebuilt-tailwind-css\">examples of UIs that I've rebuilt<\/a> and some websites that I show in my <a href=\"https:\/\/www.oliverdavies.uk\/talks\/taking-flight-with-tailwind-css\">Taking Flight with Tailwind CSS talk<\/a>.<\/p>\n\n<p>If you take a look, you'll see what I mean.<\/p>\n\n ",
"value": "\n <p>When looking at some websites, you can tell that it was built using a certain CSS framework.<\/p>\n\n<p>Whether it's using a standard component like a navbar or card, or it's using the default colour palette, you can confidently know that website uses ___.<\/p>\n\n<p>As Tailwind includes no components (other than the <code>container<\/code>) and only has low-level utility classes for things like spacing and colours (amongst many other things), you can build radically different-looking websites with the same classes.<\/p>\n\n<p>There are some <a href=\"/blog\/uis-ive-rebuilt-tailwind-css\">examples of UIs that I've rebuilt<\/a> and some websites that I show in my <a href=\"/talks\/taking-flight-with-tailwind-css\">Taking Flight with Tailwind CSS talk<\/a>.<\/p>\n\n<p>If you take a look, you'll see what I mean.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>When looking at some websites, you can tell that it was built using a certain CSS framework.<\/p>\n\n<p>Whether it's using a standard component like a navbar or card, or it's using the default colour palette, you can confidently know that website uses ___.<\/p>\n\n<p>As Tailwind includes no components (other than the <code>container<\/code>) and only has low-level utility classes for things like spacing and colours (amongst many other things), you can build radically different-looking websites with the same classes.<\/p>\n\n<p>There are some <a href=\"https:\/\/www.oliverdavies.uk\/blog\/uis-ive-rebuilt-tailwind-css\">examples of UIs that I've rebuilt<\/a> and some websites that I show in my <a href=\"https:\/\/www.oliverdavies.uk\/talks\/taking-flight-with-tailwind-css\">Taking Flight with Tailwind CSS talk<\/a>.<\/p>\n\n<p>If you take a look, you'll see what I mean.<\/p>\n\n ",
"processed": "\n <p>When looking at some websites, you can tell that it was built using a certain CSS framework.<\/p>\n\n<p>Whether it's using a standard component like a navbar or card, or it's using the default colour palette, you can confidently know that website uses ___.<\/p>\n\n<p>As Tailwind includes no components (other than the <code>container<\/code>) and only has low-level utility classes for things like spacing and colours (amongst many other things), you can build radically different-looking websites with the same classes.<\/p>\n\n<p>There are some <a href=\"/blog\/uis-ive-rebuilt-tailwind-css\">examples of UIs that I've rebuilt<\/a> and some websites that I show in my <a href=\"/talks\/taking-flight-with-tailwind-css\">Taking Flight with Tailwind CSS talk<\/a>.<\/p>\n\n<p>If you take a look, you'll see what I mean.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>In yesterday's email, I wrote about why <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/08\/16\/what-are-err--req-and-res\">readable variable names are important<\/a> and why I use descriptive variable names in my code.<\/p>\n\n<p>Given this pseudo-code:<\/p>\n\n<pre><code class=\"php\">function hande(req, res) {\n}\n<\/code><\/pre>\n\n<p>With the short variable names, whilst you can guess, it's unclear what the variable names are.<\/p>\n\n<p>However, in this code, we have the same variable names, but we also have additional type information:<\/p>\n\n<pre><code class=\"php\">function handle(Request req, Response res): void {\n}\n<\/code><\/pre>\n\n<p>Even with the same variable names, I know what their types are and what the function returns, I have better completions and diagnostics in my editor and better static analysis of my code, making it easier to identify and fix potential bugs.<\/p>\n\n ",
"value": "\n <p>In yesterday's email, I wrote about why <a href=\"/daily\/2024\/08\/16\/what-are-err--req-and-res\">readable variable names are important<\/a> and why I use descriptive variable names in my code.<\/p>\n\n<p>Given this pseudo-code:<\/p>\n\n<pre><code class=\"php\">function hande(req, res) {\n}\n<\/code><\/pre>\n\n<p>With the short variable names, whilst you can guess, it's unclear what the variable names are.<\/p>\n\n<p>However, in this code, we have the same variable names, but we also have additional type information:<\/p>\n\n<pre><code class=\"php\">function handle(Request req, Response res): void {\n}\n<\/code><\/pre>\n\n<p>Even with the same variable names, I know what their types are and what the function returns, I have better completions and diagnostics in my editor and better static analysis of my code, making it easier to identify and fix potential bugs.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>In yesterday's email, I wrote about why <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/08\/16\/what-are-err--req-and-res\">readable variable names are important<\/a> and why I use descriptive variable names in my code.<\/p>\n\n<p>Given this pseudo-code:<\/p>\n\n<pre><code class=\"php\">function hande(req, res) {\n}\n<\/code><\/pre>\n\n<p>With the short variable names, whilst you can guess, it's unclear what the variable names are.<\/p>\n\n<p>However, in this code, we have the same variable names, but we also have additional type information:<\/p>\n\n<pre><code class=\"php\">function handle(Request req, Response res): void {\n}\n<\/code><\/pre>\n\n<p>Even with the same variable names, I know what their types are and what the function returns, I have better completions and diagnostics in my editor and better static analysis of my code, making it easier to identify and fix potential bugs.<\/p>\n\n ",
"processed": "\n <p>In yesterday's email, I wrote about why <a href=\"/daily\/2024\/08\/16\/what-are-err--req-and-res\">readable variable names are important<\/a> and why I use descriptive variable names in my code.<\/p>\n\n<p>Given this pseudo-code:<\/p>\n\n<pre><code class=\"php\">function hande(req, res) {\n}\n<\/code><\/pre>\n\n<p>With the short variable names, whilst you can guess, it's unclear what the variable names are.<\/p>\n\n<p>However, in this code, we have the same variable names, but we also have additional type information:<\/p>\n\n<pre><code class=\"php\">function handle(Request req, Response res): void {\n}\n<\/code><\/pre>\n\n<p>Even with the same variable names, I know what their types are and what the function returns, I have better completions and diagnostics in my editor and better static analysis of my code, making it easier to identify and fix potential bugs.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Yesterday, I <a href=\"https:\/\/twitter.com\/scottkeckwarren\/status\/1594752744165847040\">saw a tweet<\/a> where the writer said they were \u201cfalling into the branch, pull request, and merge after actions pass I use at work even though I'm the only one working on it\u201d.<\/p>\n\n<p>After reading this, my question is, \"Should you, or do you need to, create branches if you're the only person working on a project?\".<\/p>\n\n<p>These days, I use trunk-based development as much as possible, so I hardly ever create new branches, whether working on a project myself or with a team.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/presentations\/git-flow\">I used to use Git Flow<\/a> and create branches for every new feature and bug fix, but I remember, whilst demonstrating two work-in-progress features to a client, switching between the different branches caused my local site to break. Whilst it wasn\u2019t a major issue, it wouldn't have seemed professional.<\/p>\n\n<p>In a team environment, feature branches are intended to keep different changes and different people's work separate.<\/p>\n\n<p>But is this needed if you\u2019re the only in the team?<\/p>\n\n<p>Assumingly, you're only working on one change at a time, so what's the benefit of creating a separate branch?<\/p>\n\n<p>If you need to switch to a different task, another approach could be to revert your work-in-progress commits, move them onto another local branch temporarily, or wrap them within a feature flag so that the changes are committed but not active.<\/p>\n\n<p>The other part of the tweet said, \u201cI like the little integrations to make sure the tests pass\u201d.<\/p>\n\n<p>I\u2019m comfortable working on a single branch and committing and pushing small changes often.<\/p>\n\n<p>My CI pipelines run for every change that I push, and if one fails, I\u2019ll either push a small fix to get it passing again or revert the failing change and investigate further.<\/p>\n\n<p>For me, working on a single branch keeps my workflow simple and lean, allowing me to focus on the changes and the tasks that I need to work on and not worry about which branch I\u2019m working on.<\/p>\n\n ",
"value": "\n <p>Yesterday, I <a href=\"https:\/\/twitter.com\/scottkeckwarren\/status\/1594752744165847040\">saw a tweet<\/a> where the writer said they were \u201cfalling into the branch, pull request, and merge after actions pass I use at work even though I'm the only one working on it\u201d.<\/p>\n\n<p>After reading this, my question is, \"Should you, or do you need to, create branches if you're the only person working on a project?\".<\/p>\n\n<p>These days, I use trunk-based development as much as possible, so I hardly ever create new branches, whether working on a project myself or with a team.<\/p>\n\n<p><a href=\"/presentations\/git-flow\">I used to use Git Flow<\/a> and create branches for every new feature and bug fix, but I remember, whilst demonstrating two work-in-progress features to a client, switching between the different branches caused my local site to break. Whilst it wasn\u2019t a major issue, it wouldn't have seemed professional.<\/p>\n\n<p>In a team environment, feature branches are intended to keep different changes and different people's work separate.<\/p>\n\n<p>But is this needed if you\u2019re the only in the team?<\/p>\n\n<p>Assumingly, you're only working on one change at a time, so what's the benefit of creating a separate branch?<\/p>\n\n<p>If you need to switch to a different task, another approach could be to revert your work-in-progress commits, move them onto another local branch temporarily, or wrap them within a feature flag so that the changes are committed but not active.<\/p>\n\n<p>The other part of the tweet said, \u201cI like the little integrations to make sure the tests pass\u201d.<\/p>\n\n<p>I\u2019m comfortable working on a single branch and committing and pushing small changes often.<\/p>\n\n<p>My CI pipelines run for every change that I push, and if one fails, I\u2019ll either push a small fix to get it passing again or revert the failing change and investigate further.<\/p>\n\n<p>For me, working on a single branch keeps my workflow simple and lean, allowing me to focus on the changes and the tasks that I need to work on and not worry about which branch I\u2019m working on.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Yesterday, I <a href=\"https:\/\/twitter.com\/scottkeckwarren\/status\/1594752744165847040\">saw a tweet<\/a> where the writer said they were \u201cfalling into the branch, pull request, and merge after actions pass I use at work even though I'm the only one working on it\u201d.<\/p>\n\n<p>After reading this, my question is, \"Should you, or do you need to, create branches if you're the only person working on a project?\".<\/p>\n\n<p>These days, I use trunk-based development as much as possible, so I hardly ever create new branches, whether working on a project myself or with a team.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/presentations\/git-flow\">I used to use Git Flow<\/a> and create branches for every new feature and bug fix, but I remember, whilst demonstrating two work-in-progress features to a client, switching between the different branches caused my local site to break. Whilst it wasn\u2019t a major issue, it wouldn't have seemed professional.<\/p>\n\n<p>In a team environment, feature branches are intended to keep different changes and different people's work separate.<\/p>\n\n<p>But is this needed if you\u2019re the only in the team?<\/p>\n\n<p>Assumingly, you're only working on one change at a time, so what's the benefit of creating a separate branch?<\/p>\n\n<p>If you need to switch to a different task, another approach could be to revert your work-in-progress commits, move them onto another local branch temporarily, or wrap them within a feature flag so that the changes are committed but not active.<\/p>\n\n<p>The other part of the tweet said, \u201cI like the little integrations to make sure the tests pass\u201d.<\/p>\n\n<p>I\u2019m comfortable working on a single branch and committing and pushing small changes often.<\/p>\n\n<p>My CI pipelines run for every change that I push, and if one fails, I\u2019ll either push a small fix to get it passing again or revert the failing change and investigate further.<\/p>\n\n<p>For me, working on a single branch keeps my workflow simple and lean, allowing me to focus on the changes and the tasks that I need to work on and not worry about which branch I\u2019m working on.<\/p>\n\n ",
"processed": "\n <p>Yesterday, I <a href=\"https:\/\/twitter.com\/scottkeckwarren\/status\/1594752744165847040\">saw a tweet<\/a> where the writer said they were \u201cfalling into the branch, pull request, and merge after actions pass I use at work even though I'm the only one working on it\u201d.<\/p>\n\n<p>After reading this, my question is, \"Should you, or do you need to, create branches if you're the only person working on a project?\".<\/p>\n\n<p>These days, I use trunk-based development as much as possible, so I hardly ever create new branches, whether working on a project myself or with a team.<\/p>\n\n<p><a href=\"/presentations\/git-flow\">I used to use Git Flow<\/a> and create branches for every new feature and bug fix, but I remember, whilst demonstrating two work-in-progress features to a client, switching between the different branches caused my local site to break. Whilst it wasn\u2019t a major issue, it wouldn't have seemed professional.<\/p>\n\n<p>In a team environment, feature branches are intended to keep different changes and different people's work separate.<\/p>\n\n<p>But is this needed if you\u2019re the only in the team?<\/p>\n\n<p>Assumingly, you're only working on one change at a time, so what's the benefit of creating a separate branch?<\/p>\n\n<p>If you need to switch to a different task, another approach could be to revert your work-in-progress commits, move them onto another local branch temporarily, or wrap them within a feature flag so that the changes are committed but not active.<\/p>\n\n<p>The other part of the tweet said, \u201cI like the little integrations to make sure the tests pass\u201d.<\/p>\n\n<p>I\u2019m comfortable working on a single branch and committing and pushing small changes often.<\/p>\n\n<p>My CI pipelines run for every change that I push, and if one fails, I\u2019ll either push a small fix to get it passing again or revert the failing change and investigate further.<\/p>\n\n<p>For me, working on a single branch keeps my workflow simple and lean, allowing me to focus on the changes and the tasks that I need to work on and not worry about which branch I\u2019m working on.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>This week, I'll be in Lille, France for DrupalCon Europe, where I'm presenting a session on automated testing and test-driven development in Drupal.<\/p>\n\n<p>I'll be taking a short break from these emails to enjoy the conference, focus on my talk, and finish my <a href=\"https:\/\/www.oliverdavies.uk\/atdc\">free email course on automated testing in Drupal<\/a>.<\/p>\n\n ",
"value": "\n <p>This week, I'll be in Lille, France for DrupalCon Europe, where I'm presenting a session on automated testing and test-driven development in Drupal.<\/p>\n\n<p>I'll be taking a short break from these emails to enjoy the conference, focus on my talk, and finish my <a href=\"/atdc\">free email course on automated testing in Drupal<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>This week, I'll be in Lille, France for DrupalCon Europe, where I'm presenting a session on automated testing and test-driven development in Drupal.<\/p>\n\n<p>I'll be taking a short break from these emails to enjoy the conference, focus on my talk, and finish my <a href=\"https:\/\/www.oliverdavies.uk\/atdc\">free email course on automated testing in Drupal<\/a>.<\/p>\n\n ",
"processed": "\n <p>This week, I'll be in Lille, France for DrupalCon Europe, where I'm presenting a session on automated testing and test-driven development in Drupal.<\/p>\n\n<p>I'll be taking a short break from these emails to enjoy the conference, focus on my talk, and finish my <a href=\"/atdc\">free email course on automated testing in Drupal<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Yesterday, I dusted off our Meetup page and posted our next <a href=\"https:\/\/www.meetup.com\/php-south-wales\">PHP South Wales meetup<\/a> event.<\/p>\n\n<p>We've had online meetups and code practice sessions throughout the pandemic and during lockdowns, but this will be our first offline\/in person\/IRL meetup since February 2020.<\/p>\n\n<p>As well as organising our online meetups during COVID, I attended a lot of other online events, <a href=\"https:\/\/www.oliverdavies.uk\/blog\/speaking-remotely-during-covid-19\">usually giving various talks or workshops<\/a>, and whilst they were good for a while, I eventually started to get burned out by them.<\/p>\n\n<p>I've been an organiser of various meetups and conferences for a long time, and attending events has been a very large part of my career so far - providing opportunities to learn, to network and socialise with other attendees, and pass knowledge on through talks, workshops and mentoring.<\/p>\n\n<p>It's been great to see some offline events returning, from local user groups to conferences such as DevOpsDays, DrupalCon and SymfonyLive.<\/p>\n\n<p>I've given one talk this year - a lot less than this time last year - but it was in front of an audience instead of a screen, and whilst it seemed strange, I'm sure that it's something that will feel normal again in time.<\/p>\n\n<p>I'm thinking of attending a conference next month, I've submitted some talk suggestions to some other conferences which I'm waiting to hear from, and am considering travelling to some of the other UK user groups as they restart - some of which I joined or spoke at online but it would be great to meet them in person.<\/p>\n\n<p>For next week, I'll be glad to have PHP South Wales events running again and to see our community back together in person, and then do it again and start getting ready for next month's event.<\/p>\n\n ",
"value": "\n <p>Yesterday, I dusted off our Meetup page and posted our next <a href=\"https:\/\/www.meetup.com\/php-south-wales\">PHP South Wales meetup<\/a> event.<\/p>\n\n<p>We've had online meetups and code practice sessions throughout the pandemic and during lockdowns, but this will be our first offline\/in person\/IRL meetup since February 2020.<\/p>\n\n<p>As well as organising our online meetups during COVID, I attended a lot of other online events, <a href=\"/blog\/speaking-remotely-during-covid-19\">usually giving various talks or workshops<\/a>, and whilst they were good for a while, I eventually started to get burned out by them.<\/p>\n\n<p>I've been an organiser of various meetups and conferences for a long time, and attending events has been a very large part of my career so far - providing opportunities to learn, to network and socialise with other attendees, and pass knowledge on through talks, workshops and mentoring.<\/p>\n\n<p>It's been great to see some offline events returning, from local user groups to conferences such as DevOpsDays, DrupalCon and SymfonyLive.<\/p>\n\n<p>I've given one talk this year - a lot less than this time last year - but it was in front of an audience instead of a screen, and whilst it seemed strange, I'm sure that it's something that will feel normal again in time.<\/p>\n\n<p>I'm thinking of attending a conference next month, I've submitted some talk suggestions to some other conferences which I'm waiting to hear from, and am considering travelling to some of the other UK user groups as they restart - some of which I joined or spoke at online but it would be great to meet them in person.<\/p>\n\n<p>For next week, I'll be glad to have PHP South Wales events running again and to see our community back together in person, and then do it again and start getting ready for next month's event.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Yesterday, I dusted off our Meetup page and posted our next <a href=\"https:\/\/www.meetup.com\/php-south-wales\">PHP South Wales meetup<\/a> event.<\/p>\n\n<p>We've had online meetups and code practice sessions throughout the pandemic and during lockdowns, but this will be our first offline\/in person\/IRL meetup since February 2020.<\/p>\n\n<p>As well as organising our online meetups during COVID, I attended a lot of other online events, <a href=\"https:\/\/www.oliverdavies.uk\/blog\/speaking-remotely-during-covid-19\">usually giving various talks or workshops<\/a>, and whilst they were good for a while, I eventually started to get burned out by them.<\/p>\n\n<p>I've been an organiser of various meetups and conferences for a long time, and attending events has been a very large part of my career so far - providing opportunities to learn, to network and socialise with other attendees, and pass knowledge on through talks, workshops and mentoring.<\/p>\n\n<p>It's been great to see some offline events returning, from local user groups to conferences such as DevOpsDays, DrupalCon and SymfonyLive.<\/p>\n\n<p>I've given one talk this year - a lot less than this time last year - but it was in front of an audience instead of a screen, and whilst it seemed strange, I'm sure that it's something that will feel normal again in time.<\/p>\n\n<p>I'm thinking of attending a conference next month, I've submitted some talk suggestions to some other conferences which I'm waiting to hear from, and am considering travelling to some of the other UK user groups as they restart - some of which I joined or spoke at online but it would be great to meet them in person.<\/p>\n\n<p>For next week, I'll be glad to have PHP South Wales events running again and to see our community back together in person, and then do it again and start getting ready for next month's event.<\/p>\n\n ",
"processed": "\n <p>Yesterday, I dusted off our Meetup page and posted our next <a href=\"https:\/\/www.meetup.com\/php-south-wales\">PHP South Wales meetup<\/a> event.<\/p>\n\n<p>We've had online meetups and code practice sessions throughout the pandemic and during lockdowns, but this will be our first offline\/in person\/IRL meetup since February 2020.<\/p>\n\n<p>As well as organising our online meetups during COVID, I attended a lot of other online events, <a href=\"/blog\/speaking-remotely-during-covid-19\">usually giving various talks or workshops<\/a>, and whilst they were good for a while, I eventually started to get burned out by them.<\/p>\n\n<p>I've been an organiser of various meetups and conferences for a long time, and attending events has been a very large part of my career so far - providing opportunities to learn, to network and socialise with other attendees, and pass knowledge on through talks, workshops and mentoring.<\/p>\n\n<p>It's been great to see some offline events returning, from local user groups to conferences such as DevOpsDays, DrupalCon and SymfonyLive.<\/p>\n\n<p>I've given one talk this year - a lot less than this time last year - but it was in front of an audience instead of a screen, and whilst it seemed strange, I'm sure that it's something that will feel normal again in time.<\/p>\n\n<p>I'm thinking of attending a conference next month, I've submitted some talk suggestions to some other conferences which I'm waiting to hear from, and am considering travelling to some of the other UK user groups as they restart - some of which I joined or spoke at online but it would be great to meet them in person.<\/p>\n\n<p>For next week, I'll be glad to have PHP South Wales events running again and to see our community back together in person, and then do it again and start getting ready for next month's event.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Last month, I wrote an email explaining <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/02\/28\/why-i-dont-branch\">why I don't create branches<\/a>.<\/p>\n\n<p>After sending that email, I received this question from a reader (shared with permission):<\/p>\n\n<blockquote>\n <p>I'm trying to work at one feature at a time, so I usually don't need feature branches.<\/p>\n \n <p>There's one thing that's difficult for me, maybe you could tell us something about this in one of your upcoming posts:<\/p>\n \n <p>How do you deal with hot fixes?<\/p>\n \n <p>I know, there's keeping features small, commit often and early. But sometimes this isn't possible, and a feature will take e.g. 3 days of work. Now, if there's an urgent bug in production that should be fixed asap, what are you doing?<\/p>\n \n <p>Git stash probably won't help here, as there might be commits already that would deliver an incomplete feature.<\/p>\n<\/blockquote>\n\n<h2 id=\"option-1%3A-worktrees\">Option 1: Worktrees<\/h2>\n\n<p>Whilst I don't create branches, I do use <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/12\/git-worktrees-docker-compose\">Git worktrees<\/a>, which allows me to have multiple versions of the code checked out at the same time - similar to having multiple clones of a repository.<\/p>\n\n<p>Having multiple worktrees, you don't need to stash the code for your incomplete feature or worry about commits you haven't pushed yet.<\/p>\n\n<p>You can create a new worktree, fix the urgent bug and switch back to your <code>main<\/code> worktree when you're finished.<\/p>\n\n<p>You'll still need to update the original worktree with your new changes which may result in conflicts - the same as merging or rebasing onto a branch.<\/p>\n\n<h2 id=\"option-2%3A-feature-flags\">Option 2: Feature Flags<\/h2>\n\n<p>My preferred approach is to use <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/12\/07\/separating-releases-from-deployments-with-feature-flags\">feature flags<\/a>, a.k.a. feature toggles.<\/p>\n\n<p>My wrapping the incomplete feature in a feature flag, it can be deployed but won't be active until the flag is enabled - similar to writing a new Drupal module but not enabling it.<\/p>\n\n<p>This is a technique I use often as it works well with trunk-based development and continuous integration and delivery.<\/p>\n\n<p>When the incomplete feature is feature-flagged, you can fix the bug and deploy the hotfix without stashing or rebasing any changes, and you can leave the flag disabled.\nWhen the feature is ready, enable the feature flag to activate it and, if you need to turn it off again (maybe that's causing the next bug), you can easily disable it without needing to revert and deploy the code again.<\/p>\n\n<p>You can just turn the feature flag back off.<\/p>\n\n<p>I hope that helps!<\/p>\n\n ",
"value": "\n <p>Last month, I wrote an email explaining <a href=\"/daily\/2024\/02\/28\/why-i-dont-branch\">why I don't create branches<\/a>.<\/p>\n\n<p>After sending that email, I received this question from a reader (shared with permission):<\/p>\n\n<blockquote>\n <p>I'm trying to work at one feature at a time, so I usually don't need feature branches.<\/p>\n \n <p>There's one thing that's difficult for me, maybe you could tell us something about this in one of your upcoming posts:<\/p>\n \n <p>How do you deal with hot fixes?<\/p>\n \n <p>I know, there's keeping features small, commit often and early. But sometimes this isn't possible, and a feature will take e.g. 3 days of work. Now, if there's an urgent bug in production that should be fixed asap, what are you doing?<\/p>\n \n <p>Git stash probably won't help here, as there might be commits already that would deliver an incomplete feature.<\/p>\n<\/blockquote>\n\n<h2 id=\"option-1%3A-worktrees\">Option 1: Worktrees<\/h2>\n\n<p>Whilst I don't create branches, I do use <a href=\"/daily\/2022\/08\/12\/git-worktrees-docker-compose\">Git worktrees<\/a>, which allows me to have multiple versions of the code checked out at the same time - similar to having multiple clones of a repository.<\/p>\n\n<p>Having multiple worktrees, you don't need to stash the code for your incomplete feature or worry about commits you haven't pushed yet.<\/p>\n\n<p>You can create a new worktree, fix the urgent bug and switch back to your <code>main<\/code> worktree when you're finished.<\/p>\n\n<p>You'll still need to update the original worktree with your new changes which may result in conflicts - the same as merging or rebasing onto a branch.<\/p>\n\n<h2 id=\"option-2%3A-feature-flags\">Option 2: Feature Flags<\/h2>\n\n<p>My preferred approach is to use <a href=\"/daily\/2022\/12\/07\/separating-releases-from-deployments-with-feature-flags\">feature flags<\/a>, a.k.a. feature toggles.<\/p>\n\n<p>My wrapping the incomplete feature in a feature flag, it can be deployed but won't be active until the flag is enabled - similar to writing a new Drupal module but not enabling it.<\/p>\n\n<p>This is a technique I use often as it works well with trunk-based development and continuous integration and delivery.<\/p>\n\n<p>When the incomplete feature is feature-flagged, you can fix the bug and deploy the hotfix without stashing or rebasing any changes, and you can leave the flag disabled.\nWhen the feature is ready, enable the feature flag to activate it and, if you need to turn it off again (maybe that's causing the next bug), you can easily disable it without needing to revert and deploy the code again.<\/p>\n\n<p>You can just turn the feature flag back off.<\/p>\n\n<p>I hope that helps!<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Last month, I wrote an email explaining <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/02\/28\/why-i-dont-branch\">why I don't create branches<\/a>.<\/p>\n\n<p>After sending that email, I received this question from a reader (shared with permission):<\/p>\n\n<blockquote>\n <p>I'm trying to work at one feature at a time, so I usually don't need feature branches.<\/p>\n \n <p>There's one thing that's difficult for me, maybe you could tell us something about this in one of your upcoming posts:<\/p>\n \n <p>How do you deal with hot fixes?<\/p>\n \n <p>I know, there's keeping features small, commit often and early. But sometimes this isn't possible, and a feature will take e.g. 3 days of work. Now, if there's an urgent bug in production that should be fixed asap, what are you doing?<\/p>\n \n <p>Git stash probably won't help here, as there might be commits already that would deliver an incomplete feature.<\/p>\n<\/blockquote>\n\n<h2 id=\"option-1%3A-worktrees\">Option 1: Worktrees<\/h2>\n\n<p>Whilst I don't create branches, I do use <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/12\/git-worktrees-docker-compose\">Git worktrees<\/a>, which allows me to have multiple versions of the code checked out at the same time - similar to having multiple clones of a repository.<\/p>\n\n<p>Having multiple worktrees, you don't need to stash the code for your incomplete feature or worry about commits you haven't pushed yet.<\/p>\n\n<p>You can create a new worktree, fix the urgent bug and switch back to your <code>main<\/code> worktree when you're finished.<\/p>\n\n<p>You'll still need to update the original worktree with your new changes which may result in conflicts - the same as merging or rebasing onto a branch.<\/p>\n\n<h2 id=\"option-2%3A-feature-flags\">Option 2: Feature Flags<\/h2>\n\n<p>My preferred approach is to use <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/12\/07\/separating-releases-from-deployments-with-feature-flags\">feature flags<\/a>, a.k.a. feature toggles.<\/p>\n\n<p>My wrapping the incomplete feature in a feature flag, it can be deployed but won't be active until the flag is enabled - similar to writing a new Drupal module but not enabling it.<\/p>\n\n<p>This is a technique I use often as it works well with trunk-based development and continuous integration and delivery.<\/p>\n\n<p>When the incomplete feature is feature-flagged, you can fix the bug and deploy the hotfix without stashing or rebasing any changes, and you can leave the flag disabled.\nWhen the feature is ready, enable the feature flag to activate it and, if you need to turn it off again (maybe that's causing the next bug), you can easily disable it without needing to revert and deploy the code again.<\/p>\n\n<p>You can just turn the feature flag back off.<\/p>\n\n<p>I hope that helps!<\/p>\n\n ",
"processed": "\n <p>Last month, I wrote an email explaining <a href=\"/daily\/2024\/02\/28\/why-i-dont-branch\">why I don't create branches<\/a>.<\/p>\n\n<p>After sending that email, I received this question from a reader (shared with permission):<\/p>\n\n<blockquote>\n <p>I'm trying to work at one feature at a time, so I usually don't need feature branches.<\/p>\n \n <p>There's one thing that's difficult for me, maybe you could tell us something about this in one of your upcoming posts:<\/p>\n \n <p>How do you deal with hot fixes?<\/p>\n \n <p>I know, there's keeping features small, commit often and early. But sometimes this isn't possible, and a feature will take e.g. 3 days of work. Now, if there's an urgent bug in production that should be fixed asap, what are you doing?<\/p>\n \n <p>Git stash probably won't help here, as there might be commits already that would deliver an incomplete feature.<\/p>\n<\/blockquote>\n\n<h2 id=\"option-1%3A-worktrees\">Option 1: Worktrees<\/h2>\n\n<p>Whilst I don't create branches, I do use <a href=\"/daily\/2022\/08\/12\/git-worktrees-docker-compose\">Git worktrees<\/a>, which allows me to have multiple versions of the code checked out at the same time - similar to having multiple clones of a repository.<\/p>\n\n<p>Having multiple worktrees, you don't need to stash the code for your incomplete feature or worry about commits you haven't pushed yet.<\/p>\n\n<p>You can create a new worktree, fix the urgent bug and switch back to your <code>main<\/code> worktree when you're finished.<\/p>\n\n<p>You'll still need to update the original worktree with your new changes which may result in conflicts - the same as merging or rebasing onto a branch.<\/p>\n\n<h2 id=\"option-2%3A-feature-flags\">Option 2: Feature Flags<\/h2>\n\n<p>My preferred approach is to use <a href=\"/daily\/2022\/12\/07\/separating-releases-from-deployments-with-feature-flags\">feature flags<\/a>, a.k.a. feature toggles.<\/p>\n\n<p>My wrapping the incomplete feature in a feature flag, it can be deployed but won't be active until the flag is enabled - similar to writing a new Drupal module but not enabling it.<\/p>\n\n<p>This is a technique I use often as it works well with trunk-based development and continuous integration and delivery.<\/p>\n\n<p>When the incomplete feature is feature-flagged, you can fix the bug and deploy the hotfix without stashing or rebasing any changes, and you can leave the flag disabled.\nWhen the feature is ready, enable the feature flag to activate it and, if you need to turn it off again (maybe that's causing the next bug), you can easily disable it without needing to revert and deploy the code again.<\/p>\n\n<p>You can just turn the feature flag back off.<\/p>\n\n<p>I hope that helps!<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>In <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/8-eirik-morland-violinist\">today's episode of the Beyond Blocks podcast<\/a>, I'm joined by Eirik Morland - the Developer of <a href=\"https:\/\/violinist.io\">Violinist<\/a>.<\/p>\n\n<p>We discuss why you'd want to use a tool like Violinist to manage your dependency updates, why you'd want to automate repetitive tasks and focus on providing value for clients and customers.<\/p>\n\n<p>We also discuss running a SaaS business and why Drupal is a good choice for SaaS products - though this could be a full episode on its own.<\/p>\n\n ",
"value": "\n <p>In <a href=\"/podcast\/8-eirik-morland-violinist\">today's episode of the Beyond Blocks podcast<\/a>, I'm joined by Eirik Morland - the Developer of <a href=\"https:\/\/violinist.io\">Violinist<\/a>.<\/p>\n\n<p>We discuss why you'd want to use a tool like Violinist to manage your dependency updates, why you'd want to automate repetitive tasks and focus on providing value for clients and customers.<\/p>\n\n<p>We also discuss running a SaaS business and why Drupal is a good choice for SaaS products - though this could be a full episode on its own.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>In <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/8-eirik-morland-violinist\">today's episode of the Beyond Blocks podcast<\/a>, I'm joined by Eirik Morland - the Developer of <a href=\"https:\/\/violinist.io\">Violinist<\/a>.<\/p>\n\n<p>We discuss why you'd want to use a tool like Violinist to manage your dependency updates, why you'd want to automate repetitive tasks and focus on providing value for clients and customers.<\/p>\n\n<p>We also discuss running a SaaS business and why Drupal is a good choice for SaaS products - though this could be a full episode on its own.<\/p>\n\n ",
"processed": "\n <p>In <a href=\"/podcast\/8-eirik-morland-violinist\">today's episode of the Beyond Blocks podcast<\/a>, I'm joined by Eirik Morland - the Developer of <a href=\"https:\/\/violinist.io\">Violinist<\/a>.<\/p>\n\n<p>We discuss why you'd want to use a tool like Violinist to manage your dependency updates, why you'd want to automate repetitive tasks and focus on providing value for clients and customers.<\/p>\n\n<p>We also discuss running a SaaS business and why Drupal is a good choice for SaaS products - though this could be a full episode on its own.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/archives\/2022\/09\/03\/creating-infrastructure-with-ansible\">In yesterday's email<\/a>, I described how to set up a blank server with Ansible.<\/p>\n\n<p>Now that we've done that, it needs to be configured.<\/p>\n\n<p>Once the server\u2019s IP address or hostname has been added to a <code>hosts.ini<\/code> file, you can run ad-hoc commands against it - such as <code>ansible all -i hosts.ini -m ping<\/code> to run Ansible's <code>ping<\/code> module on all of the hosts in your inventory and check that you can connect to them.<\/p>\n\n<p>Another useful one that you can use is the <code>shell<\/code> module, that runs ad-hoc run commands on each host. If you need to check the uptime of each of your servers, run <code>ansible all -i hosts.ini -m shell -a uptime<\/code>. You can replace the last argument with any other shell command that you need to run, like <code>df<\/code> or <code>free<\/code>.<\/p>\n\n<p>Running commands in this way is great for getting started, for routine maintenance, or an emergency free disk space check, but for more complex tasks like configuration management, using playbooks is the better option. They are YAML files that contain lists of tasks that Ansible will run through and execute in order.<\/p>\n\n<p>If you have a group of related tasks, such as for installing a piece of software, then you can combine them into roles. In fact, Ansible Galaxy has thousands of pre-built collections and roles that you can download, include in your playbooks, configure, and run.<\/p>\n\n<p>Very quickly, you can get a full stack installed and configured - ready to serve your application.<\/p>\n\n<hr \/>\n\n<p>Want to learn more about how I use Ansible? <a href=\"https:\/\/www.oliverdavies.uk\/ansible-course\">Register for my upcoming free email course<\/a>.<\/p>\n\n ",
"value": "\n <p><a href=\"/archives\/2022\/09\/03\/creating-infrastructure-with-ansible\">In yesterday's email<\/a>, I described how to set up a blank server with Ansible.<\/p>\n\n<p>Now that we've done that, it needs to be configured.<\/p>\n\n<p>Once the server\u2019s IP address or hostname has been added to a <code>hosts.ini<\/code> file, you can run ad-hoc commands against it - such as <code>ansible all -i hosts.ini -m ping<\/code> to run Ansible's <code>ping<\/code> module on all of the hosts in your inventory and check that you can connect to them.<\/p>\n\n<p>Another useful one that you can use is the <code>shell<\/code> module, that runs ad-hoc run commands on each host. If you need to check the uptime of each of your servers, run <code>ansible all -i hosts.ini -m shell -a uptime<\/code>. You can replace the last argument with any other shell command that you need to run, like <code>df<\/code> or <code>free<\/code>.<\/p>\n\n<p>Running commands in this way is great for getting started, for routine maintenance, or an emergency free disk space check, but for more complex tasks like configuration management, using playbooks is the better option. They are YAML files that contain lists of tasks that Ansible will run through and execute in order.<\/p>\n\n<p>If you have a group of related tasks, such as for installing a piece of software, then you can combine them into roles. In fact, Ansible Galaxy has thousands of pre-built collections and roles that you can download, include in your playbooks, configure, and run.<\/p>\n\n<p>Very quickly, you can get a full stack installed and configured - ready to serve your application.<\/p>\n\n<hr \/>\n\n<p>Want to learn more about how I use Ansible? <a href=\"/ansible-course\">Register for my upcoming free email course<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/archives\/2022\/09\/03\/creating-infrastructure-with-ansible\">In yesterday's email<\/a>, I described how to set up a blank server with Ansible.<\/p>\n\n<p>Now that we've done that, it needs to be configured.<\/p>\n\n<p>Once the server\u2019s IP address or hostname has been added to a <code>hosts.ini<\/code> file, you can run ad-hoc commands against it - such as <code>ansible all -i hosts.ini -m ping<\/code> to run Ansible's <code>ping<\/code> module on all of the hosts in your inventory and check that you can connect to them.<\/p>\n\n<p>Another useful one that you can use is the <code>shell<\/code> module, that runs ad-hoc run commands on each host. If you need to check the uptime of each of your servers, run <code>ansible all -i hosts.ini -m shell -a uptime<\/code>. You can replace the last argument with any other shell command that you need to run, like <code>df<\/code> or <code>free<\/code>.<\/p>\n\n<p>Running commands in this way is great for getting started, for routine maintenance, or an emergency free disk space check, but for more complex tasks like configuration management, using playbooks is the better option. They are YAML files that contain lists of tasks that Ansible will run through and execute in order.<\/p>\n\n<p>If you have a group of related tasks, such as for installing a piece of software, then you can combine them into roles. In fact, Ansible Galaxy has thousands of pre-built collections and roles that you can download, include in your playbooks, configure, and run.<\/p>\n\n<p>Very quickly, you can get a full stack installed and configured - ready to serve your application.<\/p>\n\n<hr>\n\n<p>Want to learn more about how I use Ansible? <a href=\"https:\/\/www.oliverdavies.uk\/ansible-course\">Register for my upcoming free email course<\/a>.<\/p>\n\n ",
"processed": "\n <p><a href=\"/archives\/2022\/09\/03\/creating-infrastructure-with-ansible\">In yesterday's email<\/a>, I described how to set up a blank server with Ansible.<\/p>\n\n<p>Now that we've done that, it needs to be configured.<\/p>\n\n<p>Once the server\u2019s IP address or hostname has been added to a <code>hosts.ini<\/code> file, you can run ad-hoc commands against it - such as <code>ansible all -i hosts.ini -m ping<\/code> to run Ansible's <code>ping<\/code> module on all of the hosts in your inventory and check that you can connect to them.<\/p>\n\n<p>Another useful one that you can use is the <code>shell<\/code> module, that runs ad-hoc run commands on each host. If you need to check the uptime of each of your servers, run <code>ansible all -i hosts.ini -m shell -a uptime<\/code>. You can replace the last argument with any other shell command that you need to run, like <code>df<\/code> or <code>free<\/code>.<\/p>\n\n<p>Running commands in this way is great for getting started, for routine maintenance, or an emergency free disk space check, but for more complex tasks like configuration management, using playbooks is the better option. They are YAML files that contain lists of tasks that Ansible will run through and execute in order.<\/p>\n\n<p>If you have a group of related tasks, such as for installing a piece of software, then you can combine them into roles. In fact, Ansible Galaxy has thousands of pre-built collections and roles that you can download, include in your playbooks, configure, and run.<\/p>\n\n<p>Very quickly, you can get a full stack installed and configured - ready to serve your application.<\/p>\n\n<hr>\n\n<p>Want to learn more about how I use Ansible? <a href=\"/ansible-course\">Register for my upcoming free email course<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/\/daily\/2024\/03\/04\/why-you-need-layers-in-your-application-code\">Yesterday<\/a>, I wrote about writing layers in your application code and the benefits of loosely coupled code.<\/p>\n\n<p>Something else you can do with this approach is to write framework-agnostic code.<\/p>\n\n<p>By writing your business logic in code that isn't tied to a specific framework or CMS, with a small adapter layer, you can upgrade to a newer version of the framework, such as Drupal 7 to 10, or a different framework, keep most of the code the same and only update the parts that connect the business logic and the framework.<\/p>\n\n<p>This is something that Commerce Guys (now Centarro) did when creating Drupal Commerce 2.0.<\/p>\n\n<p>The logic around addressing, tax, etc., was released in separate PHP libraries, each with its own release cycle and reusable logic.<\/p>\n\n<p>This meant the Drupal modules were much smaller, and other eCommerce systems and frameworks could use the agnostic libraries.<\/p>\n\n<p>It's something to consider when writing your next Drupal module.<\/p>\n\n<p>It's something <a href=\"https:\/\/github.com\/opdavies\/national-rail-enquiries-feed-parser\">I did recently<\/a> and have done on client projects previously, and it can be a good approach.<\/p>\n\n ",
"value": "\n <p><a href=\"/\/daily\/2024\/03\/04\/why-you-need-layers-in-your-application-code\">Yesterday<\/a>, I wrote about writing layers in your application code and the benefits of loosely coupled code.<\/p>\n\n<p>Something else you can do with this approach is to write framework-agnostic code.<\/p>\n\n<p>By writing your business logic in code that isn't tied to a specific framework or CMS, with a small adapter layer, you can upgrade to a newer version of the framework, such as Drupal 7 to 10, or a different framework, keep most of the code the same and only update the parts that connect the business logic and the framework.<\/p>\n\n<p>This is something that Commerce Guys (now Centarro) did when creating Drupal Commerce 2.0.<\/p>\n\n<p>The logic around addressing, tax, etc., was released in separate PHP libraries, each with its own release cycle and reusable logic.<\/p>\n\n<p>This meant the Drupal modules were much smaller, and other eCommerce systems and frameworks could use the agnostic libraries.<\/p>\n\n<p>It's something to consider when writing your next Drupal module.<\/p>\n\n<p>It's something <a href=\"https:\/\/github.com\/opdavies\/national-rail-enquiries-feed-parser\">I did recently<\/a> and have done on client projects previously, and it can be a good approach.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/\/daily\/2024\/03\/04\/why-you-need-layers-in-your-application-code\">Yesterday<\/a>, I wrote about writing layers in your application code and the benefits of loosely coupled code.<\/p>\n\n<p>Something else you can do with this approach is to write framework-agnostic code.<\/p>\n\n<p>By writing your business logic in code that isn't tied to a specific framework or CMS, with a small adapter layer, you can upgrade to a newer version of the framework, such as Drupal 7 to 10, or a different framework, keep most of the code the same and only update the parts that connect the business logic and the framework.<\/p>\n\n<p>This is something that Commerce Guys (now Centarro) did when creating Drupal Commerce 2.0.<\/p>\n\n<p>The logic around addressing, tax, etc., was released in separate PHP libraries, each with its own release cycle and reusable logic.<\/p>\n\n<p>This meant the Drupal modules were much smaller, and other eCommerce systems and frameworks could use the agnostic libraries.<\/p>\n\n<p>It's something to consider when writing your next Drupal module.<\/p>\n\n<p>It's something <a href=\"https:\/\/github.com\/opdavies\/national-rail-enquiries-feed-parser\">I did recently<\/a> and have done on client projects previously, and it can be a good approach.<\/p>\n\n ",
"processed": "\n <p><a href=\"/\/daily\/2024\/03\/04\/why-you-need-layers-in-your-application-code\">Yesterday<\/a>, I wrote about writing layers in your application code and the benefits of loosely coupled code.<\/p>\n\n<p>Something else you can do with this approach is to write framework-agnostic code.<\/p>\n\n<p>By writing your business logic in code that isn't tied to a specific framework or CMS, with a small adapter layer, you can upgrade to a newer version of the framework, such as Drupal 7 to 10, or a different framework, keep most of the code the same and only update the parts that connect the business logic and the framework.<\/p>\n\n<p>This is something that Commerce Guys (now Centarro) did when creating Drupal Commerce 2.0.<\/p>\n\n<p>The logic around addressing, tax, etc., was released in separate PHP libraries, each with its own release cycle and reusable logic.<\/p>\n\n<p>This meant the Drupal modules were much smaller, and other eCommerce systems and frameworks could use the agnostic libraries.<\/p>\n\n<p>It's something to consider when writing your next Drupal module.<\/p>\n\n<p>It's something <a href=\"https:\/\/github.com\/opdavies\/national-rail-enquiries-feed-parser\">I did recently<\/a> and have done on client projects previously, and it can be a good approach.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>At Saturday's hackathon that I mentioned in yesterday's email, most of the squads decided to try Tailwind CSS in their applications.<\/p>\n\n<p>I've been using Tailwind since it was released, and first gave <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/taking-flight-with-tailwind-css\">a Tailwind CSS talk<\/a> in January 2018.<\/p>\n\n<p>It's one of my most popular talks and, during COVID lockdowns, I also gave a workshop\/webinar on Tailwind CSS for some online conferences.<\/p>\n\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=phFDKF-9j0Y\">Here's a recording<\/a> of the session I gave for DrupalCamp Florida, in which I cover some Tailwind CSS concepts and show how to install and customise Tailwind before rebuilding the Florida DrupalCamp website live.<\/p>\n\n<p>If this helps anyone on their Tailwind CSS learning journey, please reply and let me know!<\/p>\n\n ",
"value": "\n <p>At Saturday's hackathon that I mentioned in yesterday's email, most of the squads decided to try Tailwind CSS in their applications.<\/p>\n\n<p>I've been using Tailwind since it was released, and first gave <a href=\"/presentations\/taking-flight-with-tailwind-css\">a Tailwind CSS talk<\/a> in January 2018.<\/p>\n\n<p>It's one of my most popular talks and, during COVID lockdowns, I also gave a workshop\/webinar on Tailwind CSS for some online conferences.<\/p>\n\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=phFDKF-9j0Y\">Here's a recording<\/a> of the session I gave for DrupalCamp Florida, in which I cover some Tailwind CSS concepts and show how to install and customise Tailwind before rebuilding the Florida DrupalCamp website live.<\/p>\n\n<p>If this helps anyone on their Tailwind CSS learning journey, please reply and let me know!<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>At Saturday's hackathon that I mentioned in yesterday's email, most of the squads decided to try Tailwind CSS in their applications.<\/p>\n\n<p>I've been using Tailwind since it was released, and first gave <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/taking-flight-with-tailwind-css\">a Tailwind CSS talk<\/a> in January 2018.<\/p>\n\n<p>It's one of my most popular talks and, during COVID lockdowns, I also gave a workshop\/webinar on Tailwind CSS for some online conferences.<\/p>\n\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=phFDKF-9j0Y\">Here's a recording<\/a> of the session I gave for DrupalCamp Florida, in which I cover some Tailwind CSS concepts and show how to install and customise Tailwind before rebuilding the Florida DrupalCamp website live.<\/p>\n\n<p>If this helps anyone on their Tailwind CSS learning journey, please reply and let me know!<\/p>\n\n ",
"processed": "\n <p>At Saturday's hackathon that I mentioned in yesterday's email, most of the squads decided to try Tailwind CSS in their applications.<\/p>\n\n<p>I've been using Tailwind since it was released, and first gave <a href=\"/presentations\/taking-flight-with-tailwind-css\">a Tailwind CSS talk<\/a> in January 2018.<\/p>\n\n<p>It's one of my most popular talks and, during COVID lockdowns, I also gave a workshop\/webinar on Tailwind CSS for some online conferences.<\/p>\n\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=phFDKF-9j0Y\">Here's a recording<\/a> of the session I gave for DrupalCamp Florida, in which I cover some Tailwind CSS concepts and show how to install and customise Tailwind before rebuilding the Florida DrupalCamp website live.<\/p>\n\n<p>If this helps anyone on their Tailwind CSS learning journey, please reply and let me know!<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>As someone who develops with open-source software such as Drupal, Symfony, and Sculpin and uses Linux to <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/28\/running-nixos-in-the-cloud\">host my applications<\/a> and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/23\/no-more-random-packages\">configure my laptop<\/a>, I've recently started to explore creating a home lab and self-hosting services based on other open source software.<\/p>\n\n<p>I've started using Jellyfin for media management and playback, Immich for photos, Gitea for hosting my private Git repositories, and Tube Archivist for backing up YouTube videos.<\/p>\n\n<p>There are a lot of other popular applications that people self-host that I want to look at, as well as maybe hosting my own website.<\/p>\n\n<p>I've removed proprietary note-taking applications <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/10\/write-plain-text-files\">in favour of plain text files<\/a> and continued searching for free and open source alternatives to services I've used.<\/p>\n\n<p>My ethos is to be open source first and to favour an open source solution if there is one.<\/p>\n\n<p>And if there isn't, I can write one.<\/p>\n\n<p>As well as creating free and open source software, I want to use it as much as I can as well as using open source software to create my open source software.<\/p>\n\n ",
"value": "\n <p>As someone who develops with open-source software such as Drupal, Symfony, and Sculpin and uses Linux to <a href=\"/daily\/2024\/11\/28\/running-nixos-in-the-cloud\">host my applications<\/a> and <a href=\"/daily\/2024\/11\/23\/no-more-random-packages\">configure my laptop<\/a>, I've recently started to explore creating a home lab and self-hosting services based on other open source software.<\/p>\n\n<p>I've started using Jellyfin for media management and playback, Immich for photos, Gitea for hosting my private Git repositories, and Tube Archivist for backing up YouTube videos.<\/p>\n\n<p>There are a lot of other popular applications that people self-host that I want to look at, as well as maybe hosting my own website.<\/p>\n\n<p>I've removed proprietary note-taking applications <a href=\"/daily\/2024\/11\/10\/write-plain-text-files\">in favour of plain text files<\/a> and continued searching for free and open source alternatives to services I've used.<\/p>\n\n<p>My ethos is to be open source first and to favour an open source solution if there is one.<\/p>\n\n<p>And if there isn't, I can write one.<\/p>\n\n<p>As well as creating free and open source software, I want to use it as much as I can as well as using open source software to create my open source software.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>As someone who develops with open-source software such as Drupal, Symfony, and Sculpin and uses Linux to <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/28\/running-nixos-in-the-cloud\">host my applications<\/a> and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/23\/no-more-random-packages\">configure my laptop<\/a>, I've recently started to explore creating a home lab and self-hosting services based on other open source software.<\/p>\n\n<p>I've started using Jellyfin for media management and playback, Immich for photos, Gitea for hosting my private Git repositories, and Tube Archivist for backing up YouTube videos.<\/p>\n\n<p>There are a lot of other popular applications that people self-host that I want to look at, as well as maybe hosting my own website.<\/p>\n\n<p>I've removed proprietary note-taking applications <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/10\/write-plain-text-files\">in favour of plain text files<\/a> and continued searching for free and open source alternatives to services I've used.<\/p>\n\n<p>My ethos is to be open source first and to favour an open source solution if there is one.<\/p>\n\n<p>And if there isn't, I can write one.<\/p>\n\n<p>As well as creating free and open source software, I want to use it as much as I can as well as using open source software to create my open source software.<\/p>\n\n ",
"processed": "\n <p>As someone who develops with open-source software such as Drupal, Symfony, and Sculpin and uses Linux to <a href=\"/daily\/2024\/11\/28\/running-nixos-in-the-cloud\">host my applications<\/a> and <a href=\"/daily\/2024\/11\/23\/no-more-random-packages\">configure my laptop<\/a>, I've recently started to explore creating a home lab and self-hosting services based on other open source software.<\/p>\n\n<p>I've started using Jellyfin for media management and playback, Immich for photos, Gitea for hosting my private Git repositories, and Tube Archivist for backing up YouTube videos.<\/p>\n\n<p>There are a lot of other popular applications that people self-host that I want to look at, as well as maybe hosting my own website.<\/p>\n\n<p>I've removed proprietary note-taking applications <a href=\"/daily\/2024\/11\/10\/write-plain-text-files\">in favour of plain text files<\/a> and continued searching for free and open source alternatives to services I've used.<\/p>\n\n<p>My ethos is to be open source first and to favour an open source solution if there is one.<\/p>\n\n<p>And if there isn't, I can write one.<\/p>\n\n<p>As well as creating free and open source software, I want to use it as much as I can as well as using open source software to create my open source software.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>For some time, <a href=\"https:\/\/www.drupal.org\/docs\/develop\/standards\/php\/php-coding-standards#s-functions-and-variables\">Drupal's PHP coding standards<\/a> allows for writing variables in either snake-case (e.g. <code>$my_variable<\/code>) or lower camel-case (<code>e.g. $myVariable<\/code>).<\/p>\n\n<p>It originally only allowed for snake-case variable names but once it accepted both, I switched to camel-case as my default.<\/p>\n\n<p>Why? I didn't like the inconsistency of using one approach for variable names and one for method and property names in PHP classes (which were always camel-case).<\/p>\n\n<p>I'd have had code like this with a mixture of both:<\/p>\n\n<pre><code class=\"language-php\">class MyClass {\n\n private EntityTypeManagerInterface $entityTypeManager;\n\n public function __construct(EntityTypeManagerInterface $entity_type_manager) {\n $this-&gt;entityTypeManager = $entity_type_manager;\n }\n\n}\n<\/code><\/pre>\n\n<p>Or even more simply:<\/p>\n\n<pre><code class=\"language-php\">$entity_type_manager = \\Drupal::entityTypeManager();\n<\/code><\/pre>\n\n<p>I prefer not to have to consistently think about which to use and, if possible, like to use standard approaches in different codebases whether I'm working on a Drupal project, a Symfony project, or a PHP library.<\/p>\n\n<p>Plus, I get to use new PHP features like <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/04\/12\/cleaner-php-code-with-promoted-constructor-properties\">promoted constructor properties<\/a> if everything is named in the same format.<\/p>\n\n ",
"value": "\n <p>For some time, <a href=\"https:\/\/www.drupal.org\/docs\/develop\/standards\/php\/php-coding-standards#s-functions-and-variables\">Drupal's PHP coding standards<\/a> allows for writing variables in either snake-case (e.g. <code>$my_variable<\/code>) or lower camel-case (<code>e.g. $myVariable<\/code>).<\/p>\n\n<p>It originally only allowed for snake-case variable names but once it accepted both, I switched to camel-case as my default.<\/p>\n\n<p>Why? I didn't like the inconsistency of using one approach for variable names and one for method and property names in PHP classes (which were always camel-case).<\/p>\n\n<p>I'd have had code like this with a mixture of both:<\/p>\n\n<pre><code class=\"language-php\">class MyClass {\n\n private EntityTypeManagerInterface $entityTypeManager;\n\n public function __construct(EntityTypeManagerInterface $entity_type_manager) {\n $this-&gt;entityTypeManager = $entity_type_manager;\n }\n\n}\n<\/code><\/pre>\n\n<p>Or even more simply:<\/p>\n\n<pre><code class=\"language-php\">$entity_type_manager = \\Drupal::entityTypeManager();\n<\/code><\/pre>\n\n<p>I prefer not to have to consistently think about which to use and, if possible, like to use standard approaches in different codebases whether I'm working on a Drupal project, a Symfony project, or a PHP library.<\/p>\n\n<p>Plus, I get to use new PHP features like <a href=\"/daily\/2023\/04\/12\/cleaner-php-code-with-promoted-constructor-properties\">promoted constructor properties<\/a> if everything is named in the same format.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>For some time, <a href=\"https:\/\/www.drupal.org\/docs\/develop\/standards\/php\/php-coding-standards#s-functions-and-variables\">Drupal's PHP coding standards<\/a> allows for writing variables in either snake-case (e.g. <code>$my_variable<\/code>) or lower camel-case (<code>e.g. $myVariable<\/code>).<\/p>\n\n<p>It originally only allowed for snake-case variable names but once it accepted both, I switched to camel-case as my default.<\/p>\n\n<p>Why? I didn't like the inconsistency of using one approach for variable names and one for method and property names in PHP classes (which were always camel-case).<\/p>\n\n<p>I'd have had code like this with a mixture of both:<\/p>\n\n<pre><code class=\"language-php\">class MyClass {\n\n private EntityTypeManagerInterface $entityTypeManager;\n\n public function __construct(EntityTypeManagerInterface $entity_type_manager) {\n $this-&gt;entityTypeManager = $entity_type_manager;\n }\n\n}\n<\/code><\/pre>\n\n<p>Or even more simply:<\/p>\n\n<pre><code class=\"language-php\">$entity_type_manager = \\Drupal::entityTypeManager();\n<\/code><\/pre>\n\n<p>I prefer not to have to consistently think about which to use and, if possible, like to use standard approaches in different codebases whether I'm working on a Drupal project, a Symfony project, or a PHP library.<\/p>\n\n<p>Plus, I get to use new PHP features like <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/04\/12\/cleaner-php-code-with-promoted-constructor-properties\">promoted constructor properties<\/a> if everything is named in the same format.<\/p>\n\n ",
"processed": "\n <p>For some time, <a href=\"https:\/\/www.drupal.org\/docs\/develop\/standards\/php\/php-coding-standards#s-functions-and-variables\">Drupal's PHP coding standards<\/a> allows for writing variables in either snake-case (e.g. <code>$my_variable<\/code>) or lower camel-case (<code>e.g. $myVariable<\/code>).<\/p>\n\n<p>It originally only allowed for snake-case variable names but once it accepted both, I switched to camel-case as my default.<\/p>\n\n<p>Why? I didn't like the inconsistency of using one approach for variable names and one for method and property names in PHP classes (which were always camel-case).<\/p>\n\n<p>I'd have had code like this with a mixture of both:<\/p>\n\n<pre><code class=\"language-php\">class MyClass {\n\n private EntityTypeManagerInterface $entityTypeManager;\n\n public function __construct(EntityTypeManagerInterface $entity_type_manager) {\n $this-&gt;entityTypeManager = $entity_type_manager;\n }\n\n}\n<\/code><\/pre>\n\n<p>Or even more simply:<\/p>\n\n<pre><code class=\"language-php\">$entity_type_manager = \\Drupal::entityTypeManager();\n<\/code><\/pre>\n\n<p>I prefer not to have to consistently think about which to use and, if possible, like to use standard approaches in different codebases whether I'm working on a Drupal project, a Symfony project, or a PHP library.<\/p>\n\n<p>Plus, I get to use new PHP features like <a href=\"/daily\/2023\/04\/12\/cleaner-php-code-with-promoted-constructor-properties\">promoted constructor properties<\/a> if everything is named in the same format.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>As a Developer with 15 years of experience, I still sometimes get \"deployment anxiety\" - when I've backed up the database and tagged a release, but even though the CI pipelines are passing and the staging site is working, I'm holding off on pushing the latest code to be released to production - trying to think of any potential issues that could arise from this deployment and avoid any downtime.<\/p>\n\n<p>When I thought about this further, the releases that I've felt anxious or nervous about have usually been in at one or both of the following categories:<\/p>\n\n<ul>\n<li>The release includes a lot of changes, and maybe a combination of different types of changes such as framework or CMS updates, bug fixes, or new features.<\/li>\n<li>It's been a long time, maybe weeks or months, since the last production release.<\/li>\n<\/ul>\n\n<p>The best way to resolve both of these issues, I think, is to break down the large releases into smaller ones, and to deploy them more frequently.<\/p>\n\n<p>In the opposite scenario, the releases where the changes are small and it's been a short time since the previous release - ideally minutes or hours - have been the ones where I've been the least nervous.<\/p>\n\n<p>If a single commit is being released, then I can be confident that if there is a failure, I can either revert it and put things back the way they were or quickly identify the issue and push a fix. This isn't the case for large changes as the potential source of the failure is larger and it will take longer to find and fix.<\/p>\n\n<p>If a bug fix or a feature needs to be reverted, I'm happy knowing that I can do that easily without also reverting the CMS update that was deployed separately - rather than them all being released together.<\/p>\n\n<p>There are other advantages too - clients or product owners are generally happier if the new feature or fix that they requested is on production within hours or days rather than weeks or months, and having your latest code deployed to production rather than on a staging branch makes it a lot easier if you need to deploy an urgent fix or security update.<\/p>\n\n<p>If you're familiar with the DevOps Research and Assessment (DORA) team, three of their key metrics are deployment frequency, lead time for changes, and time to restore service. All of these are improved by small and frequent releases.<\/p>\n\n<p>In my <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/deploying-php-ansible-ansistrano\">Deployments with Ansible and Ansistrano talk<\/a>, I mention that there is a separate rollback role, but I don't think that I've ever used it.<\/p>\n\n<p>Because I'm deploying small changes often, it's usually much easier to fix forward than it is to rollback, and knowing this makes me a lot less anxious when deploying changes.<\/p>\n\n ",
"value": "\n <p>As a Developer with 15 years of experience, I still sometimes get \"deployment anxiety\" - when I've backed up the database and tagged a release, but even though the CI pipelines are passing and the staging site is working, I'm holding off on pushing the latest code to be released to production - trying to think of any potential issues that could arise from this deployment and avoid any downtime.<\/p>\n\n<p>When I thought about this further, the releases that I've felt anxious or nervous about have usually been in at one or both of the following categories:<\/p>\n\n<ul>\n<li>The release includes a lot of changes, and maybe a combination of different types of changes such as framework or CMS updates, bug fixes, or new features.<\/li>\n<li>It's been a long time, maybe weeks or months, since the last production release.<\/li>\n<\/ul>\n\n<p>The best way to resolve both of these issues, I think, is to break down the large releases into smaller ones, and to deploy them more frequently.<\/p>\n\n<p>In the opposite scenario, the releases where the changes are small and it's been a short time since the previous release - ideally minutes or hours - have been the ones where I've been the least nervous.<\/p>\n\n<p>If a single commit is being released, then I can be confident that if there is a failure, I can either revert it and put things back the way they were or quickly identify the issue and push a fix. This isn't the case for large changes as the potential source of the failure is larger and it will take longer to find and fix.<\/p>\n\n<p>If a bug fix or a feature needs to be reverted, I'm happy knowing that I can do that easily without also reverting the CMS update that was deployed separately - rather than them all being released together.<\/p>\n\n<p>There are other advantages too - clients or product owners are generally happier if the new feature or fix that they requested is on production within hours or days rather than weeks or months, and having your latest code deployed to production rather than on a staging branch makes it a lot easier if you need to deploy an urgent fix or security update.<\/p>\n\n<p>If you're familiar with the DevOps Research and Assessment (DORA) team, three of their key metrics are deployment frequency, lead time for changes, and time to restore service. All of these are improved by small and frequent releases.<\/p>\n\n<p>In my <a href=\"/presentations\/deploying-php-ansible-ansistrano\">Deployments with Ansible and Ansistrano talk<\/a>, I mention that there is a separate rollback role, but I don't think that I've ever used it.<\/p>\n\n<p>Because I'm deploying small changes often, it's usually much easier to fix forward than it is to rollback, and knowing this makes me a lot less anxious when deploying changes.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>As a Developer with 15 years of experience, I still sometimes get \"deployment anxiety\" - when I've backed up the database and tagged a release, but even though the CI pipelines are passing and the staging site is working, I'm holding off on pushing the latest code to be released to production - trying to think of any potential issues that could arise from this deployment and avoid any downtime.<\/p>\n\n<p>When I thought about this further, the releases that I've felt anxious or nervous about have usually been in at one or both of the following categories:<\/p>\n\n<ul>\n<li>The release includes a lot of changes, and maybe a combination of different types of changes such as framework or CMS updates, bug fixes, or new features.<\/li>\n<li>It's been a long time, maybe weeks or months, since the last production release.<\/li>\n<\/ul>\n\n<p>The best way to resolve both of these issues, I think, is to break down the large releases into smaller ones, and to deploy them more frequently.<\/p>\n\n<p>In the opposite scenario, the releases where the changes are small and it's been a short time since the previous release - ideally minutes or hours - have been the ones where I've been the least nervous.<\/p>\n\n<p>If a single commit is being released, then I can be confident that if there is a failure, I can either revert it and put things back the way they were or quickly identify the issue and push a fix. This isn't the case for large changes as the potential source of the failure is larger and it will take longer to find and fix.<\/p>\n\n<p>If a bug fix or a feature needs to be reverted, I'm happy knowing that I can do that easily without also reverting the CMS update that was deployed separately - rather than them all being released together.<\/p>\n\n<p>There are other advantages too - clients or product owners are generally happier if the new feature or fix that they requested is on production within hours or days rather than weeks or months, and having your latest code deployed to production rather than on a staging branch makes it a lot easier if you need to deploy an urgent fix or security update.<\/p>\n\n<p>If you're familiar with the DevOps Research and Assessment (DORA) team, three of their key metrics are deployment frequency, lead time for changes, and time to restore service. All of these are improved by small and frequent releases.<\/p>\n\n<p>In my <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/deploying-php-ansible-ansistrano\">Deployments with Ansible and Ansistrano talk<\/a>, I mention that there is a separate rollback role, but I don't think that I've ever used it.<\/p>\n\n<p>Because I'm deploying small changes often, it's usually much easier to fix forward than it is to rollback, and knowing this makes me a lot less anxious when deploying changes.<\/p>\n\n ",
"processed": "\n <p>As a Developer with 15 years of experience, I still sometimes get \"deployment anxiety\" - when I've backed up the database and tagged a release, but even though the CI pipelines are passing and the staging site is working, I'm holding off on pushing the latest code to be released to production - trying to think of any potential issues that could arise from this deployment and avoid any downtime.<\/p>\n\n<p>When I thought about this further, the releases that I've felt anxious or nervous about have usually been in at one or both of the following categories:<\/p>\n\n<ul>\n<li>The release includes a lot of changes, and maybe a combination of different types of changes such as framework or CMS updates, bug fixes, or new features.<\/li>\n<li>It's been a long time, maybe weeks or months, since the last production release.<\/li>\n<\/ul>\n\n<p>The best way to resolve both of these issues, I think, is to break down the large releases into smaller ones, and to deploy them more frequently.<\/p>\n\n<p>In the opposite scenario, the releases where the changes are small and it's been a short time since the previous release - ideally minutes or hours - have been the ones where I've been the least nervous.<\/p>\n\n<p>If a single commit is being released, then I can be confident that if there is a failure, I can either revert it and put things back the way they were or quickly identify the issue and push a fix. This isn't the case for large changes as the potential source of the failure is larger and it will take longer to find and fix.<\/p>\n\n<p>If a bug fix or a feature needs to be reverted, I'm happy knowing that I can do that easily without also reverting the CMS update that was deployed separately - rather than them all being released together.<\/p>\n\n<p>There are other advantages too - clients or product owners are generally happier if the new feature or fix that they requested is on production within hours or days rather than weeks or months, and having your latest code deployed to production rather than on a staging branch makes it a lot easier if you need to deploy an urgent fix or security update.<\/p>\n\n<p>If you're familiar with the DevOps Research and Assessment (DORA) team, three of their key metrics are deployment frequency, lead time for changes, and time to restore service. All of these are improved by small and frequent releases.<\/p>\n\n<p>In my <a href=\"/presentations\/deploying-php-ansible-ansistrano\">Deployments with Ansible and Ansistrano talk<\/a>, I mention that there is a separate rollback role, but I don't think that I've ever used it.<\/p>\n\n<p>Because I'm deploying small changes often, it's usually much easier to fix forward than it is to rollback, and knowing this makes me a lot less anxious when deploying changes.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>In a typical feature release process, a feature is released when you merge the code and push it to production.<\/p>\n\n<p>If a bug is found after the release, the code needs to be reverted (and any conflicts or issues dealt with) and deployed again.<\/p>\n\n<p>Also, features can only be merged once they are complete, which may take hours, days or weeks, depending on the size of the feature.<\/p>\n\n<p>These are some reasons I like to use feature flags (aka feature toggles) and separate the code deployment from releasing the feature. The code is deployed as before, but the feature isn't released, and the code isn't executed until a feature flag is enabled.<\/p>\n\n<p>If there is a bug, the feature flag can be disabled, and the feature is turned off until a fix can be pushed - without needing another code deployment.<\/p>\n\n<p>If my feature is incomplete, if it's feature flagged, I can commit and deploy it without users seeing it or affecting the running application, resulting in smaller and more manageable commits and deployments.<\/p>\n\n<p>If you wanted, you could enable a feature flag for a subset or a certain subsection of your users - allowing them to test it before making it available to everyone.<\/p>\n\n<p>Another way I use feature flags is within a <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/11\/13\/how-i-manage-multiple-drupal-websites-using-the-same-codebase\">multi-site Drupal application<\/a> to enable a different feature set per site and allow me to keep one version of the code for all sites to keep this easy to manage and maintain.<\/p>\n\n ",
"value": "\n <p>In a typical feature release process, a feature is released when you merge the code and push it to production.<\/p>\n\n<p>If a bug is found after the release, the code needs to be reverted (and any conflicts or issues dealt with) and deployed again.<\/p>\n\n<p>Also, features can only be merged once they are complete, which may take hours, days or weeks, depending on the size of the feature.<\/p>\n\n<p>These are some reasons I like to use feature flags (aka feature toggles) and separate the code deployment from releasing the feature. The code is deployed as before, but the feature isn't released, and the code isn't executed until a feature flag is enabled.<\/p>\n\n<p>If there is a bug, the feature flag can be disabled, and the feature is turned off until a fix can be pushed - without needing another code deployment.<\/p>\n\n<p>If my feature is incomplete, if it's feature flagged, I can commit and deploy it without users seeing it or affecting the running application, resulting in smaller and more manageable commits and deployments.<\/p>\n\n<p>If you wanted, you could enable a feature flag for a subset or a certain subsection of your users - allowing them to test it before making it available to everyone.<\/p>\n\n<p>Another way I use feature flags is within a <a href=\"/daily\/2022\/11\/13\/how-i-manage-multiple-drupal-websites-using-the-same-codebase\">multi-site Drupal application<\/a> to enable a different feature set per site and allow me to keep one version of the code for all sites to keep this easy to manage and maintain.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>In a typical feature release process, a feature is released when you merge the code and push it to production.<\/p>\n\n<p>If a bug is found after the release, the code needs to be reverted (and any conflicts or issues dealt with) and deployed again.<\/p>\n\n<p>Also, features can only be merged once they are complete, which may take hours, days or weeks, depending on the size of the feature.<\/p>\n\n<p>These are some reasons I like to use feature flags (aka feature toggles) and separate the code deployment from releasing the feature. The code is deployed as before, but the feature isn't released, and the code isn't executed until a feature flag is enabled.<\/p>\n\n<p>If there is a bug, the feature flag can be disabled, and the feature is turned off until a fix can be pushed - without needing another code deployment.<\/p>\n\n<p>If my feature is incomplete, if it's feature flagged, I can commit and deploy it without users seeing it or affecting the running application, resulting in smaller and more manageable commits and deployments.<\/p>\n\n<p>If you wanted, you could enable a feature flag for a subset or a certain subsection of your users - allowing them to test it before making it available to everyone.<\/p>\n\n<p>Another way I use feature flags is within a <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/11\/13\/how-i-manage-multiple-drupal-websites-using-the-same-codebase\">multi-site Drupal application<\/a> to enable a different feature set per site and allow me to keep one version of the code for all sites to keep this easy to manage and maintain.<\/p>\n\n ",
"processed": "\n <p>In a typical feature release process, a feature is released when you merge the code and push it to production.<\/p>\n\n<p>If a bug is found after the release, the code needs to be reverted (and any conflicts or issues dealt with) and deployed again.<\/p>\n\n<p>Also, features can only be merged once they are complete, which may take hours, days or weeks, depending on the size of the feature.<\/p>\n\n<p>These are some reasons I like to use feature flags (aka feature toggles) and separate the code deployment from releasing the feature. The code is deployed as before, but the feature isn't released, and the code isn't executed until a feature flag is enabled.<\/p>\n\n<p>If there is a bug, the feature flag can be disabled, and the feature is turned off until a fix can be pushed - without needing another code deployment.<\/p>\n\n<p>If my feature is incomplete, if it's feature flagged, I can commit and deploy it without users seeing it or affecting the running application, resulting in smaller and more manageable commits and deployments.<\/p>\n\n<p>If you wanted, you could enable a feature flag for a subset or a certain subsection of your users - allowing them to test it before making it available to everyone.<\/p>\n\n<p>Another way I use feature flags is within a <a href=\"/daily\/2022\/11\/13\/how-i-manage-multiple-drupal-websites-using-the-same-codebase\">multi-site Drupal application<\/a> to enable a different feature set per site and allow me to keep one version of the code for all sites to keep this easy to manage and maintain.<\/p>\n\n ",
"summary": null
}
],

View file

@ -83,9 +83,9 @@
],
"body": [
{
"value": "<p>A few days ago, I published a new episode of the Beyond Blocks podcast with Luke McCormick, where we spoke about using AI and tools like Cursor for web coding.<\/p><p>Unfortunately, there was an export issue with the episode that affected the sound quality.<\/p><p>The recording was fine and the mp3 file was re-created and uploaded again to the episode page and the podcast feed for Spotify, Pocket Casts, etc.<\/p><p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/28-using-ai-tools-web-coding\">Listen to the episode here<\/a>.<\/p><p>Apologies to Luke and anyone who listened to the original release for the poor quality, but it should be fine now and I'll add this to my checklist when editing podcast episodes to ensure it doesn't happen again.<\/p>",
"value": "<p>A few days ago, I published a new episode of the Beyond Blocks podcast with Luke McCormick, where we spoke about using AI and tools like Cursor for web coding.<\/p><p>Unfortunately, there was an export issue with the episode that affected the sound quality.<\/p><p>The recording was fine and the mp3 file was re-created and uploaded again to the episode page and the podcast feed for Spotify, Pocket Casts, etc.<\/p><p><a href=\"/podcast\/28-using-ai-tools-web-coding\">Listen to the episode here<\/a>.<\/p><p>Apologies to Luke and anyone who listened to the original release for the poor quality, but it should be fine now and I'll add this to my checklist when editing podcast episodes to ensure it doesn't happen again.<\/p>",
"format": "basic_html",
"processed": "<p>A few days ago, I published a new episode of the Beyond Blocks podcast with Luke McCormick, where we spoke about using AI and tools like Cursor for web coding.<\/p><p>Unfortunately, there was an export issue with the episode that affected the sound quality.<\/p><p>The recording was fine and the mp3 file was re-created and uploaded again to the episode page and the podcast feed for Spotify, Pocket Casts, etc.<\/p><p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/28-using-ai-tools-web-coding\">Listen to the episode here<\/a>.<\/p><p>Apologies to Luke and anyone who listened to the original release for the poor quality, but it should be fine now and I'll add this to my checklist when editing podcast episodes to ensure it doesn't happen again.<\/p>",
"processed": "<p>A few days ago, I published a new episode of the Beyond Blocks podcast with Luke McCormick, where we spoke about using AI and tools like Cursor for web coding.<\/p><p>Unfortunately, there was an export issue with the episode that affected the sound quality.<\/p><p>The recording was fine and the mp3 file was re-created and uploaded again to the episode page and the podcast feed for Spotify, Pocket Casts, etc.<\/p><p><a href=\"/podcast\/28-using-ai-tools-web-coding\">Listen to the episode here<\/a>.<\/p><p>Apologies to Luke and anyone who listened to the original release for the poor quality, but it should be fine now and I'll add this to my checklist when editing podcast episodes to ensure it doesn't happen again.<\/p>",
"summary": ""
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>If you use PHP and need to make a static website, <a href=\"https:\/\/sculpin.io\">Sculpin<\/a> is a great choice!<\/p>\n\n<h2 id=\"what-is-it%3F\">What is it?<\/h2>\n\n<p>Built with PHP and using Symfony components, it converts Markdown files and Twig templates into static HTML that can be easily deployed and hosted.<\/p>\n\n<p>Once generated, you can upload the files to a web host of your choice as the generated files are simple HTML, such as an S3 bucket with static hosting or GitHub Pages.<\/p>\n\n<h2 id=\"why-do-i-use-it%3F\">Why do I use it?<\/h2>\n\n<p>As a PHP Developer, it's already familiar and I can immediately start instead of learning a new language or templating engine, which I'd need to do if I were to use a static site generator written in Ruby, JavaScript or Go.<\/p>\n\n<p>If I need to extend it, I already can.<\/p>\n\n<p>I already know how to write custom Twig extensions, for example, so I can do it in Sculpin in the same way. (<a href=\"https:\/\/github.com\/opdavies\/sculpin-twig-markdown-bundle\">I made one<\/a> and open-sourced it)<\/p>\n\n<p>I already know how to use PHPUnit to write tests.<\/p>\n\n<h2 id=\"what-do-i-use-it-for%3F\">What do I use it for?<\/h2>\n\n<p>I use Sculpin for <a href=\"https:\/\/github.com\/opdavies\/oliverdavies.uk\">this website<\/a> and client projects that don't need the features of a CMS or framework with the ability to have reusable components and functionality provided by Twig (this works great with Tailwind CSS, too).<\/p>\n\n<p>I used it to <a href=\"https:\/\/www.oliverdavies.uk\/test-drive-twig-with-sculpin\">learn Twig before Drupal 8 was released<\/a>, back in 2015.<\/p>\n\n<p>I've also given a talk on <a href=\"https:\/\/www.oliverdavies.uk\/building-static-websites-sculpin\">building websites with Sculpin<\/a> which I may submit to some upcoming conferences.<\/p>\n\n ",
"value": "\n <p>If you use PHP and need to make a static website, <a href=\"https:\/\/sculpin.io\">Sculpin<\/a> is a great choice!<\/p>\n\n<h2 id=\"what-is-it%3F\">What is it?<\/h2>\n\n<p>Built with PHP and using Symfony components, it converts Markdown files and Twig templates into static HTML that can be easily deployed and hosted.<\/p>\n\n<p>Once generated, you can upload the files to a web host of your choice as the generated files are simple HTML, such as an S3 bucket with static hosting or GitHub Pages.<\/p>\n\n<h2 id=\"why-do-i-use-it%3F\">Why do I use it?<\/h2>\n\n<p>As a PHP Developer, it's already familiar and I can immediately start instead of learning a new language or templating engine, which I'd need to do if I were to use a static site generator written in Ruby, JavaScript or Go.<\/p>\n\n<p>If I need to extend it, I already can.<\/p>\n\n<p>I already know how to write custom Twig extensions, for example, so I can do it in Sculpin in the same way. (<a href=\"https:\/\/github.com\/opdavies\/sculpin-twig-markdown-bundle\">I made one<\/a> and open-sourced it)<\/p>\n\n<p>I already know how to use PHPUnit to write tests.<\/p>\n\n<h2 id=\"what-do-i-use-it-for%3F\">What do I use it for?<\/h2>\n\n<p>I use Sculpin for <a href=\"https:\/\/github.com\/opdavies\/oliverdavies.uk\">this website<\/a> and client projects that don't need the features of a CMS or framework with the ability to have reusable components and functionality provided by Twig (this works great with Tailwind CSS, too).<\/p>\n\n<p>I used it to <a href=\"/test-drive-twig-with-sculpin\">learn Twig before Drupal 8 was released<\/a>, back in 2015.<\/p>\n\n<p>I've also given a talk on <a href=\"/building-static-websites-sculpin\">building websites with Sculpin<\/a> which I may submit to some upcoming conferences.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>If you use PHP and need to make a static website, <a href=\"https:\/\/sculpin.io\">Sculpin<\/a> is a great choice!<\/p>\n\n<h2 id=\"what-is-it%3F\">What is it?<\/h2>\n\n<p>Built with PHP and using Symfony components, it converts Markdown files and Twig templates into static HTML that can be easily deployed and hosted.<\/p>\n\n<p>Once generated, you can upload the files to a web host of your choice as the generated files are simple HTML, such as an S3 bucket with static hosting or GitHub Pages.<\/p>\n\n<h2 id=\"why-do-i-use-it%3F\">Why do I use it?<\/h2>\n\n<p>As a PHP Developer, it's already familiar and I can immediately start instead of learning a new language or templating engine, which I'd need to do if I were to use a static site generator written in Ruby, JavaScript or Go.<\/p>\n\n<p>If I need to extend it, I already can.<\/p>\n\n<p>I already know how to write custom Twig extensions, for example, so I can do it in Sculpin in the same way. (<a href=\"https:\/\/github.com\/opdavies\/sculpin-twig-markdown-bundle\">I made one<\/a> and open-sourced it)<\/p>\n\n<p>I already know how to use PHPUnit to write tests.<\/p>\n\n<h2 id=\"what-do-i-use-it-for%3F\">What do I use it for?<\/h2>\n\n<p>I use Sculpin for <a href=\"https:\/\/github.com\/opdavies\/oliverdavies.uk\">this website<\/a> and client projects that don't need the features of a CMS or framework with the ability to have reusable components and functionality provided by Twig (this works great with Tailwind CSS, too).<\/p>\n\n<p>I used it to <a href=\"https:\/\/www.oliverdavies.uk\/test-drive-twig-with-sculpin\">learn Twig before Drupal 8 was released<\/a>, back in 2015.<\/p>\n\n<p>I've also given a talk on <a href=\"https:\/\/www.oliverdavies.uk\/building-static-websites-sculpin\">building websites with Sculpin<\/a> which I may submit to some upcoming conferences.<\/p>\n\n ",
"processed": "\n <p>If you use PHP and need to make a static website, <a href=\"https:\/\/sculpin.io\">Sculpin<\/a> is a great choice!<\/p>\n\n<h2 id=\"what-is-it%3F\">What is it?<\/h2>\n\n<p>Built with PHP and using Symfony components, it converts Markdown files and Twig templates into static HTML that can be easily deployed and hosted.<\/p>\n\n<p>Once generated, you can upload the files to a web host of your choice as the generated files are simple HTML, such as an S3 bucket with static hosting or GitHub Pages.<\/p>\n\n<h2 id=\"why-do-i-use-it%3F\">Why do I use it?<\/h2>\n\n<p>As a PHP Developer, it's already familiar and I can immediately start instead of learning a new language or templating engine, which I'd need to do if I were to use a static site generator written in Ruby, JavaScript or Go.<\/p>\n\n<p>If I need to extend it, I already can.<\/p>\n\n<p>I already know how to write custom Twig extensions, for example, so I can do it in Sculpin in the same way. (<a href=\"https:\/\/github.com\/opdavies\/sculpin-twig-markdown-bundle\">I made one<\/a> and open-sourced it)<\/p>\n\n<p>I already know how to use PHPUnit to write tests.<\/p>\n\n<h2 id=\"what-do-i-use-it-for%3F\">What do I use it for?<\/h2>\n\n<p>I use Sculpin for <a href=\"https:\/\/github.com\/opdavies\/oliverdavies.uk\">this website<\/a> and client projects that don't need the features of a CMS or framework with the ability to have reusable components and functionality provided by Twig (this works great with Tailwind CSS, too).<\/p>\n\n<p>I used it to <a href=\"/test-drive-twig-with-sculpin\">learn Twig before Drupal 8 was released<\/a>, back in 2015.<\/p>\n\n<p>I've also given a talk on <a href=\"/building-static-websites-sculpin\">building websites with Sculpin<\/a> which I may submit to some upcoming conferences.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>On several occasions, I've seen companies who build a lot of Drupal projects creating their own in-house [Drupal distribution] for new projects.<\/p>\n\n<p>Whilst this seems like a good idea, the ones I've seen are either not well maintained due to limited time between projects, or they're bloated with features and trying to include too much out of the box.<\/p>\n\n<p>If you maintain an in-house distribution, or are thinking of creating one, my advice is to ensure it's maintained by allocating enough time for this, and to keep it lean and only include the minimum amount of required functionality.<\/p>\n\n<p>Alternatively, maybe keep a template composer.json file to base new projects on instead of a full distribution.<\/p>\n\n<p>That could declare the modules and themes you want to include, without the additional overhead.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/12\/14\/save-time-and-effort-with-drupal-distributions\">drupal distribution<\/a><\/p>\n\n ",
"value": "\n <p>On several occasions, I've seen companies who build a lot of Drupal projects creating their own in-house [Drupal distribution] for new projects.<\/p>\n\n<p>Whilst this seems like a good idea, the ones I've seen are either not well maintained due to limited time between projects, or they're bloated with features and trying to include too much out of the box.<\/p>\n\n<p>If you maintain an in-house distribution, or are thinking of creating one, my advice is to ensure it's maintained by allocating enough time for this, and to keep it lean and only include the minimum amount of required functionality.<\/p>\n\n<p>Alternatively, maybe keep a template composer.json file to base new projects on instead of a full distribution.<\/p>\n\n<p>That could declare the modules and themes you want to include, without the additional overhead.<\/p>\n\n<p><a href=\"/daily\/2023\/12\/14\/save-time-and-effort-with-drupal-distributions\">drupal distribution<\/a><\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>On several occasions, I've seen companies who build a lot of Drupal projects creating their own in-house [Drupal distribution] for new projects.<\/p>\n\n<p>Whilst this seems like a good idea, the ones I've seen are either not well maintained due to limited time between projects, or they're bloated with features and trying to include too much out of the box.<\/p>\n\n<p>If you maintain an in-house distribution, or are thinking of creating one, my advice is to ensure it's maintained by allocating enough time for this, and to keep it lean and only include the minimum amount of required functionality.<\/p>\n\n<p>Alternatively, maybe keep a template composer.json file to base new projects on instead of a full distribution.<\/p>\n\n<p>That could declare the modules and themes you want to include, without the additional overhead.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/12\/14\/save-time-and-effort-with-drupal-distributions\">drupal distribution<\/a><\/p>\n\n ",
"processed": "\n <p>On several occasions, I've seen companies who build a lot of Drupal projects creating their own in-house [Drupal distribution] for new projects.<\/p>\n\n<p>Whilst this seems like a good idea, the ones I've seen are either not well maintained due to limited time between projects, or they're bloated with features and trying to include too much out of the box.<\/p>\n\n<p>If you maintain an in-house distribution, or are thinking of creating one, my advice is to ensure it's maintained by allocating enough time for this, and to keep it lean and only include the minimum amount of required functionality.<\/p>\n\n<p>Alternatively, maybe keep a template composer.json file to base new projects on instead of a full distribution.<\/p>\n\n<p>That could declare the modules and themes you want to include, without the additional overhead.<\/p>\n\n<p><a href=\"/daily\/2023\/12\/14\/save-time-and-effort-with-drupal-distributions\">drupal distribution<\/a><\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>The <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/12\/24\/moving-changes\">harder it is to update an environment<\/a>, the less often it will be done and the more out of sync your environments will become.<\/p>\n\n<p>The more out of sync your environments are, the higher the chance there will be bugs or issues when changes are moved between environments.<\/p>\n\n<p>I've had situations where the code I wrote worked for my local database but didn't when moved to staging or production.<\/p>\n\n<p>I worked at one company where my development database was refreshed nightly, so my site was at most one day out of sync with production.<\/p>\n\n<p>I knew my code would work with the latest production data and not only the data from days, weeks or months before.<\/p>\n\n<p>It also meant that I needed to write my changes in an automated and repeatable way so they would be executed on the refreshed database and re-added instead of having to do it manually.<\/p>\n\n<p>How in sync are your environments and how similar to production is the environment you're testing against?<\/p>\n\n ",
"value": "\n <p>The <a href=\"/daily\/2024\/12\/24\/moving-changes\">harder it is to update an environment<\/a>, the less often it will be done and the more out of sync your environments will become.<\/p>\n\n<p>The more out of sync your environments are, the higher the chance there will be bugs or issues when changes are moved between environments.<\/p>\n\n<p>I've had situations where the code I wrote worked for my local database but didn't when moved to staging or production.<\/p>\n\n<p>I worked at one company where my development database was refreshed nightly, so my site was at most one day out of sync with production.<\/p>\n\n<p>I knew my code would work with the latest production data and not only the data from days, weeks or months before.<\/p>\n\n<p>It also meant that I needed to write my changes in an automated and repeatable way so they would be executed on the refreshed database and re-added instead of having to do it manually.<\/p>\n\n<p>How in sync are your environments and how similar to production is the environment you're testing against?<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>The <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/12\/24\/moving-changes\">harder it is to update an environment<\/a>, the less often it will be done and the more out of sync your environments will become.<\/p>\n\n<p>The more out of sync your environments are, the higher the chance there will be bugs or issues when changes are moved between environments.<\/p>\n\n<p>I've had situations where the code I wrote worked for my local database but didn't when moved to staging or production.<\/p>\n\n<p>I worked at one company where my development database was refreshed nightly, so my site was at most one day out of sync with production.<\/p>\n\n<p>I knew my code would work with the latest production data and not only the data from days, weeks or months before.<\/p>\n\n<p>It also meant that I needed to write my changes in an automated and repeatable way so they would be executed on the refreshed database and re-added instead of having to do it manually.<\/p>\n\n<p>How in sync are your environments and how similar to production is the environment you're testing against?<\/p>\n\n ",
"processed": "\n <p>The <a href=\"/daily\/2024\/12\/24\/moving-changes\">harder it is to update an environment<\/a>, the less often it will be done and the more out of sync your environments will become.<\/p>\n\n<p>The more out of sync your environments are, the higher the chance there will be bugs or issues when changes are moved between environments.<\/p>\n\n<p>I've had situations where the code I wrote worked for my local database but didn't when moved to staging or production.<\/p>\n\n<p>I worked at one company where my development database was refreshed nightly, so my site was at most one day out of sync with production.<\/p>\n\n<p>I knew my code would work with the latest production data and not only the data from days, weeks or months before.<\/p>\n\n<p>It also meant that I needed to write my changes in an automated and repeatable way so they would be executed on the refreshed database and re-added instead of having to do it manually.<\/p>\n\n<p>How in sync are your environments and how similar to production is the environment you're testing against?<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">I've written a few earlier emails<\/a> about <code>run<\/code> files - a simple bash file that I add to my projects to simplify or combine common commands that I need to run often.<\/p>\n\n<p>Recently, I've looked at a couple of alternatives to see how they compare.<\/p>\n\n<p>One is very YAML based where all commands are written within a YAML file, and one is very Makefile-like and it does fix some of the confusion and issues that I've made with Makefiles in the past - such as passing arguments to commands, and dealing with <code>.PHONY<\/code>.<\/p>\n\n<p>Whilst I like both of these approaches and that they offer small additional features like auto-completion of task names, after using one of them in a project for a short while, I think that I'm going to stick with the <code>run<\/code> file.<\/p>\n\n<p>The main reason for this is that I like the simplicity of the <code>run<\/code> file, and that it's just a Bash file that contains functions.<\/p>\n\n<p>There were a couple of things that I couldn't quite get to work in one of the other tools, such as setting the TTY value in a Docker Command - which is something that I was able to do with bash within the <code>run<\/code> file. The fact that I can write regular bash and reuse existing knowledge is a big plus rather than having to try to learn another syntax or DSL for another tool.<\/p>\n\n<p>The main reason though is because bash is already installed everywhere. There's no additional tool for Developers to download and install so it keeps the barrier to entry low, and there's no additional dependencies to add to my CI pipeline for it to work.<\/p>\n\n<p>I was able to use one of these other tools in GitHub Actions as someone had already written a workflow for it, and although I could possibly install it via a package manager, just being able to run a bash file in any CI tool was probably the deciding factor to stick with <code>run<\/code> files.<\/p>\n\n ",
"value": "\n <p><a href=\"/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">I've written a few earlier emails<\/a> about <code>run<\/code> files - a simple bash file that I add to my projects to simplify or combine common commands that I need to run often.<\/p>\n\n<p>Recently, I've looked at a couple of alternatives to see how they compare.<\/p>\n\n<p>One is very YAML based where all commands are written within a YAML file, and one is very Makefile-like and it does fix some of the confusion and issues that I've made with Makefiles in the past - such as passing arguments to commands, and dealing with <code>.PHONY<\/code>.<\/p>\n\n<p>Whilst I like both of these approaches and that they offer small additional features like auto-completion of task names, after using one of them in a project for a short while, I think that I'm going to stick with the <code>run<\/code> file.<\/p>\n\n<p>The main reason for this is that I like the simplicity of the <code>run<\/code> file, and that it's just a Bash file that contains functions.<\/p>\n\n<p>There were a couple of things that I couldn't quite get to work in one of the other tools, such as setting the TTY value in a Docker Command - which is something that I was able to do with bash within the <code>run<\/code> file. The fact that I can write regular bash and reuse existing knowledge is a big plus rather than having to try to learn another syntax or DSL for another tool.<\/p>\n\n<p>The main reason though is because bash is already installed everywhere. There's no additional tool for Developers to download and install so it keeps the barrier to entry low, and there's no additional dependencies to add to my CI pipeline for it to work.<\/p>\n\n<p>I was able to use one of these other tools in GitHub Actions as someone had already written a workflow for it, and although I could possibly install it via a package manager, just being able to run a bash file in any CI tool was probably the deciding factor to stick with <code>run<\/code> files.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">I've written a few earlier emails<\/a> about <code>run<\/code> files - a simple bash file that I add to my projects to simplify or combine common commands that I need to run often.<\/p>\n\n<p>Recently, I've looked at a couple of alternatives to see how they compare.<\/p>\n\n<p>One is very YAML based where all commands are written within a YAML file, and one is very Makefile-like and it does fix some of the confusion and issues that I've made with Makefiles in the past - such as passing arguments to commands, and dealing with <code>.PHONY<\/code>.<\/p>\n\n<p>Whilst I like both of these approaches and that they offer small additional features like auto-completion of task names, after using one of them in a project for a short while, I think that I'm going to stick with the <code>run<\/code> file.<\/p>\n\n<p>The main reason for this is that I like the simplicity of the <code>run<\/code> file, and that it's just a Bash file that contains functions.<\/p>\n\n<p>There were a couple of things that I couldn't quite get to work in one of the other tools, such as setting the TTY value in a Docker Command - which is something that I was able to do with bash within the <code>run<\/code> file. The fact that I can write regular bash and reuse existing knowledge is a big plus rather than having to try to learn another syntax or DSL for another tool.<\/p>\n\n<p>The main reason though is because bash is already installed everywhere. There's no additional tool for Developers to download and install so it keeps the barrier to entry low, and there's no additional dependencies to add to my CI pipeline for it to work.<\/p>\n\n<p>I was able to use one of these other tools in GitHub Actions as someone had already written a workflow for it, and although I could possibly install it via a package manager, just being able to run a bash file in any CI tool was probably the deciding factor to stick with <code>run<\/code> files.<\/p>\n\n ",
"processed": "\n <p><a href=\"/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">I've written a few earlier emails<\/a> about <code>run<\/code> files - a simple bash file that I add to my projects to simplify or combine common commands that I need to run often.<\/p>\n\n<p>Recently, I've looked at a couple of alternatives to see how they compare.<\/p>\n\n<p>One is very YAML based where all commands are written within a YAML file, and one is very Makefile-like and it does fix some of the confusion and issues that I've made with Makefiles in the past - such as passing arguments to commands, and dealing with <code>.PHONY<\/code>.<\/p>\n\n<p>Whilst I like both of these approaches and that they offer small additional features like auto-completion of task names, after using one of them in a project for a short while, I think that I'm going to stick with the <code>run<\/code> file.<\/p>\n\n<p>The main reason for this is that I like the simplicity of the <code>run<\/code> file, and that it's just a Bash file that contains functions.<\/p>\n\n<p>There were a couple of things that I couldn't quite get to work in one of the other tools, such as setting the TTY value in a Docker Command - which is something that I was able to do with bash within the <code>run<\/code> file. The fact that I can write regular bash and reuse existing knowledge is a big plus rather than having to try to learn another syntax or DSL for another tool.<\/p>\n\n<p>The main reason though is because bash is already installed everywhere. There's no additional tool for Developers to download and install so it keeps the barrier to entry low, and there's no additional dependencies to add to my CI pipeline for it to work.<\/p>\n\n<p>I was able to use one of these other tools in GitHub Actions as someone had already written a workflow for it, and although I could possibly install it via a package manager, just being able to run a bash file in any CI tool was probably the deciding factor to stick with <code>run<\/code> files.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>How do you know if a commit to your codebase is deployable?<\/p>\n\n<p>What gives you confidence if a change will work once it's released?<\/p>\n\n<p>This can be from manual testing but also automated testing and quality checks from tools such as static analysis and code linting.<\/p>\n\n<p>However, this relies on every Developer running them before pushing each change and for their development environments to be consistent and matching the target environment.<\/p>\n\n<p>This can be automated by using a CI pipeline - a series of checks that are run automatically for each code push.<\/p>\n\n<p>This can include running automated tests, linting code and running static analysis and anything else you need.<\/p>\n\n<p>This is what determines if the change is deployable.<\/p>\n\n<p>If your CI pipeline passes, the commit is good can be deployed.<\/p>\n\n<p>If it fails, the commit should not be deployed and you should get it passing again as quickly as possible as <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/06\/28\/theres-no-value-in-a-broken-ci-pipeline\">there's no value in a broken CI pipeline<\/a>.<\/p>\n\n ",
"value": "\n <p>How do you know if a commit to your codebase is deployable?<\/p>\n\n<p>What gives you confidence if a change will work once it's released?<\/p>\n\n<p>This can be from manual testing but also automated testing and quality checks from tools such as static analysis and code linting.<\/p>\n\n<p>However, this relies on every Developer running them before pushing each change and for their development environments to be consistent and matching the target environment.<\/p>\n\n<p>This can be automated by using a CI pipeline - a series of checks that are run automatically for each code push.<\/p>\n\n<p>This can include running automated tests, linting code and running static analysis and anything else you need.<\/p>\n\n<p>This is what determines if the change is deployable.<\/p>\n\n<p>If your CI pipeline passes, the commit is good can be deployed.<\/p>\n\n<p>If it fails, the commit should not be deployed and you should get it passing again as quickly as possible as <a href=\"/daily\/2023\/06\/28\/theres-no-value-in-a-broken-ci-pipeline\">there's no value in a broken CI pipeline<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>How do you know if a commit to your codebase is deployable?<\/p>\n\n<p>What gives you confidence if a change will work once it's released?<\/p>\n\n<p>This can be from manual testing but also automated testing and quality checks from tools such as static analysis and code linting.<\/p>\n\n<p>However, this relies on every Developer running them before pushing each change and for their development environments to be consistent and matching the target environment.<\/p>\n\n<p>This can be automated by using a CI pipeline - a series of checks that are run automatically for each code push.<\/p>\n\n<p>This can include running automated tests, linting code and running static analysis and anything else you need.<\/p>\n\n<p>This is what determines if the change is deployable.<\/p>\n\n<p>If your CI pipeline passes, the commit is good can be deployed.<\/p>\n\n<p>If it fails, the commit should not be deployed and you should get it passing again as quickly as possible as <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/06\/28\/theres-no-value-in-a-broken-ci-pipeline\">there's no value in a broken CI pipeline<\/a>.<\/p>\n\n ",
"processed": "\n <p>How do you know if a commit to your codebase is deployable?<\/p>\n\n<p>What gives you confidence if a change will work once it's released?<\/p>\n\n<p>This can be from manual testing but also automated testing and quality checks from tools such as static analysis and code linting.<\/p>\n\n<p>However, this relies on every Developer running them before pushing each change and for their development environments to be consistent and matching the target environment.<\/p>\n\n<p>This can be automated by using a CI pipeline - a series of checks that are run automatically for each code push.<\/p>\n\n<p>This can include running automated tests, linting code and running static analysis and anything else you need.<\/p>\n\n<p>This is what determines if the change is deployable.<\/p>\n\n<p>If your CI pipeline passes, the commit is good can be deployed.<\/p>\n\n<p>If it fails, the commit should not be deployed and you should get it passing again as quickly as possible as <a href=\"/daily\/2023\/06\/28\/theres-no-value-in-a-broken-ci-pipeline\">there's no value in a broken CI pipeline<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>It's June, so there's only seven months left of security updates for Drupal 7.<\/p>\n\n<p>Originally released in 2011, Drupal 7 is now on version 7.101 and there are still over 315,000 active Drupal 7 websites according to the project page on Drupal.org.<\/p>\n\n<p>Are you stuck on D7 or haven't upgraded yet?<\/p>\n\n<p>I'm interested to know why. Reply to this email and let me know.<\/p>\n\n<p>Will you be migrating to Drupal 10, or something else?<\/p>\n\n<p>If you need help, with <a href=\"https:\/\/www.oliverdavies.uk\/drupal-upgrade\">my Drupal 7 upgrade roadmap<\/a>, I'll create an individual plan to upgrade and enjoy easy upgrades to Drupal 11 and beyond!<\/p>\n\n ",
"value": "\n <p>It's June, so there's only seven months left of security updates for Drupal 7.<\/p>\n\n<p>Originally released in 2011, Drupal 7 is now on version 7.101 and there are still over 315,000 active Drupal 7 websites according to the project page on Drupal.org.<\/p>\n\n<p>Are you stuck on D7 or haven't upgraded yet?<\/p>\n\n<p>I'm interested to know why. Reply to this email and let me know.<\/p>\n\n<p>Will you be migrating to Drupal 10, or something else?<\/p>\n\n<p>If you need help, with <a href=\"/drupal-upgrade\">my Drupal 7 upgrade roadmap<\/a>, I'll create an individual plan to upgrade and enjoy easy upgrades to Drupal 11 and beyond!<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>It's June, so there's only seven months left of security updates for Drupal 7.<\/p>\n\n<p>Originally released in 2011, Drupal 7 is now on version 7.101 and there are still over 315,000 active Drupal 7 websites according to the project page on Drupal.org.<\/p>\n\n<p>Are you stuck on D7 or haven't upgraded yet?<\/p>\n\n<p>I'm interested to know why. Reply to this email and let me know.<\/p>\n\n<p>Will you be migrating to Drupal 10, or something else?<\/p>\n\n<p>If you need help, with <a href=\"https:\/\/www.oliverdavies.uk\/drupal-upgrade\">my Drupal 7 upgrade roadmap<\/a>, I'll create an individual plan to upgrade and enjoy easy upgrades to Drupal 11 and beyond!<\/p>\n\n ",
"processed": "\n <p>It's June, so there's only seven months left of security updates for Drupal 7.<\/p>\n\n<p>Originally released in 2011, Drupal 7 is now on version 7.101 and there are still over 315,000 active Drupal 7 websites according to the project page on Drupal.org.<\/p>\n\n<p>Are you stuck on D7 or haven't upgraded yet?<\/p>\n\n<p>I'm interested to know why. Reply to this email and let me know.<\/p>\n\n<p>Will you be migrating to Drupal 10, or something else?<\/p>\n\n<p>If you need help, with <a href=\"/drupal-upgrade\">my Drupal 7 upgrade roadmap<\/a>, I'll create an individual plan to upgrade and enjoy easy upgrades to Drupal 11 and beyond!<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>After the topic of Drupalisms and Drupal jargon came up in previous podcast episodes, I was happy to speak with Emma Horrell and Luke McCormick.<\/p>\n\n<p>We discussed the work happening in Drupal and Drupal CMS to de-jargon Drupal, the Drupalisms working group.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/27-drupalisms\">Listen to the episode here<\/a>.<\/p>\n\n<p>If you want to be a guest on the <a href=\"https:\/\/www.oliverdavies.uk\/podcast\">Beyond Blocks podcast<\/a>, reply and let me know.<\/p>\n\n ",
"value": "\n <p>After the topic of Drupalisms and Drupal jargon came up in previous podcast episodes, I was happy to speak with Emma Horrell and Luke McCormick.<\/p>\n\n<p>We discussed the work happening in Drupal and Drupal CMS to de-jargon Drupal, the Drupalisms working group.<\/p>\n\n<p><a href=\"/podcast\/27-drupalisms\">Listen to the episode here<\/a>.<\/p>\n\n<p>If you want to be a guest on the <a href=\"/podcast\">Beyond Blocks podcast<\/a>, reply and let me know.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>After the topic of Drupalisms and Drupal jargon came up in previous podcast episodes, I was happy to speak with Emma Horrell and Luke McCormick.<\/p>\n\n<p>We discussed the work happening in Drupal and Drupal CMS to de-jargon Drupal, the Drupalisms working group.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/27-drupalisms\">Listen to the episode here<\/a>.<\/p>\n\n<p>If you want to be a guest on the <a href=\"https:\/\/www.oliverdavies.uk\/podcast\">Beyond Blocks podcast<\/a>, reply and let me know.<\/p>\n\n ",
"processed": "\n <p>After the topic of Drupalisms and Drupal jargon came up in previous podcast episodes, I was happy to speak with Emma Horrell and Luke McCormick.<\/p>\n\n<p>We discussed the work happening in Drupal and Drupal CMS to de-jargon Drupal, the Drupalisms working group.<\/p>\n\n<p><a href=\"/podcast\/27-drupalisms\">Listen to the episode here<\/a>.<\/p>\n\n<p>If you want to be a guest on the <a href=\"/podcast\">Beyond Blocks podcast<\/a>, reply and let me know.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Since I posted about <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/10\/optimise-for-revertability\">optimising for revertability<\/a>, I've received a few questions about how I avoid merge commits when working with Git.<\/p>\n\n<p>This is an extract from my <code>.config\/git\/.config<\/code> file:<\/p>\n\n<pre><code class=\"ini\">[merge]\n ff = \"only\"\n\n[pull]\n ff = \"only\"\n rebase = true\n<\/code><\/pre>\n\n<p>This changes the behaviour of when I run <code>git pull<\/code> to always include <code>--rebase<\/code> by default and to only allow fast-forward merges and pulls.<\/p>\n\n<p>Only allowing fast-forward merges avoids merge commits as Git can just move the pointer for the branch to the latest commit.<\/p>\n\n<p>If I can't do a fast-forward merge, I need to rebase first to update everything and bring it up to date.<\/p>\n\n<p>Sometimes, when working in team, merge commits will still creep in sometimes and there are situations where you can only create a merge commit.<\/p>\n\n<p>In this situation, I can do <code>git merge --ff<\/code> to allow a merge commit temporarily, but this is the exception instead of the default.<\/p>\n\n<blockquote>\n <p>Hint: there's a lot more information on the configuration and arguments if you run and read <code>man git-merge<\/code>.<\/p>\n<\/blockquote>\n\n<p>When working with online tools such as GitHub and GitLab, I avoid any options like <code>Squash and merge<\/code> or <code>Create a merge commit<\/code> and will use rebase options, although I've seen where different commit IDs have been generated when merged in the UI, which is why I prefer to do merges locally.<\/p>\n\n<p>Or use <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/06\/17\/avoid-git-merge-hell-with-trunk-based-development\">trunk-based development<\/a> and don't work on topic branches at all.<\/p>\n\n ",
"value": "\n <p>Since I posted about <a href=\"/daily\/2024\/05\/10\/optimise-for-revertability\">optimising for revertability<\/a>, I've received a few questions about how I avoid merge commits when working with Git.<\/p>\n\n<p>This is an extract from my <code>.config\/git\/.config<\/code> file:<\/p>\n\n<pre><code class=\"ini\">[merge]\n ff = \"only\"\n\n[pull]\n ff = \"only\"\n rebase = true\n<\/code><\/pre>\n\n<p>This changes the behaviour of when I run <code>git pull<\/code> to always include <code>--rebase<\/code> by default and to only allow fast-forward merges and pulls.<\/p>\n\n<p>Only allowing fast-forward merges avoids merge commits as Git can just move the pointer for the branch to the latest commit.<\/p>\n\n<p>If I can't do a fast-forward merge, I need to rebase first to update everything and bring it up to date.<\/p>\n\n<p>Sometimes, when working in team, merge commits will still creep in sometimes and there are situations where you can only create a merge commit.<\/p>\n\n<p>In this situation, I can do <code>git merge --ff<\/code> to allow a merge commit temporarily, but this is the exception instead of the default.<\/p>\n\n<blockquote>\n <p>Hint: there's a lot more information on the configuration and arguments if you run and read <code>man git-merge<\/code>.<\/p>\n<\/blockquote>\n\n<p>When working with online tools such as GitHub and GitLab, I avoid any options like <code>Squash and merge<\/code> or <code>Create a merge commit<\/code> and will use rebase options, although I've seen where different commit IDs have been generated when merged in the UI, which is why I prefer to do merges locally.<\/p>\n\n<p>Or use <a href=\"/daily\/2023\/06\/17\/avoid-git-merge-hell-with-trunk-based-development\">trunk-based development<\/a> and don't work on topic branches at all.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Since I posted about <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/10\/optimise-for-revertability\">optimising for revertability<\/a>, I've received a few questions about how I avoid merge commits when working with Git.<\/p>\n\n<p>This is an extract from my <code>.config\/git\/.config<\/code> file:<\/p>\n\n<pre><code class=\"ini\">[merge]\n ff = \"only\"\n\n[pull]\n ff = \"only\"\n rebase = true\n<\/code><\/pre>\n\n<p>This changes the behaviour of when I run <code>git pull<\/code> to always include <code>--rebase<\/code> by default and to only allow fast-forward merges and pulls.<\/p>\n\n<p>Only allowing fast-forward merges avoids merge commits as Git can just move the pointer for the branch to the latest commit.<\/p>\n\n<p>If I can't do a fast-forward merge, I need to rebase first to update everything and bring it up to date.<\/p>\n\n<p>Sometimes, when working in team, merge commits will still creep in sometimes and there are situations where you can only create a merge commit.<\/p>\n\n<p>In this situation, I can do <code>git merge --ff<\/code> to allow a merge commit temporarily, but this is the exception instead of the default.<\/p>\n\n<blockquote>\n <p>Hint: there's a lot more information on the configuration and arguments if you run and read <code>man git-merge<\/code>.<\/p>\n<\/blockquote>\n\n<p>When working with online tools such as GitHub and GitLab, I avoid any options like <code>Squash and merge<\/code> or <code>Create a merge commit<\/code> and will use rebase options, although I've seen where different commit IDs have been generated when merged in the UI, which is why I prefer to do merges locally.<\/p>\n\n<p>Or use <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/06\/17\/avoid-git-merge-hell-with-trunk-based-development\">trunk-based development<\/a> and don't work on topic branches at all.<\/p>\n\n ",
"processed": "\n <p>Since I posted about <a href=\"/daily\/2024\/05\/10\/optimise-for-revertability\">optimising for revertability<\/a>, I've received a few questions about how I avoid merge commits when working with Git.<\/p>\n\n<p>This is an extract from my <code>.config\/git\/.config<\/code> file:<\/p>\n\n<pre><code class=\"ini\">[merge]\n ff = \"only\"\n\n[pull]\n ff = \"only\"\n rebase = true\n<\/code><\/pre>\n\n<p>This changes the behaviour of when I run <code>git pull<\/code> to always include <code>--rebase<\/code> by default and to only allow fast-forward merges and pulls.<\/p>\n\n<p>Only allowing fast-forward merges avoids merge commits as Git can just move the pointer for the branch to the latest commit.<\/p>\n\n<p>If I can't do a fast-forward merge, I need to rebase first to update everything and bring it up to date.<\/p>\n\n<p>Sometimes, when working in team, merge commits will still creep in sometimes and there are situations where you can only create a merge commit.<\/p>\n\n<p>In this situation, I can do <code>git merge --ff<\/code> to allow a merge commit temporarily, but this is the exception instead of the default.<\/p>\n\n<blockquote>\n <p>Hint: there's a lot more information on the configuration and arguments if you run and read <code>man git-merge<\/code>.<\/p>\n<\/blockquote>\n\n<p>When working with online tools such as GitHub and GitLab, I avoid any options like <code>Squash and merge<\/code> or <code>Create a merge commit<\/code> and will use rebase options, although I've seen where different commit IDs have been generated when merged in the UI, which is why I prefer to do merges locally.<\/p>\n\n<p>Or use <a href=\"/daily\/2023\/06\/17\/avoid-git-merge-hell-with-trunk-based-development\">trunk-based development<\/a> and don't work on topic branches at all.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>When you're working on a task - <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/08\/31\/make-it-work-then-make-it-good\">whether you're making it work or making it good<\/a>, you can commit your code changes as often as you like.<\/p>\n\n<p>You should definitely commit your changes every time you have a working iteration, even if it's not the complete or final version, or even if the code doesn't pass all the coding standards and static analysis checks.<\/p>\n\n<p>Things can be fixed or improved in subsequent commits.<\/p>\n\n<p>You can amend or squash commits locally so your clean-up and work-in-progress commits are removed before you push your final version to your remote repository.<\/p>\n\n<p>Whilst test-driven development says you should work in small feedback loops and steps, you don't need to push every commit as you wrote them.<\/p>\n\n<p>Until you run <code>git push<\/code>, your commits are yours and yours only.<\/p>\n\n<p>You have the opportunity to tidy up and organise your changes - making your commits easier to review and more likely to be approved in a code review.<\/p>\n\n ",
"value": "\n <p>When you're working on a task - <a href=\"/daily\/2024\/08\/31\/make-it-work-then-make-it-good\">whether you're making it work or making it good<\/a>, you can commit your code changes as often as you like.<\/p>\n\n<p>You should definitely commit your changes every time you have a working iteration, even if it's not the complete or final version, or even if the code doesn't pass all the coding standards and static analysis checks.<\/p>\n\n<p>Things can be fixed or improved in subsequent commits.<\/p>\n\n<p>You can amend or squash commits locally so your clean-up and work-in-progress commits are removed before you push your final version to your remote repository.<\/p>\n\n<p>Whilst test-driven development says you should work in small feedback loops and steps, you don't need to push every commit as you wrote them.<\/p>\n\n<p>Until you run <code>git push<\/code>, your commits are yours and yours only.<\/p>\n\n<p>You have the opportunity to tidy up and organise your changes - making your commits easier to review and more likely to be approved in a code review.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>When you're working on a task - <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/08\/31\/make-it-work-then-make-it-good\">whether you're making it work or making it good<\/a>, you can commit your code changes as often as you like.<\/p>\n\n<p>You should definitely commit your changes every time you have a working iteration, even if it's not the complete or final version, or even if the code doesn't pass all the coding standards and static analysis checks.<\/p>\n\n<p>Things can be fixed or improved in subsequent commits.<\/p>\n\n<p>You can amend or squash commits locally so your clean-up and work-in-progress commits are removed before you push your final version to your remote repository.<\/p>\n\n<p>Whilst test-driven development says you should work in small feedback loops and steps, you don't need to push every commit as you wrote them.<\/p>\n\n<p>Until you run <code>git push<\/code>, your commits are yours and yours only.<\/p>\n\n<p>You have the opportunity to tidy up and organise your changes - making your commits easier to review and more likely to be approved in a code review.<\/p>\n\n ",
"processed": "\n <p>When you're working on a task - <a href=\"/daily\/2024\/08\/31\/make-it-work-then-make-it-good\">whether you're making it work or making it good<\/a>, you can commit your code changes as often as you like.<\/p>\n\n<p>You should definitely commit your changes every time you have a working iteration, even if it's not the complete or final version, or even if the code doesn't pass all the coding standards and static analysis checks.<\/p>\n\n<p>Things can be fixed or improved in subsequent commits.<\/p>\n\n<p>You can amend or squash commits locally so your clean-up and work-in-progress commits are removed before you push your final version to your remote repository.<\/p>\n\n<p>Whilst test-driven development says you should work in small feedback loops and steps, you don't need to push every commit as you wrote them.<\/p>\n\n<p>Until you run <code>git push<\/code>, your commits are yours and yours only.<\/p>\n\n<p>You have the opportunity to tidy up and organise your changes - making your commits easier to review and more likely to be approved in a code review.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>As I said <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/10\/refactoring\">in yesterday's email<\/a>, sometimes you change your mind whilst working on something.<\/p>\n\n<p>Maybe you change your approach and have a commit that supersedes an earlier one, fix a typo, or find a bug and need to revert a commit.<\/p>\n\n<p>If you're pushing your changes to a branch for review, I suggest using <code>git rebase<\/code> to clean up your commits.<\/p>\n\n<p>You can squash the typo fix into the commit that introduced the typo, or remove the original implementation that you later moved away from.<\/p>\n\n<p>Whilst there is an option to squash all the commits when merging, I don't like it and prefer people to tidy their commits before pushing.<\/p>\n\n<p>This means the commits are easier to review and you can keep the original commit history and all the context within the messages instead of a generic <code>Merge commit..<\/code> message.<\/p>\n\n ",
"value": "\n <p>As I said <a href=\"/daily\/2025\/02\/10\/refactoring\">in yesterday's email<\/a>, sometimes you change your mind whilst working on something.<\/p>\n\n<p>Maybe you change your approach and have a commit that supersedes an earlier one, fix a typo, or find a bug and need to revert a commit.<\/p>\n\n<p>If you're pushing your changes to a branch for review, I suggest using <code>git rebase<\/code> to clean up your commits.<\/p>\n\n<p>You can squash the typo fix into the commit that introduced the typo, or remove the original implementation that you later moved away from.<\/p>\n\n<p>Whilst there is an option to squash all the commits when merging, I don't like it and prefer people to tidy their commits before pushing.<\/p>\n\n<p>This means the commits are easier to review and you can keep the original commit history and all the context within the messages instead of a generic <code>Merge commit..<\/code> message.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>As I said <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/10\/refactoring\">in yesterday's email<\/a>, sometimes you change your mind whilst working on something.<\/p>\n\n<p>Maybe you change your approach and have a commit that supersedes an earlier one, fix a typo, or find a bug and need to revert a commit.<\/p>\n\n<p>If you're pushing your changes to a branch for review, I suggest using <code>git rebase<\/code> to clean up your commits.<\/p>\n\n<p>You can squash the typo fix into the commit that introduced the typo, or remove the original implementation that you later moved away from.<\/p>\n\n<p>Whilst there is an option to squash all the commits when merging, I don't like it and prefer people to tidy their commits before pushing.<\/p>\n\n<p>This means the commits are easier to review and you can keep the original commit history and all the context within the messages instead of a generic <code>Merge commit..<\/code> message.<\/p>\n\n ",
"processed": "\n <p>As I said <a href=\"/daily\/2025\/02\/10\/refactoring\">in yesterday's email<\/a>, sometimes you change your mind whilst working on something.<\/p>\n\n<p>Maybe you change your approach and have a commit that supersedes an earlier one, fix a typo, or find a bug and need to revert a commit.<\/p>\n\n<p>If you're pushing your changes to a branch for review, I suggest using <code>git rebase<\/code> to clean up your commits.<\/p>\n\n<p>You can squash the typo fix into the commit that introduced the typo, or remove the original implementation that you later moved away from.<\/p>\n\n<p>Whilst there is an option to squash all the commits when merging, I don't like it and prefer people to tidy their commits before pushing.<\/p>\n\n<p>This means the commits are easier to review and you can keep the original commit history and all the context within the messages instead of a generic <code>Merge commit..<\/code> message.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "<p>I use NixOS as the Linux distribution on my laptop and home server, and specifically the unstable channel.<\/p><p>This is the \"rolling\" version of NixOS that is continuously updated with the newest and latest packages, compared to the stable releases like 24.11 and 25.05 that are released twice a year.<\/p><p>I don't necessarily do this to get the latest packages.<\/p><p>I do it to keep on top of configuration changes.<\/p><p>I run \"nix flake update\" usually once a week to download the latest updates.<\/p><p>If there are breaking changes or notices since I last updated, I can address them and do it iteratively rather than waiting to do them every six months.<\/p><p>Similar to application deployments, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/05\/14\/releasing-small-changes-often-is-less-risky\">I update early and often<\/a>.<\/p><p>One of the great things about NixOS is, if there is an application that breaks on the unstable branch, I can pin it to the stable release until it works again.<\/p><p>This means I get the benefits of both the rolling and stable approaches.<\/p><p>If you want to see my NixOS configuration, it's <a href=\"https:\/\/code.oliverdavies.uk\/opdavies\/nix-config\">publicly available on my Forgejo instance<\/a>.<\/p>",
"value": "<p>I use NixOS as the Linux distribution on my laptop and home server, and specifically the unstable channel.<\/p><p>This is the \"rolling\" version of NixOS that is continuously updated with the newest and latest packages, compared to the stable releases like 24.11 and 25.05 that are released twice a year.<\/p><p>I don't necessarily do this to get the latest packages.<\/p><p>I do it to keep on top of configuration changes.<\/p><p>I run \"nix flake update\" usually once a week to download the latest updates.<\/p><p>If there are breaking changes or notices since I last updated, I can address them and do it iteratively rather than waiting to do them every six months.<\/p><p>Similar to application deployments, <a href=\"/daily\/2023\/05\/14\/releasing-small-changes-often-is-less-risky\">I update early and often<\/a>.<\/p><p>One of the great things about NixOS is, if there is an application that breaks on the unstable branch, I can pin it to the stable release until it works again.<\/p><p>This means I get the benefits of both the rolling and stable approaches.<\/p><p>If you want to see my NixOS configuration, it's <a href=\"https:\/\/code.oliverdavies.uk\/opdavies\/nix-config\">publicly available on my Forgejo instance<\/a>.<\/p>",
"format": "basic_html",
"processed": "<p>I use NixOS as the Linux distribution on my laptop and home server, and specifically the unstable channel.<\/p><p>This is the \"rolling\" version of NixOS that is continuously updated with the newest and latest packages, compared to the stable releases like 24.11 and 25.05 that are released twice a year.<\/p><p>I don't necessarily do this to get the latest packages.<\/p><p>I do it to keep on top of configuration changes.<\/p><p>I run \"nix flake update\" usually once a week to download the latest updates.<\/p><p>If there are breaking changes or notices since I last updated, I can address them and do it iteratively rather than waiting to do them every six months.<\/p><p>Similar to application deployments, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/05\/14\/releasing-small-changes-often-is-less-risky\">I update early and often<\/a>.<\/p><p>One of the great things about NixOS is, if there is an application that breaks on the unstable branch, I can pin it to the stable release until it works again.<\/p><p>This means I get the benefits of both the rolling and stable approaches.<\/p><p>If you want to see my NixOS configuration, it's <a href=\"https:\/\/code.oliverdavies.uk\/opdavies\/nix-config\">publicly available on my Forgejo instance<\/a>.<\/p>",
"processed": "<p>I use NixOS as the Linux distribution on my laptop and home server, and specifically the unstable channel.<\/p><p>This is the \"rolling\" version of NixOS that is continuously updated with the newest and latest packages, compared to the stable releases like 24.11 and 25.05 that are released twice a year.<\/p><p>I don't necessarily do this to get the latest packages.<\/p><p>I do it to keep on top of configuration changes.<\/p><p>I run \"nix flake update\" usually once a week to download the latest updates.<\/p><p>If there are breaking changes or notices since I last updated, I can address them and do it iteratively rather than waiting to do them every six months.<\/p><p>Similar to application deployments, <a href=\"/daily\/2023\/05\/14\/releasing-small-changes-often-is-less-risky\">I update early and often<\/a>.<\/p><p>One of the great things about NixOS is, if there is an application that breaks on the unstable branch, I can pin it to the stable release until it works again.<\/p><p>This means I get the benefits of both the rolling and stable approaches.<\/p><p>If you want to see my NixOS configuration, it's <a href=\"https:\/\/code.oliverdavies.uk\/opdavies\/nix-config\">publicly available on my Forgejo instance<\/a>.<\/p>",
"summary": ""
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Today, I started to build a new open-source project - Versa, the versatile command-line tool that standardises common commands across projects.<\/p>\n\n<p>After watching a Twitch streamer building something similar in Rust, I decided to build my take on it and add features I'd need, such as support for local vs Docker-based commands and to run different commands for different projects.<\/p>\n\n<p>For example, <code>versa run<\/code> would need to run different commands for Drupal and Sculpin projects, <code>versa test<\/code> should support different test frameworks for the same language - e.g. PHPUnit, Pest and ParaTest for PHP - and the commands will need to be different in Docker Compose-based projects.<\/p>\n\n<p>Currently, this logic is within my <a href=\"https:\/\/www.oliverdavies.uk\/build-configs\">Build Configs<\/a> project but can be moved to Versa.<\/p>\n\n<p>This reduces the complexity within that codebase and means I can open-source it as it's a separate project.<\/p>\n\n<p>At the moment, I've added PHP as the only supported language but I will add JavaScript\/TypeScript support so it supports projects like Fractal.<\/p>\n\n<p>It's still in the prototype phase and includes some initial commands, but the interesting parts will be making it clever.<\/p>\n\n<p>Instead of running <code>versa run --type sculpin<\/code>, I'd like to just do <code>versa run<\/code> and have it determine the type of project automatically.<\/p>\n\n<p><code>versa test<\/code> should be able to determine the testing framework automatically based on what's in the project's <code>composer.json<\/code> file instead of having to specify it.<\/p>\n\n<p>Likewise, for JavaScript, <code>versa install<\/code> should be able to determine if <code>npm<\/code>, <code>yarn<\/code> or <code>pnpm<\/code> is used.<\/p>\n\n<p>That'll be where the more complex code will be added and when I start doing test-driven development - maybe with Behat, which is also something I've been thinking about for Build Configs.<\/p>\n\n<p>Interested? <a href=\"https:\/\/github.com\/opdavies\/versa\">Take a look at the code<\/a>.<\/p>\n\n ",
"value": "\n <p>Today, I started to build a new open-source project - Versa, the versatile command-line tool that standardises common commands across projects.<\/p>\n\n<p>After watching a Twitch streamer building something similar in Rust, I decided to build my take on it and add features I'd need, such as support for local vs Docker-based commands and to run different commands for different projects.<\/p>\n\n<p>For example, <code>versa run<\/code> would need to run different commands for Drupal and Sculpin projects, <code>versa test<\/code> should support different test frameworks for the same language - e.g. PHPUnit, Pest and ParaTest for PHP - and the commands will need to be different in Docker Compose-based projects.<\/p>\n\n<p>Currently, this logic is within my <a href=\"/build-configs\">Build Configs<\/a> project but can be moved to Versa.<\/p>\n\n<p>This reduces the complexity within that codebase and means I can open-source it as it's a separate project.<\/p>\n\n<p>At the moment, I've added PHP as the only supported language but I will add JavaScript\/TypeScript support so it supports projects like Fractal.<\/p>\n\n<p>It's still in the prototype phase and includes some initial commands, but the interesting parts will be making it clever.<\/p>\n\n<p>Instead of running <code>versa run --type sculpin<\/code>, I'd like to just do <code>versa run<\/code> and have it determine the type of project automatically.<\/p>\n\n<p><code>versa test<\/code> should be able to determine the testing framework automatically based on what's in the project's <code>composer.json<\/code> file instead of having to specify it.<\/p>\n\n<p>Likewise, for JavaScript, <code>versa install<\/code> should be able to determine if <code>npm<\/code>, <code>yarn<\/code> or <code>pnpm<\/code> is used.<\/p>\n\n<p>That'll be where the more complex code will be added and when I start doing test-driven development - maybe with Behat, which is also something I've been thinking about for Build Configs.<\/p>\n\n<p>Interested? <a href=\"https:\/\/github.com\/opdavies\/versa\">Take a look at the code<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Today, I started to build a new open-source project - Versa, the versatile command-line tool that standardises common commands across projects.<\/p>\n\n<p>After watching a Twitch streamer building something similar in Rust, I decided to build my take on it and add features I'd need, such as support for local vs Docker-based commands and to run different commands for different projects.<\/p>\n\n<p>For example, <code>versa run<\/code> would need to run different commands for Drupal and Sculpin projects, <code>versa test<\/code> should support different test frameworks for the same language - e.g. PHPUnit, Pest and ParaTest for PHP - and the commands will need to be different in Docker Compose-based projects.<\/p>\n\n<p>Currently, this logic is within my <a href=\"https:\/\/www.oliverdavies.uk\/build-configs\">Build Configs<\/a> project but can be moved to Versa.<\/p>\n\n<p>This reduces the complexity within that codebase and means I can open-source it as it's a separate project.<\/p>\n\n<p>At the moment, I've added PHP as the only supported language but I will add JavaScript\/TypeScript support so it supports projects like Fractal.<\/p>\n\n<p>It's still in the prototype phase and includes some initial commands, but the interesting parts will be making it clever.<\/p>\n\n<p>Instead of running <code>versa run --type sculpin<\/code>, I'd like to just do <code>versa run<\/code> and have it determine the type of project automatically.<\/p>\n\n<p><code>versa test<\/code> should be able to determine the testing framework automatically based on what's in the project's <code>composer.json<\/code> file instead of having to specify it.<\/p>\n\n<p>Likewise, for JavaScript, <code>versa install<\/code> should be able to determine if <code>npm<\/code>, <code>yarn<\/code> or <code>pnpm<\/code> is used.<\/p>\n\n<p>That'll be where the more complex code will be added and when I start doing test-driven development - maybe with Behat, which is also something I've been thinking about for Build Configs.<\/p>\n\n<p>Interested? <a href=\"https:\/\/github.com\/opdavies\/versa\">Take a look at the code<\/a>.<\/p>\n\n ",
"processed": "\n <p>Today, I started to build a new open-source project - Versa, the versatile command-line tool that standardises common commands across projects.<\/p>\n\n<p>After watching a Twitch streamer building something similar in Rust, I decided to build my take on it and add features I'd need, such as support for local vs Docker-based commands and to run different commands for different projects.<\/p>\n\n<p>For example, <code>versa run<\/code> would need to run different commands for Drupal and Sculpin projects, <code>versa test<\/code> should support different test frameworks for the same language - e.g. PHPUnit, Pest and ParaTest for PHP - and the commands will need to be different in Docker Compose-based projects.<\/p>\n\n<p>Currently, this logic is within my <a href=\"/build-configs\">Build Configs<\/a> project but can be moved to Versa.<\/p>\n\n<p>This reduces the complexity within that codebase and means I can open-source it as it's a separate project.<\/p>\n\n<p>At the moment, I've added PHP as the only supported language but I will add JavaScript\/TypeScript support so it supports projects like Fractal.<\/p>\n\n<p>It's still in the prototype phase and includes some initial commands, but the interesting parts will be making it clever.<\/p>\n\n<p>Instead of running <code>versa run --type sculpin<\/code>, I'd like to just do <code>versa run<\/code> and have it determine the type of project automatically.<\/p>\n\n<p><code>versa test<\/code> should be able to determine the testing framework automatically based on what's in the project's <code>composer.json<\/code> file instead of having to specify it.<\/p>\n\n<p>Likewise, for JavaScript, <code>versa install<\/code> should be able to determine if <code>npm<\/code>, <code>yarn<\/code> or <code>pnpm<\/code> is used.<\/p>\n\n<p>That'll be where the more complex code will be added and when I start doing test-driven development - maybe with Behat, which is also something I've been thinking about for Build Configs.<\/p>\n\n<p>Interested? <a href=\"https:\/\/github.com\/opdavies\/versa\">Take a look at the code<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>This week on the Beyond Blocks podcast, I spoke with George Gordon - a graduate from the School of Code who was recently employed in their first Junior Developer role - about their move into tech and software development, their experiences at hack days and meetups, and their introduction to Drupal.<\/p>\n\n<p>I've been a mentor for School of Code for the last few cohorts as well as attending on-site events such as the TechConnect meetup and hack days.<\/p>\n\n<p>I wasn't George's mentor, but I met him at a hackday earlier this year and at a PHP meetup a few months later, so I was happy to have him on the podcast.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/20-george-gordon\">Listen to the episode now<\/a>.<\/p>\n\n ",
"value": "\n <p>This week on the Beyond Blocks podcast, I spoke with George Gordon - a graduate from the School of Code who was recently employed in their first Junior Developer role - about their move into tech and software development, their experiences at hack days and meetups, and their introduction to Drupal.<\/p>\n\n<p>I've been a mentor for School of Code for the last few cohorts as well as attending on-site events such as the TechConnect meetup and hack days.<\/p>\n\n<p>I wasn't George's mentor, but I met him at a hackday earlier this year and at a PHP meetup a few months later, so I was happy to have him on the podcast.<\/p>\n\n<p><a href=\"/podcast\/20-george-gordon\">Listen to the episode now<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>This week on the Beyond Blocks podcast, I spoke with George Gordon - a graduate from the School of Code who was recently employed in their first Junior Developer role - about their move into tech and software development, their experiences at hack days and meetups, and their introduction to Drupal.<\/p>\n\n<p>I've been a mentor for School of Code for the last few cohorts as well as attending on-site events such as the TechConnect meetup and hack days.<\/p>\n\n<p>I wasn't George's mentor, but I met him at a hackday earlier this year and at a PHP meetup a few months later, so I was happy to have him on the podcast.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/20-george-gordon\">Listen to the episode now<\/a>.<\/p>\n\n ",
"processed": "\n <p>This week on the Beyond Blocks podcast, I spoke with George Gordon - a graduate from the School of Code who was recently employed in their first Junior Developer role - about their move into tech and software development, their experiences at hack days and meetups, and their introduction to Drupal.<\/p>\n\n<p>I've been a mentor for School of Code for the last few cohorts as well as attending on-site events such as the TechConnect meetup and hack days.<\/p>\n\n<p>I wasn't George's mentor, but I met him at a hackday earlier this year and at a PHP meetup a few months later, so I was happy to have him on the podcast.<\/p>\n\n<p><a href=\"/podcast\/20-george-gordon\">Listen to the episode now<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Have you worked on a project where different Developers are developing with different tools or have different versions of packages installed?<\/p>\n\n<p>In a development team, you want all environments to be consistent - including every Developer's local environment.<\/p>\n\n<p>You want to have every environment to be as close as possible to each other or, ideally, identical.<\/p>\n\n<p>You want everyone to use the same PHP version, the same web and database servers and the same packages installed.<\/p>\n\n<p>Once things start to diverge, bugs can be introduced - such as writing code locally in a newer version of PHP than what's on production.<\/p>\n\n<p>Ideally, you also want everything to be reproducible with locked dependencies and generate the same outcome regardless of when the commands are run.<\/p>\n\n<p>This is one of the main reasons I've <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/11\/could-nix-and-devenv-replace-docker-compose\">started to use Nix and devenv for projects<\/a> - because they create environments that are both consistent and reproducible, reducing the chances of dependency mismatches and bugs creeping into my code.<\/p>\n\n ",
"value": "\n <p>Have you worked on a project where different Developers are developing with different tools or have different versions of packages installed?<\/p>\n\n<p>In a development team, you want all environments to be consistent - including every Developer's local environment.<\/p>\n\n<p>You want to have every environment to be as close as possible to each other or, ideally, identical.<\/p>\n\n<p>You want everyone to use the same PHP version, the same web and database servers and the same packages installed.<\/p>\n\n<p>Once things start to diverge, bugs can be introduced - such as writing code locally in a newer version of PHP than what's on production.<\/p>\n\n<p>Ideally, you also want everything to be reproducible with locked dependencies and generate the same outcome regardless of when the commands are run.<\/p>\n\n<p>This is one of the main reasons I've <a href=\"/daily\/2024\/11\/11\/could-nix-and-devenv-replace-docker-compose\">started to use Nix and devenv for projects<\/a> - because they create environments that are both consistent and reproducible, reducing the chances of dependency mismatches and bugs creeping into my code.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Have you worked on a project where different Developers are developing with different tools or have different versions of packages installed?<\/p>\n\n<p>In a development team, you want all environments to be consistent - including every Developer's local environment.<\/p>\n\n<p>You want to have every environment to be as close as possible to each other or, ideally, identical.<\/p>\n\n<p>You want everyone to use the same PHP version, the same web and database servers and the same packages installed.<\/p>\n\n<p>Once things start to diverge, bugs can be introduced - such as writing code locally in a newer version of PHP than what's on production.<\/p>\n\n<p>Ideally, you also want everything to be reproducible with locked dependencies and generate the same outcome regardless of when the commands are run.<\/p>\n\n<p>This is one of the main reasons I've <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/11\/could-nix-and-devenv-replace-docker-compose\">started to use Nix and devenv for projects<\/a> - because they create environments that are both consistent and reproducible, reducing the chances of dependency mismatches and bugs creeping into my code.<\/p>\n\n ",
"processed": "\n <p>Have you worked on a project where different Developers are developing with different tools or have different versions of packages installed?<\/p>\n\n<p>In a development team, you want all environments to be consistent - including every Developer's local environment.<\/p>\n\n<p>You want to have every environment to be as close as possible to each other or, ideally, identical.<\/p>\n\n<p>You want everyone to use the same PHP version, the same web and database servers and the same packages installed.<\/p>\n\n<p>Once things start to diverge, bugs can be introduced - such as writing code locally in a newer version of PHP than what's on production.<\/p>\n\n<p>Ideally, you also want everything to be reproducible with locked dependencies and generate the same outcome regardless of when the commands are run.<\/p>\n\n<p>This is one of the main reasons I've <a href=\"/daily\/2024\/11\/11\/could-nix-and-devenv-replace-docker-compose\">started to use Nix and devenv for projects<\/a> - because they create environments that are both consistent and reproducible, reducing the chances of dependency mismatches and bugs creeping into my code.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Before <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/13\/speaking-at-the-drupal-london-meetup\">my remote talk for the Drupal London meetup<\/a>, I'm updating the usage statistics for <a href=\"https:\/\/www.drupal.org\/project\/override_node_options\">the Override Node Options module<\/a> - one of the modules I maintain on Drupal.org.<\/p>\n\n<p>In my slides for DrupalCamp Belgium, I showed the usage figures from October 2023, which showed 38,096 installations and it being the 173rd most installed module.<\/p>\n\n<p>This week, the number of installations has slightly increased to 38,223.<\/p>\n\n<p>What's interesting is that whilst the number of installations has been consistent, there are a lot less Drupal 7 websites using the module and a lot more Drupal 8+ sites using it.<\/p>\n\n<h2 id=\"october-2023\">October 2023<\/h2>\n\n<ul>\n<li>5.x-1.x: 1<\/li>\n<li>6.x-1.x: 297<\/li>\n<li>7.x-1.x: 13,717<\/li>\n<li>8.x-2.x: 24,081<\/li>\n<li>Total: 38,096<\/li>\n<\/ul>\n\n<h2 id=\"november-2024\">November 2024<\/h2>\n\n<ul>\n<li>5.x-1.x: 4<\/li>\n<li>6.x-1.x: 202<\/li>\n<li>7.x-1.x: 10,429<\/li>\n<li>8.x-2.x: 27,588<\/li>\n<li>Total: 38,223<\/li>\n<\/ul>\n\n<p>Assuming these numbers are correct, this makes me feel very positive and happy about the adoption of newer versions of Drupal and that people are upgrading their D7 websites to Drupal 10 or 11.<\/p>\n\n ",
"value": "\n <p>Before <a href=\"/daily\/2024\/11\/13\/speaking-at-the-drupal-london-meetup\">my remote talk for the Drupal London meetup<\/a>, I'm updating the usage statistics for <a href=\"https:\/\/www.drupal.org\/project\/override_node_options\">the Override Node Options module<\/a> - one of the modules I maintain on Drupal.org.<\/p>\n\n<p>In my slides for DrupalCamp Belgium, I showed the usage figures from October 2023, which showed 38,096 installations and it being the 173rd most installed module.<\/p>\n\n<p>This week, the number of installations has slightly increased to 38,223.<\/p>\n\n<p>What's interesting is that whilst the number of installations has been consistent, there are a lot less Drupal 7 websites using the module and a lot more Drupal 8+ sites using it.<\/p>\n\n<h2 id=\"october-2023\">October 2023<\/h2>\n\n<ul>\n<li>5.x-1.x: 1<\/li>\n<li>6.x-1.x: 297<\/li>\n<li>7.x-1.x: 13,717<\/li>\n<li>8.x-2.x: 24,081<\/li>\n<li>Total: 38,096<\/li>\n<\/ul>\n\n<h2 id=\"november-2024\">November 2024<\/h2>\n\n<ul>\n<li>5.x-1.x: 4<\/li>\n<li>6.x-1.x: 202<\/li>\n<li>7.x-1.x: 10,429<\/li>\n<li>8.x-2.x: 27,588<\/li>\n<li>Total: 38,223<\/li>\n<\/ul>\n\n<p>Assuming these numbers are correct, this makes me feel very positive and happy about the adoption of newer versions of Drupal and that people are upgrading their D7 websites to Drupal 10 or 11.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Before <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/13\/speaking-at-the-drupal-london-meetup\">my remote talk for the Drupal London meetup<\/a>, I'm updating the usage statistics for <a href=\"https:\/\/www.drupal.org\/project\/override_node_options\">the Override Node Options module<\/a> - one of the modules I maintain on Drupal.org.<\/p>\n\n<p>In my slides for DrupalCamp Belgium, I showed the usage figures from October 2023, which showed 38,096 installations and it being the 173rd most installed module.<\/p>\n\n<p>This week, the number of installations has slightly increased to 38,223.<\/p>\n\n<p>What's interesting is that whilst the number of installations has been consistent, there are a lot less Drupal 7 websites using the module and a lot more Drupal 8+ sites using it.<\/p>\n\n<h2 id=\"october-2023\">October 2023<\/h2>\n\n<ul>\n<li>5.x-1.x: 1<\/li>\n<li>6.x-1.x: 297<\/li>\n<li>7.x-1.x: 13,717<\/li>\n<li>8.x-2.x: 24,081<\/li>\n<li>Total: 38,096<\/li>\n<\/ul>\n\n<h2 id=\"november-2024\">November 2024<\/h2>\n\n<ul>\n<li>5.x-1.x: 4<\/li>\n<li>6.x-1.x: 202<\/li>\n<li>7.x-1.x: 10,429<\/li>\n<li>8.x-2.x: 27,588<\/li>\n<li>Total: 38,223<\/li>\n<\/ul>\n\n<p>Assuming these numbers are correct, this makes me feel very positive and happy about the adoption of newer versions of Drupal and that people are upgrading their D7 websites to Drupal 10 or 11.<\/p>\n\n ",
"processed": "\n <p>Before <a href=\"/daily\/2024\/11\/13\/speaking-at-the-drupal-london-meetup\">my remote talk for the Drupal London meetup<\/a>, I'm updating the usage statistics for <a href=\"https:\/\/www.drupal.org\/project\/override_node_options\">the Override Node Options module<\/a> - one of the modules I maintain on Drupal.org.<\/p>\n\n<p>In my slides for DrupalCamp Belgium, I showed the usage figures from October 2023, which showed 38,096 installations and it being the 173rd most installed module.<\/p>\n\n<p>This week, the number of installations has slightly increased to 38,223.<\/p>\n\n<p>What's interesting is that whilst the number of installations has been consistent, there are a lot less Drupal 7 websites using the module and a lot more Drupal 8+ sites using it.<\/p>\n\n<h2 id=\"october-2023\">October 2023<\/h2>\n\n<ul>\n<li>5.x-1.x: 1<\/li>\n<li>6.x-1.x: 297<\/li>\n<li>7.x-1.x: 13,717<\/li>\n<li>8.x-2.x: 24,081<\/li>\n<li>Total: 38,096<\/li>\n<\/ul>\n\n<h2 id=\"november-2024\">November 2024<\/h2>\n\n<ul>\n<li>5.x-1.x: 4<\/li>\n<li>6.x-1.x: 202<\/li>\n<li>7.x-1.x: 10,429<\/li>\n<li>8.x-2.x: 27,588<\/li>\n<li>Total: 38,223<\/li>\n<\/ul>\n\n<p>Assuming these numbers are correct, this makes me feel very positive and happy about the adoption of newer versions of Drupal and that people are upgrading their D7 websites to Drupal 10 or 11.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Yesterday, I received the first \"Automated Drupal 11 compatibility fixes\" email from the Rector-powered Project Update Bot.<\/p>\n\n<p>It was for the <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle_twig\">Feature Toggle Twig module<\/a> that adds a <code>featureIsEnabled()<\/code> function to Twig to check if a feature toggle is enabled.<\/p>\n\n<p>For example:<\/p>\n\n<pre><code class=\"language-twig\">{% if featureIsEnabled('foo') %}\n {# ... #}\n{% endif %}\n<\/code><\/pre>\n\n<h2 id=\"what-changes-were-needed%3F\">What Changes Were Needed?<\/h2>\n\n<p>The only change needed to make the module Drupal 11 compatible was updating the <code>core_version_requirement<\/code> to <code>^10 || ^11<\/code> - allowing the module to support Drupal 10 and 11 at the same time as it uses no deprecated code.<\/p>\n\n<p>That's a great thing about modern Drupal compared to legacy versions - no major changes or rewrites to support a new major version!<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the Thing<\/h2>\n\n<p>I thought this was a great initiative in previous versions and I'm glad to see it again for Drupal 11, and it's great that it's being done with time before the Drupal 11 release as it gives maintainers the time to update their projects so as many modules as possible will be Drupal 11-compatible when it's released.<\/p>\n\n<p>I look forward to getting more of these emails for my <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/03\/09\/override-node-options-40624-drupal-websites\">other contributed projects on Drupal.org<\/a>.<\/p>\n\n ",
"value": "\n <p>Yesterday, I received the first \"Automated Drupal 11 compatibility fixes\" email from the Rector-powered Project Update Bot.<\/p>\n\n<p>It was for the <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle_twig\">Feature Toggle Twig module<\/a> that adds a <code>featureIsEnabled()<\/code> function to Twig to check if a feature toggle is enabled.<\/p>\n\n<p>For example:<\/p>\n\n<pre><code class=\"language-twig\">{% if featureIsEnabled('foo') %}\n {# ... #}\n{% endif %}\n<\/code><\/pre>\n\n<h2 id=\"what-changes-were-needed%3F\">What Changes Were Needed?<\/h2>\n\n<p>The only change needed to make the module Drupal 11 compatible was updating the <code>core_version_requirement<\/code> to <code>^10 || ^11<\/code> - allowing the module to support Drupal 10 and 11 at the same time as it uses no deprecated code.<\/p>\n\n<p>That's a great thing about modern Drupal compared to legacy versions - no major changes or rewrites to support a new major version!<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the Thing<\/h2>\n\n<p>I thought this was a great initiative in previous versions and I'm glad to see it again for Drupal 11, and it's great that it's being done with time before the Drupal 11 release as it gives maintainers the time to update their projects so as many modules as possible will be Drupal 11-compatible when it's released.<\/p>\n\n<p>I look forward to getting more of these emails for my <a href=\"/daily\/2024\/03\/09\/override-node-options-40624-drupal-websites\">other contributed projects on Drupal.org<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Yesterday, I received the first \"Automated Drupal 11 compatibility fixes\" email from the Rector-powered Project Update Bot.<\/p>\n\n<p>It was for the <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle_twig\">Feature Toggle Twig module<\/a> that adds a <code>featureIsEnabled()<\/code> function to Twig to check if a feature toggle is enabled.<\/p>\n\n<p>For example:<\/p>\n\n<pre><code class=\"language-twig\">{% if featureIsEnabled('foo') %}\n {# ... #}\n{% endif %}\n<\/code><\/pre>\n\n<h2 id=\"what-changes-were-needed%3F\">What Changes Were Needed?<\/h2>\n\n<p>The only change needed to make the module Drupal 11 compatible was updating the <code>core_version_requirement<\/code> to <code>^10 || ^11<\/code> - allowing the module to support Drupal 10 and 11 at the same time as it uses no deprecated code.<\/p>\n\n<p>That's a great thing about modern Drupal compared to legacy versions - no major changes or rewrites to support a new major version!<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the Thing<\/h2>\n\n<p>I thought this was a great initiative in previous versions and I'm glad to see it again for Drupal 11, and it's great that it's being done with time before the Drupal 11 release as it gives maintainers the time to update their projects so as many modules as possible will be Drupal 11-compatible when it's released.<\/p>\n\n<p>I look forward to getting more of these emails for my <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/03\/09\/override-node-options-40624-drupal-websites\">other contributed projects on Drupal.org<\/a>.<\/p>\n\n ",
"processed": "\n <p>Yesterday, I received the first \"Automated Drupal 11 compatibility fixes\" email from the Rector-powered Project Update Bot.<\/p>\n\n<p>It was for the <a href=\"https:\/\/www.drupal.org\/project\/feature_toggle_twig\">Feature Toggle Twig module<\/a> that adds a <code>featureIsEnabled()<\/code> function to Twig to check if a feature toggle is enabled.<\/p>\n\n<p>For example:<\/p>\n\n<pre><code class=\"language-twig\">{% if featureIsEnabled('foo') %}\n {# ... #}\n{% endif %}\n<\/code><\/pre>\n\n<h2 id=\"what-changes-were-needed%3F\">What Changes Were Needed?<\/h2>\n\n<p>The only change needed to make the module Drupal 11 compatible was updating the <code>core_version_requirement<\/code> to <code>^10 || ^11<\/code> - allowing the module to support Drupal 10 and 11 at the same time as it uses no deprecated code.<\/p>\n\n<p>That's a great thing about modern Drupal compared to legacy versions - no major changes or rewrites to support a new major version!<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the Thing<\/h2>\n\n<p>I thought this was a great initiative in previous versions and I'm glad to see it again for Drupal 11, and it's great that it's being done with time before the Drupal 11 release as it gives maintainers the time to update their projects so as many modules as possible will be Drupal 11-compatible when it's released.<\/p>\n\n<p>I look forward to getting more of these emails for my <a href=\"/daily\/2024\/03\/09\/override-node-options-40624-drupal-websites\">other contributed projects on Drupal.org<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/08\/16\/what-are-err--req-and-res\">Whilst mentoring at the School of Code Hackathon<\/a>, something the team and I discussed was documentation and documenting any decisions we made about the approaches they were taking, the techologies to use, etc.<\/p>\n\n<p>We kept it simple by adding this to a README file, but I also mentioned <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/09\/23\/adrs-technical-design-documents\">ADRs and technical decision documents<\/a> and how they can be written in Markdown and stored alongside the code in the same repository.<\/p>\n\n<p>Another approach to documentation that I like is to create diagrams and flow charts.<\/p>\n\n<p>I've used various tools to do this, but recently, I've started to use <a href=\"https:\/\/github.com\/mermaid-js\/mermaid\">Mermaid<\/a>, which is a Markdown-like syntax to generate charts and diagrams.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>There are online tools to do this, but there's also <code>mmdc<\/code> command-line tool that generates diagrams locally.<\/p>\n\n<p>This means that I can easily generate diagrams and store in the codebase too, and have them version-controlled so I can see the history as they evolve during the project.<\/p>\n\n<h2 id=\"want-an-example%3F\">Want an example?<\/h2>\n\n<p><a href=\"https:\/\/github.com\/opdavies\/build-configs\/blob\/f02fce7ff5b5cff202ec8b893a4b3c7e7c56f3c4\/docs\/diagram.mmd\">Here's one I did for the Build Configs tool<\/a>, which I recently open-sourced, and that GitHub renders by default (you can click the 'Code' tab to see the code for the chart).<\/p>\n\n ",
"value": "\n <p><a href=\"/daily\/2024\/08\/16\/what-are-err--req-and-res\">Whilst mentoring at the School of Code Hackathon<\/a>, something the team and I discussed was documentation and documenting any decisions we made about the approaches they were taking, the techologies to use, etc.<\/p>\n\n<p>We kept it simple by adding this to a README file, but I also mentioned <a href=\"/daily\/2022\/09\/23\/adrs-technical-design-documents\">ADRs and technical decision documents<\/a> and how they can be written in Markdown and stored alongside the code in the same repository.<\/p>\n\n<p>Another approach to documentation that I like is to create diagrams and flow charts.<\/p>\n\n<p>I've used various tools to do this, but recently, I've started to use <a href=\"https:\/\/github.com\/mermaid-js\/mermaid\">Mermaid<\/a>, which is a Markdown-like syntax to generate charts and diagrams.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>There are online tools to do this, but there's also <code>mmdc<\/code> command-line tool that generates diagrams locally.<\/p>\n\n<p>This means that I can easily generate diagrams and store in the codebase too, and have them version-controlled so I can see the history as they evolve during the project.<\/p>\n\n<h2 id=\"want-an-example%3F\">Want an example?<\/h2>\n\n<p><a href=\"https:\/\/github.com\/opdavies\/build-configs\/blob\/f02fce7ff5b5cff202ec8b893a4b3c7e7c56f3c4\/docs\/diagram.mmd\">Here's one I did for the Build Configs tool<\/a>, which I recently open-sourced, and that GitHub renders by default (you can click the 'Code' tab to see the code for the chart).<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/08\/16\/what-are-err--req-and-res\">Whilst mentoring at the School of Code Hackathon<\/a>, something the team and I discussed was documentation and documenting any decisions we made about the approaches they were taking, the techologies to use, etc.<\/p>\n\n<p>We kept it simple by adding this to a README file, but I also mentioned <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/09\/23\/adrs-technical-design-documents\">ADRs and technical decision documents<\/a> and how they can be written in Markdown and stored alongside the code in the same repository.<\/p>\n\n<p>Another approach to documentation that I like is to create diagrams and flow charts.<\/p>\n\n<p>I've used various tools to do this, but recently, I've started to use <a href=\"https:\/\/github.com\/mermaid-js\/mermaid\">Mermaid<\/a>, which is a Markdown-like syntax to generate charts and diagrams.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>There are online tools to do this, but there's also <code>mmdc<\/code> command-line tool that generates diagrams locally.<\/p>\n\n<p>This means that I can easily generate diagrams and store in the codebase too, and have them version-controlled so I can see the history as they evolve during the project.<\/p>\n\n<h2 id=\"want-an-example%3F\">Want an example?<\/h2>\n\n<p><a href=\"https:\/\/github.com\/opdavies\/build-configs\/blob\/f02fce7ff5b5cff202ec8b893a4b3c7e7c56f3c4\/docs\/diagram.mmd\">Here's one I did for the Build Configs tool<\/a>, which I recently open-sourced, and that GitHub renders by default (you can click the 'Code' tab to see the code for the chart).<\/p>\n\n ",
"processed": "\n <p><a href=\"/daily\/2024\/08\/16\/what-are-err--req-and-res\">Whilst mentoring at the School of Code Hackathon<\/a>, something the team and I discussed was documentation and documenting any decisions we made about the approaches they were taking, the techologies to use, etc.<\/p>\n\n<p>We kept it simple by adding this to a README file, but I also mentioned <a href=\"/daily\/2022\/09\/23\/adrs-technical-design-documents\">ADRs and technical decision documents<\/a> and how they can be written in Markdown and stored alongside the code in the same repository.<\/p>\n\n<p>Another approach to documentation that I like is to create diagrams and flow charts.<\/p>\n\n<p>I've used various tools to do this, but recently, I've started to use <a href=\"https:\/\/github.com\/mermaid-js\/mermaid\">Mermaid<\/a>, which is a Markdown-like syntax to generate charts and diagrams.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>There are online tools to do this, but there's also <code>mmdc<\/code> command-line tool that generates diagrams locally.<\/p>\n\n<p>This means that I can easily generate diagrams and store in the codebase too, and have them version-controlled so I can see the history as they evolve during the project.<\/p>\n\n<h2 id=\"want-an-example%3F\">Want an example?<\/h2>\n\n<p><a href=\"https:\/\/github.com\/opdavies\/build-configs\/blob\/f02fce7ff5b5cff202ec8b893a4b3c7e7c56f3c4\/docs\/diagram.mmd\">Here's one I did for the Build Configs tool<\/a>, which I recently open-sourced, and that GitHub renders by default (you can click the 'Code' tab to see the code for the chart).<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>In the most recent episode of the <a href=\"https:\/\/www.oliverdavies.uk\/podcast\">Beyond Blocks podcast<\/a>, I spoke with <a href=\"https:\/\/mortenson.coffee\">Sam Mortenson<\/a> about Single File Components in Drupal as well as building static Drupal websites with Tome.<\/p>\n\n<p>As a Drupal Specialist who works with other technologies including Vue.js, Symfony and Sculpin, it was great to discuss and learn more about both topics.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/19-sam-mortenson\">Listen to the episode now<\/a>.<\/p>\n\n<p>Also, prior to releasing this episode, the total downloads for the podcast are almost at 1,000. Thank you to all the previous guests and everyone who listens to the podcast!<\/p>\n\n ",
"value": "\n <p>In the most recent episode of the <a href=\"/podcast\">Beyond Blocks podcast<\/a>, I spoke with <a href=\"https:\/\/mortenson.coffee\">Sam Mortenson<\/a> about Single File Components in Drupal as well as building static Drupal websites with Tome.<\/p>\n\n<p>As a Drupal Specialist who works with other technologies including Vue.js, Symfony and Sculpin, it was great to discuss and learn more about both topics.<\/p>\n\n<p><a href=\"/podcast\/19-sam-mortenson\">Listen to the episode now<\/a>.<\/p>\n\n<p>Also, prior to releasing this episode, the total downloads for the podcast are almost at 1,000. Thank you to all the previous guests and everyone who listens to the podcast!<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>In the most recent episode of the <a href=\"https:\/\/www.oliverdavies.uk\/podcast\">Beyond Blocks podcast<\/a>, I spoke with <a href=\"https:\/\/mortenson.coffee\">Sam Mortenson<\/a> about Single File Components in Drupal as well as building static Drupal websites with Tome.<\/p>\n\n<p>As a Drupal Specialist who works with other technologies including Vue.js, Symfony and Sculpin, it was great to discuss and learn more about both topics.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/19-sam-mortenson\">Listen to the episode now<\/a>.<\/p>\n\n<p>Also, prior to releasing this episode, the total downloads for the podcast are almost at 1,000. Thank you to all the previous guests and everyone who listens to the podcast!<\/p>\n\n ",
"processed": "\n <p>In the most recent episode of the <a href=\"/podcast\">Beyond Blocks podcast<\/a>, I spoke with <a href=\"https:\/\/mortenson.coffee\">Sam Mortenson<\/a> about Single File Components in Drupal as well as building static Drupal websites with Tome.<\/p>\n\n<p>As a Drupal Specialist who works with other technologies including Vue.js, Symfony and Sculpin, it was great to discuss and learn more about both topics.<\/p>\n\n<p><a href=\"/podcast\/19-sam-mortenson\">Listen to the episode now<\/a>.<\/p>\n\n<p>Also, prior to releasing this episode, the total downloads for the podcast are almost at 1,000. Thank you to all the previous guests and everyone who listens to the podcast!<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/10\/19\/phpunit-or-pest\">Whether you prefer PHPUnit or Pest PHP<\/a>, or if you're coding in a different language, it's important to have automated tests - especially before you refactor any code.<\/p>\n\n<p>Before you refactor, you want to have passing tests that you're confident cover all the required functionality.<\/p>\n\n<p>When you finish refactoring, the tests should still pass.<\/p>\n\n<p>Then you know the functionality is the same and the code still works after it's been refactored.<\/p>\n\n<p>If you don't have tests, how do you know everything still works, or how likely are you to do the refactor at all?<\/p>\n\n ",
"value": "\n <p><a href=\"/daily\/2024\/10\/19\/phpunit-or-pest\">Whether you prefer PHPUnit or Pest PHP<\/a>, or if you're coding in a different language, it's important to have automated tests - especially before you refactor any code.<\/p>\n\n<p>Before you refactor, you want to have passing tests that you're confident cover all the required functionality.<\/p>\n\n<p>When you finish refactoring, the tests should still pass.<\/p>\n\n<p>Then you know the functionality is the same and the code still works after it's been refactored.<\/p>\n\n<p>If you don't have tests, how do you know everything still works, or how likely are you to do the refactor at all?<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/10\/19\/phpunit-or-pest\">Whether you prefer PHPUnit or Pest PHP<\/a>, or if you're coding in a different language, it's important to have automated tests - especially before you refactor any code.<\/p>\n\n<p>Before you refactor, you want to have passing tests that you're confident cover all the required functionality.<\/p>\n\n<p>When you finish refactoring, the tests should still pass.<\/p>\n\n<p>Then you know the functionality is the same and the code still works after it's been refactored.<\/p>\n\n<p>If you don't have tests, how do you know everything still works, or how likely are you to do the refactor at all?<\/p>\n\n ",
"processed": "\n <p><a href=\"/daily\/2024\/10\/19\/phpunit-or-pest\">Whether you prefer PHPUnit or Pest PHP<\/a>, or if you're coding in a different language, it's important to have automated tests - especially before you refactor any code.<\/p>\n\n<p>Before you refactor, you want to have passing tests that you're confident cover all the required functionality.<\/p>\n\n<p>When you finish refactoring, the tests should still pass.<\/p>\n\n<p>Then you know the functionality is the same and the code still works after it's been refactored.<\/p>\n\n<p>If you don't have tests, how do you know everything still works, or how likely are you to do the refactor at all?<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Imagine you've made a commit and want to undo it, or a particular commit is causing issues in production and you want to roll it back.<\/p>\n\n<p>Instead of having to change it back manually, <code>git revert<\/code> can do it for you.<\/p>\n\n<p>You specify the commit SHA you want to revert and Git will automatically try and revert that commit.<\/p>\n\n<p>It creates its own commit message which includes the original commit message and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/20\/referencing-other-commits-in-commit-messages\">the reverted commit SHA<\/a>, so you can easily find or navigate to the original commit.<\/p>\n\n<p>For example:<\/p>\n\n<blockquote>\n <p>Revert \"Sort talks only by the event date\"<\/p>\n \n <p>This reverts commit cbd1417b24a608df8b451a3ab5c9f888de41e758.<\/p>\n<\/blockquote>\n\n<p>Next time, instead of manually reverting a commit, give <code>git revert<\/code> a try.<\/p>\n\n ",
"value": "\n <p>Imagine you've made a commit and want to undo it, or a particular commit is causing issues in production and you want to roll it back.<\/p>\n\n<p>Instead of having to change it back manually, <code>git revert<\/code> can do it for you.<\/p>\n\n<p>You specify the commit SHA you want to revert and Git will automatically try and revert that commit.<\/p>\n\n<p>It creates its own commit message which includes the original commit message and <a href=\"/daily\/2024\/05\/20\/referencing-other-commits-in-commit-messages\">the reverted commit SHA<\/a>, so you can easily find or navigate to the original commit.<\/p>\n\n<p>For example:<\/p>\n\n<blockquote>\n <p>Revert \"Sort talks only by the event date\"<\/p>\n \n <p>This reverts commit cbd1417b24a608df8b451a3ab5c9f888de41e758.<\/p>\n<\/blockquote>\n\n<p>Next time, instead of manually reverting a commit, give <code>git revert<\/code> a try.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Imagine you've made a commit and want to undo it, or a particular commit is causing issues in production and you want to roll it back.<\/p>\n\n<p>Instead of having to change it back manually, <code>git revert<\/code> can do it for you.<\/p>\n\n<p>You specify the commit SHA you want to revert and Git will automatically try and revert that commit.<\/p>\n\n<p>It creates its own commit message which includes the original commit message and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/20\/referencing-other-commits-in-commit-messages\">the reverted commit SHA<\/a>, so you can easily find or navigate to the original commit.<\/p>\n\n<p>For example:<\/p>\n\n<blockquote>\n <p>Revert \"Sort talks only by the event date\"<\/p>\n \n <p>This reverts commit cbd1417b24a608df8b451a3ab5c9f888de41e758.<\/p>\n<\/blockquote>\n\n<p>Next time, instead of manually reverting a commit, give <code>git revert<\/code> a try.<\/p>\n\n ",
"processed": "\n <p>Imagine you've made a commit and want to undo it, or a particular commit is causing issues in production and you want to roll it back.<\/p>\n\n<p>Instead of having to change it back manually, <code>git revert<\/code> can do it for you.<\/p>\n\n<p>You specify the commit SHA you want to revert and Git will automatically try and revert that commit.<\/p>\n\n<p>It creates its own commit message which includes the original commit message and <a href=\"/daily\/2024\/05\/20\/referencing-other-commits-in-commit-messages\">the reverted commit SHA<\/a>, so you can easily find or navigate to the original commit.<\/p>\n\n<p>For example:<\/p>\n\n<blockquote>\n <p>Revert \"Sort talks only by the event date\"<\/p>\n \n <p>This reverts commit cbd1417b24a608df8b451a3ab5c9f888de41e758.<\/p>\n<\/blockquote>\n\n<p>Next time, instead of manually reverting a commit, give <code>git revert<\/code> a try.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>I recently started <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/04\/07\/nix-rst2pdf\">using Nix to build my PDF presentation slides<\/a> that <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/building-presenting-slide-decks-rst2pdf\">I create with rst2pdf<\/a>.<\/p>\n\n<p>I removed the custom build script that was generating the PDF files and moved that code into a Nix derivation.<\/p>\n\n<p>Now I can run <code>nix build .#test-driven-drupal<\/code> and it will generate the slides for that talk.<\/p>\n\n<p>As well as the files specific to each presentation, I also have a derivation for shared assets that apply to all talks - i.e. the stylesheets and fonts that are embedded within the PDF.<\/p>\n\n<p>The font files were stored in the repository but I wanted to remove them and use the font files available in nixpkgs.<\/p>\n\n<p>After some small changes, <a href=\"https:\/\/code.oliverdavies.uk\/opdavies\/talks\/commit\/e24d2df83f04e492151b1a1f4901490ce76ffd45\">I was able to do it<\/a> and remove the font files from my repository.<\/p>\n\n<p>The Inter font is available in nixpkgs, but it downloads an <code>InterVariable.ttf<\/code> font that rst2pdf didn't know how to change the font weight for, so I made my own derivation of the static Inter font based on the releases from GitHub.<\/p>\n\n<p>I'm happy that I was able to achieve this, as my repository is leaner and I'm continuing to find new and interesting uses for Nix in my workflows.<\/p>\n\n ",
"value": "\n <p>I recently started <a href=\"/daily\/2025\/04\/07\/nix-rst2pdf\">using Nix to build my PDF presentation slides<\/a> that <a href=\"/presentations\/building-presenting-slide-decks-rst2pdf\">I create with rst2pdf<\/a>.<\/p>\n\n<p>I removed the custom build script that was generating the PDF files and moved that code into a Nix derivation.<\/p>\n\n<p>Now I can run <code>nix build .#test-driven-drupal<\/code> and it will generate the slides for that talk.<\/p>\n\n<p>As well as the files specific to each presentation, I also have a derivation for shared assets that apply to all talks - i.e. the stylesheets and fonts that are embedded within the PDF.<\/p>\n\n<p>The font files were stored in the repository but I wanted to remove them and use the font files available in nixpkgs.<\/p>\n\n<p>After some small changes, <a href=\"https:\/\/code.oliverdavies.uk\/opdavies\/talks\/commit\/e24d2df83f04e492151b1a1f4901490ce76ffd45\">I was able to do it<\/a> and remove the font files from my repository.<\/p>\n\n<p>The Inter font is available in nixpkgs, but it downloads an <code>InterVariable.ttf<\/code> font that rst2pdf didn't know how to change the font weight for, so I made my own derivation of the static Inter font based on the releases from GitHub.<\/p>\n\n<p>I'm happy that I was able to achieve this, as my repository is leaner and I'm continuing to find new and interesting uses for Nix in my workflows.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>I recently started <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/04\/07\/nix-rst2pdf\">using Nix to build my PDF presentation slides<\/a> that <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/building-presenting-slide-decks-rst2pdf\">I create with rst2pdf<\/a>.<\/p>\n\n<p>I removed the custom build script that was generating the PDF files and moved that code into a Nix derivation.<\/p>\n\n<p>Now I can run <code>nix build .#test-driven-drupal<\/code> and it will generate the slides for that talk.<\/p>\n\n<p>As well as the files specific to each presentation, I also have a derivation for shared assets that apply to all talks - i.e. the stylesheets and fonts that are embedded within the PDF.<\/p>\n\n<p>The font files were stored in the repository but I wanted to remove them and use the font files available in nixpkgs.<\/p>\n\n<p>After some small changes, <a href=\"https:\/\/code.oliverdavies.uk\/opdavies\/talks\/commit\/e24d2df83f04e492151b1a1f4901490ce76ffd45\">I was able to do it<\/a> and remove the font files from my repository.<\/p>\n\n<p>The Inter font is available in nixpkgs, but it downloads an <code>InterVariable.ttf<\/code> font that rst2pdf didn't know how to change the font weight for, so I made my own derivation of the static Inter font based on the releases from GitHub.<\/p>\n\n<p>I'm happy that I was able to achieve this, as my repository is leaner and I'm continuing to find new and interesting uses for Nix in my workflows.<\/p>\n\n ",
"processed": "\n <p>I recently started <a href=\"/daily\/2025\/04\/07\/nix-rst2pdf\">using Nix to build my PDF presentation slides<\/a> that <a href=\"/presentations\/building-presenting-slide-decks-rst2pdf\">I create with rst2pdf<\/a>.<\/p>\n\n<p>I removed the custom build script that was generating the PDF files and moved that code into a Nix derivation.<\/p>\n\n<p>Now I can run <code>nix build .#test-driven-drupal<\/code> and it will generate the slides for that talk.<\/p>\n\n<p>As well as the files specific to each presentation, I also have a derivation for shared assets that apply to all talks - i.e. the stylesheets and fonts that are embedded within the PDF.<\/p>\n\n<p>The font files were stored in the repository but I wanted to remove them and use the font files available in nixpkgs.<\/p>\n\n<p>After some small changes, <a href=\"https:\/\/code.oliverdavies.uk\/opdavies\/talks\/commit\/e24d2df83f04e492151b1a1f4901490ce76ffd45\">I was able to do it<\/a> and remove the font files from my repository.<\/p>\n\n<p>The Inter font is available in nixpkgs, but it downloads an <code>InterVariable.ttf<\/code> font that rst2pdf didn't know how to change the font weight for, so I made my own derivation of the static Inter font based on the releases from GitHub.<\/p>\n\n<p>I'm happy that I was able to achieve this, as my repository is leaner and I'm continuing to find new and interesting uses for Nix in my workflows.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>As well as PHP, JavaScript, HTML, CSS, etc, I write a lot of Bash scripts.<\/p>\n\n<p>From <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">project-specific run files<\/a> to CI pipelines, Dockerfiles and deployment scripts, Bash is used a lot in the ops side of software development.<\/p>\n\n<p>Today, though, I wrote <a href=\"https:\/\/github.com\/opdavies\/dotfiles.nix\/blob\/a1ef2d1402c9c607e7a3e4427ce125d0cabeddcd\/lib\/shared\/scripts\/export-video-list.nix#L12-L31\">a small Bash script for my personal laptop<\/a>.<\/p>\n\n<p>I store an archive of video files on an external hard drive of conference talks, courses, tutorials or live streams that I want to keep or rewatch, and found that I've sometimes downloaded the same videos more than once, with the same files on my laptop and hard drive.<\/p>\n\n<p>A few days ago, I was watching a video that I thought I'd save, but wasn't sure if I already had, so this script dumps the contents of my hard drive into a JSON file that I can easily browse or search through to see if I already have a video archived.<\/p>\n\n<p>The script is fairly simple and uses <code>tree<\/code> and <code>jq<\/code> to display and format the data before saving it to a file on my laptop.<\/p>\n\n<p>When I need to update the file, I plug in the hard drive and run it again.<\/p>\n\n<p>A simple problem, and not something related to a particular project, but something I was able to solve with a Bash script.<\/p>\n\n ",
"value": "\n <p>As well as PHP, JavaScript, HTML, CSS, etc, I write a lot of Bash scripts.<\/p>\n\n<p>From <a href=\"/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">project-specific run files<\/a> to CI pipelines, Dockerfiles and deployment scripts, Bash is used a lot in the ops side of software development.<\/p>\n\n<p>Today, though, I wrote <a href=\"https:\/\/github.com\/opdavies\/dotfiles.nix\/blob\/a1ef2d1402c9c607e7a3e4427ce125d0cabeddcd\/lib\/shared\/scripts\/export-video-list.nix#L12-L31\">a small Bash script for my personal laptop<\/a>.<\/p>\n\n<p>I store an archive of video files on an external hard drive of conference talks, courses, tutorials or live streams that I want to keep or rewatch, and found that I've sometimes downloaded the same videos more than once, with the same files on my laptop and hard drive.<\/p>\n\n<p>A few days ago, I was watching a video that I thought I'd save, but wasn't sure if I already had, so this script dumps the contents of my hard drive into a JSON file that I can easily browse or search through to see if I already have a video archived.<\/p>\n\n<p>The script is fairly simple and uses <code>tree<\/code> and <code>jq<\/code> to display and format the data before saving it to a file on my laptop.<\/p>\n\n<p>When I need to update the file, I plug in the hard drive and run it again.<\/p>\n\n<p>A simple problem, and not something related to a particular project, but something I was able to solve with a Bash script.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>As well as PHP, JavaScript, HTML, CSS, etc, I write a lot of Bash scripts.<\/p>\n\n<p>From <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">project-specific run files<\/a> to CI pipelines, Dockerfiles and deployment scripts, Bash is used a lot in the ops side of software development.<\/p>\n\n<p>Today, though, I wrote <a href=\"https:\/\/github.com\/opdavies\/dotfiles.nix\/blob\/a1ef2d1402c9c607e7a3e4427ce125d0cabeddcd\/lib\/shared\/scripts\/export-video-list.nix#L12-L31\">a small Bash script for my personal laptop<\/a>.<\/p>\n\n<p>I store an archive of video files on an external hard drive of conference talks, courses, tutorials or live streams that I want to keep or rewatch, and found that I've sometimes downloaded the same videos more than once, with the same files on my laptop and hard drive.<\/p>\n\n<p>A few days ago, I was watching a video that I thought I'd save, but wasn't sure if I already had, so this script dumps the contents of my hard drive into a JSON file that I can easily browse or search through to see if I already have a video archived.<\/p>\n\n<p>The script is fairly simple and uses <code>tree<\/code> and <code>jq<\/code> to display and format the data before saving it to a file on my laptop.<\/p>\n\n<p>When I need to update the file, I plug in the hard drive and run it again.<\/p>\n\n<p>A simple problem, and not something related to a particular project, but something I was able to solve with a Bash script.<\/p>\n\n ",
"processed": "\n <p>As well as PHP, JavaScript, HTML, CSS, etc, I write a lot of Bash scripts.<\/p>\n\n<p>From <a href=\"/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">project-specific run files<\/a> to CI pipelines, Dockerfiles and deployment scripts, Bash is used a lot in the ops side of software development.<\/p>\n\n<p>Today, though, I wrote <a href=\"https:\/\/github.com\/opdavies\/dotfiles.nix\/blob\/a1ef2d1402c9c607e7a3e4427ce125d0cabeddcd\/lib\/shared\/scripts\/export-video-list.nix#L12-L31\">a small Bash script for my personal laptop<\/a>.<\/p>\n\n<p>I store an archive of video files on an external hard drive of conference talks, courses, tutorials or live streams that I want to keep or rewatch, and found that I've sometimes downloaded the same videos more than once, with the same files on my laptop and hard drive.<\/p>\n\n<p>A few days ago, I was watching a video that I thought I'd save, but wasn't sure if I already had, so this script dumps the contents of my hard drive into a JSON file that I can easily browse or search through to see if I already have a video archived.<\/p>\n\n<p>The script is fairly simple and uses <code>tree<\/code> and <code>jq<\/code> to display and format the data before saving it to a file on my laptop.<\/p>\n\n<p>When I need to update the file, I plug in the hard drive and run it again.<\/p>\n\n<p>A simple problem, and not something related to a particular project, but something I was able to solve with a Bash script.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>This week, I'm speaking at the newly-restarted PHP Berkshire meetup.<\/p>\n\n<p>Organised by Humand Talent, the same people who now organise PHP Oxford (where I spoke in January), this time I'm <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/building-static-websites-sculpin\">speaking about Sculpin<\/a> - the PHP static site generator I use for my website and to publish my <a href=\"https:\/\/zet.oliverdavies.uk\">new Zettlekasten notes<\/a>.<\/p>\n\n<p>I'm looking forward to discussing again why I like static site generators and what benefits they offer.<\/p>\n\n<p>I have some things I want to make sure I mention, so expect a note in my Zettlekasten about that soon, too.<\/p>\n\n<p>If you're interested, <a href=\"https:\/\/phpsw-sculpin-demo.oliverdavies.uk\">here's the demo website<\/a> I did for PHP South West, <a href=\"https:\/\/github.com\/opdavies\/phpsw-sculpin-demo\">along with the code on GitHub<\/a>.<\/p>\n\n ",
"value": "\n <p>This week, I'm speaking at the newly-restarted PHP Berkshire meetup.<\/p>\n\n<p>Organised by Humand Talent, the same people who now organise PHP Oxford (where I spoke in January), this time I'm <a href=\"/presentations\/building-static-websites-sculpin\">speaking about Sculpin<\/a> - the PHP static site generator I use for my website and to publish my <a href=\"https:\/\/zet.oliverdavies.uk\">new Zettlekasten notes<\/a>.<\/p>\n\n<p>I'm looking forward to discussing again why I like static site generators and what benefits they offer.<\/p>\n\n<p>I have some things I want to make sure I mention, so expect a note in my Zettlekasten about that soon, too.<\/p>\n\n<p>If you're interested, <a href=\"https:\/\/phpsw-sculpin-demo.oliverdavies.uk\">here's the demo website<\/a> I did for PHP South West, <a href=\"https:\/\/github.com\/opdavies\/phpsw-sculpin-demo\">along with the code on GitHub<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>This week, I'm speaking at the newly-restarted PHP Berkshire meetup.<\/p>\n\n<p>Organised by Humand Talent, the same people who now organise PHP Oxford (where I spoke in January), this time I'm <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/building-static-websites-sculpin\">speaking about Sculpin<\/a> - the PHP static site generator I use for my website and to publish my <a href=\"https:\/\/zet.oliverdavies.uk\">new Zettlekasten notes<\/a>.<\/p>\n\n<p>I'm looking forward to discussing again why I like static site generators and what benefits they offer.<\/p>\n\n<p>I have some things I want to make sure I mention, so expect a note in my Zettlekasten about that soon, too.<\/p>\n\n<p>If you're interested, <a href=\"https:\/\/phpsw-sculpin-demo.oliverdavies.uk\">here's the demo website<\/a> I did for PHP South West, <a href=\"https:\/\/github.com\/opdavies\/phpsw-sculpin-demo\">along with the code on GitHub<\/a>.<\/p>\n\n ",
"processed": "\n <p>This week, I'm speaking at the newly-restarted PHP Berkshire meetup.<\/p>\n\n<p>Organised by Humand Talent, the same people who now organise PHP Oxford (where I spoke in January), this time I'm <a href=\"/presentations\/building-static-websites-sculpin\">speaking about Sculpin<\/a> - the PHP static site generator I use for my website and to publish my <a href=\"https:\/\/zet.oliverdavies.uk\">new Zettlekasten notes<\/a>.<\/p>\n\n<p>I'm looking forward to discussing again why I like static site generators and what benefits they offer.<\/p>\n\n<p>I have some things I want to make sure I mention, so expect a note in my Zettlekasten about that soon, too.<\/p>\n\n<p>If you're interested, <a href=\"https:\/\/phpsw-sculpin-demo.oliverdavies.uk\">here's the demo website<\/a> I did for PHP South West, <a href=\"https:\/\/github.com\/opdavies\/phpsw-sculpin-demo\">along with the code on GitHub<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Yesterday, I said that <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/07\/08\/back-to-sass-and-traditional-css\">I'm working on a Sass project with no utility or atomic styles<\/a>.<\/p>\n\n<p>But, the two aren't mutually exclusive.<\/p>\n\n<p>You can do both.<\/p>\n\n<p>You can write your own utility classes, like <code>flex<\/code>, <code>font-bold<\/code> or <code>text-red<\/code> in Sass or plain CSS.<\/p>\n\n<p>You can use a framework like Tailwind CSS, but you don't need to.<\/p>\n\n<p>In some projects, with existing stylesheets and usually other frameworks, you can't add anothe full framework without having unintended consequences.<\/p>\n\n<p>Usually, if I want to introduce utility classes to an existing project, I start by writing my own that are inspired by a framework such as Tailwind CSS and maybe refactor to the framework later once the concept has been introduced and the codebase is able to work with it.<\/p>\n\n ",
"value": "\n <p>Yesterday, I said that <a href=\"/daily\/2024\/07\/08\/back-to-sass-and-traditional-css\">I'm working on a Sass project with no utility or atomic styles<\/a>.<\/p>\n\n<p>But, the two aren't mutually exclusive.<\/p>\n\n<p>You can do both.<\/p>\n\n<p>You can write your own utility classes, like <code>flex<\/code>, <code>font-bold<\/code> or <code>text-red<\/code> in Sass or plain CSS.<\/p>\n\n<p>You can use a framework like Tailwind CSS, but you don't need to.<\/p>\n\n<p>In some projects, with existing stylesheets and usually other frameworks, you can't add anothe full framework without having unintended consequences.<\/p>\n\n<p>Usually, if I want to introduce utility classes to an existing project, I start by writing my own that are inspired by a framework such as Tailwind CSS and maybe refactor to the framework later once the concept has been introduced and the codebase is able to work with it.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Yesterday, I said that <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/07\/08\/back-to-sass-and-traditional-css\">I'm working on a Sass project with no utility or atomic styles<\/a>.<\/p>\n\n<p>But, the two aren't mutually exclusive.<\/p>\n\n<p>You can do both.<\/p>\n\n<p>You can write your own utility classes, like <code>flex<\/code>, <code>font-bold<\/code> or <code>text-red<\/code> in Sass or plain CSS.<\/p>\n\n<p>You can use a framework like Tailwind CSS, but you don't need to.<\/p>\n\n<p>In some projects, with existing stylesheets and usually other frameworks, you can't add anothe full framework without having unintended consequences.<\/p>\n\n<p>Usually, if I want to introduce utility classes to an existing project, I start by writing my own that are inspired by a framework such as Tailwind CSS and maybe refactor to the framework later once the concept has been introduced and the codebase is able to work with it.<\/p>\n\n ",
"processed": "\n <p>Yesterday, I said that <a href=\"/daily\/2024\/07\/08\/back-to-sass-and-traditional-css\">I'm working on a Sass project with no utility or atomic styles<\/a>.<\/p>\n\n<p>But, the two aren't mutually exclusive.<\/p>\n\n<p>You can do both.<\/p>\n\n<p>You can write your own utility classes, like <code>flex<\/code>, <code>font-bold<\/code> or <code>text-red<\/code> in Sass or plain CSS.<\/p>\n\n<p>You can use a framework like Tailwind CSS, but you don't need to.<\/p>\n\n<p>In some projects, with existing stylesheets and usually other frameworks, you can't add anothe full framework without having unintended consequences.<\/p>\n\n<p>Usually, if I want to introduce utility classes to an existing project, I start by writing my own that are inspired by a framework such as Tailwind CSS and maybe refactor to the framework later once the concept has been introduced and the codebase is able to work with it.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/04\/10\/resurrecting-the-speakerdeck-field-module\">In Wednesday's email<\/a>, I said I was resurrecting the Speakerdeck Field module, and the same version works on Drupal 8, 9, 10 and 11.<\/p>\n\n<p>How do I know this?<\/p>\n\n<p>One of my favourite PHP libraries is Rector - a tool for upgrading code to the newest versions of PHP or, in this case, Drupal using Drupal Rector.<\/p>\n\n<p>It runs automatically on modules, including Speakerdeck Field, via the Project Upgrade Bot and generates a set of updates to apply.<\/p>\n\n<p>CI pipelines with GitLab CI and a reliable test suite make it much easier to upgrade modules to the latest Drupal version and ensure they still work.<\/p>\n\n ",
"value": "\n <p><a href=\"/daily\/2024\/04\/10\/resurrecting-the-speakerdeck-field-module\">In Wednesday's email<\/a>, I said I was resurrecting the Speakerdeck Field module, and the same version works on Drupal 8, 9, 10 and 11.<\/p>\n\n<p>How do I know this?<\/p>\n\n<p>One of my favourite PHP libraries is Rector - a tool for upgrading code to the newest versions of PHP or, in this case, Drupal using Drupal Rector.<\/p>\n\n<p>It runs automatically on modules, including Speakerdeck Field, via the Project Upgrade Bot and generates a set of updates to apply.<\/p>\n\n<p>CI pipelines with GitLab CI and a reliable test suite make it much easier to upgrade modules to the latest Drupal version and ensure they still work.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/04\/10\/resurrecting-the-speakerdeck-field-module\">In Wednesday's email<\/a>, I said I was resurrecting the Speakerdeck Field module, and the same version works on Drupal 8, 9, 10 and 11.<\/p>\n\n<p>How do I know this?<\/p>\n\n<p>One of my favourite PHP libraries is Rector - a tool for upgrading code to the newest versions of PHP or, in this case, Drupal using Drupal Rector.<\/p>\n\n<p>It runs automatically on modules, including Speakerdeck Field, via the Project Upgrade Bot and generates a set of updates to apply.<\/p>\n\n<p>CI pipelines with GitLab CI and a reliable test suite make it much easier to upgrade modules to the latest Drupal version and ensure they still work.<\/p>\n\n ",
"processed": "\n <p><a href=\"/daily\/2024\/04\/10\/resurrecting-the-speakerdeck-field-module\">In Wednesday's email<\/a>, I said I was resurrecting the Speakerdeck Field module, and the same version works on Drupal 8, 9, 10 and 11.<\/p>\n\n<p>How do I know this?<\/p>\n\n<p>One of my favourite PHP libraries is Rector - a tool for upgrading code to the newest versions of PHP or, in this case, Drupal using Drupal Rector.<\/p>\n\n<p>It runs automatically on modules, including Speakerdeck Field, via the Project Upgrade Bot and generates a set of updates to apply.<\/p>\n\n<p>CI pipelines with GitLab CI and a reliable test suite make it much easier to upgrade modules to the latest Drupal version and ensure they still work.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>On the 24th of April, I'll be attending a LocalGov Drupal Camp in Birmingham, UK.<\/p>\n\n<p>As someone keen to get more involved and contribute more to the project, and who's <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/03\/25\/newport-city-council-running-localgov-drupal\">local council recently switched to LocalGov<\/a>, I'm looking forward to the chance to learn and contribute on the day and afterwards.<\/p>\n\n<p>If you want to attend also, there are a few remaining tickets available and you can <a href=\"https:\/\/www.eventbrite.co.uk\/e\/localgov-drupal-camp-2024-tickets-847025314517\">register on Eventbrite<\/a>.<\/p>\n\n ",
"value": "\n <p>On the 24th of April, I'll be attending a LocalGov Drupal Camp in Birmingham, UK.<\/p>\n\n<p>As someone keen to get more involved and contribute more to the project, and who's <a href=\"/daily\/2024\/03\/25\/newport-city-council-running-localgov-drupal\">local council recently switched to LocalGov<\/a>, I'm looking forward to the chance to learn and contribute on the day and afterwards.<\/p>\n\n<p>If you want to attend also, there are a few remaining tickets available and you can <a href=\"https:\/\/www.eventbrite.co.uk\/e\/localgov-drupal-camp-2024-tickets-847025314517\">register on Eventbrite<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>On the 24th of April, I'll be attending a LocalGov Drupal Camp in Birmingham, UK.<\/p>\n\n<p>As someone keen to get more involved and contribute more to the project, and who's <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/03\/25\/newport-city-council-running-localgov-drupal\">local council recently switched to LocalGov<\/a>, I'm looking forward to the chance to learn and contribute on the day and afterwards.<\/p>\n\n<p>If you want to attend also, there are a few remaining tickets available and you can <a href=\"https:\/\/www.eventbrite.co.uk\/e\/localgov-drupal-camp-2024-tickets-847025314517\">register on Eventbrite<\/a>.<\/p>\n\n ",
"processed": "\n <p>On the 24th of April, I'll be attending a LocalGov Drupal Camp in Birmingham, UK.<\/p>\n\n<p>As someone keen to get more involved and contribute more to the project, and who's <a href=\"/daily\/2024\/03\/25\/newport-city-council-running-localgov-drupal\">local council recently switched to LocalGov<\/a>, I'm looking forward to the chance to learn and contribute on the day and afterwards.<\/p>\n\n<p>If you want to attend also, there are a few remaining tickets available and you can <a href=\"https:\/\/www.eventbrite.co.uk\/e\/localgov-drupal-camp-2024-tickets-847025314517\">register on Eventbrite<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>In <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/09\/14\/simpletest-drupal-test\">Wednesday's email<\/a>, I showed how quick it is to get started writing automated tests for a new Drupal module, starting with a functional test.<\/p>\n\n<p>I prefer the outside-in style (or London approach) of test-driven development, where I start with a the highest-level test that I can for a task. If the task needs me to make a HTTP request, then I\u2019ll use a functional test. If not, I\u2019ll use a kernel (or integration) test.<\/p>\n\n<p>I find that these higher-level types of tests are easier and quicker to set up compared to starting with lower-level unit tests, cover more functionality, and make it easier to refactor.<\/p>\n\n<h2 id=\"an-example\">An example<\/h2>\n\n<p>For example, this <code>Device<\/code> class which is a data transfer object around Drupal's <code>NodeInterface<\/code>. It ensures that the correct type of node is provided, and includes a named constructor and a helper method to retrieve a device's asset ID from a field:<\/p>\n\n<pre><code class=\"language-php\">final class Device {\n\n private NodeInterface $node;\n\n public function __construct(NodeInterface $node) {\n if ($node-&gt;bundle() != 'device') {\n throw new \\InvalidArgumentException();\n }\n\n $this-&gt;node = $node;\n }\n\n public function getAssetId(): string {\n return $this-&gt;node-&gt;get('field_asset_id')-&gt;getString();\n }\n\n public static function fromNode(NodeInterface $node): self {\n return new self($node);\n }\n\n}\n<\/code><\/pre>\n\n<h2 id=\"testing-getting-the-asset-id-using-a-unit-test\">Testing getting the asset ID using a unit test<\/h2>\n\n<p>As the <code>Node::create()<\/code> method (what I'd normally use to create a node) interacts with the database, I need to create a mock node to wrap with my DTO.<\/p>\n\n<p>I need to specify what value is returned from the <code>bundle()<\/code> method as well as getting the asset ID field value.<\/p>\n\n<p>I need to mock the <code>get()<\/code> method and specify the field name that I'm getting the value for, which also returns it's own mock for <code>FieldItemListInterface<\/code> with a value set for the <code>getString()<\/code> method.<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\npublic function should_return_an_asset_id(): void {\n \/\/ Arrange.\n $fieldItemList = $this-&gt;createMock(FieldItemListInterface::class);\n\n $fieldItemList\n -&gt;method('getString')\n -&gt;willReturn('ABC');\n\n $deviceNode = $this-&gt;createMock(NodeInterface::class);\n\n $deviceNode\n -&gt;method('bundle')\n -&gt;willReturn('device');\n\n $deviceNode\n -&gt;method('get')\n -&gt;with('field_asset_id')\n -&gt;willReturn($fieldItemList);\n\n \/\/ Act.\n $device = Device::fromNode($deviceNode);\n\n \/\/ Assert.\n self::assertSame('ABC', $device-&gt;getAssetId());\n}\n<\/code><\/pre>\n\n<p>This is quite a long 'arrange' section for this test, and just be confusing for those new to automated testing.<\/p>\n\n<p>If I was to refactor from using the <code>get()<\/code> and <code>getString()<\/code> methods to a different implementation, it's likely that the test would fail.<\/p>\n\n<h2 id=\"refactoring-to-a-kernel-test\">Refactoring to a kernel test<\/h2>\n\n<p>This is how I could write the same test using a kernel (integration) test:<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\npublic function should_return_an_asset_id(): void {\n \/\/ Arrange.\n $node = Node::create([\n 'field_asset_id' =&gt; 'ABC',\n 'type' =&gt; 'device'\n ]);\n\n \/\/ Assert.\n self::assertSame('ABC', Device::fromNode($node)-&gt;getAssetId());\n}\n<\/code><\/pre>\n\n<p>I can create a real <code>Node<\/code> object, pass that to the <code>Device<\/code> DTO, and call the <code>getAssetId()<\/code> method.<\/p>\n\n<p>As I can interact with the database, there's no need to create mocks or define return values.<\/p>\n\n<p>The 'arrange' step is much smaller, and I think that this is easier to read and understand.<\/p>\n\n<h3 id=\"trade-offs\">Trade-offs<\/h3>\n\n<p>Even though the test is cleaner, because there are no mocks there's other setup to do, including having the required configuration available, enabling modules, and installing schemas and configuration as part of the test - and having test-specific modules to store the needed configuration files.<\/p>\n\n<p>Because of this, functional and kernel tests will take more time to run than unit tests, but an outside-in approach could be worth considering, depending on your project and team.<\/p>\n\n ",
"value": "\n <p>In <a href=\"/daily\/2022\/09\/14\/simpletest-drupal-test\">Wednesday's email<\/a>, I showed how quick it is to get started writing automated tests for a new Drupal module, starting with a functional test.<\/p>\n\n<p>I prefer the outside-in style (or London approach) of test-driven development, where I start with a the highest-level test that I can for a task. If the task needs me to make a HTTP request, then I\u2019ll use a functional test. If not, I\u2019ll use a kernel (or integration) test.<\/p>\n\n<p>I find that these higher-level types of tests are easier and quicker to set up compared to starting with lower-level unit tests, cover more functionality, and make it easier to refactor.<\/p>\n\n<h2 id=\"an-example\">An example<\/h2>\n\n<p>For example, this <code>Device<\/code> class which is a data transfer object around Drupal's <code>NodeInterface<\/code>. It ensures that the correct type of node is provided, and includes a named constructor and a helper method to retrieve a device's asset ID from a field:<\/p>\n\n<pre><code class=\"language-php\">final class Device {\n\n private NodeInterface $node;\n\n public function __construct(NodeInterface $node) {\n if ($node-&gt;bundle() != 'device') {\n throw new \\InvalidArgumentException();\n }\n\n $this-&gt;node = $node;\n }\n\n public function getAssetId(): string {\n return $this-&gt;node-&gt;get('field_asset_id')-&gt;getString();\n }\n\n public static function fromNode(NodeInterface $node): self {\n return new self($node);\n }\n\n}\n<\/code><\/pre>\n\n<h2 id=\"testing-getting-the-asset-id-using-a-unit-test\">Testing getting the asset ID using a unit test<\/h2>\n\n<p>As the <code>Node::create()<\/code> method (what I'd normally use to create a node) interacts with the database, I need to create a mock node to wrap with my DTO.<\/p>\n\n<p>I need to specify what value is returned from the <code>bundle()<\/code> method as well as getting the asset ID field value.<\/p>\n\n<p>I need to mock the <code>get()<\/code> method and specify the field name that I'm getting the value for, which also returns it's own mock for <code>FieldItemListInterface<\/code> with a value set for the <code>getString()<\/code> method.<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\npublic function should_return_an_asset_id(): void {\n \/\/ Arrange.\n $fieldItemList = $this-&gt;createMock(FieldItemListInterface::class);\n\n $fieldItemList\n -&gt;method('getString')\n -&gt;willReturn('ABC');\n\n $deviceNode = $this-&gt;createMock(NodeInterface::class);\n\n $deviceNode\n -&gt;method('bundle')\n -&gt;willReturn('device');\n\n $deviceNode\n -&gt;method('get')\n -&gt;with('field_asset_id')\n -&gt;willReturn($fieldItemList);\n\n \/\/ Act.\n $device = Device::fromNode($deviceNode);\n\n \/\/ Assert.\n self::assertSame('ABC', $device-&gt;getAssetId());\n}\n<\/code><\/pre>\n\n<p>This is quite a long 'arrange' section for this test, and just be confusing for those new to automated testing.<\/p>\n\n<p>If I was to refactor from using the <code>get()<\/code> and <code>getString()<\/code> methods to a different implementation, it's likely that the test would fail.<\/p>\n\n<h2 id=\"refactoring-to-a-kernel-test\">Refactoring to a kernel test<\/h2>\n\n<p>This is how I could write the same test using a kernel (integration) test:<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\npublic function should_return_an_asset_id(): void {\n \/\/ Arrange.\n $node = Node::create([\n 'field_asset_id' =&gt; 'ABC',\n 'type' =&gt; 'device'\n ]);\n\n \/\/ Assert.\n self::assertSame('ABC', Device::fromNode($node)-&gt;getAssetId());\n}\n<\/code><\/pre>\n\n<p>I can create a real <code>Node<\/code> object, pass that to the <code>Device<\/code> DTO, and call the <code>getAssetId()<\/code> method.<\/p>\n\n<p>As I can interact with the database, there's no need to create mocks or define return values.<\/p>\n\n<p>The 'arrange' step is much smaller, and I think that this is easier to read and understand.<\/p>\n\n<h3 id=\"trade-offs\">Trade-offs<\/h3>\n\n<p>Even though the test is cleaner, because there are no mocks there's other setup to do, including having the required configuration available, enabling modules, and installing schemas and configuration as part of the test - and having test-specific modules to store the needed configuration files.<\/p>\n\n<p>Because of this, functional and kernel tests will take more time to run than unit tests, but an outside-in approach could be worth considering, depending on your project and team.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>In <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/09\/14\/simpletest-drupal-test\">Wednesday's email<\/a>, I showed how quick it is to get started writing automated tests for a new Drupal module, starting with a functional test.<\/p>\n\n<p>I prefer the outside-in style (or London approach) of test-driven development, where I start with a the highest-level test that I can for a task. If the task needs me to make a HTTP request, then I\u2019ll use a functional test. If not, I\u2019ll use a kernel (or integration) test.<\/p>\n\n<p>I find that these higher-level types of tests are easier and quicker to set up compared to starting with lower-level unit tests, cover more functionality, and make it easier to refactor.<\/p>\n\n<h2 id=\"an-example\">An example<\/h2>\n\n<p>For example, this <code>Device<\/code> class which is a data transfer object around Drupal's <code>NodeInterface<\/code>. It ensures that the correct type of node is provided, and includes a named constructor and a helper method to retrieve a device's asset ID from a field:<\/p>\n\n<pre><code class=\"language-php\">final class Device {\n\n private NodeInterface $node;\n\n public function __construct(NodeInterface $node) {\n if ($node-&gt;bundle() != 'device') {\n throw new \\InvalidArgumentException();\n }\n\n $this-&gt;node = $node;\n }\n\n public function getAssetId(): string {\n return $this-&gt;node-&gt;get('field_asset_id')-&gt;getString();\n }\n\n public static function fromNode(NodeInterface $node): self {\n return new self($node);\n }\n\n}\n<\/code><\/pre>\n\n<h2 id=\"testing-getting-the-asset-id-using-a-unit-test\">Testing getting the asset ID using a unit test<\/h2>\n\n<p>As the <code>Node::create()<\/code> method (what I'd normally use to create a node) interacts with the database, I need to create a mock node to wrap with my DTO.<\/p>\n\n<p>I need to specify what value is returned from the <code>bundle()<\/code> method as well as getting the asset ID field value.<\/p>\n\n<p>I need to mock the <code>get()<\/code> method and specify the field name that I'm getting the value for, which also returns it's own mock for <code>FieldItemListInterface<\/code> with a value set for the <code>getString()<\/code> method.<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\npublic function should_return_an_asset_id(): void {\n \/\/ Arrange.\n $fieldItemList = $this-&gt;createMock(FieldItemListInterface::class);\n\n $fieldItemList\n -&gt;method('getString')\n -&gt;willReturn('ABC');\n\n $deviceNode = $this-&gt;createMock(NodeInterface::class);\n\n $deviceNode\n -&gt;method('bundle')\n -&gt;willReturn('device');\n\n $deviceNode\n -&gt;method('get')\n -&gt;with('field_asset_id')\n -&gt;willReturn($fieldItemList);\n\n \/\/ Act.\n $device = Device::fromNode($deviceNode);\n\n \/\/ Assert.\n self::assertSame('ABC', $device-&gt;getAssetId());\n}\n<\/code><\/pre>\n\n<p>This is quite a long 'arrange' section for this test, and just be confusing for those new to automated testing.<\/p>\n\n<p>If I was to refactor from using the <code>get()<\/code> and <code>getString()<\/code> methods to a different implementation, it's likely that the test would fail.<\/p>\n\n<h2 id=\"refactoring-to-a-kernel-test\">Refactoring to a kernel test<\/h2>\n\n<p>This is how I could write the same test using a kernel (integration) test:<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\npublic function should_return_an_asset_id(): void {\n \/\/ Arrange.\n $node = Node::create([\n 'field_asset_id' =&gt; 'ABC',\n 'type' =&gt; 'device'\n ]);\n\n \/\/ Assert.\n self::assertSame('ABC', Device::fromNode($node)-&gt;getAssetId());\n}\n<\/code><\/pre>\n\n<p>I can create a real <code>Node<\/code> object, pass that to the <code>Device<\/code> DTO, and call the <code>getAssetId()<\/code> method.<\/p>\n\n<p>As I can interact with the database, there's no need to create mocks or define return values.<\/p>\n\n<p>The 'arrange' step is much smaller, and I think that this is easier to read and understand.<\/p>\n\n<h3 id=\"trade-offs\">Trade-offs<\/h3>\n\n<p>Even though the test is cleaner, because there are no mocks there's other setup to do, including having the required configuration available, enabling modules, and installing schemas and configuration as part of the test - and having test-specific modules to store the needed configuration files.<\/p>\n\n<p>Because of this, functional and kernel tests will take more time to run than unit tests, but an outside-in approach could be worth considering, depending on your project and team.<\/p>\n\n ",
"processed": "\n <p>In <a href=\"/daily\/2022\/09\/14\/simpletest-drupal-test\">Wednesday's email<\/a>, I showed how quick it is to get started writing automated tests for a new Drupal module, starting with a functional test.<\/p>\n\n<p>I prefer the outside-in style (or London approach) of test-driven development, where I start with a the highest-level test that I can for a task. If the task needs me to make a HTTP request, then I\u2019ll use a functional test. If not, I\u2019ll use a kernel (or integration) test.<\/p>\n\n<p>I find that these higher-level types of tests are easier and quicker to set up compared to starting with lower-level unit tests, cover more functionality, and make it easier to refactor.<\/p>\n\n<h2 id=\"an-example\">An example<\/h2>\n\n<p>For example, this <code>Device<\/code> class which is a data transfer object around Drupal's <code>NodeInterface<\/code>. It ensures that the correct type of node is provided, and includes a named constructor and a helper method to retrieve a device's asset ID from a field:<\/p>\n\n<pre><code class=\"language-php\">final class Device {\n\n private NodeInterface $node;\n\n public function __construct(NodeInterface $node) {\n if ($node-&gt;bundle() != 'device') {\n throw new \\InvalidArgumentException();\n }\n\n $this-&gt;node = $node;\n }\n\n public function getAssetId(): string {\n return $this-&gt;node-&gt;get('field_asset_id')-&gt;getString();\n }\n\n public static function fromNode(NodeInterface $node): self {\n return new self($node);\n }\n\n}\n<\/code><\/pre>\n\n<h2 id=\"testing-getting-the-asset-id-using-a-unit-test\">Testing getting the asset ID using a unit test<\/h2>\n\n<p>As the <code>Node::create()<\/code> method (what I'd normally use to create a node) interacts with the database, I need to create a mock node to wrap with my DTO.<\/p>\n\n<p>I need to specify what value is returned from the <code>bundle()<\/code> method as well as getting the asset ID field value.<\/p>\n\n<p>I need to mock the <code>get()<\/code> method and specify the field name that I'm getting the value for, which also returns it's own mock for <code>FieldItemListInterface<\/code> with a value set for the <code>getString()<\/code> method.<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\npublic function should_return_an_asset_id(): void {\n \/\/ Arrange.\n $fieldItemList = $this-&gt;createMock(FieldItemListInterface::class);\n\n $fieldItemList\n -&gt;method('getString')\n -&gt;willReturn('ABC');\n\n $deviceNode = $this-&gt;createMock(NodeInterface::class);\n\n $deviceNode\n -&gt;method('bundle')\n -&gt;willReturn('device');\n\n $deviceNode\n -&gt;method('get')\n -&gt;with('field_asset_id')\n -&gt;willReturn($fieldItemList);\n\n \/\/ Act.\n $device = Device::fromNode($deviceNode);\n\n \/\/ Assert.\n self::assertSame('ABC', $device-&gt;getAssetId());\n}\n<\/code><\/pre>\n\n<p>This is quite a long 'arrange' section for this test, and just be confusing for those new to automated testing.<\/p>\n\n<p>If I was to refactor from using the <code>get()<\/code> and <code>getString()<\/code> methods to a different implementation, it's likely that the test would fail.<\/p>\n\n<h2 id=\"refactoring-to-a-kernel-test\">Refactoring to a kernel test<\/h2>\n\n<p>This is how I could write the same test using a kernel (integration) test:<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\npublic function should_return_an_asset_id(): void {\n \/\/ Arrange.\n $node = Node::create([\n 'field_asset_id' =&gt; 'ABC',\n 'type' =&gt; 'device'\n ]);\n\n \/\/ Assert.\n self::assertSame('ABC', Device::fromNode($node)-&gt;getAssetId());\n}\n<\/code><\/pre>\n\n<p>I can create a real <code>Node<\/code> object, pass that to the <code>Device<\/code> DTO, and call the <code>getAssetId()<\/code> method.<\/p>\n\n<p>As I can interact with the database, there's no need to create mocks or define return values.<\/p>\n\n<p>The 'arrange' step is much smaller, and I think that this is easier to read and understand.<\/p>\n\n<h3 id=\"trade-offs\">Trade-offs<\/h3>\n\n<p>Even though the test is cleaner, because there are no mocks there's other setup to do, including having the required configuration available, enabling modules, and installing schemas and configuration as part of the test - and having test-specific modules to store the needed configuration files.<\/p>\n\n<p>Because of this, functional and kernel tests will take more time to run than unit tests, but an outside-in approach could be worth considering, depending on your project and team.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>An interesting exercise is to run a tool like <a href=\"https:\/\/github.com\/AlDanial\/cloc\">cloc<\/a> to count the number of lines in your application.<\/p>\n\n<p>It counts the number of files and lines within them, as well as how many lines are blank, comments or code.<\/p>\n\n<p>It's a metric that I like to check occasionally as I like to keep codebases lean and with the minimum amount of code.<\/p>\n\n<p>I don't like to have features that aren't used or <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/16\/pre-optimise\">pre-optimised code<\/a> for use cases that may not happen.<\/p>\n\n<p>The more code there is in your application, the problems you could encounter.<\/p>\n\n<p>There are more places for bugs and issues to hide.<\/p>\n\n<p>Keeping the amount of code to a minimum makes it quicker and easier to write, review and release as well as fix any bugs that are found in the future.<\/p>\n\n ",
"value": "\n <p>An interesting exercise is to run a tool like <a href=\"https:\/\/github.com\/AlDanial\/cloc\">cloc<\/a> to count the number of lines in your application.<\/p>\n\n<p>It counts the number of files and lines within them, as well as how many lines are blank, comments or code.<\/p>\n\n<p>It's a metric that I like to check occasionally as I like to keep codebases lean and with the minimum amount of code.<\/p>\n\n<p>I don't like to have features that aren't used or <a href=\"/daily\/2025\/02\/16\/pre-optimise\">pre-optimised code<\/a> for use cases that may not happen.<\/p>\n\n<p>The more code there is in your application, the problems you could encounter.<\/p>\n\n<p>There are more places for bugs and issues to hide.<\/p>\n\n<p>Keeping the amount of code to a minimum makes it quicker and easier to write, review and release as well as fix any bugs that are found in the future.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>An interesting exercise is to run a tool like <a href=\"https:\/\/github.com\/AlDanial\/cloc\">cloc<\/a> to count the number of lines in your application.<\/p>\n\n<p>It counts the number of files and lines within them, as well as how many lines are blank, comments or code.<\/p>\n\n<p>It's a metric that I like to check occasionally as I like to keep codebases lean and with the minimum amount of code.<\/p>\n\n<p>I don't like to have features that aren't used or <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/16\/pre-optimise\">pre-optimised code<\/a> for use cases that may not happen.<\/p>\n\n<p>The more code there is in your application, the problems you could encounter.<\/p>\n\n<p>There are more places for bugs and issues to hide.<\/p>\n\n<p>Keeping the amount of code to a minimum makes it quicker and easier to write, review and release as well as fix any bugs that are found in the future.<\/p>\n\n ",
"processed": "\n <p>An interesting exercise is to run a tool like <a href=\"https:\/\/github.com\/AlDanial\/cloc\">cloc<\/a> to count the number of lines in your application.<\/p>\n\n<p>It counts the number of files and lines within them, as well as how many lines are blank, comments or code.<\/p>\n\n<p>It's a metric that I like to check occasionally as I like to keep codebases lean and with the minimum amount of code.<\/p>\n\n<p>I don't like to have features that aren't used or <a href=\"/daily\/2025\/02\/16\/pre-optimise\">pre-optimised code<\/a> for use cases that may not happen.<\/p>\n\n<p>The more code there is in your application, the problems you could encounter.<\/p>\n\n<p>There are more places for bugs and issues to hide.<\/p>\n\n<p>Keeping the amount of code to a minimum makes it quicker and easier to write, review and release as well as fix any bugs that are found in the future.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Yesterday's email talked about <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/10\/28\/why-write-framework-agnostic-packages\">writing reusable, framework-agnostic packages<\/a> but didn't mention where those packages could be located.<\/p>\n\n<p>They could be kept within a private repository and still have the same benefits, such as re-usability for internal projects, but I like to open-source code as often as I can and make it available publicly to see and use.<\/p>\n\n<p>My preference is to follow an open-source-first workflow, identify which parts of a solution can be open-sourced and create them as open-source libraries or modules from the beginning rather than planning to extract them later. They can then be included within the main project using a dependency manager tool like Composer, npm or Yarn.<\/p>\n\n<p>The eBook integration project that I mentioned was an example of this. I identified which pieces could be open-sourced, set up a public repository and put together an MVP based on that project's requirements. Issues were created for nice-to-have additions that could be added later, and the working version was installed with Composer.<\/p>\n\n<p>There was no need to extract the code from the main project, no need to \"clean it up\" or check that it contained no client information, and I had the full Git history for the project - not just a new history from the point when the code was extracted and open-sourced.<\/p>\n\n<p>I've worked on projects that contained a number of potential open-source components that would be released after project completion, but this didn't always happen - I assume due to time pressures to move on to the next project, a focus on adding new features or avoiding the risk of introducing breakages into the code. If the code had been open-sourced from the beginning, these things wouldn't have been an issue.<\/p>\n\n<p>I've also worked on projects where I've followed an open-source-first approach and released a number of PHP libraries and Drupal modules, including <a href=\"https:\/\/www.drupal.org\/project\/private_message_queue\">Private Message Queue<\/a>, <a href=\"https:\/\/www.drupal.org\/project\/system_user\">System User<\/a>, and <a href=\"https:\/\/www.drupal.org\/project\/null_user\">Null User<\/a> modules. I've also been working on some legacy code recently and started to replace it with a library that I've already open-sourced, even though I'm in the early stages of developing it.<\/p>\n\n<p>As someone who enjoys creating and working on open-source software, I would encourage you to open-source your code if you can and to do so sooner rather than later and not wait until the end of your project.<\/p>\n\n ",
"value": "\n <p>Yesterday's email talked about <a href=\"/daily\/2022\/10\/28\/why-write-framework-agnostic-packages\">writing reusable, framework-agnostic packages<\/a> but didn't mention where those packages could be located.<\/p>\n\n<p>They could be kept within a private repository and still have the same benefits, such as re-usability for internal projects, but I like to open-source code as often as I can and make it available publicly to see and use.<\/p>\n\n<p>My preference is to follow an open-source-first workflow, identify which parts of a solution can be open-sourced and create them as open-source libraries or modules from the beginning rather than planning to extract them later. They can then be included within the main project using a dependency manager tool like Composer, npm or Yarn.<\/p>\n\n<p>The eBook integration project that I mentioned was an example of this. I identified which pieces could be open-sourced, set up a public repository and put together an MVP based on that project's requirements. Issues were created for nice-to-have additions that could be added later, and the working version was installed with Composer.<\/p>\n\n<p>There was no need to extract the code from the main project, no need to \"clean it up\" or check that it contained no client information, and I had the full Git history for the project - not just a new history from the point when the code was extracted and open-sourced.<\/p>\n\n<p>I've worked on projects that contained a number of potential open-source components that would be released after project completion, but this didn't always happen - I assume due to time pressures to move on to the next project, a focus on adding new features or avoiding the risk of introducing breakages into the code. If the code had been open-sourced from the beginning, these things wouldn't have been an issue.<\/p>\n\n<p>I've also worked on projects where I've followed an open-source-first approach and released a number of PHP libraries and Drupal modules, including <a href=\"https:\/\/www.drupal.org\/project\/private_message_queue\">Private Message Queue<\/a>, <a href=\"https:\/\/www.drupal.org\/project\/system_user\">System User<\/a>, and <a href=\"https:\/\/www.drupal.org\/project\/null_user\">Null User<\/a> modules. I've also been working on some legacy code recently and started to replace it with a library that I've already open-sourced, even though I'm in the early stages of developing it.<\/p>\n\n<p>As someone who enjoys creating and working on open-source software, I would encourage you to open-source your code if you can and to do so sooner rather than later and not wait until the end of your project.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Yesterday's email talked about <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/10\/28\/why-write-framework-agnostic-packages\">writing reusable, framework-agnostic packages<\/a> but didn't mention where those packages could be located.<\/p>\n\n<p>They could be kept within a private repository and still have the same benefits, such as re-usability for internal projects, but I like to open-source code as often as I can and make it available publicly to see and use.<\/p>\n\n<p>My preference is to follow an open-source-first workflow, identify which parts of a solution can be open-sourced and create them as open-source libraries or modules from the beginning rather than planning to extract them later. They can then be included within the main project using a dependency manager tool like Composer, npm or Yarn.<\/p>\n\n<p>The eBook integration project that I mentioned was an example of this. I identified which pieces could be open-sourced, set up a public repository and put together an MVP based on that project's requirements. Issues were created for nice-to-have additions that could be added later, and the working version was installed with Composer.<\/p>\n\n<p>There was no need to extract the code from the main project, no need to \"clean it up\" or check that it contained no client information, and I had the full Git history for the project - not just a new history from the point when the code was extracted and open-sourced.<\/p>\n\n<p>I've worked on projects that contained a number of potential open-source components that would be released after project completion, but this didn't always happen - I assume due to time pressures to move on to the next project, a focus on adding new features or avoiding the risk of introducing breakages into the code. If the code had been open-sourced from the beginning, these things wouldn't have been an issue.<\/p>\n\n<p>I've also worked on projects where I've followed an open-source-first approach and released a number of PHP libraries and Drupal modules, including <a href=\"https:\/\/www.drupal.org\/project\/private_message_queue\">Private Message Queue<\/a>, <a href=\"https:\/\/www.drupal.org\/project\/system_user\">System User<\/a>, and <a href=\"https:\/\/www.drupal.org\/project\/null_user\">Null User<\/a> modules. I've also been working on some legacy code recently and started to replace it with a library that I've already open-sourced, even though I'm in the early stages of developing it.<\/p>\n\n<p>As someone who enjoys creating and working on open-source software, I would encourage you to open-source your code if you can and to do so sooner rather than later and not wait until the end of your project.<\/p>\n\n ",
"processed": "\n <p>Yesterday's email talked about <a href=\"/daily\/2022\/10\/28\/why-write-framework-agnostic-packages\">writing reusable, framework-agnostic packages<\/a> but didn't mention where those packages could be located.<\/p>\n\n<p>They could be kept within a private repository and still have the same benefits, such as re-usability for internal projects, but I like to open-source code as often as I can and make it available publicly to see and use.<\/p>\n\n<p>My preference is to follow an open-source-first workflow, identify which parts of a solution can be open-sourced and create them as open-source libraries or modules from the beginning rather than planning to extract them later. They can then be included within the main project using a dependency manager tool like Composer, npm or Yarn.<\/p>\n\n<p>The eBook integration project that I mentioned was an example of this. I identified which pieces could be open-sourced, set up a public repository and put together an MVP based on that project's requirements. Issues were created for nice-to-have additions that could be added later, and the working version was installed with Composer.<\/p>\n\n<p>There was no need to extract the code from the main project, no need to \"clean it up\" or check that it contained no client information, and I had the full Git history for the project - not just a new history from the point when the code was extracted and open-sourced.<\/p>\n\n<p>I've worked on projects that contained a number of potential open-source components that would be released after project completion, but this didn't always happen - I assume due to time pressures to move on to the next project, a focus on adding new features or avoiding the risk of introducing breakages into the code. If the code had been open-sourced from the beginning, these things wouldn't have been an issue.<\/p>\n\n<p>I've also worked on projects where I've followed an open-source-first approach and released a number of PHP libraries and Drupal modules, including <a href=\"https:\/\/www.drupal.org\/project\/private_message_queue\">Private Message Queue<\/a>, <a href=\"https:\/\/www.drupal.org\/project\/system_user\">System User<\/a>, and <a href=\"https:\/\/www.drupal.org\/project\/null_user\">Null User<\/a> modules. I've also been working on some legacy code recently and started to replace it with a library that I've already open-sourced, even though I'm in the early stages of developing it.<\/p>\n\n<p>As someone who enjoys creating and working on open-source software, I would encourage you to open-source your code if you can and to do so sooner rather than later and not wait until the end of your project.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Another reason I like static websites is that they're easy and quick to deploy.<\/p>\n\n<p>Whether you use write each HTML file by hand or <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/03\/12\/easy\">use a static site generator<\/a>, a simple Web server like Caddy, Nginx or Apache can load and serve your website for everyone to see.<\/p>\n\n<p>My Sculpin website generates an output_prod directory after I run <code>sculpin generate<\/code> with my deployable files.<\/p>\n\n<p>I manage my own server with NixOS that hosts a number of static websites, such as examples from talks and blog posts.<\/p>\n\n<p>To upload my files onto the server, I just use rsync - a small command line tool to synchronise files between computers.<\/p>\n\n<p>It's a single command to upload the contents of my output_prod directory to the directory on my server.<\/p>\n\n<p>No complex CI pipelines or database migrations.<\/p>\n\n<p>It's fast, simple and minimal.<\/p>\n\n<p>If you prefer to use a service like Netlify or Vercel, they work great for static websites too.<\/p>\n\n ",
"value": "\n <p>Another reason I like static websites is that they're easy and quick to deploy.<\/p>\n\n<p>Whether you use write each HTML file by hand or <a href=\"/daily\/2025\/03\/12\/easy\">use a static site generator<\/a>, a simple Web server like Caddy, Nginx or Apache can load and serve your website for everyone to see.<\/p>\n\n<p>My Sculpin website generates an output_prod directory after I run <code>sculpin generate<\/code> with my deployable files.<\/p>\n\n<p>I manage my own server with NixOS that hosts a number of static websites, such as examples from talks and blog posts.<\/p>\n\n<p>To upload my files onto the server, I just use rsync - a small command line tool to synchronise files between computers.<\/p>\n\n<p>It's a single command to upload the contents of my output_prod directory to the directory on my server.<\/p>\n\n<p>No complex CI pipelines or database migrations.<\/p>\n\n<p>It's fast, simple and minimal.<\/p>\n\n<p>If you prefer to use a service like Netlify or Vercel, they work great for static websites too.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Another reason I like static websites is that they're easy and quick to deploy.<\/p>\n\n<p>Whether you use write each HTML file by hand or <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/03\/12\/easy\">use a static site generator<\/a>, a simple Web server like Caddy, Nginx or Apache can load and serve your website for everyone to see.<\/p>\n\n<p>My Sculpin website generates an output_prod directory after I run <code>sculpin generate<\/code> with my deployable files.<\/p>\n\n<p>I manage my own server with NixOS that hosts a number of static websites, such as examples from talks and blog posts.<\/p>\n\n<p>To upload my files onto the server, I just use rsync - a small command line tool to synchronise files between computers.<\/p>\n\n<p>It's a single command to upload the contents of my output_prod directory to the directory on my server.<\/p>\n\n<p>No complex CI pipelines or database migrations.<\/p>\n\n<p>It's fast, simple and minimal.<\/p>\n\n<p>If you prefer to use a service like Netlify or Vercel, they work great for static websites too.<\/p>\n\n ",
"processed": "\n <p>Another reason I like static websites is that they're easy and quick to deploy.<\/p>\n\n<p>Whether you use write each HTML file by hand or <a href=\"/daily\/2025\/03\/12\/easy\">use a static site generator<\/a>, a simple Web server like Caddy, Nginx or Apache can load and serve your website for everyone to see.<\/p>\n\n<p>My Sculpin website generates an output_prod directory after I run <code>sculpin generate<\/code> with my deployable files.<\/p>\n\n<p>I manage my own server with NixOS that hosts a number of static websites, such as examples from talks and blog posts.<\/p>\n\n<p>To upload my files onto the server, I just use rsync - a small command line tool to synchronise files between computers.<\/p>\n\n<p>It's a single command to upload the contents of my output_prod directory to the directory on my server.<\/p>\n\n<p>No complex CI pipelines or database migrations.<\/p>\n\n<p>It's fast, simple and minimal.<\/p>\n\n<p>If you prefer to use a service like Netlify or Vercel, they work great for static websites too.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/11\/20\/version-controlled-commented-out-code\">Yesterday's email<\/a> talked about whether commented-out code should be present if your code is version-controlled, but how do you avoid committing it in the first place?<\/p>\n\n<p>You could make sure that you remove everything manually before you stage and commit your changes, or I like to use <code>git add --patch<\/code> (or <code>git add -p<\/code>) to interactively stage my changes, allowing me to select which parts of files I want to include in my commit and ignore anything else. The <code>--patch<\/code> option also works for other commands, including <code>checkout<\/code> and <code>reset<\/code>.<\/p>\n\n<p>If you've already committed something like some debug code, you can use <code>git commit --amend<\/code> to amend the previous commit before pushing it, or if you have a separate clean-up commit, you can use <code>git rebase --interactive<\/code> and either the squash or fixup options to amend the original commit.<\/p>\n\n<p>If some old code has been removed and you want to find it, you can use <code>git log -S<\/code> with a string to search for, and Git will show a list of commits where the specified string was changed.<\/p>\n\n<p>If instead, you wanted to search for text within the commit message, you can use <code>git log --grep<\/code> with a string like an issue number to see a list of commits with that text in the commit message subject line or body.<\/p>\n\n<p>I hope these tips help keep unwanted code out of your version-control repository.<\/p>\n\n ",
"value": "\n <p><a href=\"/daily\/2022\/11\/20\/version-controlled-commented-out-code\">Yesterday's email<\/a> talked about whether commented-out code should be present if your code is version-controlled, but how do you avoid committing it in the first place?<\/p>\n\n<p>You could make sure that you remove everything manually before you stage and commit your changes, or I like to use <code>git add --patch<\/code> (or <code>git add -p<\/code>) to interactively stage my changes, allowing me to select which parts of files I want to include in my commit and ignore anything else. The <code>--patch<\/code> option also works for other commands, including <code>checkout<\/code> and <code>reset<\/code>.<\/p>\n\n<p>If you've already committed something like some debug code, you can use <code>git commit --amend<\/code> to amend the previous commit before pushing it, or if you have a separate clean-up commit, you can use <code>git rebase --interactive<\/code> and either the squash or fixup options to amend the original commit.<\/p>\n\n<p>If some old code has been removed and you want to find it, you can use <code>git log -S<\/code> with a string to search for, and Git will show a list of commits where the specified string was changed.<\/p>\n\n<p>If instead, you wanted to search for text within the commit message, you can use <code>git log --grep<\/code> with a string like an issue number to see a list of commits with that text in the commit message subject line or body.<\/p>\n\n<p>I hope these tips help keep unwanted code out of your version-control repository.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/11\/20\/version-controlled-commented-out-code\">Yesterday's email<\/a> talked about whether commented-out code should be present if your code is version-controlled, but how do you avoid committing it in the first place?<\/p>\n\n<p>You could make sure that you remove everything manually before you stage and commit your changes, or I like to use <code>git add --patch<\/code> (or <code>git add -p<\/code>) to interactively stage my changes, allowing me to select which parts of files I want to include in my commit and ignore anything else. The <code>--patch<\/code> option also works for other commands, including <code>checkout<\/code> and <code>reset<\/code>.<\/p>\n\n<p>If you've already committed something like some debug code, you can use <code>git commit --amend<\/code> to amend the previous commit before pushing it, or if you have a separate clean-up commit, you can use <code>git rebase --interactive<\/code> and either the squash or fixup options to amend the original commit.<\/p>\n\n<p>If some old code has been removed and you want to find it, you can use <code>git log -S<\/code> with a string to search for, and Git will show a list of commits where the specified string was changed.<\/p>\n\n<p>If instead, you wanted to search for text within the commit message, you can use <code>git log --grep<\/code> with a string like an issue number to see a list of commits with that text in the commit message subject line or body.<\/p>\n\n<p>I hope these tips help keep unwanted code out of your version-control repository.<\/p>\n\n ",
"processed": "\n <p><a href=\"/daily\/2022\/11\/20\/version-controlled-commented-out-code\">Yesterday's email<\/a> talked about whether commented-out code should be present if your code is version-controlled, but how do you avoid committing it in the first place?<\/p>\n\n<p>You could make sure that you remove everything manually before you stage and commit your changes, or I like to use <code>git add --patch<\/code> (or <code>git add -p<\/code>) to interactively stage my changes, allowing me to select which parts of files I want to include in my commit and ignore anything else. The <code>--patch<\/code> option also works for other commands, including <code>checkout<\/code> and <code>reset<\/code>.<\/p>\n\n<p>If you've already committed something like some debug code, you can use <code>git commit --amend<\/code> to amend the previous commit before pushing it, or if you have a separate clean-up commit, you can use <code>git rebase --interactive<\/code> and either the squash or fixup options to amend the original commit.<\/p>\n\n<p>If some old code has been removed and you want to find it, you can use <code>git log -S<\/code> with a string to search for, and Git will show a list of commits where the specified string was changed.<\/p>\n\n<p>If instead, you wanted to search for text within the commit message, you can use <code>git log --grep<\/code> with a string like an issue number to see a list of commits with that text in the commit message subject line or body.<\/p>\n\n<p>I hope these tips help keep unwanted code out of your version-control repository.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Whilst writing <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/06\/07\/not-invented-here\">yesterday's email<\/a> about \"not invented here\", I started thinking about how Drupal's timeline (which was created 23 years ago) compares to some of the other similar or related projects.<\/p>\n\n<p>Here's a list of project release dates from ChatGPT, which seem correct to me at a glance:<\/p>\n\n<ul>\n<li>Drupal: January 15, 2001.<\/li>\n<li>Git: April 7, 2005.<\/li>\n<li>Symfony 1: October 22, 2005.<\/li>\n<li>GitHub and Bitbucket: 2008.<\/li>\n<li>GitLab: October 2011.<\/li>\n<li>Laravel: June 9, 2011.<\/li>\n<li>Drupal 7: January 5, 2011.<\/li>\n<li>Symfony 2: July 28, 2011.<\/li>\n<li>Composer: March 1, 2012.<\/li>\n<li>Drupal 8: November 19, 2015.<\/li>\n<\/ul>\n\n<p>Looking at this list, when speaking about \"not invented here\", a lot of what Drupal would come to use and depend on just didn't exist in its early years.<\/p>\n\n ",
"value": "\n <p>Whilst writing <a href=\"/daily\/2024\/06\/07\/not-invented-here\">yesterday's email<\/a> about \"not invented here\", I started thinking about how Drupal's timeline (which was created 23 years ago) compares to some of the other similar or related projects.<\/p>\n\n<p>Here's a list of project release dates from ChatGPT, which seem correct to me at a glance:<\/p>\n\n<ul>\n<li>Drupal: January 15, 2001.<\/li>\n<li>Git: April 7, 2005.<\/li>\n<li>Symfony 1: October 22, 2005.<\/li>\n<li>GitHub and Bitbucket: 2008.<\/li>\n<li>GitLab: October 2011.<\/li>\n<li>Laravel: June 9, 2011.<\/li>\n<li>Drupal 7: January 5, 2011.<\/li>\n<li>Symfony 2: July 28, 2011.<\/li>\n<li>Composer: March 1, 2012.<\/li>\n<li>Drupal 8: November 19, 2015.<\/li>\n<\/ul>\n\n<p>Looking at this list, when speaking about \"not invented here\", a lot of what Drupal would come to use and depend on just didn't exist in its early years.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Whilst writing <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/06\/07\/not-invented-here\">yesterday's email<\/a> about \"not invented here\", I started thinking about how Drupal's timeline (which was created 23 years ago) compares to some of the other similar or related projects.<\/p>\n\n<p>Here's a list of project release dates from ChatGPT, which seem correct to me at a glance:<\/p>\n\n<ul>\n<li>Drupal: January 15, 2001.<\/li>\n<li>Git: April 7, 2005.<\/li>\n<li>Symfony 1: October 22, 2005.<\/li>\n<li>GitHub and Bitbucket: 2008.<\/li>\n<li>GitLab: October 2011.<\/li>\n<li>Laravel: June 9, 2011.<\/li>\n<li>Drupal 7: January 5, 2011.<\/li>\n<li>Symfony 2: July 28, 2011.<\/li>\n<li>Composer: March 1, 2012.<\/li>\n<li>Drupal 8: November 19, 2015.<\/li>\n<\/ul>\n\n<p>Looking at this list, when speaking about \"not invented here\", a lot of what Drupal would come to use and depend on just didn't exist in its early years.<\/p>\n\n ",
"processed": "\n <p>Whilst writing <a href=\"/daily\/2024\/06\/07\/not-invented-here\">yesterday's email<\/a> about \"not invented here\", I started thinking about how Drupal's timeline (which was created 23 years ago) compares to some of the other similar or related projects.<\/p>\n\n<p>Here's a list of project release dates from ChatGPT, which seem correct to me at a glance:<\/p>\n\n<ul>\n<li>Drupal: January 15, 2001.<\/li>\n<li>Git: April 7, 2005.<\/li>\n<li>Symfony 1: October 22, 2005.<\/li>\n<li>GitHub and Bitbucket: 2008.<\/li>\n<li>GitLab: October 2011.<\/li>\n<li>Laravel: June 9, 2011.<\/li>\n<li>Drupal 7: January 5, 2011.<\/li>\n<li>Symfony 2: July 28, 2011.<\/li>\n<li>Composer: March 1, 2012.<\/li>\n<li>Drupal 8: November 19, 2015.<\/li>\n<\/ul>\n\n<p>Looking at this list, when speaking about \"not invented here\", a lot of what Drupal would come to use and depend on just didn't exist in its early years.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>I'm currently working on a project that doesn't use any atomic or utility-first CSS.<\/p>\n\n<p>It uses Sass, which I haven't used for some time, but it has reminded me of some of the reasons I like the utility-first approach to CSS.<\/p>\n\n<h2 id=\"specificity-and-cascading\">Specificity and cascading<\/h2>\n\n<p>With utility styles, there are no specificity or cascading issues as styles are added to each element and provide a local scope.<\/p>\n\n<p>With global styles, your element can be overridden or altered by another part of CSS elsewhere in the stylesheet.<\/p>\n\n<p>I've also had situations where I've had to \"undo\" unwanted styling that was added elsewhere, such as on a hover or focus state.<\/p>\n\n<h2 id=\"easier-to-read-and-understand\">Easier to read and understand<\/h2>\n\n<p>With utility styles, I can read the classes on an element and understand straight away what styles are applied to it and start to make changes - especially when using a framework, such as Tailwind CSS.<\/p>\n\n<p>With generic class names or IDs, I'm not able to do that.<\/p>\n\n<h2 id=\"context-switching\">Context switching<\/h2>\n\n<p>To make changes to an element, once I've found it in the HTML, I then need to find the stylesheet (or stylesheets) that add the styling and switch between the HTML and CSS files as many times as needed.<\/p>\n\n<p>Usually with utility styles, I rarely need to edit the stylesheet and can work almost exclusively in the HTML and not need to switch between files.<\/p>\n\n<h2 id=\"concatination-and-nesting\">Concatination and nesting<\/h2>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/07\/08\/back-to-sass-and-traditional-css\">Something I've avoided with Sass<\/a>, as well as newer versions of CSS, is the over-use of nesting styles, which makes it harder to find them when searching for the correct stylesheet.<\/p>\n\n<p>If there was this CSS:<\/p>\n\n<pre><code class=\"css\">.sidebar {\n &amp;-wrapper {\n a {\n &amp;:hover,\n &amp;:focus {\n }\n }\n }\n}\n<\/code><\/pre>\n\n<p>If I tried searching for <code>.sidebar-wrapper<\/code> or <code>.sidebar-wrapper a:hover<\/code>, they wouldn't be found and it would take me longer to find it.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>It's taken me a while to get back into this way of working with CSS, but it does remind me <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/taking-flight-with-tailwind-css\">why I prefer to use utility styles<\/a> for my own projects.<\/p>\n\n ",
"value": "\n <p>I'm currently working on a project that doesn't use any atomic or utility-first CSS.<\/p>\n\n<p>It uses Sass, which I haven't used for some time, but it has reminded me of some of the reasons I like the utility-first approach to CSS.<\/p>\n\n<h2 id=\"specificity-and-cascading\">Specificity and cascading<\/h2>\n\n<p>With utility styles, there are no specificity or cascading issues as styles are added to each element and provide a local scope.<\/p>\n\n<p>With global styles, your element can be overridden or altered by another part of CSS elsewhere in the stylesheet.<\/p>\n\n<p>I've also had situations where I've had to \"undo\" unwanted styling that was added elsewhere, such as on a hover or focus state.<\/p>\n\n<h2 id=\"easier-to-read-and-understand\">Easier to read and understand<\/h2>\n\n<p>With utility styles, I can read the classes on an element and understand straight away what styles are applied to it and start to make changes - especially when using a framework, such as Tailwind CSS.<\/p>\n\n<p>With generic class names or IDs, I'm not able to do that.<\/p>\n\n<h2 id=\"context-switching\">Context switching<\/h2>\n\n<p>To make changes to an element, once I've found it in the HTML, I then need to find the stylesheet (or stylesheets) that add the styling and switch between the HTML and CSS files as many times as needed.<\/p>\n\n<p>Usually with utility styles, I rarely need to edit the stylesheet and can work almost exclusively in the HTML and not need to switch between files.<\/p>\n\n<h2 id=\"concatination-and-nesting\">Concatination and nesting<\/h2>\n\n<p><a href=\"/daily\/2024\/07\/08\/back-to-sass-and-traditional-css\">Something I've avoided with Sass<\/a>, as well as newer versions of CSS, is the over-use of nesting styles, which makes it harder to find them when searching for the correct stylesheet.<\/p>\n\n<p>If there was this CSS:<\/p>\n\n<pre><code class=\"css\">.sidebar {\n &amp;-wrapper {\n a {\n &amp;:hover,\n &amp;:focus {\n }\n }\n }\n}\n<\/code><\/pre>\n\n<p>If I tried searching for <code>.sidebar-wrapper<\/code> or <code>.sidebar-wrapper a:hover<\/code>, they wouldn't be found and it would take me longer to find it.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>It's taken me a while to get back into this way of working with CSS, but it does remind me <a href=\"/presentations\/taking-flight-with-tailwind-css\">why I prefer to use utility styles<\/a> for my own projects.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>I'm currently working on a project that doesn't use any atomic or utility-first CSS.<\/p>\n\n<p>It uses Sass, which I haven't used for some time, but it has reminded me of some of the reasons I like the utility-first approach to CSS.<\/p>\n\n<h2 id=\"specificity-and-cascading\">Specificity and cascading<\/h2>\n\n<p>With utility styles, there are no specificity or cascading issues as styles are added to each element and provide a local scope.<\/p>\n\n<p>With global styles, your element can be overridden or altered by another part of CSS elsewhere in the stylesheet.<\/p>\n\n<p>I've also had situations where I've had to \"undo\" unwanted styling that was added elsewhere, such as on a hover or focus state.<\/p>\n\n<h2 id=\"easier-to-read-and-understand\">Easier to read and understand<\/h2>\n\n<p>With utility styles, I can read the classes on an element and understand straight away what styles are applied to it and start to make changes - especially when using a framework, such as Tailwind CSS.<\/p>\n\n<p>With generic class names or IDs, I'm not able to do that.<\/p>\n\n<h2 id=\"context-switching\">Context switching<\/h2>\n\n<p>To make changes to an element, once I've found it in the HTML, I then need to find the stylesheet (or stylesheets) that add the styling and switch between the HTML and CSS files as many times as needed.<\/p>\n\n<p>Usually with utility styles, I rarely need to edit the stylesheet and can work almost exclusively in the HTML and not need to switch between files.<\/p>\n\n<h2 id=\"concatination-and-nesting\">Concatination and nesting<\/h2>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/07\/08\/back-to-sass-and-traditional-css\">Something I've avoided with Sass<\/a>, as well as newer versions of CSS, is the over-use of nesting styles, which makes it harder to find them when searching for the correct stylesheet.<\/p>\n\n<p>If there was this CSS:<\/p>\n\n<pre><code class=\"css\">.sidebar {\n &amp;-wrapper {\n a {\n &amp;:hover,\n &amp;:focus {\n }\n }\n }\n}\n<\/code><\/pre>\n\n<p>If I tried searching for <code>.sidebar-wrapper<\/code> or <code>.sidebar-wrapper a:hover<\/code>, they wouldn't be found and it would take me longer to find it.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>It's taken me a while to get back into this way of working with CSS, but it does remind me <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/taking-flight-with-tailwind-css\">why I prefer to use utility styles<\/a> for my own projects.<\/p>\n\n ",
"processed": "\n <p>I'm currently working on a project that doesn't use any atomic or utility-first CSS.<\/p>\n\n<p>It uses Sass, which I haven't used for some time, but it has reminded me of some of the reasons I like the utility-first approach to CSS.<\/p>\n\n<h2 id=\"specificity-and-cascading\">Specificity and cascading<\/h2>\n\n<p>With utility styles, there are no specificity or cascading issues as styles are added to each element and provide a local scope.<\/p>\n\n<p>With global styles, your element can be overridden or altered by another part of CSS elsewhere in the stylesheet.<\/p>\n\n<p>I've also had situations where I've had to \"undo\" unwanted styling that was added elsewhere, such as on a hover or focus state.<\/p>\n\n<h2 id=\"easier-to-read-and-understand\">Easier to read and understand<\/h2>\n\n<p>With utility styles, I can read the classes on an element and understand straight away what styles are applied to it and start to make changes - especially when using a framework, such as Tailwind CSS.<\/p>\n\n<p>With generic class names or IDs, I'm not able to do that.<\/p>\n\n<h2 id=\"context-switching\">Context switching<\/h2>\n\n<p>To make changes to an element, once I've found it in the HTML, I then need to find the stylesheet (or stylesheets) that add the styling and switch between the HTML and CSS files as many times as needed.<\/p>\n\n<p>Usually with utility styles, I rarely need to edit the stylesheet and can work almost exclusively in the HTML and not need to switch between files.<\/p>\n\n<h2 id=\"concatination-and-nesting\">Concatination and nesting<\/h2>\n\n<p><a href=\"/daily\/2024\/07\/08\/back-to-sass-and-traditional-css\">Something I've avoided with Sass<\/a>, as well as newer versions of CSS, is the over-use of nesting styles, which makes it harder to find them when searching for the correct stylesheet.<\/p>\n\n<p>If there was this CSS:<\/p>\n\n<pre><code class=\"css\">.sidebar {\n &amp;-wrapper {\n a {\n &amp;:hover,\n &amp;:focus {\n }\n }\n }\n}\n<\/code><\/pre>\n\n<p>If I tried searching for <code>.sidebar-wrapper<\/code> or <code>.sidebar-wrapper a:hover<\/code>, they wouldn't be found and it would take me longer to find it.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>It's taken me a while to get back into this way of working with CSS, but it does remind me <a href=\"/presentations\/taking-flight-with-tailwind-css\">why I prefer to use utility styles<\/a> for my own projects.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>As I work on various projects, I use several different CI tools, such as GitHub Actions, Bitbucket Pipelines, and GitLab CI, as well as hosting providers that have build and deploy steps.<\/p>\n\n<p>Some only run continuous integration checks, like automated tests and static analysis, some build and push Docker images, and some use Ansible and Ansistrano to deploy the changes to production.<\/p>\n\n<p>Each tool has its configuration file with different settings and formats.<\/p>\n\n<p>Rather than being too tightly coupled to a particular tool, I like to keep things as agnostic as possible and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">use a run file<\/a> with separate <code>ci:build<\/code> and <code>ci:deploy<\/code> tasks.<\/p>\n\n<p>This means that all the logic is within the run file rather than the CI tool-specific configuration file, so the file is shorter and cleaner; I can make changes to the CI tasks locally and quickly test changes and iterate, and also, as the logic is within the run file, I can easily switch to a different CI tool if needed without making changes to the tasks themselves.<\/p>\n\n ",
"value": "\n <p>As I work on various projects, I use several different CI tools, such as GitHub Actions, Bitbucket Pipelines, and GitLab CI, as well as hosting providers that have build and deploy steps.<\/p>\n\n<p>Some only run continuous integration checks, like automated tests and static analysis, some build and push Docker images, and some use Ansible and Ansistrano to deploy the changes to production.<\/p>\n\n<p>Each tool has its configuration file with different settings and formats.<\/p>\n\n<p>Rather than being too tightly coupled to a particular tool, I like to keep things as agnostic as possible and <a href=\"/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">use a run file<\/a> with separate <code>ci:build<\/code> and <code>ci:deploy<\/code> tasks.<\/p>\n\n<p>This means that all the logic is within the run file rather than the CI tool-specific configuration file, so the file is shorter and cleaner; I can make changes to the CI tasks locally and quickly test changes and iterate, and also, as the logic is within the run file, I can easily switch to a different CI tool if needed without making changes to the tasks themselves.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>As I work on various projects, I use several different CI tools, such as GitHub Actions, Bitbucket Pipelines, and GitLab CI, as well as hosting providers that have build and deploy steps.<\/p>\n\n<p>Some only run continuous integration checks, like automated tests and static analysis, some build and push Docker images, and some use Ansible and Ansistrano to deploy the changes to production.<\/p>\n\n<p>Each tool has its configuration file with different settings and formats.<\/p>\n\n<p>Rather than being too tightly coupled to a particular tool, I like to keep things as agnostic as possible and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">use a run file<\/a> with separate <code>ci:build<\/code> and <code>ci:deploy<\/code> tasks.<\/p>\n\n<p>This means that all the logic is within the run file rather than the CI tool-specific configuration file, so the file is shorter and cleaner; I can make changes to the CI tasks locally and quickly test changes and iterate, and also, as the logic is within the run file, I can easily switch to a different CI tool if needed without making changes to the tasks themselves.<\/p>\n\n ",
"processed": "\n <p>As I work on various projects, I use several different CI tools, such as GitHub Actions, Bitbucket Pipelines, and GitLab CI, as well as hosting providers that have build and deploy steps.<\/p>\n\n<p>Some only run continuous integration checks, like automated tests and static analysis, some build and push Docker images, and some use Ansible and Ansistrano to deploy the changes to production.<\/p>\n\n<p>Each tool has its configuration file with different settings and formats.<\/p>\n\n<p>Rather than being too tightly coupled to a particular tool, I like to keep things as agnostic as possible and <a href=\"/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">use a run file<\/a> with separate <code>ci:build<\/code> and <code>ci:deploy<\/code> tasks.<\/p>\n\n<p>This means that all the logic is within the run file rather than the CI tool-specific configuration file, so the file is shorter and cleaner; I can make changes to the CI tasks locally and quickly test changes and iterate, and also, as the logic is within the run file, I can easily switch to a different CI tool if needed without making changes to the tasks themselves.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>A few days ago, I said that <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/02\/simple\">I still like to use RSS<\/a> to consume a lot of online content.<\/p>\n\n<p>Unfortunately, a lot of websites either don't have RSS or Atom feeds, or they aren't easy to find without viewing the website's source code.<\/p>\n\n<p>The ability for people to publish and easily consume other people's content is a main principle of the open web, instead of relying on other websites and social media.<\/p>\n\n<p>Drupal is one of the projects <a href=\"https:\/\/www.drupal.org\/association\/open-web-manifesto\">that make an open web possible<\/a>.<\/p>\n\n<p>It's easy to create an RSS feed of your articles, events or any other content on your Drupal website for others to consume.<\/p>\n\n<p>I also love that Drupal.org itself does this by publishing RSS feeds for project releases and various other content - not just news or blog posts.<\/p>\n\n<p>Because of this, I can subscribe to the feeds I want from any website that creates them and I can consume it how and when I want.<\/p>\n\n<p>Long live the open web!<\/p>\n\n ",
"value": "\n <p>A few days ago, I said that <a href=\"/daily\/2025\/02\/02\/simple\">I still like to use RSS<\/a> to consume a lot of online content.<\/p>\n\n<p>Unfortunately, a lot of websites either don't have RSS or Atom feeds, or they aren't easy to find without viewing the website's source code.<\/p>\n\n<p>The ability for people to publish and easily consume other people's content is a main principle of the open web, instead of relying on other websites and social media.<\/p>\n\n<p>Drupal is one of the projects <a href=\"https:\/\/www.drupal.org\/association\/open-web-manifesto\">that make an open web possible<\/a>.<\/p>\n\n<p>It's easy to create an RSS feed of your articles, events or any other content on your Drupal website for others to consume.<\/p>\n\n<p>I also love that Drupal.org itself does this by publishing RSS feeds for project releases and various other content - not just news or blog posts.<\/p>\n\n<p>Because of this, I can subscribe to the feeds I want from any website that creates them and I can consume it how and when I want.<\/p>\n\n<p>Long live the open web!<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>A few days ago, I said that <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/02\/02\/simple\">I still like to use RSS<\/a> to consume a lot of online content.<\/p>\n\n<p>Unfortunately, a lot of websites either don't have RSS or Atom feeds, or they aren't easy to find without viewing the website's source code.<\/p>\n\n<p>The ability for people to publish and easily consume other people's content is a main principle of the open web, instead of relying on other websites and social media.<\/p>\n\n<p>Drupal is one of the projects <a href=\"https:\/\/www.drupal.org\/association\/open-web-manifesto\">that make an open web possible<\/a>.<\/p>\n\n<p>It's easy to create an RSS feed of your articles, events or any other content on your Drupal website for others to consume.<\/p>\n\n<p>I also love that Drupal.org itself does this by publishing RSS feeds for project releases and various other content - not just news or blog posts.<\/p>\n\n<p>Because of this, I can subscribe to the feeds I want from any website that creates them and I can consume it how and when I want.<\/p>\n\n<p>Long live the open web!<\/p>\n\n ",
"processed": "\n <p>A few days ago, I said that <a href=\"/daily\/2025\/02\/02\/simple\">I still like to use RSS<\/a> to consume a lot of online content.<\/p>\n\n<p>Unfortunately, a lot of websites either don't have RSS or Atom feeds, or they aren't easy to find without viewing the website's source code.<\/p>\n\n<p>The ability for people to publish and easily consume other people's content is a main principle of the open web, instead of relying on other websites and social media.<\/p>\n\n<p>Drupal is one of the projects <a href=\"https:\/\/www.drupal.org\/association\/open-web-manifesto\">that make an open web possible<\/a>.<\/p>\n\n<p>It's easy to create an RSS feed of your articles, events or any other content on your Drupal website for others to consume.<\/p>\n\n<p>I also love that Drupal.org itself does this by publishing RSS feeds for project releases and various other content - not just news or blog posts.<\/p>\n\n<p>Because of this, I can subscribe to the feeds I want from any website that creates them and I can consume it how and when I want.<\/p>\n\n<p>Long live the open web!<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Yesterday, I asked <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/26\/is-it-time-to-stop-writing-sass\">if it's time to stop writing Sass<\/a>.<\/p>\n\n<p>If you still use Sass and are writing new styles with Sass, I'd like to know why.<\/p>\n\n<p>Reply to this email and let me know.<\/p>\n\n<p>I'm working on a project and migrating from the existing Sass styles to Tailwind CSS-generated utility classes, but with CSS custom properties (variables) and other Sass-like features now supported by browsers, writing vanilla CSS again is an interesting option.<\/p>\n\n ",
"value": "\n <p>Yesterday, I asked <a href=\"/daily\/2024\/05\/26\/is-it-time-to-stop-writing-sass\">if it's time to stop writing Sass<\/a>.<\/p>\n\n<p>If you still use Sass and are writing new styles with Sass, I'd like to know why.<\/p>\n\n<p>Reply to this email and let me know.<\/p>\n\n<p>I'm working on a project and migrating from the existing Sass styles to Tailwind CSS-generated utility classes, but with CSS custom properties (variables) and other Sass-like features now supported by browsers, writing vanilla CSS again is an interesting option.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Yesterday, I asked <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/26\/is-it-time-to-stop-writing-sass\">if it's time to stop writing Sass<\/a>.<\/p>\n\n<p>If you still use Sass and are writing new styles with Sass, I'd like to know why.<\/p>\n\n<p>Reply to this email and let me know.<\/p>\n\n<p>I'm working on a project and migrating from the existing Sass styles to Tailwind CSS-generated utility classes, but with CSS custom properties (variables) and other Sass-like features now supported by browsers, writing vanilla CSS again is an interesting option.<\/p>\n\n ",
"processed": "\n <p>Yesterday, I asked <a href=\"/daily\/2024\/05\/26\/is-it-time-to-stop-writing-sass\">if it's time to stop writing Sass<\/a>.<\/p>\n\n<p>If you still use Sass and are writing new styles with Sass, I'd like to know why.<\/p>\n\n<p>Reply to this email and let me know.<\/p>\n\n<p>I'm working on a project and migrating from the existing Sass styles to Tailwind CSS-generated utility classes, but with CSS custom properties (variables) and other Sass-like features now supported by browsers, writing vanilla CSS again is an interesting option.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>This week on the Beyond Blocks podcast, I'm joined by Mark Conroy - Director of Development at Annertech to discuss all things front-end development and building something useful in one day.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/11-mark-conroy\">Listen now<\/a><\/p>\n\n<h2 id=\"talking-points\">Talking points<\/h2>\n\n<ul>\n<li>Building better websites faster, including Drupal distributions, such as LocalGov.<\/li>\n<li>What Drupal gives you out of the box and using the right tool for the job.<\/li>\n<li>Drupal migrations and migrating Drupal configuration from a spreadsheet.<\/li>\n<li>Saving time and improving efficiency by standardising base builds with Docksal and Composer.<\/li>\n<li>How to build projects, like the Running Plan Generator, in a day and training for 10Ks and marathons.<\/li>\n<li>Prioritising tasks.<\/li>\n<li>Annertech's development workflow and standardisation by developing on remote servers.<\/li>\n<li>Why you may not need preprocessors and complicated front-end build tools, and reducing complexity using vanilla CSS, JavaScript and web components.<\/li>\n<li>Lowering the barrier to entry to contribute to open-source projects.<\/li>\n<li>Building a design system\/component library with web components.<\/li>\n<li>The Content Access by Path module that was developed for Essex County Council.<\/li>\n<\/ul>\n\n ",
"value": "\n <p>This week on the Beyond Blocks podcast, I'm joined by Mark Conroy - Director of Development at Annertech to discuss all things front-end development and building something useful in one day.<\/p>\n\n<p><a href=\"/podcast\/11-mark-conroy\">Listen now<\/a><\/p>\n\n<h2 id=\"talking-points\">Talking points<\/h2>\n\n<ul>\n<li>Building better websites faster, including Drupal distributions, such as LocalGov.<\/li>\n<li>What Drupal gives you out of the box and using the right tool for the job.<\/li>\n<li>Drupal migrations and migrating Drupal configuration from a spreadsheet.<\/li>\n<li>Saving time and improving efficiency by standardising base builds with Docksal and Composer.<\/li>\n<li>How to build projects, like the Running Plan Generator, in a day and training for 10Ks and marathons.<\/li>\n<li>Prioritising tasks.<\/li>\n<li>Annertech's development workflow and standardisation by developing on remote servers.<\/li>\n<li>Why you may not need preprocessors and complicated front-end build tools, and reducing complexity using vanilla CSS, JavaScript and web components.<\/li>\n<li>Lowering the barrier to entry to contribute to open-source projects.<\/li>\n<li>Building a design system\/component library with web components.<\/li>\n<li>The Content Access by Path module that was developed for Essex County Council.<\/li>\n<\/ul>\n\n ",
"format": "full_html",
"processed": "\n <p>This week on the Beyond Blocks podcast, I'm joined by Mark Conroy - Director of Development at Annertech to discuss all things front-end development and building something useful in one day.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/11-mark-conroy\">Listen now<\/a><\/p>\n\n<h2 id=\"talking-points\">Talking points<\/h2>\n\n<ul>\n<li>Building better websites faster, including Drupal distributions, such as LocalGov.<\/li>\n<li>What Drupal gives you out of the box and using the right tool for the job.<\/li>\n<li>Drupal migrations and migrating Drupal configuration from a spreadsheet.<\/li>\n<li>Saving time and improving efficiency by standardising base builds with Docksal and Composer.<\/li>\n<li>How to build projects, like the Running Plan Generator, in a day and training for 10Ks and marathons.<\/li>\n<li>Prioritising tasks.<\/li>\n<li>Annertech's development workflow and standardisation by developing on remote servers.<\/li>\n<li>Why you may not need preprocessors and complicated front-end build tools, and reducing complexity using vanilla CSS, JavaScript and web components.<\/li>\n<li>Lowering the barrier to entry to contribute to open-source projects.<\/li>\n<li>Building a design system\/component library with web components.<\/li>\n<li>The Content Access by Path module that was developed for Essex County Council.<\/li>\n<\/ul>\n\n ",
"processed": "\n <p>This week on the Beyond Blocks podcast, I'm joined by Mark Conroy - Director of Development at Annertech to discuss all things front-end development and building something useful in one day.<\/p>\n\n<p><a href=\"/podcast\/11-mark-conroy\">Listen now<\/a><\/p>\n\n<h2 id=\"talking-points\">Talking points<\/h2>\n\n<ul>\n<li>Building better websites faster, including Drupal distributions, such as LocalGov.<\/li>\n<li>What Drupal gives you out of the box and using the right tool for the job.<\/li>\n<li>Drupal migrations and migrating Drupal configuration from a spreadsheet.<\/li>\n<li>Saving time and improving efficiency by standardising base builds with Docksal and Composer.<\/li>\n<li>How to build projects, like the Running Plan Generator, in a day and training for 10Ks and marathons.<\/li>\n<li>Prioritising tasks.<\/li>\n<li>Annertech's development workflow and standardisation by developing on remote servers.<\/li>\n<li>Why you may not need preprocessors and complicated front-end build tools, and reducing complexity using vanilla CSS, JavaScript and web components.<\/li>\n<li>Lowering the barrier to entry to contribute to open-source projects.<\/li>\n<li>Building a design system\/component library with web components.<\/li>\n<li>The Content Access by Path module that was developed for Essex County Council.<\/li>\n<\/ul>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>As part of my recent digital simplification, I've started hosting the episodes of the <a href=\"https:\/\/www.oliverdavies.uk\/podcast\">Beyond Blocks podcast<\/a> myself.<\/p>\n\n<p>I've always had the podcast pages on my website and used them as the primary pages to redirect people for information about the episodes.<\/p>\n\n<p>I embedded an audio player from a third party service that were hosting the files, but have replaced it with the native HTML audio element.<\/p>\n\n<p>It's simpler, but I like it.<\/p>\n\n<p>My website is built with Sculpin, so I was able to do this easily with Twig by adding the path to the MP3 file to each episode:<\/p>\n\n<pre><code class=\"twig\">&lt;audio controls&gt;\n &lt;source src=\"\/files\/bb\/episodes\/{{ page.episode_filename }}\" type=\"audio\/mp3\"&gt;\n&lt;\/audio&gt;\n<\/code><\/pre>\n\n<p>This is already live. You can see it on <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/25-jess-archer-drush-laravel-prompts\">any of the podcast episode pages<\/a>.<\/p>\n\n<p>The other thing I'm using is the feed that publishes episodes to Spotify, iTunes, etc.<\/p>\n\n<p>But I have all the information and ability to create this myself.<\/p>\n\n<p>This part is still in development and I'll need to test it before switching to it, but it will mean the feed URL will change and people may need to resubscribe.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Using a hosted service was a great way to get the podcast up and running quickly, but I'm looking forward to having more control over it, even if it involves a little upfront development work.<\/p>\n\n<p>But, it will make it easier to post future episodes as I'll be able to do it all in one place.<\/p>\n\n<p>I have some new guests lined up for 2025, which I'm looking forward to.<\/p>\n\n<p>If you want to be a guest on the podcast or want to make a suggestion for someone I should have on, reply to this email and let me know.<\/p>\n\n ",
"value": "\n <p>As part of my recent digital simplification, I've started hosting the episodes of the <a href=\"/podcast\">Beyond Blocks podcast<\/a> myself.<\/p>\n\n<p>I've always had the podcast pages on my website and used them as the primary pages to redirect people for information about the episodes.<\/p>\n\n<p>I embedded an audio player from a third party service that were hosting the files, but have replaced it with the native HTML audio element.<\/p>\n\n<p>It's simpler, but I like it.<\/p>\n\n<p>My website is built with Sculpin, so I was able to do this easily with Twig by adding the path to the MP3 file to each episode:<\/p>\n\n<pre><code class=\"twig\">&lt;audio controls&gt;\n &lt;source src=\"\/files\/bb\/episodes\/{{ page.episode_filename }}\" type=\"audio\/mp3\"&gt;\n&lt;\/audio&gt;\n<\/code><\/pre>\n\n<p>This is already live. You can see it on <a href=\"/podcast\/25-jess-archer-drush-laravel-prompts\">any of the podcast episode pages<\/a>.<\/p>\n\n<p>The other thing I'm using is the feed that publishes episodes to Spotify, iTunes, etc.<\/p>\n\n<p>But I have all the information and ability to create this myself.<\/p>\n\n<p>This part is still in development and I'll need to test it before switching to it, but it will mean the feed URL will change and people may need to resubscribe.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Using a hosted service was a great way to get the podcast up and running quickly, but I'm looking forward to having more control over it, even if it involves a little upfront development work.<\/p>\n\n<p>But, it will make it easier to post future episodes as I'll be able to do it all in one place.<\/p>\n\n<p>I have some new guests lined up for 2025, which I'm looking forward to.<\/p>\n\n<p>If you want to be a guest on the podcast or want to make a suggestion for someone I should have on, reply to this email and let me know.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>As part of my recent digital simplification, I've started hosting the episodes of the <a href=\"https:\/\/www.oliverdavies.uk\/podcast\">Beyond Blocks podcast<\/a> myself.<\/p>\n\n<p>I've always had the podcast pages on my website and used them as the primary pages to redirect people for information about the episodes.<\/p>\n\n<p>I embedded an audio player from a third party service that were hosting the files, but have replaced it with the native HTML audio element.<\/p>\n\n<p>It's simpler, but I like it.<\/p>\n\n<p>My website is built with Sculpin, so I was able to do this easily with Twig by adding the path to the MP3 file to each episode:<\/p>\n\n<pre><code class=\"twig\">&lt;audio controls&gt;\n &lt;source src=\"\/files\/bb\/episodes\/{{ page.episode_filename }}\" type=\"audio\/mp3\"&gt;\n&lt;\/audio&gt;\n<\/code><\/pre>\n\n<p>This is already live. You can see it on <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/25-jess-archer-drush-laravel-prompts\">any of the podcast episode pages<\/a>.<\/p>\n\n<p>The other thing I'm using is the feed that publishes episodes to Spotify, iTunes, etc.<\/p>\n\n<p>But I have all the information and ability to create this myself.<\/p>\n\n<p>This part is still in development and I'll need to test it before switching to it, but it will mean the feed URL will change and people may need to resubscribe.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Using a hosted service was a great way to get the podcast up and running quickly, but I'm looking forward to having more control over it, even if it involves a little upfront development work.<\/p>\n\n<p>But, it will make it easier to post future episodes as I'll be able to do it all in one place.<\/p>\n\n<p>I have some new guests lined up for 2025, which I'm looking forward to.<\/p>\n\n<p>If you want to be a guest on the podcast or want to make a suggestion for someone I should have on, reply to this email and let me know.<\/p>\n\n ",
"processed": "\n <p>As part of my recent digital simplification, I've started hosting the episodes of the <a href=\"/podcast\">Beyond Blocks podcast<\/a> myself.<\/p>\n\n<p>I've always had the podcast pages on my website and used them as the primary pages to redirect people for information about the episodes.<\/p>\n\n<p>I embedded an audio player from a third party service that were hosting the files, but have replaced it with the native HTML audio element.<\/p>\n\n<p>It's simpler, but I like it.<\/p>\n\n<p>My website is built with Sculpin, so I was able to do this easily with Twig by adding the path to the MP3 file to each episode:<\/p>\n\n<pre><code class=\"twig\">&lt;audio controls&gt;\n &lt;source src=\"\/files\/bb\/episodes\/{{ page.episode_filename }}\" type=\"audio\/mp3\"&gt;\n&lt;\/audio&gt;\n<\/code><\/pre>\n\n<p>This is already live. You can see it on <a href=\"/podcast\/25-jess-archer-drush-laravel-prompts\">any of the podcast episode pages<\/a>.<\/p>\n\n<p>The other thing I'm using is the feed that publishes episodes to Spotify, iTunes, etc.<\/p>\n\n<p>But I have all the information and ability to create this myself.<\/p>\n\n<p>This part is still in development and I'll need to test it before switching to it, but it will mean the feed URL will change and people may need to resubscribe.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Using a hosted service was a great way to get the podcast up and running quickly, but I'm looking forward to having more control over it, even if it involves a little upfront development work.<\/p>\n\n<p>But, it will make it easier to post future episodes as I'll be able to do it all in one place.<\/p>\n\n<p>I have some new guests lined up for 2025, which I'm looking forward to.<\/p>\n\n<p>If you want to be a guest on the podcast or want to make a suggestion for someone I should have on, reply to this email and let me know.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>There are a lot of <a href=\"https:\/\/www.drupal.org\/project\/issues\/search?status[]=1&amp;status[]=13&amp;issue_tags_op=%3D&amp;issue_tags=Needs+tests\">open issues on Drupal.org<\/a> that have the \"Needs tests\" label.<\/p>\n\n<p>These could be maintainers leaving themselves reminders to add tests once they've finished spiking out the first version of their code, or someone contributing to project but needs an accompanying test to ensure the feature works or that a bug is fixed (and will stay fixed).<\/p>\n\n<p>There are currently 3,711 issues across all projects and 2,030 in Drupal core.<\/p>\n\n<p>If one of those is your issue or module, I can write the tests you need.<\/p>\n\n<p>After my <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/11-mark-conroy\">first podcast episode with Mark Conroy<\/a>, I did this for <a href=\"https:\/\/www.drupal.org\/project\/content_access_by_path\/issues\/3428680\">the Content Access by Path module<\/a>, which now has tests and automated checks with GitLab CI - so they will be run for every future merge request.<\/p>\n\n<p>You can see me writing them on <a href=\"https:\/\/www.youtube.com\/watch?v=XTpliKd47Lg\">a previous live stream<\/a>.<\/p>\n\n<p>If you need tests written or help writing them yourself, reply and get in touch.<\/p>\n\n<p>If you want to <a href=\"https:\/\/www.oliverdavies.uk\/sponsor\">sponsor my contribution time<\/a>, you'll also get contribution credit for any issues or merge requests I work on during that time and, whilst it's been a while since my last live stream, you'd also be mentioned there as I work on these issues.<\/p>\n\n<p>I have around a day a week available for sponsored contribution time.<\/p>\n\n<p>If you're interested, reply and let's get it arranged.<\/p>\n\n ",
"value": "\n <p>There are a lot of <a href=\"https:\/\/www.drupal.org\/project\/issues\/search?status[]=1&amp;status[]=13&amp;issue_tags_op=%3D&amp;issue_tags=Needs+tests\">open issues on Drupal.org<\/a> that have the \"Needs tests\" label.<\/p>\n\n<p>These could be maintainers leaving themselves reminders to add tests once they've finished spiking out the first version of their code, or someone contributing to project but needs an accompanying test to ensure the feature works or that a bug is fixed (and will stay fixed).<\/p>\n\n<p>There are currently 3,711 issues across all projects and 2,030 in Drupal core.<\/p>\n\n<p>If one of those is your issue or module, I can write the tests you need.<\/p>\n\n<p>After my <a href=\"/podcast\/11-mark-conroy\">first podcast episode with Mark Conroy<\/a>, I did this for <a href=\"https:\/\/www.drupal.org\/project\/content_access_by_path\/issues\/3428680\">the Content Access by Path module<\/a>, which now has tests and automated checks with GitLab CI - so they will be run for every future merge request.<\/p>\n\n<p>You can see me writing them on <a href=\"https:\/\/www.youtube.com\/watch?v=XTpliKd47Lg\">a previous live stream<\/a>.<\/p>\n\n<p>If you need tests written or help writing them yourself, reply and get in touch.<\/p>\n\n<p>If you want to <a href=\"/sponsor\">sponsor my contribution time<\/a>, you'll also get contribution credit for any issues or merge requests I work on during that time and, whilst it's been a while since my last live stream, you'd also be mentioned there as I work on these issues.<\/p>\n\n<p>I have around a day a week available for sponsored contribution time.<\/p>\n\n<p>If you're interested, reply and let's get it arranged.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>There are a lot of <a href=\"https:\/\/www.drupal.org\/project\/issues\/search?status[]=1&amp;status[]=13&amp;issue_tags_op=%3D&amp;issue_tags=Needs+tests\">open issues on Drupal.org<\/a> that have the \"Needs tests\" label.<\/p>\n\n<p>These could be maintainers leaving themselves reminders to add tests once they've finished spiking out the first version of their code, or someone contributing to project but needs an accompanying test to ensure the feature works or that a bug is fixed (and will stay fixed).<\/p>\n\n<p>There are currently 3,711 issues across all projects and 2,030 in Drupal core.<\/p>\n\n<p>If one of those is your issue or module, I can write the tests you need.<\/p>\n\n<p>After my <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/11-mark-conroy\">first podcast episode with Mark Conroy<\/a>, I did this for <a href=\"https:\/\/www.drupal.org\/project\/content_access_by_path\/issues\/3428680\">the Content Access by Path module<\/a>, which now has tests and automated checks with GitLab CI - so they will be run for every future merge request.<\/p>\n\n<p>You can see me writing them on <a href=\"https:\/\/www.youtube.com\/watch?v=XTpliKd47Lg\">a previous live stream<\/a>.<\/p>\n\n<p>If you need tests written or help writing them yourself, reply and get in touch.<\/p>\n\n<p>If you want to <a href=\"https:\/\/www.oliverdavies.uk\/sponsor\">sponsor my contribution time<\/a>, you'll also get contribution credit for any issues or merge requests I work on during that time and, whilst it's been a while since my last live stream, you'd also be mentioned there as I work on these issues.<\/p>\n\n<p>I have around a day a week available for sponsored contribution time.<\/p>\n\n<p>If you're interested, reply and let's get it arranged.<\/p>\n\n ",
"processed": "\n <p>There are a lot of <a href=\"https:\/\/www.drupal.org\/project\/issues\/search?status[]=1&amp;status[]=13&amp;issue_tags_op=%3D&amp;issue_tags=Needs+tests\">open issues on Drupal.org<\/a> that have the \"Needs tests\" label.<\/p>\n\n<p>These could be maintainers leaving themselves reminders to add tests once they've finished spiking out the first version of their code, or someone contributing to project but needs an accompanying test to ensure the feature works or that a bug is fixed (and will stay fixed).<\/p>\n\n<p>There are currently 3,711 issues across all projects and 2,030 in Drupal core.<\/p>\n\n<p>If one of those is your issue or module, I can write the tests you need.<\/p>\n\n<p>After my <a href=\"/podcast\/11-mark-conroy\">first podcast episode with Mark Conroy<\/a>, I did this for <a href=\"https:\/\/www.drupal.org\/project\/content_access_by_path\/issues\/3428680\">the Content Access by Path module<\/a>, which now has tests and automated checks with GitLab CI - so they will be run for every future merge request.<\/p>\n\n<p>You can see me writing them on <a href=\"https:\/\/www.youtube.com\/watch?v=XTpliKd47Lg\">a previous live stream<\/a>.<\/p>\n\n<p>If you need tests written or help writing them yourself, reply and get in touch.<\/p>\n\n<p>If you want to <a href=\"/sponsor\">sponsor my contribution time<\/a>, you'll also get contribution credit for any issues or merge requests I work on during that time and, whilst it's been a while since my last live stream, you'd also be mentioned there as I work on these issues.<\/p>\n\n<p>I have around a day a week available for sponsored contribution time.<\/p>\n\n<p>If you're interested, reply and let's get it arranged.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>I like framework-agnostic tools.<\/p>\n\n<p>I like to reuse knowledge and tools across projects, whether I'm working with Drupal, Symfony, Laravel or Sculpin.<\/p>\n\n<p>Rector is one of those tools.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/04\/12\/drupal-rector-and-the-project-update-bot\">Yesterday<\/a> I said I use it to create automatic updates to my Drupal module code, but it can be used for other PHP projects, too.<\/p>\n\n<p>If you're upgrading a PHP library and want to use promoted constructor properties, for example, Rector can do that for you - and a lot more.<\/p>\n\n<p>You define which rules or presets you want to use, run Rector on the code, and it will make those changes.<\/p>\n\n<p>Having Rector do this work leaves me free to stay focused on other tasks.<\/p>\n\n ",
"value": "\n <p>I like framework-agnostic tools.<\/p>\n\n<p>I like to reuse knowledge and tools across projects, whether I'm working with Drupal, Symfony, Laravel or Sculpin.<\/p>\n\n<p>Rector is one of those tools.<\/p>\n\n<p><a href=\"/daily\/2024\/04\/12\/drupal-rector-and-the-project-update-bot\">Yesterday<\/a> I said I use it to create automatic updates to my Drupal module code, but it can be used for other PHP projects, too.<\/p>\n\n<p>If you're upgrading a PHP library and want to use promoted constructor properties, for example, Rector can do that for you - and a lot more.<\/p>\n\n<p>You define which rules or presets you want to use, run Rector on the code, and it will make those changes.<\/p>\n\n<p>Having Rector do this work leaves me free to stay focused on other tasks.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>I like framework-agnostic tools.<\/p>\n\n<p>I like to reuse knowledge and tools across projects, whether I'm working with Drupal, Symfony, Laravel or Sculpin.<\/p>\n\n<p>Rector is one of those tools.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/04\/12\/drupal-rector-and-the-project-update-bot\">Yesterday<\/a> I said I use it to create automatic updates to my Drupal module code, but it can be used for other PHP projects, too.<\/p>\n\n<p>If you're upgrading a PHP library and want to use promoted constructor properties, for example, Rector can do that for you - and a lot more.<\/p>\n\n<p>You define which rules or presets you want to use, run Rector on the code, and it will make those changes.<\/p>\n\n<p>Having Rector do this work leaves me free to stay focused on other tasks.<\/p>\n\n ",
"processed": "\n <p>I like framework-agnostic tools.<\/p>\n\n<p>I like to reuse knowledge and tools across projects, whether I'm working with Drupal, Symfony, Laravel or Sculpin.<\/p>\n\n<p>Rector is one of those tools.<\/p>\n\n<p><a href=\"/daily\/2024\/04\/12\/drupal-rector-and-the-project-update-bot\">Yesterday<\/a> I said I use it to create automatic updates to my Drupal module code, but it can be used for other PHP projects, too.<\/p>\n\n<p>If you're upgrading a PHP library and want to use promoted constructor properties, for example, Rector can do that for you - and a lot more.<\/p>\n\n<p>You define which rules or presets you want to use, run Rector on the code, and it will make those changes.<\/p>\n\n<p>Having Rector do this work leaves me free to stay focused on other tasks.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Continuing yesterday's thought on <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/04\/strict-typing-in-php\">strictness in PHP<\/a>, today I want to talk about adding more strictness to PHPStan.<\/p>\n\n<p>Adding the <a href=\"https:\/\/github.com\/phpstan\/phpstan-strict-rules\">PHPStan Strict Rules extension<\/a> makes PHPStan stricter by adding new, more opinionated rules.<\/p>\n\n<p>For example:<\/p>\n\n<ul>\n<li>Require booleans in if, elseif, ternary operator, after !, and on both sides of &amp;&amp; and ||.<\/li>\n<li>Use the <code>$strict<\/code> parameter with <code>in_array<\/code>, <code>array_search<\/code>, <code>array_keys<\/code> and <code>base64_decode<\/code>.<\/li>\n<li>Disallow empty().<\/li>\n<li>Require calling parent constructor.<\/li>\n<\/ul>\n\n<p>You can enable and disable rules as needed but, like setting the PHPStan level, ideally I like to enable them all by default and see how strict I go.<\/p>\n\n<p>It depends on the code being tested and the preference of the team, though I find the stricter the rules, the less bugs there are.<\/p>\n\n ",
"value": "\n <p>Continuing yesterday's thought on <a href=\"/daily\/2024\/05\/04\/strict-typing-in-php\">strictness in PHP<\/a>, today I want to talk about adding more strictness to PHPStan.<\/p>\n\n<p>Adding the <a href=\"https:\/\/github.com\/phpstan\/phpstan-strict-rules\">PHPStan Strict Rules extension<\/a> makes PHPStan stricter by adding new, more opinionated rules.<\/p>\n\n<p>For example:<\/p>\n\n<ul>\n<li>Require booleans in if, elseif, ternary operator, after !, and on both sides of &amp;&amp; and ||.<\/li>\n<li>Use the <code>$strict<\/code> parameter with <code>in_array<\/code>, <code>array_search<\/code>, <code>array_keys<\/code> and <code>base64_decode<\/code>.<\/li>\n<li>Disallow empty().<\/li>\n<li>Require calling parent constructor.<\/li>\n<\/ul>\n\n<p>You can enable and disable rules as needed but, like setting the PHPStan level, ideally I like to enable them all by default and see how strict I go.<\/p>\n\n<p>It depends on the code being tested and the preference of the team, though I find the stricter the rules, the less bugs there are.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Continuing yesterday's thought on <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/04\/strict-typing-in-php\">strictness in PHP<\/a>, today I want to talk about adding more strictness to PHPStan.<\/p>\n\n<p>Adding the <a href=\"https:\/\/github.com\/phpstan\/phpstan-strict-rules\">PHPStan Strict Rules extension<\/a> makes PHPStan stricter by adding new, more opinionated rules.<\/p>\n\n<p>For example:<\/p>\n\n<ul>\n<li>Require booleans in if, elseif, ternary operator, after !, and on both sides of &amp;&amp; and ||.<\/li>\n<li>Use the <code>$strict<\/code> parameter with <code>in_array<\/code>, <code>array_search<\/code>, <code>array_keys<\/code> and <code>base64_decode<\/code>.<\/li>\n<li>Disallow empty().<\/li>\n<li>Require calling parent constructor.<\/li>\n<\/ul>\n\n<p>You can enable and disable rules as needed but, like setting the PHPStan level, ideally I like to enable them all by default and see how strict I go.<\/p>\n\n<p>It depends on the code being tested and the preference of the team, though I find the stricter the rules, the less bugs there are.<\/p>\n\n ",
"processed": "\n <p>Continuing yesterday's thought on <a href=\"/daily\/2024\/05\/04\/strict-typing-in-php\">strictness in PHP<\/a>, today I want to talk about adding more strictness to PHPStan.<\/p>\n\n<p>Adding the <a href=\"https:\/\/github.com\/phpstan\/phpstan-strict-rules\">PHPStan Strict Rules extension<\/a> makes PHPStan stricter by adding new, more opinionated rules.<\/p>\n\n<p>For example:<\/p>\n\n<ul>\n<li>Require booleans in if, elseif, ternary operator, after !, and on both sides of &amp;&amp; and ||.<\/li>\n<li>Use the <code>$strict<\/code> parameter with <code>in_array<\/code>, <code>array_search<\/code>, <code>array_keys<\/code> and <code>base64_decode<\/code>.<\/li>\n<li>Disallow empty().<\/li>\n<li>Require calling parent constructor.<\/li>\n<\/ul>\n\n<p>You can enable and disable rules as needed but, like setting the PHPStan level, ideally I like to enable them all by default and see how strict I go.<\/p>\n\n<p>It depends on the code being tested and the preference of the team, though I find the stricter the rules, the less bugs there are.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>One of the main uses for <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/07\/02\/ci-not-ci-pipeline\">a CI pipeline<\/a> is to build artifacts for your application, such as installing your dependencies using Composer or npm, or using build tools to perform tasks such as building your CSS and JavaScript assets.<\/p>\n\n<p>Performing these tasks in a CI pipeline means the resulting files can be ignored from your code repository and not committed - making your commits smaller and easier to review, and less likely for you to encounter merge conflicts.<\/p>\n\n<p>The alternative approach is to not use a CI pipline and to perform the tasks manually and commit them to your repository.<\/p>\n\n<p>This introduces a separate set of challenges, but people like having the files in their repository and not worrying about failures in their pipeline.<\/p>\n\n<p>Which do you prefer?<\/p>\n\n ",
"value": "\n <p>One of the main uses for <a href=\"/daily\/2024\/07\/02\/ci-not-ci-pipeline\">a CI pipeline<\/a> is to build artifacts for your application, such as installing your dependencies using Composer or npm, or using build tools to perform tasks such as building your CSS and JavaScript assets.<\/p>\n\n<p>Performing these tasks in a CI pipeline means the resulting files can be ignored from your code repository and not committed - making your commits smaller and easier to review, and less likely for you to encounter merge conflicts.<\/p>\n\n<p>The alternative approach is to not use a CI pipline and to perform the tasks manually and commit them to your repository.<\/p>\n\n<p>This introduces a separate set of challenges, but people like having the files in their repository and not worrying about failures in their pipeline.<\/p>\n\n<p>Which do you prefer?<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>One of the main uses for <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/07\/02\/ci-not-ci-pipeline\">a CI pipeline<\/a> is to build artifacts for your application, such as installing your dependencies using Composer or npm, or using build tools to perform tasks such as building your CSS and JavaScript assets.<\/p>\n\n<p>Performing these tasks in a CI pipeline means the resulting files can be ignored from your code repository and not committed - making your commits smaller and easier to review, and less likely for you to encounter merge conflicts.<\/p>\n\n<p>The alternative approach is to not use a CI pipline and to perform the tasks manually and commit them to your repository.<\/p>\n\n<p>This introduces a separate set of challenges, but people like having the files in their repository and not worrying about failures in their pipeline.<\/p>\n\n<p>Which do you prefer?<\/p>\n\n ",
"processed": "\n <p>One of the main uses for <a href=\"/daily\/2024\/07\/02\/ci-not-ci-pipeline\">a CI pipeline<\/a> is to build artifacts for your application, such as installing your dependencies using Composer or npm, or using build tools to perform tasks such as building your CSS and JavaScript assets.<\/p>\n\n<p>Performing these tasks in a CI pipeline means the resulting files can be ignored from your code repository and not committed - making your commits smaller and easier to review, and less likely for you to encounter merge conflicts.<\/p>\n\n<p>The alternative approach is to not use a CI pipline and to perform the tasks manually and commit them to your repository.<\/p>\n\n<p>This introduces a separate set of challenges, but people like having the files in their repository and not worrying about failures in their pipeline.<\/p>\n\n<p>Which do you prefer?<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>It's been <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/08\/08\/8-years-of-dotfiles\">more than nine years<\/a> since I started <a href=\"https:\/\/github.com\/opdavies\/dotfiles.nix\">my dotfiles repository<\/a>, which is a collection of configuration files for tools I use.<\/p>\n\n<p>Originally containing my <code>.gitconfig<\/code> configuration file for Git, it now contains my configuration for Neovim, tmux, Git and a lot more.<\/p>\n\n<p>One of the things I like is being able to see and read other peoples' dotfiles and take inspiration from their configurations.<\/p>\n\n<p>I see some configurations that are very complex and customised, and some which are simpler.<\/p>\n\n<p>Recently, I've been thinking about how much customisation is too much, and moving towards a more minimal configuration.<\/p>\n\n<p>This isn't specific to command-line tools and also applies to customising GUI programs such as PhpStorm or VSCode.<\/p>\n\n<p>A more complex configuration means more code to maintain.<\/p>\n\n<p>It's more difficult to work on different computers, whether you're pair or mob programming, or working on a remote server. Would you still be productive if you didn't have all your configurations?<\/p>\n\n<p>If you've changed the default behaviour of a command, such as not allowing merge commits in Git or rebasing by default, if someone doesn't have that same option, is that going to cause confusion or introduce inconsistencies?<\/p>\n\n<p>I'm not going to reset all my configuration files to their default values, but I'll continue to review and decide whether I want to customise something on a case by case basis and whether adding it - especially if it's a larger addition, such as adding a Vim plugin - is worth the maintenance overhead.<\/p>\n\n<p>The same as in an application, I don't want to add modules or plugins that I'm not going to use or aren't adding value, and I want to ensure I'm making the most of what the software offers.<\/p>\n\n ",
"value": "\n <p>It's been <a href=\"/daily\/2023\/08\/08\/8-years-of-dotfiles\">more than nine years<\/a> since I started <a href=\"https:\/\/github.com\/opdavies\/dotfiles.nix\">my dotfiles repository<\/a>, which is a collection of configuration files for tools I use.<\/p>\n\n<p>Originally containing my <code>.gitconfig<\/code> configuration file for Git, it now contains my configuration for Neovim, tmux, Git and a lot more.<\/p>\n\n<p>One of the things I like is being able to see and read other peoples' dotfiles and take inspiration from their configurations.<\/p>\n\n<p>I see some configurations that are very complex and customised, and some which are simpler.<\/p>\n\n<p>Recently, I've been thinking about how much customisation is too much, and moving towards a more minimal configuration.<\/p>\n\n<p>This isn't specific to command-line tools and also applies to customising GUI programs such as PhpStorm or VSCode.<\/p>\n\n<p>A more complex configuration means more code to maintain.<\/p>\n\n<p>It's more difficult to work on different computers, whether you're pair or mob programming, or working on a remote server. Would you still be productive if you didn't have all your configurations?<\/p>\n\n<p>If you've changed the default behaviour of a command, such as not allowing merge commits in Git or rebasing by default, if someone doesn't have that same option, is that going to cause confusion or introduce inconsistencies?<\/p>\n\n<p>I'm not going to reset all my configuration files to their default values, but I'll continue to review and decide whether I want to customise something on a case by case basis and whether adding it - especially if it's a larger addition, such as adding a Vim plugin - is worth the maintenance overhead.<\/p>\n\n<p>The same as in an application, I don't want to add modules or plugins that I'm not going to use or aren't adding value, and I want to ensure I'm making the most of what the software offers.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>It's been <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/08\/08\/8-years-of-dotfiles\">more than nine years<\/a> since I started <a href=\"https:\/\/github.com\/opdavies\/dotfiles.nix\">my dotfiles repository<\/a>, which is a collection of configuration files for tools I use.<\/p>\n\n<p>Originally containing my <code>.gitconfig<\/code> configuration file for Git, it now contains my configuration for Neovim, tmux, Git and a lot more.<\/p>\n\n<p>One of the things I like is being able to see and read other peoples' dotfiles and take inspiration from their configurations.<\/p>\n\n<p>I see some configurations that are very complex and customised, and some which are simpler.<\/p>\n\n<p>Recently, I've been thinking about how much customisation is too much, and moving towards a more minimal configuration.<\/p>\n\n<p>This isn't specific to command-line tools and also applies to customising GUI programs such as PhpStorm or VSCode.<\/p>\n\n<p>A more complex configuration means more code to maintain.<\/p>\n\n<p>It's more difficult to work on different computers, whether you're pair or mob programming, or working on a remote server. Would you still be productive if you didn't have all your configurations?<\/p>\n\n<p>If you've changed the default behaviour of a command, such as not allowing merge commits in Git or rebasing by default, if someone doesn't have that same option, is that going to cause confusion or introduce inconsistencies?<\/p>\n\n<p>I'm not going to reset all my configuration files to their default values, but I'll continue to review and decide whether I want to customise something on a case by case basis and whether adding it - especially if it's a larger addition, such as adding a Vim plugin - is worth the maintenance overhead.<\/p>\n\n<p>The same as in an application, I don't want to add modules or plugins that I'm not going to use or aren't adding value, and I want to ensure I'm making the most of what the software offers.<\/p>\n\n ",
"processed": "\n <p>It's been <a href=\"/daily\/2023\/08\/08\/8-years-of-dotfiles\">more than nine years<\/a> since I started <a href=\"https:\/\/github.com\/opdavies\/dotfiles.nix\">my dotfiles repository<\/a>, which is a collection of configuration files for tools I use.<\/p>\n\n<p>Originally containing my <code>.gitconfig<\/code> configuration file for Git, it now contains my configuration for Neovim, tmux, Git and a lot more.<\/p>\n\n<p>One of the things I like is being able to see and read other peoples' dotfiles and take inspiration from their configurations.<\/p>\n\n<p>I see some configurations that are very complex and customised, and some which are simpler.<\/p>\n\n<p>Recently, I've been thinking about how much customisation is too much, and moving towards a more minimal configuration.<\/p>\n\n<p>This isn't specific to command-line tools and also applies to customising GUI programs such as PhpStorm or VSCode.<\/p>\n\n<p>A more complex configuration means more code to maintain.<\/p>\n\n<p>It's more difficult to work on different computers, whether you're pair or mob programming, or working on a remote server. Would you still be productive if you didn't have all your configurations?<\/p>\n\n<p>If you've changed the default behaviour of a command, such as not allowing merge commits in Git or rebasing by default, if someone doesn't have that same option, is that going to cause confusion or introduce inconsistencies?<\/p>\n\n<p>I'm not going to reset all my configuration files to their default values, but I'll continue to review and decide whether I want to customise something on a case by case basis and whether adding it - especially if it's a larger addition, such as adding a Vim plugin - is worth the maintenance overhead.<\/p>\n\n<p>The same as in an application, I don't want to add modules or plugins that I'm not going to use or aren't adding value, and I want to ensure I'm making the most of what the software offers.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Yesterday, I posted a screenshot from my <a href=\"https:\/\/www.oliverdavies.uk\/atdc\">automated testing in Drupal email course<\/a> on Twitter as a sneak peek of what's included.<\/p>\n\n<p>Here it is again:<\/p>\n\n<p><img src=\"https:\/\/www.oliverdavies.uk\/assets\/images\/php-neovim-1.png\" alt=\"Screenshot of a lesson from my automated testing email course\" \/><\/p>\n\n<p>I also posted a screenshot of the accompanying code in my text editor, Neovim, which had a few likes.<\/p>\n\n<p><img src=\"https:\/\/www.oliverdavies.uk\/assets\/images\/php-neovim-2.png\" alt=\"Screenshot of Drupal code in Neovim\" \/><\/p>\n\n<p>Since July 2021, I've used Neovim as my daily driver for writing all my code, which I spoke about during my <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/working-without-workspace\">Working without Workspace talk<\/a>.<\/p>\n\n<p>You can also see my NixOS-based <a href=\"https:\/\/github.com\/opdavies\/dotfiles\">dotfiles on GitHub<\/a> which contains my Neovim configuration.<\/p>\n\n<p>Register now to find out when the email course is live, or <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/12\/25\/zero-to-test\">read the first lesson<\/a>.<\/p>\n\n ",
"value": "\n <p>Yesterday, I posted a screenshot from my <a href=\"/atdc\">automated testing in Drupal email course<\/a> on Twitter as a sneak peek of what's included.<\/p>\n\n<p>Here it is again:<\/p>\n\n<p><img src=\"https:\/\/www.oliverdavies.uk\/assets\/images\/php-neovim-1.png\" alt=\"Screenshot of a lesson from my automated testing email course\" \/><\/p>\n\n<p>I also posted a screenshot of the accompanying code in my text editor, Neovim, which had a few likes.<\/p>\n\n<p><img src=\"https:\/\/www.oliverdavies.uk\/assets\/images\/php-neovim-2.png\" alt=\"Screenshot of Drupal code in Neovim\" \/><\/p>\n\n<p>Since July 2021, I've used Neovim as my daily driver for writing all my code, which I spoke about during my <a href=\"/presentations\/working-without-workspace\">Working without Workspace talk<\/a>.<\/p>\n\n<p>You can also see my NixOS-based <a href=\"https:\/\/github.com\/opdavies\/dotfiles\">dotfiles on GitHub<\/a> which contains my Neovim configuration.<\/p>\n\n<p>Register now to find out when the email course is live, or <a href=\"/daily\/2023\/12\/25\/zero-to-test\">read the first lesson<\/a>.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Yesterday, I posted a screenshot from my <a href=\"https:\/\/www.oliverdavies.uk\/atdc\">automated testing in Drupal email course<\/a> on Twitter as a sneak peek of what's included.<\/p>\n\n<p>Here it is again:<\/p>\n\n<p><img src=\"https:\/\/www.oliverdavies.uk\/assets\/images\/php-neovim-1.png\" alt=\"Screenshot of a lesson from my automated testing email course\"><\/p>\n\n<p>I also posted a screenshot of the accompanying code in my text editor, Neovim, which had a few likes.<\/p>\n\n<p><img src=\"https:\/\/www.oliverdavies.uk\/assets\/images\/php-neovim-2.png\" alt=\"Screenshot of Drupal code in Neovim\"><\/p>\n\n<p>Since July 2021, I've used Neovim as my daily driver for writing all my code, which I spoke about during my <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/working-without-workspace\">Working without Workspace talk<\/a>.<\/p>\n\n<p>You can also see my NixOS-based <a href=\"https:\/\/github.com\/opdavies\/dotfiles\">dotfiles on GitHub<\/a> which contains my Neovim configuration.<\/p>\n\n<p>Register now to find out when the email course is live, or <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2023\/12\/25\/zero-to-test\">read the first lesson<\/a>.<\/p>\n\n ",
"processed": "\n <p>Yesterday, I posted a screenshot from my <a href=\"/atdc\">automated testing in Drupal email course<\/a> on Twitter as a sneak peek of what's included.<\/p>\n\n<p>Here it is again:<\/p>\n\n<p><img src=\"https:\/\/www.oliverdavies.uk\/assets\/images\/php-neovim-1.png\" alt=\"Screenshot of a lesson from my automated testing email course\"><\/p>\n\n<p>I also posted a screenshot of the accompanying code in my text editor, Neovim, which had a few likes.<\/p>\n\n<p><img src=\"https:\/\/www.oliverdavies.uk\/assets\/images\/php-neovim-2.png\" alt=\"Screenshot of Drupal code in Neovim\"><\/p>\n\n<p>Since July 2021, I've used Neovim as my daily driver for writing all my code, which I spoke about during my <a href=\"/presentations\/working-without-workspace\">Working without Workspace talk<\/a>.<\/p>\n\n<p>You can also see my NixOS-based <a href=\"https:\/\/github.com\/opdavies\/dotfiles\">dotfiles on GitHub<\/a> which contains my Neovim configuration.<\/p>\n\n<p>Register now to find out when the email course is live, or <a href=\"/daily\/2023\/12\/25\/zero-to-test\">read the first lesson<\/a>.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>Last week, I recorded an episode of <a href=\"https:\/\/www.oliverdavies.uk\/podcast\">Beyond Blocks<\/a> with Eirik Morland - the Developer of violinist.io, a tool for automating dependency updates in PHP projects.<\/p>\n\n<p>Instead of a person manually running <code>composer update<\/code> in each project, tools like Violinist can do that for you and submit pull or merge requests to your project for you to review.<\/p>\n\n<p>But why would you want this?<\/p>\n\n<p>There are technical reasons, such as not having to rely on everyone having the same local environment and avoiding potential conflicts, and consistency by ensuring the same command is run every time.<\/p>\n\n<p>But, the big advantage, in my opinion, is the time it saves and allows you to reuse.<\/p>\n\n<p>Instead of manually updating each project's dependencies, I can focus on tasks that deliver value to my customers and clients and move us towards our objectives.<\/p>\n\n<p>Dependency updates, such as a new version of Drupal core or a contrib module, don't contain any perceived value compared to other tasks, such as adding a new feature or fixing a bug.<\/p>\n\n<p>They happen behind the scenes, often invisibly, without any visual changes to show an update has been done.<\/p>\n\n<p>If they aren't done often, they will be riskier to deploy due to the larger changes, and the longer it takes, the greater the potential for insecure versions to be exploited - potentially affecting your reputation and your customer's and with any remedial work taking the focus from other tasks.<\/p>\n\n<p>Having a service like Violinist performing the updates for you means they can be applied and deployed more regularly, reducing the risk and making it easier to stay up-to-date and run secure versions of your dependencies.<\/p>\n\n ",
"value": "\n <p>Last week, I recorded an episode of <a href=\"/podcast\">Beyond Blocks<\/a> with Eirik Morland - the Developer of violinist.io, a tool for automating dependency updates in PHP projects.<\/p>\n\n<p>Instead of a person manually running <code>composer update<\/code> in each project, tools like Violinist can do that for you and submit pull or merge requests to your project for you to review.<\/p>\n\n<p>But why would you want this?<\/p>\n\n<p>There are technical reasons, such as not having to rely on everyone having the same local environment and avoiding potential conflicts, and consistency by ensuring the same command is run every time.<\/p>\n\n<p>But, the big advantage, in my opinion, is the time it saves and allows you to reuse.<\/p>\n\n<p>Instead of manually updating each project's dependencies, I can focus on tasks that deliver value to my customers and clients and move us towards our objectives.<\/p>\n\n<p>Dependency updates, such as a new version of Drupal core or a contrib module, don't contain any perceived value compared to other tasks, such as adding a new feature or fixing a bug.<\/p>\n\n<p>They happen behind the scenes, often invisibly, without any visual changes to show an update has been done.<\/p>\n\n<p>If they aren't done often, they will be riskier to deploy due to the larger changes, and the longer it takes, the greater the potential for insecure versions to be exploited - potentially affecting your reputation and your customer's and with any remedial work taking the focus from other tasks.<\/p>\n\n<p>Having a service like Violinist performing the updates for you means they can be applied and deployed more regularly, reducing the risk and making it easier to stay up-to-date and run secure versions of your dependencies.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>Last week, I recorded an episode of <a href=\"https:\/\/www.oliverdavies.uk\/podcast\">Beyond Blocks<\/a> with Eirik Morland - the Developer of violinist.io, a tool for automating dependency updates in PHP projects.<\/p>\n\n<p>Instead of a person manually running <code>composer update<\/code> in each project, tools like Violinist can do that for you and submit pull or merge requests to your project for you to review.<\/p>\n\n<p>But why would you want this?<\/p>\n\n<p>There are technical reasons, such as not having to rely on everyone having the same local environment and avoiding potential conflicts, and consistency by ensuring the same command is run every time.<\/p>\n\n<p>But, the big advantage, in my opinion, is the time it saves and allows you to reuse.<\/p>\n\n<p>Instead of manually updating each project's dependencies, I can focus on tasks that deliver value to my customers and clients and move us towards our objectives.<\/p>\n\n<p>Dependency updates, such as a new version of Drupal core or a contrib module, don't contain any perceived value compared to other tasks, such as adding a new feature or fixing a bug.<\/p>\n\n<p>They happen behind the scenes, often invisibly, without any visual changes to show an update has been done.<\/p>\n\n<p>If they aren't done often, they will be riskier to deploy due to the larger changes, and the longer it takes, the greater the potential for insecure versions to be exploited - potentially affecting your reputation and your customer's and with any remedial work taking the focus from other tasks.<\/p>\n\n<p>Having a service like Violinist performing the updates for you means they can be applied and deployed more regularly, reducing the risk and making it easier to stay up-to-date and run secure versions of your dependencies.<\/p>\n\n ",
"processed": "\n <p>Last week, I recorded an episode of <a href=\"/podcast\">Beyond Blocks<\/a> with Eirik Morland - the Developer of violinist.io, a tool for automating dependency updates in PHP projects.<\/p>\n\n<p>Instead of a person manually running <code>composer update<\/code> in each project, tools like Violinist can do that for you and submit pull or merge requests to your project for you to review.<\/p>\n\n<p>But why would you want this?<\/p>\n\n<p>There are technical reasons, such as not having to rely on everyone having the same local environment and avoiding potential conflicts, and consistency by ensuring the same command is run every time.<\/p>\n\n<p>But, the big advantage, in my opinion, is the time it saves and allows you to reuse.<\/p>\n\n<p>Instead of manually updating each project's dependencies, I can focus on tasks that deliver value to my customers and clients and move us towards our objectives.<\/p>\n\n<p>Dependency updates, such as a new version of Drupal core or a contrib module, don't contain any perceived value compared to other tasks, such as adding a new feature or fixing a bug.<\/p>\n\n<p>They happen behind the scenes, often invisibly, without any visual changes to show an update has been done.<\/p>\n\n<p>If they aren't done often, they will be riskier to deploy due to the larger changes, and the longer it takes, the greater the potential for insecure versions to be exploited - potentially affecting your reputation and your customer's and with any remedial work taking the focus from other tasks.<\/p>\n\n<p>Having a service like Violinist performing the updates for you means they can be applied and deployed more regularly, reducing the risk and making it easier to stay up-to-date and run secure versions of your dependencies.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>It was announced this week at DrupalCon that the end-of-life date for Drupal 7 has been extended until the 5th of January 2025, giving another year for people to upgrade the 40,000+ Drupal 7 websites.<\/p>\n\n<p>Whilst there's no official announcement yet, it seems this is the final extension and will be when support ends.<\/p>\n\n<p>Of course, it doesn't mean all of the contributed modules, themes and distributions will be supported or updated until then, but this will give additional time to plan and migrate the remaining Drupal 7 websites whilst still giving clarity by setting a final date that will not be extended again.<\/p>\n\n<p>If you're still on Drupal 7 and need to learn more about upgrading to Drupal 10, <a href=\"https:\/\/www.oliverdavies.uk\/call\">book an advisory call<\/a> or <a href=\"https:\/\/www.oliverdavies.uk\/drupal7\">an upgrade roadmap<\/a> for your Drupal 7 project.<\/p>\n\n ",
"value": "\n <p>It was announced this week at DrupalCon that the end-of-life date for Drupal 7 has been extended until the 5th of January 2025, giving another year for people to upgrade the 40,000+ Drupal 7 websites.<\/p>\n\n<p>Whilst there's no official announcement yet, it seems this is the final extension and will be when support ends.<\/p>\n\n<p>Of course, it doesn't mean all of the contributed modules, themes and distributions will be supported or updated until then, but this will give additional time to plan and migrate the remaining Drupal 7 websites whilst still giving clarity by setting a final date that will not be extended again.<\/p>\n\n<p>If you're still on Drupal 7 and need to learn more about upgrading to Drupal 10, <a href=\"/call\">book an advisory call<\/a> or <a href=\"/drupal7\">an upgrade roadmap<\/a> for your Drupal 7 project.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>It was announced this week at DrupalCon that the end-of-life date for Drupal 7 has been extended until the 5th of January 2025, giving another year for people to upgrade the 40,000+ Drupal 7 websites.<\/p>\n\n<p>Whilst there's no official announcement yet, it seems this is the final extension and will be when support ends.<\/p>\n\n<p>Of course, it doesn't mean all of the contributed modules, themes and distributions will be supported or updated until then, but this will give additional time to plan and migrate the remaining Drupal 7 websites whilst still giving clarity by setting a final date that will not be extended again.<\/p>\n\n<p>If you're still on Drupal 7 and need to learn more about upgrading to Drupal 10, <a href=\"https:\/\/www.oliverdavies.uk\/call\">book an advisory call<\/a> or <a href=\"https:\/\/www.oliverdavies.uk\/drupal7\">an upgrade roadmap<\/a> for your Drupal 7 project.<\/p>\n\n ",
"processed": "\n <p>It was announced this week at DrupalCon that the end-of-life date for Drupal 7 has been extended until the 5th of January 2025, giving another year for people to upgrade the 40,000+ Drupal 7 websites.<\/p>\n\n<p>Whilst there's no official announcement yet, it seems this is the final extension and will be when support ends.<\/p>\n\n<p>Of course, it doesn't mean all of the contributed modules, themes and distributions will be supported or updated until then, but this will give additional time to plan and migrate the remaining Drupal 7 websites whilst still giving clarity by setting a final date that will not be extended again.<\/p>\n\n<p>If you're still on Drupal 7 and need to learn more about upgrading to Drupal 10, <a href=\"/call\">book an advisory call<\/a> or <a href=\"/drupal7\">an upgrade roadmap<\/a> for your Drupal 7 project.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>As well as being <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/03\/12\/easy\">easy to build<\/a> and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/03\/13\/deploy\">simple to deploy<\/a>, static websites are easy to backup and, if needed, restore.<\/p>\n\n<p>I backup several static websites from my server using rsync - the same command I use to deploy them.<\/p>\n\n<p>rsync is fast as it only downloads files that have changed, so backing up several websites only takes a few seconds.<\/p>\n\n<p>There are are no databases to worry about - all I need to do is backup the static files themselves.<\/p>\n\n<p>Running the backups is also easy.<\/p>\n\n<p>I have a scheduled cron job that downloads everything from the <code>\/var\/www\/vhosts<\/code> directory on my server and creates a local copy.<\/p>\n\n<p>If I need to restore from a backup or migrate to a different server, I just run the appropriate rsync command to re-upload them - the same as how I deployed them originally.<\/p>\n\n ",
"value": "\n <p>As well as being <a href=\"/daily\/2025\/03\/12\/easy\">easy to build<\/a> and <a href=\"/daily\/2025\/03\/13\/deploy\">simple to deploy<\/a>, static websites are easy to backup and, if needed, restore.<\/p>\n\n<p>I backup several static websites from my server using rsync - the same command I use to deploy them.<\/p>\n\n<p>rsync is fast as it only downloads files that have changed, so backing up several websites only takes a few seconds.<\/p>\n\n<p>There are are no databases to worry about - all I need to do is backup the static files themselves.<\/p>\n\n<p>Running the backups is also easy.<\/p>\n\n<p>I have a scheduled cron job that downloads everything from the <code>\/var\/www\/vhosts<\/code> directory on my server and creates a local copy.<\/p>\n\n<p>If I need to restore from a backup or migrate to a different server, I just run the appropriate rsync command to re-upload them - the same as how I deployed them originally.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>As well as being <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/03\/12\/easy\">easy to build<\/a> and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/03\/13\/deploy\">simple to deploy<\/a>, static websites are easy to backup and, if needed, restore.<\/p>\n\n<p>I backup several static websites from my server using rsync - the same command I use to deploy them.<\/p>\n\n<p>rsync is fast as it only downloads files that have changed, so backing up several websites only takes a few seconds.<\/p>\n\n<p>There are are no databases to worry about - all I need to do is backup the static files themselves.<\/p>\n\n<p>Running the backups is also easy.<\/p>\n\n<p>I have a scheduled cron job that downloads everything from the <code>\/var\/www\/vhosts<\/code> directory on my server and creates a local copy.<\/p>\n\n<p>If I need to restore from a backup or migrate to a different server, I just run the appropriate rsync command to re-upload them - the same as how I deployed them originally.<\/p>\n\n ",
"processed": "\n <p>As well as being <a href=\"/daily\/2025\/03\/12\/easy\">easy to build<\/a> and <a href=\"/daily\/2025\/03\/13\/deploy\">simple to deploy<\/a>, static websites are easy to backup and, if needed, restore.<\/p>\n\n<p>I backup several static websites from my server using rsync - the same command I use to deploy them.<\/p>\n\n<p>rsync is fast as it only downloads files that have changed, so backing up several websites only takes a few seconds.<\/p>\n\n<p>There are are no databases to worry about - all I need to do is backup the static files themselves.<\/p>\n\n<p>Running the backups is also easy.<\/p>\n\n<p>I have a scheduled cron job that downloads everything from the <code>\/var\/www\/vhosts<\/code> directory on my server and creates a local copy.<\/p>\n\n<p>If I need to restore from a backup or migrate to a different server, I just run the appropriate rsync command to re-upload them - the same as how I deployed them originally.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/25\/nix-the-package-manager\">As well as Nix managing packages<\/a> and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/27\/nix-as-an-operating-system\">NixOS as your operating system<\/a>, you can use Nix to manage your user configuration and dotfiles.<\/p>\n\n<p>Enter, Home Manager.<\/p>\n\n<p>Home Manager is available as a module for NixOS and a standalone package for other Linux distributions and macOS.<\/p>\n\n<p>With it, you can install and configure programs for specific users and create and manage dotfiles such as .gitconfig, .tmux.conf and .zshrc instead of using a tool like Stow.<\/p>\n\n<p>There's also the extra benefit that <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/21\/one-configuration-language-to-rule-them-all\">you can write these files in the Nix language<\/a> and only focus on one configuration language.<\/p>\n\n<p>Nix and Home Manager will create the desired output file in whatever the program wants, whether it's JSON, ini, YAML or something else.<\/p>\n\n<p>A good example is <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/3acd73f6a2e19eadcc16baf22afad5dfad5e049b\/nix\/modules\/home-manager\/features\/cli\/git.nix\">my .gitconfig configuration<\/a>. It includes settings for Git itself, aliases, global excludes, adds extra packages such as <a href=\"https:\/\/zet.oliverdavies.uk\/notes\/10\">git-instafix<\/a> and some environment variables.<\/p>\n\n<p>All in one file and all in one language.<\/p>\n\n ",
"value": "\n <p><a href=\"/daily\/2024\/11\/25\/nix-the-package-manager\">As well as Nix managing packages<\/a> and <a href=\"/daily\/2024\/11\/27\/nix-as-an-operating-system\">NixOS as your operating system<\/a>, you can use Nix to manage your user configuration and dotfiles.<\/p>\n\n<p>Enter, Home Manager.<\/p>\n\n<p>Home Manager is available as a module for NixOS and a standalone package for other Linux distributions and macOS.<\/p>\n\n<p>With it, you can install and configure programs for specific users and create and manage dotfiles such as .gitconfig, .tmux.conf and .zshrc instead of using a tool like Stow.<\/p>\n\n<p>There's also the extra benefit that <a href=\"/daily\/2024\/11\/21\/one-configuration-language-to-rule-them-all\">you can write these files in the Nix language<\/a> and only focus on one configuration language.<\/p>\n\n<p>Nix and Home Manager will create the desired output file in whatever the program wants, whether it's JSON, ini, YAML or something else.<\/p>\n\n<p>A good example is <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/3acd73f6a2e19eadcc16baf22afad5dfad5e049b\/nix\/modules\/home-manager\/features\/cli\/git.nix\">my .gitconfig configuration<\/a>. It includes settings for Git itself, aliases, global excludes, adds extra packages such as <a href=\"https:\/\/zet.oliverdavies.uk\/notes\/10\">git-instafix<\/a> and some environment variables.<\/p>\n\n<p>All in one file and all in one language.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/25\/nix-the-package-manager\">As well as Nix managing packages<\/a> and <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/27\/nix-as-an-operating-system\">NixOS as your operating system<\/a>, you can use Nix to manage your user configuration and dotfiles.<\/p>\n\n<p>Enter, Home Manager.<\/p>\n\n<p>Home Manager is available as a module for NixOS and a standalone package for other Linux distributions and macOS.<\/p>\n\n<p>With it, you can install and configure programs for specific users and create and manage dotfiles such as .gitconfig, .tmux.conf and .zshrc instead of using a tool like Stow.<\/p>\n\n<p>There's also the extra benefit that <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/21\/one-configuration-language-to-rule-them-all\">you can write these files in the Nix language<\/a> and only focus on one configuration language.<\/p>\n\n<p>Nix and Home Manager will create the desired output file in whatever the program wants, whether it's JSON, ini, YAML or something else.<\/p>\n\n<p>A good example is <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/3acd73f6a2e19eadcc16baf22afad5dfad5e049b\/nix\/modules\/home-manager\/features\/cli\/git.nix\">my .gitconfig configuration<\/a>. It includes settings for Git itself, aliases, global excludes, adds extra packages such as <a href=\"https:\/\/zet.oliverdavies.uk\/notes\/10\">git-instafix<\/a> and some environment variables.<\/p>\n\n<p>All in one file and all in one language.<\/p>\n\n ",
"processed": "\n <p><a href=\"/daily\/2024\/11\/25\/nix-the-package-manager\">As well as Nix managing packages<\/a> and <a href=\"/daily\/2024\/11\/27\/nix-as-an-operating-system\">NixOS as your operating system<\/a>, you can use Nix to manage your user configuration and dotfiles.<\/p>\n\n<p>Enter, Home Manager.<\/p>\n\n<p>Home Manager is available as a module for NixOS and a standalone package for other Linux distributions and macOS.<\/p>\n\n<p>With it, you can install and configure programs for specific users and create and manage dotfiles such as .gitconfig, .tmux.conf and .zshrc instead of using a tool like Stow.<\/p>\n\n<p>There's also the extra benefit that <a href=\"/daily\/2024\/11\/21\/one-configuration-language-to-rule-them-all\">you can write these files in the Nix language<\/a> and only focus on one configuration language.<\/p>\n\n<p>Nix and Home Manager will create the desired output file in whatever the program wants, whether it's JSON, ini, YAML or something else.<\/p>\n\n<p>A good example is <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/3acd73f6a2e19eadcc16baf22afad5dfad5e049b\/nix\/modules\/home-manager\/features\/cli\/git.nix\">my .gitconfig configuration<\/a>. It includes settings for Git itself, aliases, global excludes, adds extra packages such as <a href=\"https:\/\/zet.oliverdavies.uk\/notes\/10\">git-instafix<\/a> and some environment variables.<\/p>\n\n<p>All in one file and all in one language.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>How often have you need code like this?<\/p>\n\n<pre><code class=\"php\">\/\/ Returns true.\nreturn false;\n<\/code><\/pre>\n\n<p>Whilst a comment like this could have been true when it was written, the code can change independently of the comment - making them out of sync and the comment no longer true.<\/p>\n\n<p>As the comment is not evaluated or executed, there isn't a way to validate whether it's still correct, so whilst it could be, it may not be.<\/p>\n\n<p>Comments should describe why the code is needed, not what it does.<\/p>\n\n<p>If a comment describes the functionality, it can be refactored and extracted to a class, method or function - a.k.a. self-documenting code.<\/p>\n\n<p>But, if you want something that will alert you if the functionality changes, look into <a href=\"https:\/\/www.oliverdavies.uk\/atdc\">automated testing<\/a>.<\/p>\n\n<p>If you have a passing test that suddenly starts to fail, you know the behaviour has changed.<\/p>\n\n ",
"value": "\n <p>How often have you need code like this?<\/p>\n\n<pre><code class=\"php\">\/\/ Returns true.\nreturn false;\n<\/code><\/pre>\n\n<p>Whilst a comment like this could have been true when it was written, the code can change independently of the comment - making them out of sync and the comment no longer true.<\/p>\n\n<p>As the comment is not evaluated or executed, there isn't a way to validate whether it's still correct, so whilst it could be, it may not be.<\/p>\n\n<p>Comments should describe why the code is needed, not what it does.<\/p>\n\n<p>If a comment describes the functionality, it can be refactored and extracted to a class, method or function - a.k.a. self-documenting code.<\/p>\n\n<p>But, if you want something that will alert you if the functionality changes, look into <a href=\"/atdc\">automated testing<\/a>.<\/p>\n\n<p>If you have a passing test that suddenly starts to fail, you know the behaviour has changed.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>How often have you need code like this?<\/p>\n\n<pre><code class=\"php\">\/\/ Returns true.\nreturn false;\n<\/code><\/pre>\n\n<p>Whilst a comment like this could have been true when it was written, the code can change independently of the comment - making them out of sync and the comment no longer true.<\/p>\n\n<p>As the comment is not evaluated or executed, there isn't a way to validate whether it's still correct, so whilst it could be, it may not be.<\/p>\n\n<p>Comments should describe why the code is needed, not what it does.<\/p>\n\n<p>If a comment describes the functionality, it can be refactored and extracted to a class, method or function - a.k.a. self-documenting code.<\/p>\n\n<p>But, if you want something that will alert you if the functionality changes, look into <a href=\"https:\/\/www.oliverdavies.uk\/atdc\">automated testing<\/a>.<\/p>\n\n<p>If you have a passing test that suddenly starts to fail, you know the behaviour has changed.<\/p>\n\n ",
"processed": "\n <p>How often have you need code like this?<\/p>\n\n<pre><code class=\"php\">\/\/ Returns true.\nreturn false;\n<\/code><\/pre>\n\n<p>Whilst a comment like this could have been true when it was written, the code can change independently of the comment - making them out of sync and the comment no longer true.<\/p>\n\n<p>As the comment is not evaluated or executed, there isn't a way to validate whether it's still correct, so whilst it could be, it may not be.<\/p>\n\n<p>Comments should describe why the code is needed, not what it does.<\/p>\n\n<p>If a comment describes the functionality, it can be refactored and extracted to a class, method or function - a.k.a. self-documenting code.<\/p>\n\n<p>But, if you want something that will alert you if the functionality changes, look into <a href=\"/atdc\">automated testing<\/a>.<\/p>\n\n<p>If you have a passing test that suddenly starts to fail, you know the behaviour has changed.<\/p>\n\n ",
"summary": null
}
],

View file

@ -82,9 +82,9 @@
],
"body": [
{
"value": "\n <p>After starting with jQuery in Drupal 6 and moving to full JavaScript frameworks like Vue, I've recently been using Stimulus when adding JavaScript to my projects.<\/p>\n\n<p>After finding it via SymfonyCasts and Symfony UX (I can't remember if Ryan and I discussed it <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/10-ryan-weaver-symfonycasts\">in our podcast episode<\/a>), I like that it works on top of my existing HTML and Twig templates instead of having to rewrite or duplicate all the markup.<\/p>\n\n<p>You enable and configure it with data attributes like <code>data-controller<\/code> and <code>data-action<\/code> in your HTML which refer to separate JavaScript classes and methods, so you have some structure and organisation compared to putting all the logic in Twig.<\/p>\n\n<p>Having separate controllers also makes it easy to reuse logic in other parts of your application or extract it for use in other projects.<\/p>\n\n<p>If you want an example of how I've set up stimulus with esbuild, <a href=\"https:\/\/github.com\/opdavies\/stimulus-esbuild-example\">take a look at this GitHub repository<\/a>, or <a href=\"https:\/\/symfonycasts.com\/screencast\/stimulus\">watch the Stimulus course on SymfonyCasts<\/a>.<\/p>\n\n<p>I skipped the lessons on Stimulus before and didn't try it for a while, but I'm glad I have.<\/p>\n\n ",
"value": "\n <p>After starting with jQuery in Drupal 6 and moving to full JavaScript frameworks like Vue, I've recently been using Stimulus when adding JavaScript to my projects.<\/p>\n\n<p>After finding it via SymfonyCasts and Symfony UX (I can't remember if Ryan and I discussed it <a href=\"/podcast\/10-ryan-weaver-symfonycasts\">in our podcast episode<\/a>), I like that it works on top of my existing HTML and Twig templates instead of having to rewrite or duplicate all the markup.<\/p>\n\n<p>You enable and configure it with data attributes like <code>data-controller<\/code> and <code>data-action<\/code> in your HTML which refer to separate JavaScript classes and methods, so you have some structure and organisation compared to putting all the logic in Twig.<\/p>\n\n<p>Having separate controllers also makes it easy to reuse logic in other parts of your application or extract it for use in other projects.<\/p>\n\n<p>If you want an example of how I've set up stimulus with esbuild, <a href=\"https:\/\/github.com\/opdavies\/stimulus-esbuild-example\">take a look at this GitHub repository<\/a>, or <a href=\"https:\/\/symfonycasts.com\/screencast\/stimulus\">watch the Stimulus course on SymfonyCasts<\/a>.<\/p>\n\n<p>I skipped the lessons on Stimulus before and didn't try it for a while, but I'm glad I have.<\/p>\n\n ",
"format": "full_html",
"processed": "\n <p>After starting with jQuery in Drupal 6 and moving to full JavaScript frameworks like Vue, I've recently been using Stimulus when adding JavaScript to my projects.<\/p>\n\n<p>After finding it via SymfonyCasts and Symfony UX (I can't remember if Ryan and I discussed it <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/10-ryan-weaver-symfonycasts\">in our podcast episode<\/a>), I like that it works on top of my existing HTML and Twig templates instead of having to rewrite or duplicate all the markup.<\/p>\n\n<p>You enable and configure it with data attributes like <code>data-controller<\/code> and <code>data-action<\/code> in your HTML which refer to separate JavaScript classes and methods, so you have some structure and organisation compared to putting all the logic in Twig.<\/p>\n\n<p>Having separate controllers also makes it easy to reuse logic in other parts of your application or extract it for use in other projects.<\/p>\n\n<p>If you want an example of how I've set up stimulus with esbuild, <a href=\"https:\/\/github.com\/opdavies\/stimulus-esbuild-example\">take a look at this GitHub repository<\/a>, or <a href=\"https:\/\/symfonycasts.com\/screencast\/stimulus\">watch the Stimulus course on SymfonyCasts<\/a>.<\/p>\n\n<p>I skipped the lessons on Stimulus before and didn't try it for a while, but I'm glad I have.<\/p>\n\n ",
"processed": "\n <p>After starting with jQuery in Drupal 6 and moving to full JavaScript frameworks like Vue, I've recently been using Stimulus when adding JavaScript to my projects.<\/p>\n\n<p>After finding it via SymfonyCasts and Symfony UX (I can't remember if Ryan and I discussed it <a href=\"/podcast\/10-ryan-weaver-symfonycasts\">in our podcast episode<\/a>), I like that it works on top of my existing HTML and Twig templates instead of having to rewrite or duplicate all the markup.<\/p>\n\n<p>You enable and configure it with data attributes like <code>data-controller<\/code> and <code>data-action<\/code> in your HTML which refer to separate JavaScript classes and methods, so you have some structure and organisation compared to putting all the logic in Twig.<\/p>\n\n<p>Having separate controllers also makes it easy to reuse logic in other parts of your application or extract it for use in other projects.<\/p>\n\n<p>If you want an example of how I've set up stimulus with esbuild, <a href=\"https:\/\/github.com\/opdavies\/stimulus-esbuild-example\">take a look at this GitHub repository<\/a>, or <a href=\"https:\/\/symfonycasts.com\/screencast\/stimulus\">watch the Stimulus course on SymfonyCasts<\/a>.<\/p>\n\n<p>I skipped the lessons on Stimulus before and didn't try it for a while, but I'm glad I have.<\/p>\n\n ",
"summary": null
}
],

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show more