tome export
This commit is contained in:
parent
328502c279
commit
ac1484b1e0
5044 changed files with 111225 additions and 224219 deletions
|
@ -11,7 +11,7 @@ label: 'Daily emails'
|
|||
id: daily_emails
|
||||
description: ''
|
||||
help: ''
|
||||
import_period: 43200
|
||||
import_period: -1
|
||||
fetcher: http
|
||||
fetcher_configuration:
|
||||
auto_detect_feeds: false
|
||||
|
@ -27,7 +27,7 @@ processor_configuration:
|
|||
type: daily_email
|
||||
langcode: en
|
||||
insert_new: 1
|
||||
update_existing: 2
|
||||
update_existing: 0
|
||||
update_non_existent: _keep
|
||||
skip_hash_check: false
|
||||
skip_validation: false
|
||||
|
|
|
@ -34,17 +34,17 @@
|
|||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
"value": "2025-05-11T09:01:00+00:00"
|
||||
}
|
||||
],
|
||||
"imported": [
|
||||
{
|
||||
"value": "2025-05-11T06:11:07+00:00"
|
||||
"value": "2025-05-11T09:01:00+00:00"
|
||||
}
|
||||
],
|
||||
"next": [
|
||||
{
|
||||
"value": "2025-05-11T18:11:07+00:00"
|
||||
"value": "1969-12-31T23:59:59+00:00"
|
||||
}
|
||||
],
|
||||
"queued": [
|
||||
|
@ -67,7 +67,7 @@
|
|||
],
|
||||
"item_count": [
|
||||
{
|
||||
"value": 1673
|
||||
"value": 820
|
||||
}
|
||||
]
|
||||
}
|
17595
content/meta/index.json
17595
content/meta/index.json
File diff suppressed because it is too large
Load diff
100
content/node.0001428e-621c-49ca-83d3-4323ea446f48.json
Normal file
100
content/node.0001428e-621c-49ca-83d3-4323ea446f48.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0001428e-621c-49ca-83d3-4323ea446f48"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:01+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Tests aren't a line item"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-02-23T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:01+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/02\/23\/line-item",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>A common mistake I see with new Developers and Development teams when starting with automated testing is to split development time and testing into separate tasks.<\/p>\n\n<p>They'll say when quoting a client or in an estimation session that the development time will take x hours and writing tests will take y hours.<\/p>\n\n<p>This is something I've always avoided.<\/p>\n\n<p>When broken out this way, it implies the automated tests are optional when they should be an integral part of the development process.<\/p>\n\n<p>They aren't a separate task that can be removed or skipped to save time or money.<\/p>\n\n<p>If I take my car to a garage, I don't ask them how long it will take to repair and how long to test what they've done.<\/p>\n\n<p>I want to know how much the whole task will cost and how long it will take.<\/p>\n\n<p>I assume they automatically test and verify the work they do and follow their industry's standard and best practices.<\/p>\n\n<p>I'm doing the same when developing software.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>A common mistake I see with new Developers and Development teams when starting with automated testing is to split development time and testing into separate tasks.<\/p>\n\n<p>They'll say when quoting a client or in an estimation session that the development time will take x hours and writing tests will take y hours.<\/p>\n\n<p>This is something I've always avoided.<\/p>\n\n<p>When broken out this way, it implies the automated tests are optional when they should be an integral part of the development process.<\/p>\n\n<p>They aren't a separate task that can be removed or skipped to save time or money.<\/p>\n\n<p>If I take my car to a garage, I don't ask them how long it will take to repair and how long to test what they've done.<\/p>\n\n<p>I want to know how much the whole task will cost and how long it will take.<\/p>\n\n<p>I assume they automatically test and verify the work they do and follow their industry's standard and best practices.<\/p>\n\n<p>I'm doing the same when developing software.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:01+00:00",
|
||||
"guid": null,
|
||||
"hash": "71938847a402f6b5af7c2e34bca063d3",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.001f3ebb-79dc-43ad-a363-6dc668d06a0c.json
Normal file
100
content/node.001f3ebb-79dc-43ad-a363-6dc668d06a0c.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "001f3ebb-79dc-43ad-a363-6dc668d06a0c"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:44+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Structure a new test by writing comments first\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-04-26T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:44+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/04\/26\/tdd-structure-a-new-test-by-writing-comments-first",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Test cases are usually split into two or three sections - \"Arrange, Act, Assert\" or \"Given, When, Then\".<\/p>\n\n<p>If the test has a prerequisite, such as some users or content to be created or in a given state, you create the required environment for the test. With unit tests, this would include mocking any dependencies you need to use.<\/p>\n\n<p>Then you perform an action on the subject under test and, finally, assert that the system is in the desired state.<\/p>\n\n<p>Maybe a user was pending initially, and they're active after running a command or a cron task. You can assert the initial state of the user as well as the final state to ensure the action did what it was supposed to do.<\/p>\n\n<h2 id=\"option-1\">Option 1<\/h2>\n\n<p>To help me get started, I'll sometimes write a test like this with placeholders to separate the test into its separate stages:<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\nfunction should_activate_a_pending_user(): void {\n \/\/ Arrange.\n\n \/\/ Act.\n\n \/\/ Assert.\n}\n<\/code><\/pre>\n\n<p>This makes me think about the different stages and what each might need to contain.<\/p>\n\n<h2 id=\"option-2\">Option 2<\/h2>\n\n<p>Or I might write it out in the \"Given, When, Then\" format:<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\nfunction should_activate_a_pending_user(): void {\n \/\/ Given I have a user.\n \/\/ And the user is pending.\n\n \/\/ When I run the user update command.\n\n \/\/ Then the user should no longer be 'pending'.\n \/\/ And the user status should be 'active'.\n}\n<\/code><\/pre>\n\n<p>This takes a little longer to write but feels more familiar if you're used to a behavioural testing framework like Behat.<\/p>\n\n<p>Either way, sometimes, I'll remove the comments once I've written the code around them or leave them to provide additional context.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Test cases are usually split into two or three sections - \"Arrange, Act, Assert\" or \"Given, When, Then\".<\/p>\n\n<p>If the test has a prerequisite, such as some users or content to be created or in a given state, you create the required environment for the test. With unit tests, this would include mocking any dependencies you need to use.<\/p>\n\n<p>Then you perform an action on the subject under test and, finally, assert that the system is in the desired state.<\/p>\n\n<p>Maybe a user was pending initially, and they're active after running a command or a cron task. You can assert the initial state of the user as well as the final state to ensure the action did what it was supposed to do.<\/p>\n\n<h2 id=\"option-1\">Option 1<\/h2>\n\n<p>To help me get started, I'll sometimes write a test like this with placeholders to separate the test into its separate stages:<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\nfunction should_activate_a_pending_user(): void {\n \/\/ Arrange.\n\n \/\/ Act.\n\n \/\/ Assert.\n}\n<\/code><\/pre>\n\n<p>This makes me think about the different stages and what each might need to contain.<\/p>\n\n<h2 id=\"option-2\">Option 2<\/h2>\n\n<p>Or I might write it out in the \"Given, When, Then\" format:<\/p>\n\n<pre><code class=\"language-php\">\/** @test *\/\nfunction should_activate_a_pending_user(): void {\n \/\/ Given I have a user.\n \/\/ And the user is pending.\n\n \/\/ When I run the user update command.\n\n \/\/ Then the user should no longer be 'pending'.\n \/\/ And the user status should be 'active'.\n}\n<\/code><\/pre>\n\n<p>This takes a little longer to write but feels more familiar if you're used to a behavioural testing framework like Behat.<\/p>\n\n<p>Either way, sometimes, I'll remove the comments once I've written the code around them or leave them to provide additional context.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:44+00:00",
|
||||
"guid": null,
|
||||
"hash": "a1a228d3231ffab8895ec0cbd78f0b1d",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "00204e36-4f2d-4b4a-bcf6-c0140209e835"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-01T23:43:31+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Writing good commit messages"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-04-04T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-01T23:43:31+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/04\/04\/good",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>There are many good resources and interesting articles online about how to write good messages when committing changes to a Git repository.<\/p>\n\n<p>The post I often refer to is <a href=\"https:\/\/cbea.ms\/git-commit\">How to Write a Git Commit Message<\/a> by Chris Beams.<\/p>\n\n<p>In his post, he explains why good commit messages matter and gives these seven rules:<\/p>\n\n<blockquote>\n <ul>\n <li>Separate the subject from body with a blank line.<\/li>\n <li>Limit the subject line to 50 characters.<\/li>\n <li>Capitalize the subject line.<\/li>\n <li>Do not end the subject line with a period.<\/li>\n <li>Use the imperative mood in the subject line.<\/li>\n <li>Wrap the body at 72 characters.<\/li>\n <li>Use the body to explain what and why vs. how.<\/li>\n <\/ul>\n<\/blockquote>\n\n<p>I'd recommend reading the article to get the full context.<\/p>\n\n<p>Rules two and six suggest lengths for the subject line and body which is another reason <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/04\/02\/commit\">why I rarely use <code>-m<\/code><\/a> when committing changes.<\/p>\n\n<p>Whilst you can create multi-line commit messages on the command line, by opening it in my preferred editor (Neovim for me), I can see where the lines should end and be warned if I exceed them.<\/p>\n\n<p>I can even include Chris' rules in my commit message template so I see them whenever I'm about to commit something.<\/p>\n\n<p>This additional feedback helps me create my commit messages how I intend.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>There are many good resources and interesting articles online about how to write good messages when committing changes to a Git repository.<\/p>\n\n<p>The post I often refer to is <a href=\"https:\/\/cbea.ms\/git-commit\">How to Write a Git Commit Message<\/a> by Chris Beams.<\/p>\n\n<p>In his post, he explains why good commit messages matter and gives these seven rules:<\/p>\n\n<blockquote>\n <ul>\n <li>Separate the subject from body with a blank line.<\/li>\n <li>Limit the subject line to 50 characters.<\/li>\n <li>Capitalize the subject line.<\/li>\n <li>Do not end the subject line with a period.<\/li>\n <li>Use the imperative mood in the subject line.<\/li>\n <li>Wrap the body at 72 characters.<\/li>\n <li>Use the body to explain what and why vs. how.<\/li>\n <\/ul>\n<\/blockquote>\n\n<p>I'd recommend reading the article to get the full context.<\/p>\n\n<p>Rules two and six suggest lengths for the subject line and body which is another reason <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/04\/02\/commit\">why I rarely use <code>-m<\/code><\/a> when committing changes.<\/p>\n\n<p>Whilst you can create multi-line commit messages on the command line, by opening it in my preferred editor (Neovim for me), I can see where the lines should end and be warned if I exceed them.<\/p>\n\n<p>I can even include Chris' rules in my commit message template so I see them whenever I'm about to commit something.<\/p>\n\n<p>This additional feedback helps me create my commit messages how I intend.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-01T23:43:31+00:00",
|
||||
"guid": null,
|
||||
"hash": "7430242f1d716198aa6fb01f727d1f9a",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.00497277-4b40-4d36-a473-8d8e1a187c18.json
Normal file
100
content/node.00497277-4b40-4d36-a473-8d8e1a187c18.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "00497277-4b40-4d36-a473-8d8e1a187c18"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:44+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Consistency is key\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-04-18T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:44+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/04\/18\/consistency-is-key",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:44+00:00",
|
||||
"guid": null,
|
||||
"hash": "aacb745c094cf5a9f668c64b15000f49",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "00519b3f-3eaf-4595-9620-4ff1a1fb3b6d"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Building different-looking UIs with consistent class names"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-11-22T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/11\/22\/building-different-looking-uis-with-consistent-class-names",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Something I've said when <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/taking-flight-with-tailwind-css.md\">speaking about Tailwind CSS<\/a> and also during <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/19\/tailwind-css-v4-is-so-easy-to-set-up\">my recent consulting engagement<\/a>, is that you can build dramatically different-looking UIs even though you're using the same class names.<\/p>\n\n<p>For example, I've rebuilt <a href=\"https:\/\/rebuilding-bartik.oliverdavies.uk\">the Bartik theme<\/a>, <a href=\"https:\/\/rebuilding-acquia.oliverdavies.uk\">the Acquia hosting dashboard<\/a> and <a href=\"https:\/\/rebuilding-bristol-js.oliverdavies.uk\">various other UIs<\/a> for talk demos - none of which look the same or are even similar.<\/p>\n\n<p>This website is themed with Tailwind CSS.<\/p>\n\n<p>As the classes are very low-level, there is no \"Tailwind-looking website\" like there is with other CSS frameworks.<\/p>\n\n<p>And, when you move to other application, the same classes are there and available to use.<\/p>\n\n<p>You just need to customise them, use what you need and ignore what you don't.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Something I've said when <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/taking-flight-with-tailwind-css.md\">speaking about Tailwind CSS<\/a> and also during <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/19\/tailwind-css-v4-is-so-easy-to-set-up\">my recent consulting engagement<\/a>, is that you can build dramatically different-looking UIs even though you're using the same class names.<\/p>\n\n<p>For example, I've rebuilt <a href=\"https:\/\/rebuilding-bartik.oliverdavies.uk\">the Bartik theme<\/a>, <a href=\"https:\/\/rebuilding-acquia.oliverdavies.uk\">the Acquia hosting dashboard<\/a> and <a href=\"https:\/\/rebuilding-bristol-js.oliverdavies.uk\">various other UIs<\/a> for talk demos - none of which look the same or are even similar.<\/p>\n\n<p>This website is themed with Tailwind CSS.<\/p>\n\n<p>As the classes are very low-level, there is no \"Tailwind-looking website\" like there is with other CSS frameworks.<\/p>\n\n<p>And, when you move to other application, the same classes are there and available to use.<\/p>\n\n<p>You just need to customise them, use what you need and ignore what you don't.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "5b4b4815f291bc6b2a7f37552c3d1102",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0086c29b-9324-4d72-bdc0-c2a75c2aaca5"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:17+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Building fonts with Nix"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-04-16T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:17+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/04\/16\/fonts",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:17+00:00",
|
||||
"guid": null,
|
||||
"hash": "663165d347672170986b3ba5d0f0ac13",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "008a122d-b219-46fa-8774-999d1e56e18b"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:56+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Consistency is key\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-04-18T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:56+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/04\/18\/consistency-is-key",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:56+00:00",
|
||||
"guid": null,
|
||||
"hash": "aacb745c094cf5a9f668c64b15000f49",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.00d62e94-80d1-4792-bdea-88a064f6bf65.json
Normal file
100
content/node.00d62e94-80d1-4792-bdea-88a064f6bf65.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "00d62e94-80d1-4792-bdea-88a064f6bf65"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:18+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "80% of PHP?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-03-13T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:18+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/03\/13\/80--of-php",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Something I see on many Developers' websites and CVs is percentages or levels of how well they know certain tools and frameworks.<\/p>\n\n<p>Things like \"80% of PHP\" or \"Advanced in HTML and CSS\".<\/p>\n\n<p>But how do you quantify that?<\/p>\n\n<p>Do people alter their percentages accordingly if a new feature is added to a language or framework?<\/p>\n\n<p>Or, instead of trying to show how much you understand, focus on what problems you can solve with those tools and how you can provide value to customers or employers instead of what tools you'd use to do it.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Something I see on many Developers' websites and CVs is percentages or levels of how well they know certain tools and frameworks.<\/p>\n\n<p>Things like \"80% of PHP\" or \"Advanced in HTML and CSS\".<\/p>\n\n<p>But how do you quantify that?<\/p>\n\n<p>Do people alter their percentages accordingly if a new feature is added to a language or framework?<\/p>\n\n<p>Or, instead of trying to show how much you understand, focus on what problems you can solve with those tools and how you can provide value to customers or employers instead of what tools you'd use to do it.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:18+00:00",
|
||||
"guid": null,
|
||||
"hash": "3bf8b7e44f82bf7d6ad5ce1fda692ae6",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "00e8b0fc-a551-47e4-b0df-b568beada250"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:17+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Legacy code is anything older than..."
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-03-22T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:17+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/03\/22\/legacy",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>How do you define legacy code?<\/p>\n\n<p>Code that was written by someone else?<\/p>\n\n<p>Code that doesn't have tests?<\/p>\n\n<p>Any code that has been released to production?<\/p>\n\n<p>Code that's more than a day old?<\/p>\n\n<p>In a talk I recently watched, the speaker suggested that any code written more than thirty minutes ago is legacy code.<\/p>\n\n<p>Once you've written some code and left it for half an hour, you need to re-read it to remember and re-learn what the code does and decide how you want to implement your next requirement.<\/p>\n\n<p>This is the same approach for code that was written longer ago or written by someone else.<\/p>\n\n<p>What do you think?<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>How do you define legacy code?<\/p>\n\n<p>Code that was written by someone else?<\/p>\n\n<p>Code that doesn't have tests?<\/p>\n\n<p>Any code that has been released to production?<\/p>\n\n<p>Code that's more than a day old?<\/p>\n\n<p>In a talk I recently watched, the speaker suggested that any code written more than thirty minutes ago is legacy code.<\/p>\n\n<p>Once you've written some code and left it for half an hour, you need to re-read it to remember and re-learn what the code does and decide how you want to implement your next requirement.<\/p>\n\n<p>This is the same approach for code that was written longer ago or written by someone else.<\/p>\n\n<p>What do you think?<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:17+00:00",
|
||||
"guid": null,
|
||||
"hash": "9983c859dafd94ec45282b7438b9cb59",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.0100be71-79ef-44ea-922e-e75fcc26ae16.json
Normal file
100
content/node.0100be71-79ef-44ea-922e-e75fcc26ae16.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0100be71-79ef-44ea-922e-e75fcc26ae16"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:03+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "How quickly can you create or update an environment?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-12-27T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:03+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/12\/27\/quick",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:03+00:00",
|
||||
"guid": null,
|
||||
"hash": "957251b7baf05530d91b2a9731016317",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "01090310-9114-436a-93d8-55c966a816ea"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "How long should a feature flag live?\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-06-05T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/06\/05\/how-long-should-a-feature-flag-live",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Instead of creating a branch that lives for as long as the code takes to write, if it's behind a feature flag, the code can be merged into the mainline branch without affecting the rest of the codebase.<\/p>\n\n<p>Being able to release changes incrementally lowers the risk compared to releasing a large change all at once.<\/p>\n\n<p>But the same issue can occur with feature flags, and the longer that code is behind a feature flag, the more risk there will be when enabling the feature.<\/p>\n\n<p>So, like feature branches, feature flags should be short-lived and only used for as long as is needed to create the first releasable version of the feature. The feature flag can be removed once the feature is live, and the feature can continue to be iterated on and improved.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Instead of creating a branch that lives for as long as the code takes to write, if it's behind a feature flag, the code can be merged into the mainline branch without affecting the rest of the codebase.<\/p>\n\n<p>Being able to release changes incrementally lowers the risk compared to releasing a large change all at once.<\/p>\n\n<p>But the same issue can occur with feature flags, and the longer that code is behind a feature flag, the more risk there will be when enabling the feature.<\/p>\n\n<p>So, like feature branches, feature flags should be short-lived and only used for as long as is needed to create the first releasable version of the feature. The feature flag can be removed once the feature is live, and the feature can continue to be iterated on and improved.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "d7e1f6d61d5541ac83cd2bfe9bc3e669",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.01230324-62b5-442b-80e4-09268a31819b.json
Normal file
100
content/node.01230324-62b5-442b-80e4-09268a31819b.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "01230324-62b5-442b-80e4-09268a31819b"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:05+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Drupal 11 is not Drupal 6"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-11-06T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:05+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/11\/06\/drupal-11-is-not-drupal-6",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I started learning software and web development with HTML and CSS in 2007. Then I started with PHP and soon after started to learn Drupal 6 (or maybe 5).<\/p>\n\n<p>A lot of Developers' first programming language was PHP and maybe used earlier versions of Drupal before moving to another CMS, framework or language.<\/p>\n\n<p>They still remember, though, how things were when they used it and aren't aware of the advancements and improvements that have been made.<\/p>\n\n<p>The PHP language itself has improved significantly in recent versions with new features and much better peformance.<\/p>\n\n<p>Drupal is more powerful with a lot more available in core compared to when I started to use it and, since adopting modern PHP approaches and third-party code in Drupal 8, writing custom Drupal modules is different with fewer Drupalisms and more industry-standard approaches.<\/p>\n\n<p>If there's a tool you haven't tried for a while, maybe take another look and see if it's improved since you last used it.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I started learning software and web development with HTML and CSS in 2007. Then I started with PHP and soon after started to learn Drupal 6 (or maybe 5).<\/p>\n\n<p>A lot of Developers' first programming language was PHP and maybe used earlier versions of Drupal before moving to another CMS, framework or language.<\/p>\n\n<p>They still remember, though, how things were when they used it and aren't aware of the advancements and improvements that have been made.<\/p>\n\n<p>The PHP language itself has improved significantly in recent versions with new features and much better peformance.<\/p>\n\n<p>Drupal is more powerful with a lot more available in core compared to when I started to use it and, since adopting modern PHP approaches and third-party code in Drupal 8, writing custom Drupal modules is different with fewer Drupalisms and more industry-standard approaches.<\/p>\n\n<p>If there's a tool you haven't tried for a while, maybe take another look and see if it's improved since you last used it.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:05+00:00",
|
||||
"guid": null,
|
||||
"hash": "3baa147faae6a26ac886bb26940c8f43",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "012bd3a8-e679-4f0c-acf3-cef4523591f7"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Open source software all the way down"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-12-07T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/12\/07\/open-source",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "826ea7f42a178becea87291123dedc78",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "015fc769-e2c2-49c2-9eb6-95bfc3bfe06e"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Running tests in parallel with Paratest"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-02-07T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/02\/07\/running-tests-in-parallel-with-paratest",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Something that I've recently added to my PHP projects is <a href=\"https:\/\/github.com\/paratestphp\/paratest\">Paratest<\/a>.<\/p>\n\n<p>It adds parallel testing to PHPUnit, so your tests will be run in parallel instead of sequentially.<\/p>\n\n<p>For the example module in my <a href=\"https:\/\/www.oliverdavies.uk\/atdc\">automated testing in Drupal email course<\/a>, using Paratest reduces the execution time from ~16 seconds to ~8 seconds.<\/p>\n\n<p>In a client project with 136 tests, it reduces the time from four and a half minutes to less than two minutes.<\/p>\n\n<p>This is a big improvement just from running a single Composer command to add Paratest.<\/p>\n\n<p>There's also <a href=\"https:\/\/www.drupal.org\/project\/drupal\/issues\/2781123\">an open issue<\/a> for using it for Drupal core's tests, which is something I'll keep an eye on and will look to contribute to.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Something that I've recently added to my PHP projects is <a href=\"https:\/\/github.com\/paratestphp\/paratest\">Paratest<\/a>.<\/p>\n\n<p>It adds parallel testing to PHPUnit, so your tests will be run in parallel instead of sequentially.<\/p>\n\n<p>For the example module in my <a href=\"https:\/\/www.oliverdavies.uk\/atdc\">automated testing in Drupal email course<\/a>, using Paratest reduces the execution time from ~16 seconds to ~8 seconds.<\/p>\n\n<p>In a client project with 136 tests, it reduces the time from four and a half minutes to less than two minutes.<\/p>\n\n<p>This is a big improvement just from running a single Composer command to add Paratest.<\/p>\n\n<p>There's also <a href=\"https:\/\/www.drupal.org\/project\/drupal\/issues\/2781123\">an open issue<\/a> for using it for Drupal core's tests, which is something I'll keep an eye on and will look to contribute to.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "d6723cf0326f529b61786870511d23ff",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.01893784-8f45-4466-8586-17df23e7e4b5.json
Normal file
100
content/node.01893784-8f45-4466-8586-17df23e7e4b5.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "01893784-8f45-4466-8586-17df23e7e4b5"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "What's the correct way to add PHPStan to an existing codebase?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-03-16T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/03\/16\/what-s-the-correct-way-to-add-phpstan-to-an-existing-codebase",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:00+00:00",
|
||||
"guid": null,
|
||||
"hash": "9a7b258b69b97c51304c0aa8d6b87263",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "018a674d-e084-4947-b3d9-9459fb4b5e43"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:42+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Finding the best test base\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-11-27T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:42+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/11\/27\/finding-the-best-test-base",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>As well as different base classes for types of tests - i.e. functional, kernel and unit - there are other test base classes within those that can be used to simplify things.<\/p>\n\n<p>For example, if we have this test:<\/p>\n\n<pre><code class=\"language-php\"><?php\n\nnamespace Drupal\\Tests\\example\\Kernel;\n\nuse Drupal\\KernelTests\\KernelTestBase;\nuse Drupal\\Tests\\node\\Traits\\NodeCreationTrait;\nuse Drupal\\Tests\\user\\Traits\\UserCreationTrait;\n\nclass ExampleTest extends KernelTestBase {\n\n use NodeCreationTrait;\n use UserCreationTrait;\n\n protected static $modules = [\n 'node',\n 'user',\n ];\n\n public function setUp(): void {\n parent::setUp();\n\n $this->installEntitySchema(entity_type_id: 'node');\n $this->installEntitySchema(entity_type_id: 'user');\n }\n\n public function testExample(): void {\n $user = $this->createUser();\n\n $article = $this->createNode([\n 'title' => 'Test article',\n 'uid' => $user,\n ]);\n\n self::assertSame('1', $article->getOwnerId());\n }\n\n}\n<\/code><\/pre>\n\n<p>Both creation traits must be imported, the <code>node<\/code> and <code>user<\/code> modules must be enabled, and the entity tables must be installed.<\/p>\n\n<p>When writing a lot of tests, this can result in duplication and more complex tests that take longer to write.<\/p>\n\n<p>This can be simplified using <code>EntityKernelTestBase<\/code> instead of <code>KernelTestBase<\/code>:<\/p>\n\n<pre><code class=\"language-php\"><?php\n\nuse Drupal\\KernelTests\\Core\\Entity\\EntityKernelTestBase;\nuse Drupal\\Tests\\node\\Traits\\NodeCreationTrait;\n\nclass ExampleTest extends EntityKernelTestBase {\n\n use NodeCreationTrait;\n\n protected static $modules = [\n 'node',\n ];\n\n public function testExample(): void {\n $user = $this->createUser();\n\n $article = $this->createNode([\n 'title' => 'Test article',\n 'uid' => $user,\n ]);\n\n self::assertSame('1', $article->getOwnerId());\n }\n\n}\n<\/code><\/pre>\n\n<p>The class is simpler, fewer modules must be specified, and the entity schemas are automatically installed.<\/p>\n\n<p>As well as the core modules, some contrib modules also provide their own base test cases.<\/p>\n\n<p>If you're using the Webform module, you may want to use <code>WebformAccessTestBase<\/code> instead of the standard <code>UnitTestCase<\/code>.<\/p>\n\n<p>It's definitely worth spending some time looking at what base test cases are available and which are the best ones to use for your own tests.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>As well as different base classes for types of tests - i.e. functional, kernel and unit - there are other test base classes within those that can be used to simplify things.<\/p>\n\n<p>For example, if we have this test:<\/p>\n\n<pre><code class=\"language-php\"><?php\n\nnamespace Drupal\\Tests\\example\\Kernel;\n\nuse Drupal\\KernelTests\\KernelTestBase;\nuse Drupal\\Tests\\node\\Traits\\NodeCreationTrait;\nuse Drupal\\Tests\\user\\Traits\\UserCreationTrait;\n\nclass ExampleTest extends KernelTestBase {\n\n use NodeCreationTrait;\n use UserCreationTrait;\n\n protected static $modules = [\n 'node',\n 'user',\n ];\n\n public function setUp(): void {\n parent::setUp();\n\n $this->installEntitySchema(entity_type_id: 'node');\n $this->installEntitySchema(entity_type_id: 'user');\n }\n\n public function testExample(): void {\n $user = $this->createUser();\n\n $article = $this->createNode([\n 'title' => 'Test article',\n 'uid' => $user,\n ]);\n\n self::assertSame('1', $article->getOwnerId());\n }\n\n}\n<\/code><\/pre>\n\n<p>Both creation traits must be imported, the <code>node<\/code> and <code>user<\/code> modules must be enabled, and the entity tables must be installed.<\/p>\n\n<p>When writing a lot of tests, this can result in duplication and more complex tests that take longer to write.<\/p>\n\n<p>This can be simplified using <code>EntityKernelTestBase<\/code> instead of <code>KernelTestBase<\/code>:<\/p>\n\n<pre><code class=\"language-php\"><?php\n\nuse Drupal\\KernelTests\\Core\\Entity\\EntityKernelTestBase;\nuse Drupal\\Tests\\node\\Traits\\NodeCreationTrait;\n\nclass ExampleTest extends EntityKernelTestBase {\n\n use NodeCreationTrait;\n\n protected static $modules = [\n 'node',\n ];\n\n public function testExample(): void {\n $user = $this->createUser();\n\n $article = $this->createNode([\n 'title' => 'Test article',\n 'uid' => $user,\n ]);\n\n self::assertSame('1', $article->getOwnerId());\n }\n\n}\n<\/code><\/pre>\n\n<p>The class is simpler, fewer modules must be specified, and the entity schemas are automatically installed.<\/p>\n\n<p>As well as the core modules, some contrib modules also provide their own base test cases.<\/p>\n\n<p>If you're using the Webform module, you may want to use <code>WebformAccessTestBase<\/code> instead of the standard <code>UnitTestCase<\/code>.<\/p>\n\n<p>It's definitely worth spending some time looking at what base test cases are available and which are the best ones to use for your own tests.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:42+00:00",
|
||||
"guid": null,
|
||||
"hash": "550456dfd70a84795f8c61ba84691a1d",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.018bf894-2d3e-4130-b0bd-43450ef5753a.json
Normal file
100
content/node.018bf894-2d3e-4130-b0bd-43450ef5753a.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "018bf894-2d3e-4130-b0bd-43450ef5753a"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Do we still need CSS preprocessors?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-02-28T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/02\/28\/preprocessors",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Before I started to use [Tailwind CSS][0], I used CSS preprocessors like Less and Sass to add features like variables and nesting to my CSS files.<\/p>\n\n<p>Stylesheets would be written in .scss, .sass or .less files and processed to create the stylesheets that would be used by browsers.<\/p>\n\n<p>But, with the recent improvements to CSS, do we still need these preprocessors?<\/p>\n\n<p>Here's a very small example of some CSS that just works:<\/p>\n\n<pre><code class=\"css\">:root {\n --color-primary: red;\n --color-secondary: green;\n}\n\na {\n color: var(--color-primary);\n\n &:hover, &:focus {\n color: var(--color-secondary);\n }\n}\n<\/code><\/pre>\n\n<p>It looks like a Sass file, but it's native CSS.<\/p>\n\n<p>It has variables (a.k.a. custom properties) and nesting, which I think are the most used features from preprocessors.<\/p>\n\n<p>But there's no additional build step to generate the end stylesheet. I can use this stylesheet as it is - making it easier to work on and less confusing for new Developers.<\/p>\n\n<p>If I'm not using Tailwind CSS or atomic styles, writing plain CSS files is the approach I'd use.<\/p>\n\n<p>No preprocessors needed.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Before I started to use [Tailwind CSS][0], I used CSS preprocessors like Less and Sass to add features like variables and nesting to my CSS files.<\/p>\n\n<p>Stylesheets would be written in .scss, .sass or .less files and processed to create the stylesheets that would be used by browsers.<\/p>\n\n<p>But, with the recent improvements to CSS, do we still need these preprocessors?<\/p>\n\n<p>Here's a very small example of some CSS that just works:<\/p>\n\n<pre><code class=\"css\">:root {\n --color-primary: red;\n --color-secondary: green;\n}\n\na {\n color: var(--color-primary);\n\n &:hover, &:focus {\n color: var(--color-secondary);\n }\n}\n<\/code><\/pre>\n\n<p>It looks like a Sass file, but it's native CSS.<\/p>\n\n<p>It has variables (a.k.a. custom properties) and nesting, which I think are the most used features from preprocessors.<\/p>\n\n<p>But there's no additional build step to generate the end stylesheet. I can use this stylesheet as it is - making it easier to work on and less confusing for new Developers.<\/p>\n\n<p>If I'm not using Tailwind CSS or atomic styles, writing plain CSS files is the approach I'd use.<\/p>\n\n<p>No preprocessors needed.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:00+00:00",
|
||||
"guid": null,
|
||||
"hash": "cdd9ab25b0351a9082e1580898e5ecbc",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "01b112a4-915a-4518-a75d-f9af67d2b119"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:40+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Just..."
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-12-31T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:40+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/12\/31\/just",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>If you have a request that starts with \"Just\", it's likely a red flag!<\/p>\n\n<p>Why is it being made?<\/p>\n\n<p>What problem is it going to solve?<\/p>\n\n<p>Whose problem does it solve?<\/p>\n\n<p>Is the problem time-sensitive?<\/p>\n\n<p>What value does it add?<\/p>\n\n<p>Is it the best solution to fix the problem?<\/p>\n\n<p>Is it the best solution to fix the problem right now?<\/p>\n\n<p>To know this, we need to know why it's needed and it \"just\" needs doing.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>If you have a request that starts with \"Just\", it's likely a red flag!<\/p>\n\n<p>Why is it being made?<\/p>\n\n<p>What problem is it going to solve?<\/p>\n\n<p>Whose problem does it solve?<\/p>\n\n<p>Is the problem time-sensitive?<\/p>\n\n<p>What value does it add?<\/p>\n\n<p>Is it the best solution to fix the problem?<\/p>\n\n<p>Is it the best solution to fix the problem right now?<\/p>\n\n<p>To know this, we need to know why it's needed and it \"just\" needs doing.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:40+00:00",
|
||||
"guid": null,
|
||||
"hash": "4f25a7d5fdd045a4a767afa851b0d6f0",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "01ba9676-20ed-4ba2-80de-5caf92ba7407"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:25+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Why \"no build\" is appealing"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-10-28T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:25+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/10\/28\/why-no-build-is-appealing",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>You're or a new\u00a0team member are\u00a0onboarded to a project to make some CSS changes.<\/p>\n\n<p>The project uses Sass, Less or another preprocessor.<\/p>\n\n<p>Not knowing this, the generated CSS files are changed instead of the Sass files.<\/p>\n\n<p>The changes are committed and pushed, but because they weren't added to the Sass files, they will be lost when the\u00a0CSS files are re-generated in the future.<\/p>\n\n<p>Or, if the Sass and CSS files become too out of sync, everyone will be too worried about losing changes to use the Sass files, so they will be abandoned\u00a0and not used.<\/p>\n\n<p>What if you change the\u00a0correct files but don't know the magic command to generate the assets for that project?<\/p>\n\n<p>I've seen things like this happen on numerous projects and is an example of why the \"no build\" approach is appealing.<\/p>\n\n<p>Especially with enhancements to CSS, such as custom properties (variables) and nesting, a lot of the functionality from preprocessors can now be done with normal CSS.<\/p>\n\n<p>This means the front-end build steps can be simplified\u00a0or removed entirely, reducing the technical overhead and dependency cost, and it's easier for new Developers to get started.<\/p>\n\n<p>Win, win!<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>You're or a new team member are onboarded to a project to make some CSS changes.<\/p>\n\n<p>The project uses Sass, Less or another preprocessor.<\/p>\n\n<p>Not knowing this, the generated CSS files are changed instead of the Sass files.<\/p>\n\n<p>The changes are committed and pushed, but because they weren't added to the Sass files, they will be lost when the CSS files are re-generated in the future.<\/p>\n\n<p>Or, if the Sass and CSS files become too out of sync, everyone will be too worried about losing changes to use the Sass files, so they will be abandoned and not used.<\/p>\n\n<p>What if you change the correct files but don't know the magic command to generate the assets for that project?<\/p>\n\n<p>I've seen things like this happen on numerous projects and is an example of why the \"no build\" approach is appealing.<\/p>\n\n<p>Especially with enhancements to CSS, such as custom properties (variables) and nesting, a lot of the functionality from preprocessors can now be done with normal CSS.<\/p>\n\n<p>This means the front-end build steps can be simplified or removed entirely, reducing the technical overhead and dependency cost, and it's easier for new Developers to get started.<\/p>\n\n<p>Win, win!<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:25+00:00",
|
||||
"guid": null,
|
||||
"hash": "247a1b12455fa21f13c5bcd13b69f5c7",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "01d71d60-5764-4631-9294-38db7515d1d4"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "The best solution is the one that gets the tests to pass\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-10-04T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/10\/04\/the-best-solution-is-the-one-that-gets-the-tests-to-pass",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>As I said yesterday, there is no perfect solution or approach for every situation.<\/p>\n\n<p>However, when doing test-driven development, there is a best solution.<\/p>\n\n<p>The simplest thing that gets a failing test to pass.<\/p>\n\n<p>Whether it's hard-coding a return value or putting the initial logic in a Controller, that's the objective.<\/p>\n\n<p>Once the test is passing, you can refactor the code or continue writing tests, which will each have their own best solution.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>As I said yesterday, there is no perfect solution or approach for every situation.<\/p>\n\n<p>However, when doing test-driven development, there is a best solution.<\/p>\n\n<p>The simplest thing that gets a failing test to pass.<\/p>\n\n<p>Whether it's hard-coding a return value or putting the initial logic in a Controller, that's the objective.<\/p>\n\n<p>Once the test is passing, you can refactor the code or continue writing tests, which will each have their own best solution.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "f999f40729d1c4017022ac0e4fd81a1d",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "01edae5a-f2cd-4e26-8de3-999d4ea7af3a"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Docker or Nix?\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-07-02T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/07\/02\/docker-or-nix",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I've been a Nix user for about a year, starting with its package manager on my previously installed Linux distribution.<\/p>\n\n<p>I started to use Home Manager for my user configuration and dotfiles and later switched to the NixOS operating system.<\/p>\n\n<h2 id=\"using-nix-for-software-development\">Using Nix for software development<\/h2>\n\n<p>I've also been using Nix Flakes for per-project configuration.<\/p>\n\n<p>A Flake file is a simple file written in the Nix language that defines the project's dependencies and installs them from the Nix package manager.<\/p>\n\n<p>Here is an example Flake for a PHP CLI application:<\/p>\n\n<pre><code class=\"nix\">{\n\u00a0 inputs.nixpkgs.url = \"github:NixOS\/nixpkgs\/nixos-unstable\";\n\n\u00a0 outputs = inputs@{ flake-parts, ... }:\n\u00a0 \u00a0 flake-parts.lib.mkFlake { inherit inputs; } {\n\u00a0 \u00a0 \u00a0 systems = [ \"x86_64-linux\" ];\n\n\u00a0 \u00a0 \u00a0 perSystem = { config, self', inputs', pkgs, system, ... }: {\n\u00a0 \u00a0 \u00a0 \u00a0 devShells = {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 default = pkgs.mkShell {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 buildInputs = with pkgs; [ php82 php82Packages.composer ];\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 };\n\u00a0 \u00a0 \u00a0 \u00a0 };\n\u00a0 \u00a0 \u00a0 };\n\u00a0 \u00a0 };\n}\n<\/code><\/pre>\n\n<p>It declares that PHP 8.2 and Composer are available, even if I have different versions installed globally.<\/p>\n\n<h2 id=\"will-nix-replace-docker%3F\">Will Nix replace Docker?<\/h2>\n\n<p>Nix and Flakes have replaced Docker for me on some projects.<\/p>\n\n<p>If I have a simple setup and need a specific version of PHP or Node and some additional programs, I can get those from the Flake.<\/p>\n\n<p>I don't know if it'll replace Docker for me completely and work on more complex projects, but it's working well for me where I'm using it.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I've been a Nix user for about a year, starting with its package manager on my previously installed Linux distribution.<\/p>\n\n<p>I started to use Home Manager for my user configuration and dotfiles and later switched to the NixOS operating system.<\/p>\n\n<h2 id=\"using-nix-for-software-development\">Using Nix for software development<\/h2>\n\n<p>I've also been using Nix Flakes for per-project configuration.<\/p>\n\n<p>A Flake file is a simple file written in the Nix language that defines the project's dependencies and installs them from the Nix package manager.<\/p>\n\n<p>Here is an example Flake for a PHP CLI application:<\/p>\n\n<pre><code class=\"nix\">{\n inputs.nixpkgs.url = \"github:NixOS\/nixpkgs\/nixos-unstable\";\n\n outputs = inputs@{ flake-parts, ... }:\n flake-parts.lib.mkFlake { inherit inputs; } {\n systems = [ \"x86_64-linux\" ];\n\n perSystem = { config, self', inputs', pkgs, system, ... }: {\n devShells = {\n default = pkgs.mkShell {\n buildInputs = with pkgs; [ php82 php82Packages.composer ];\n };\n };\n };\n };\n}\n<\/code><\/pre>\n\n<p>It declares that PHP 8.2 and Composer are available, even if I have different versions installed globally.<\/p>\n\n<h2 id=\"will-nix-replace-docker%3F\">Will Nix replace Docker?<\/h2>\n\n<p>Nix and Flakes have replaced Docker for me on some projects.<\/p>\n\n<p>If I have a simple setup and need a specific version of PHP or Node and some additional programs, I can get those from the Flake.<\/p>\n\n<p>I don't know if it'll replace Docker for me completely and work on more complex projects, but it's working well for me where I'm using it.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "7f55d425fa5b0836f5c8d0f6980cc54e",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.01f3b831-e981-471f-aef9-076b054e3495.json
Normal file
100
content/node.01f3b831-e981-471f-aef9-076b054e3495.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "01f3b831-e981-471f-aef9-076b054e3495"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:36+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Testing is all about confidence\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-07-24T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:36+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/07\/24\/testing-is-all-about-confidence",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Testing - manual or automated - is about building confidence.<\/p>\n\n<p>If we deploy this change or release this feature, are we confident it will work as expected and not cause regressions elsewhere?<\/p>\n\n<p>What if someone asked you on a scale between one and ten?<\/p>\n\n<p>From an automated perspective, have you written enough tests for the feature to be confident it works?<\/p>\n\n<p>If you're fixing a bug, do you have a test that reproduces the bug that was originally failing but now passing since you've added the fix?<\/p>\n\n<p>Do the tests have enough assertions, and have you covered enough use cases and scenarios?<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>You can utilise code coverage metrics, but no hard rule says that the feature will work once x percentage is covered. Something with 100% coverage can still contain bugs.<\/p>\n\n<p>For me, it's about the answer to the question:<\/p>\n\n<p>If we deploy this change, how confident are you that it will work as expected?<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Testing - manual or automated - is about building confidence.<\/p>\n\n<p>If we deploy this change or release this feature, are we confident it will work as expected and not cause regressions elsewhere?<\/p>\n\n<p>What if someone asked you on a scale between one and ten?<\/p>\n\n<p>From an automated perspective, have you written enough tests for the feature to be confident it works?<\/p>\n\n<p>If you're fixing a bug, do you have a test that reproduces the bug that was originally failing but now passing since you've added the fix?<\/p>\n\n<p>Do the tests have enough assertions, and have you covered enough use cases and scenarios?<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>You can utilise code coverage metrics, but no hard rule says that the feature will work once x percentage is covered. Something with 100% coverage can still contain bugs.<\/p>\n\n<p>For me, it's about the answer to the question:<\/p>\n\n<p>If we deploy this change, how confident are you that it will work as expected?<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:36+00:00",
|
||||
"guid": null,
|
||||
"hash": "60c550711c51c2b739051e4640eba954",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "01f4015e-252c-4e96-9e0c-91cf1045044b"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Busy working on client projects\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-03-02T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/03\/02\/busy-working-on-client-projects",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>As well as starting to speak again at conferences and meetups, I've been very busy lately with various client projects. I've been working on completing the next phase and launch of the next website for a long-term client and handed over some other completed projects.<\/p>\n\n<p>This has affected me sending out these emails every day and I missed a few days last month.<\/p>\n\n<p>I'll do better!<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>As well as starting to speak again at conferences and meetups, I've been very busy lately with various client projects. I've been working on completing the next phase and launch of the next website for a long-term client and handed over some other completed projects.<\/p>\n\n<p>This has affected me sending out these emails every day and I missed a few days last month.<\/p>\n\n<p>I'll do better!<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "6b223577d98aafcacf18ecbf423a3497",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "020b3de3-da10-4107-9616-a40786092144"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Don't estimate separately for testing\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-08-13T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/08\/13\/dont-estimate-separately-for-testing",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>A common issue I see for people introducing automated testing is estimating the testing and implementation of a task separately.<\/p>\n\n<p>Something like, \"It'll take x to do the work and x to write the tests for it\".<\/p>\n\n<p>As well as implying you'd write all the code and then all the tests or vice versa, if you provide separate estimates, it's easy for someone to think the tests are optional and can be removed.<\/p>\n\n<p>If you provide one estimate for both, this can't happen.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>A common issue I see for people introducing automated testing is estimating the testing and implementation of a task separately.<\/p>\n\n<p>Something like, \"It'll take x to do the work and x to write the tests for it\".<\/p>\n\n<p>As well as implying you'd write all the code and then all the tests or vice versa, if you provide separate estimates, it's easy for someone to think the tests are optional and can be removed.<\/p>\n\n<p>If you provide one estimate for both, this can't happen.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "b2a503f52e0d13b65158e0770ce490d5",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.021e00c1-b813-4edd-8064-71285bc3647d.json
Normal file
100
content/node.021e00c1-b813-4edd-8064-71285bc3647d.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "021e00c1-b813-4edd-8064-71285bc3647d"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:10+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Recording architectural decisions"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-06-12T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:10+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/06\/12\/recording-architectural-decisions",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I recently <a href=\"https:\/\/x.com\/StefanGalescu\/status\/1798421063355007017\">saw this post on X<\/a>, talking about an open-source project.<\/p>\n\n<p>This was the part that I want to highlight:<\/p>\n\n<blockquote>\n <p>I was also impressed by the decisions documents. More projects should implement this concept.<\/p>\n<\/blockquote>\n\n<p>Looking at the repository, it contains records of 36 decisions made on the project between May 2023 and April 2024.<\/p>\n\n<p>Decision records provide useful information to new people to a project, whether you want to contribute to an open-source project or it's a new client or work codebase.<\/p>\n\n<p>The code and project will likely continue once you've finished working on it, so capturing decisions for future Developers is key.<\/p>\n\n<p>I've often joined projects and wondered why or how something was done, and can only guess as the decision wasn't recorded or is somewhere not available to me, such as an old wiki or ticketing system.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>I agree with the poster.<\/p>\n\n<p>More people should record the decisions made on their project, whether it's open-source or not.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I recently <a href=\"https:\/\/x.com\/StefanGalescu\/status\/1798421063355007017\">saw this post on X<\/a>, talking about an open-source project.<\/p>\n\n<p>This was the part that I want to highlight:<\/p>\n\n<blockquote>\n <p>I was also impressed by the decisions documents. More projects should implement this concept.<\/p>\n<\/blockquote>\n\n<p>Looking at the repository, it contains records of 36 decisions made on the project between May 2023 and April 2024.<\/p>\n\n<p>Decision records provide useful information to new people to a project, whether you want to contribute to an open-source project or it's a new client or work codebase.<\/p>\n\n<p>The code and project will likely continue once you've finished working on it, so capturing decisions for future Developers is key.<\/p>\n\n<p>I've often joined projects and wondered why or how something was done, and can only guess as the decision wasn't recorded or is somewhere not available to me, such as an old wiki or ticketing system.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>I agree with the poster.<\/p>\n\n<p>More people should record the decisions made on their project, whether it's open-source or not.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:10+00:00",
|
||||
"guid": null,
|
||||
"hash": "bc11c3125e2e228f16b76f91b749c764",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.0231b26c-ac28-44e8-a2bf-cc7c86984e7e.json
Normal file
100
content/node.0231b26c-ac28-44e8-a2bf-cc7c86984e7e.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0231b26c-ac28-44e8-a2bf-cc7c86984e7e"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:48+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "To squash or not to squash\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-01-25T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:48+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/01\/25\/to-squash-or-not-to-squash",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:48+00:00",
|
||||
"guid": null,
|
||||
"hash": "54447bfd288cd6e71d4b06bd0646502d",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.024f2c81-68af-4eef-bea5-1b1d43bd1b39.json
Normal file
100
content/node.024f2c81-68af-4eef-bea5-1b1d43bd1b39.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "024f2c81-68af-4eef-bea5-1b1d43bd1b39"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:40+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Why is backward compatibility important?\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-05-18T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:40+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/05\/18\/why-is-backward-compatibility-important",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>In yesterday's email, I mentioned that deprecating code allows it to be backwards compatible - but what does that mean?<\/p>\n\n<p>If I were to remove a function like <code>drupal_set_message()<\/code> that is used code elsewhere in an application, the code would no longer work and would break.<\/p>\n\n<p>As a module or library maintainer, I don't want to cause applications to break by making backward incompatible changes (a \"BC break\" or a \"breaking change\").<\/p>\n\n<p>Maintaining backward compatibility means that people who use the code can update to the latest version without breakages, and if they use any deprecated code, they know to update it to be compatible with future versions.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>In yesterday's email, I mentioned that deprecating code allows it to be backwards compatible - but what does that mean?<\/p>\n\n<p>If I were to remove a function like <code>drupal_set_message()<\/code> that is used code elsewhere in an application, the code would no longer work and would break.<\/p>\n\n<p>As a module or library maintainer, I don't want to cause applications to break by making backward incompatible changes (a \"BC break\" or a \"breaking change\").<\/p>\n\n<p>Maintaining backward compatibility means that people who use the code can update to the latest version without breakages, and if they use any deprecated code, they know to update it to be compatible with future versions.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:40+00:00",
|
||||
"guid": null,
|
||||
"hash": "18e7b8e123a0c299bb44600a75b56d9e",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.025f0dde-748b-44f4-93e2-4e0602d30104.json
Normal file
100
content/node.025f0dde-748b-44f4-93e2-4e0602d30104.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "025f0dde-748b-44f4-93e2-4e0602d30104"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:34+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "8 years of dotfiles\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-08-08T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:34+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/08\/08\/8-years-of-dotfiles",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Today, I was speaking with a colleague about configuring Git, which led to a conversation about dotfiles repositories - somewhere where you version the changes to your configuration files and, usually, create symlinks to their expected locations.<\/p>\n\n<p>Afterwards, I realised the first commit to <a href=\"https:\/\/github.com\/opdavies\/dotfiles\">my personal dotfiles repository<\/a> was over eight years ago, in July 2015.<\/p>\n\n<p>What started as a repository to put my own Git configuration has undergone various changes since the tools I use changed, as well as the tools to manage the files themselves.<\/p>\n\n<p>In 2021, I switched my <code>.vimrc<\/code> configuration file to an <code>init.vim<\/code> and switched to Neovim full-time and, most recently, almost a year ago, I started to use the Nix package manager and later adopted NixOS as my primary Linux distribution.<\/p>\n\n<p>My complete NixOS and Home Manager configurations are within my <code>dotfiles<\/code> repository, and the configuration for tools, including Neovim, tmux and Git.<\/p>\n\n<p>I wonder what the repository will look like in another eight years...<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Today, I was speaking with a colleague about configuring Git, which led to a conversation about dotfiles repositories - somewhere where you version the changes to your configuration files and, usually, create symlinks to their expected locations.<\/p>\n\n<p>Afterwards, I realised the first commit to <a href=\"https:\/\/github.com\/opdavies\/dotfiles\">my personal dotfiles repository<\/a> was over eight years ago, in July 2015.<\/p>\n\n<p>What started as a repository to put my own Git configuration has undergone various changes since the tools I use changed, as well as the tools to manage the files themselves.<\/p>\n\n<p>In 2021, I switched my <code>.vimrc<\/code> configuration file to an <code>init.vim<\/code> and switched to Neovim full-time and, most recently, almost a year ago, I started to use the Nix package manager and later adopted NixOS as my primary Linux distribution.<\/p>\n\n<p>My complete NixOS and Home Manager configurations are within my <code>dotfiles<\/code> repository, and the configuration for tools, including Neovim, tmux and Git.<\/p>\n\n<p>I wonder what the repository will look like in another eight years...<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:34+00:00",
|
||||
"guid": null,
|
||||
"hash": "b663fb9c5e0257d2fdece24454ad3bfd",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.02777730-3fe8-4eba-8a16-e847042b7351.json
Normal file
100
content/node.02777730-3fe8-4eba-8a16-e847042b7351.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "02777730-3fe8-4eba-8a16-e847042b7351"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:57+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Giving back"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2022-08-27T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:57+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2022\/08\/27\/giving-back",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Today, I've been at an event run by a local animal rescue charity. It's one that we attend often as my children like to enter the dog show, but this year, I've also sponsored one of the categories.<\/p>\n\n<p>As well as organising the PHP South Wales user group, I'm also now a sponsor - donating books and elePHPant plushies for raffle prizes and paying the group's Meetup.com subscription costs.<\/p>\n\n<p>Giving back and supporting open-source maintainers and content creators is a big priority of mine. If I use some open-source software or find that someone's Twitch or YouTube channel is useful, if that person or organisation is on GitHub or Patron, then I'll sponsor them, or I'll subscribe to their channel.<\/p>\n\n<p>If I find a useful blog post or video, I'll add a comment or link to it on Twitter, thanking them and letting them know that it helped me.<\/p>\n\n<p>Especially if it's something that I've used within my projects, it makes sense to support it and it's maintainers, so that they keep working on and improving the software, continue streaming, and keep writing blog posts and recording videos for me to learn from.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Today, I've been at an event run by a local animal rescue charity. It's one that we attend often as my children like to enter the dog show, but this year, I've also sponsored one of the categories.<\/p>\n\n<p>As well as organising the PHP South Wales user group, I'm also now a sponsor - donating books and elePHPant plushies for raffle prizes and paying the group's Meetup.com subscription costs.<\/p>\n\n<p>Giving back and supporting open-source maintainers and content creators is a big priority of mine. If I use some open-source software or find that someone's Twitch or YouTube channel is useful, if that person or organisation is on GitHub or Patron, then I'll sponsor them, or I'll subscribe to their channel.<\/p>\n\n<p>If I find a useful blog post or video, I'll add a comment or link to it on Twitter, thanking them and letting them know that it helped me.<\/p>\n\n<p>Especially if it's something that I've used within my projects, it makes sense to support it and it's maintainers, so that they keep working on and improving the software, continue streaming, and keep writing blog posts and recording videos for me to learn from.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:57+00:00",
|
||||
"guid": null,
|
||||
"hash": "891d018e5d9b5fa68288878004365cce",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "027d3741-bf06-4348-9293-9993b2adb5e3"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "One more month of Drupal 7"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-12-06T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/12\/06\/one-more-month",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>On the 5th of January, Drupal 7 will be end of life and have no further updates.<\/p>\n\n<p><a href=\"https:\/\/www.drupal.org\/blog\/drupal-70-is-released\">Released in January 2011<\/a>, Drupal 7 will be 14 years old in January and will have outlived Drupal 8 and 9 which are already unsupported.<\/p>\n\n<p>There are a lot of Drupal 7 sites still in production, but it's been interesting to see usage numbers for the Override Node Options module <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/16\/an-interesting-thing-i-spotted-about-the-override-node-options-module\">decrease for Drupal 7 and increase for Drupal 8+<\/a> over the last year.<\/p>\n\n<p>I'm excited to see Drupal usage continue to move towards the newer versions so everyone can benefit from the new features and improvements in Drupal 10 and 11 and the new Drupal CMS project.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>On the 5th of January, Drupal 7 will be end of life and have no further updates.<\/p>\n\n<p><a href=\"https:\/\/www.drupal.org\/blog\/drupal-70-is-released\">Released in January 2011<\/a>, Drupal 7 will be 14 years old in January and will have outlived Drupal 8 and 9 which are already unsupported.<\/p>\n\n<p>There are a lot of Drupal 7 sites still in production, but it's been interesting to see usage numbers for the Override Node Options module <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/16\/an-interesting-thing-i-spotted-about-the-override-node-options-module\">decrease for Drupal 7 and increase for Drupal 8+<\/a> over the last year.<\/p>\n\n<p>I'm excited to see Drupal usage continue to move towards the newer versions so everyone can benefit from the new features and improvements in Drupal 10 and 11 and the new Drupal CMS project.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "e93df0be19a187ce2cfa64f7e7f55371",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "027ebf68-13b3-4ae5-bd71-08e0f42f7898"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:31+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Ask questions"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-05-30T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:31+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/05\/30\/ask-questions",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>As a Software Developer, it's common to hear that you need to ask questions to progress or work efficiently.<\/p>\n\n<p>You shouldn't just ask technical questions, though.<\/p>\n\n<p>Also ask questions like:<\/p>\n\n<ul>\n<li>What do we want to achieve by delivering this feature?<\/li>\n<li>How do we know if it's a success (or not)?<\/li>\n<li>What business value does this add and who will benefit?<\/li>\n<li>Why do this now? Why not wait a few months or not do it at all?<\/li>\n<li>Is there an existing solution for this?<\/li>\n<li>Can we achieve the same or a similar result in a different way?<\/li>\n<\/ul>\n\n<p>As well as knowing how to do something, it's important to know why it needs to be done.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>As a Software Developer, it's common to hear that you need to ask questions to progress or work efficiently.<\/p>\n\n<p>You shouldn't just ask technical questions, though.<\/p>\n\n<p>Also ask questions like:<\/p>\n\n<ul>\n<li>What do we want to achieve by delivering this feature?<\/li>\n<li>How do we know if it's a success (or not)?<\/li>\n<li>What business value does this add and who will benefit?<\/li>\n<li>Why do this now? Why not wait a few months or not do it at all?<\/li>\n<li>Is there an existing solution for this?<\/li>\n<li>Can we achieve the same or a similar result in a different way?<\/li>\n<\/ul>\n\n<p>As well as knowing how to do something, it's important to know why it needs to be done.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:31+00:00",
|
||||
"guid": null,
|
||||
"hash": "f0c3d6e951782cfb763d893c57d2dced",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.02bd7b93-43c7-453f-8af9-0be875b27f82.json
Normal file
100
content/node.02bd7b93-43c7-453f-8af9-0be875b27f82.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "02bd7b93-43c7-453f-8af9-0be875b27f82"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:10+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Proof of concept"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-06-20T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:10+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/06\/20\/proof-of-concept",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>How do you validate an idea from a client or stakeholder?<\/p>\n\n<p>Unlike a minimum viable product, which is the smallest amount of functionality for a feature to be released, a proof of concept is an initial investigation into whether the idea is viable.<\/p>\n\n<p>What's the least amount of development you can do to prove the concept?<\/p>\n\n<p>Can you create something using a smaller data set or with simplified functionality?<\/p>\n\n<p>What can you build within a minimal timeframe so, if the idea isn't used, too much time wasn't invested in it, but still verifies it?<\/p>\n\n<p>Do you need to write any code or do any development at all?<\/p>\n\n<p>All we need to do is find out if the concept could work.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>How do you validate an idea from a client or stakeholder?<\/p>\n\n<p>Unlike a minimum viable product, which is the smallest amount of functionality for a feature to be released, a proof of concept is an initial investigation into whether the idea is viable.<\/p>\n\n<p>What's the least amount of development you can do to prove the concept?<\/p>\n\n<p>Can you create something using a smaller data set or with simplified functionality?<\/p>\n\n<p>What can you build within a minimal timeframe so, if the idea isn't used, too much time wasn't invested in it, but still verifies it?<\/p>\n\n<p>Do you need to write any code or do any development at all?<\/p>\n\n<p>All we need to do is find out if the concept could work.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:10+00:00",
|
||||
"guid": null,
|
||||
"hash": "f671ea961bdda4e275277b04dc159c79",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.02c9e148-b98f-42ae-80f1-d19a6d3fcfb2.json
Normal file
100
content/node.02c9e148-b98f-42ae-80f1-d19a6d3fcfb2.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "02c9e148-b98f-42ae-80f1-d19a6d3fcfb2"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:18+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Types are optional"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-03-06T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:18+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/03\/06\/types-are-optional",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>The main programming languages I write are PHP and JavaScript.<\/p>\n\n<p>Both offer types where, as well as declaring a parameter or property, you can define what type it is - whether it's a string, array, boolean, etc.<\/p>\n\n<p>Adding types is optional.<\/p>\n\n<p>You don't need to add types to your PHP code, and you can choose to write plain JavaScript instead of TypeScript.<\/p>\n\n<p>Some people prefer simpler or cleaner code or less \"visual debt\".<\/p>\n\n<p>I like the extra clarity that types add.<\/p>\n\n<p>I like to be able to read some code and immediately know what types things should be.<\/p>\n\n<p>I like the clearer errors and messages if a different type is given than was expected.<\/p>\n\n<p>Tools like PHPStan know more about my code and give better recommendations than if I don't add types.<\/p>\n\n<p>I like the better autocompletion I get when writing code that has types.<\/p>\n\n<p>I like types, but I also like the flexibility of whether or not to add them and for Developers and development teams to make their own decisions based on their preferences.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>The main programming languages I write are PHP and JavaScript.<\/p>\n\n<p>Both offer types where, as well as declaring a parameter or property, you can define what type it is - whether it's a string, array, boolean, etc.<\/p>\n\n<p>Adding types is optional.<\/p>\n\n<p>You don't need to add types to your PHP code, and you can choose to write plain JavaScript instead of TypeScript.<\/p>\n\n<p>Some people prefer simpler or cleaner code or less \"visual debt\".<\/p>\n\n<p>I like the extra clarity that types add.<\/p>\n\n<p>I like to be able to read some code and immediately know what types things should be.<\/p>\n\n<p>I like the clearer errors and messages if a different type is given than was expected.<\/p>\n\n<p>Tools like PHPStan know more about my code and give better recommendations than if I don't add types.<\/p>\n\n<p>I like the better autocompletion I get when writing code that has types.<\/p>\n\n<p>I like types, but I also like the flexibility of whether or not to add them and for Developers and development teams to make their own decisions based on their preferences.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:18+00:00",
|
||||
"guid": null,
|
||||
"hash": "c50e363614371738c421f8a32ee763f3",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "02db45dc-db1a-4d95-a449-6fe4c7884c3e"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:38+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Don't put business logic in templates"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-01-10T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:38+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/01\/10\/dont-put-business-logic-in-templates",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Here is some code from my website:<\/p>\n\n<p><img src=\"https:\/\/www.oliverdavies.uk\/assets\/images\/talk-count-code.png\" alt=\"A screenshot of the code that calculates the number of talks I've given.\" \/><\/p>\n\n<p>If you want, you can also <a href=\"https:\/\/raw.githubusercontent.com\/opdavies\/oliverdavies.uk\/main\/source\/_pages\/presentations.md\">view it on GitHub<\/a>.<\/p>\n\n<p>It is business logic responsible for counting the number of talks I've given at different events so I can display it on my Talks page.<\/p>\n\n<p>It starts at zero, loops over each talk, and increments the talk count if the event is the current day or a past date.<\/p>\n\n<p>It's only used in a single place, so the same logic isn't duplicated elsewhere.<\/p>\n\n<p>But it's in the page's Twig template.<\/p>\n\n<p>It has no test coverage.<\/p>\n\n<p>If I need to change or refactor it, I'd need to test it again manually.<\/p>\n\n<p>Don't do this.<\/p>\n\n<h2 id=\"so%2C-what-should-i-do%3F\">So, what should I do?<\/h2>\n\n<p>It's OK to put simple presentational logic, such as looping over a list or whether to show or hide a value within a template, but not complex business logic.<\/p>\n\n<p>Business logic should be separated and executed elsewhere. The values should be passed to the template to be rendered.<\/p>\n\n<p>This makes the business logic easier to test as you can test the logic itself and determine the value passed to the template is correct without being concerned about the templating engine.<\/p>\n\n<p>In an application, you may need to output a value to a template and a terminal. You'd have one source of truth, such as a Service, Action or Command class that calculates the value before passing it to the appropriate output.<\/p>\n\n<p>Once the logic is separated, you only need to test it once.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>In a previous version of my website, I did this by creating a custom Twig function.<\/p>\n\n<p>It was as simple as adding <code><\/code> to the template.<\/p>\n\n<p>All the logic was moved from the template to my custom extension.<\/p>\n\n<p>The logic was separated.<\/p>\n\n<p>It had tests.<\/p>\n\n<p>This is the approach I'd take to achieve the same result for a client application.<\/p>\n\n<p>For a client, I want to run a test suite and be confident my logic works as expected - now and in the future.<\/p>\n\n<p>For myself, and for calculating something simple, this is fine.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Here is some code from my website:<\/p>\n\n<p><img src=\"https:\/\/www.oliverdavies.uk\/assets\/images\/talk-count-code.png\" alt=\"A screenshot of the code that calculates the number of talks I've given.\"><\/p>\n\n<p>If you want, you can also <a href=\"https:\/\/raw.githubusercontent.com\/opdavies\/oliverdavies.uk\/main\/source\/_pages\/presentations.md\">view it on GitHub<\/a>.<\/p>\n\n<p>It is business logic responsible for counting the number of talks I've given at different events so I can display it on my Talks page.<\/p>\n\n<p>It starts at zero, loops over each talk, and increments the talk count if the event is the current day or a past date.<\/p>\n\n<p>It's only used in a single place, so the same logic isn't duplicated elsewhere.<\/p>\n\n<p>But it's in the page's Twig template.<\/p>\n\n<p>It has no test coverage.<\/p>\n\n<p>If I need to change or refactor it, I'd need to test it again manually.<\/p>\n\n<p>Don't do this.<\/p>\n\n<h2 id=\"so%2C-what-should-i-do%3F\">So, what should I do?<\/h2>\n\n<p>It's OK to put simple presentational logic, such as looping over a list or whether to show or hide a value within a template, but not complex business logic.<\/p>\n\n<p>Business logic should be separated and executed elsewhere. The values should be passed to the template to be rendered.<\/p>\n\n<p>This makes the business logic easier to test as you can test the logic itself and determine the value passed to the template is correct without being concerned about the templating engine.<\/p>\n\n<p>In an application, you may need to output a value to a template and a terminal. You'd have one source of truth, such as a Service, Action or Command class that calculates the value before passing it to the appropriate output.<\/p>\n\n<p>Once the logic is separated, you only need to test it once.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>In a previous version of my website, I did this by creating a custom Twig function.<\/p>\n\n<p>It was as simple as adding <code><\/code> to the template.<\/p>\n\n<p>All the logic was moved from the template to my custom extension.<\/p>\n\n<p>The logic was separated.<\/p>\n\n<p>It had tests.<\/p>\n\n<p>This is the approach I'd take to achieve the same result for a client application.<\/p>\n\n<p>For a client, I want to run a test suite and be confident my logic works as expected - now and in the future.<\/p>\n\n<p>For myself, and for calculating something simple, this is fine.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:38+00:00",
|
||||
"guid": null,
|
||||
"hash": "a75b22468e6abeb329819fa5a65c2bc1",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "02eee27f-311e-45da-b022-0deaf156a6f0"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:21+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Who's Travis?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-01-23T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:21+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/01\/23\/travis",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I remember seeing a talk or listening to a podcast during which they mentioned Travis, as in the CI pipeline tool, and some of the things they were using it for.<\/p>\n\n<p>They also said that their client thought Travis was a person on their team.<\/p>\n\n<p>In some ways, having a CI pipeline performing automated checks and tests is like having another team member.<\/p>\n\n<p>Instead of waiting for a person to manually check code styles, run tests and spot potential bugs, why not automate them and run them in the CI pipeline every time code changes are pushed?<\/p>\n\n<p>You'll get results sooner than waiting for a person do check the code by hand and, arguably, more consistent results.<\/p>\n\n<p>Then, if you do peer code reviews, you know the basics are already done and the reviewer can focus on other things.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I remember seeing a talk or listening to a podcast during which they mentioned Travis, as in the CI pipeline tool, and some of the things they were using it for.<\/p>\n\n<p>They also said that their client thought Travis was a person on their team.<\/p>\n\n<p>In some ways, having a CI pipeline performing automated checks and tests is like having another team member.<\/p>\n\n<p>Instead of waiting for a person to manually check code styles, run tests and spot potential bugs, why not automate them and run them in the CI pipeline every time code changes are pushed?<\/p>\n\n<p>You'll get results sooner than waiting for a person do check the code by hand and, arguably, more consistent results.<\/p>\n\n<p>Then, if you do peer code reviews, you know the basics are already done and the reviewer can focus on other things.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:21+00:00",
|
||||
"guid": null,
|
||||
"hash": "58c9da441a16db434c006de482ddb439",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.0300b4ea-e71b-4f9c-b4f2-f04f98e92d6c.json
Normal file
100
content/node.0300b4ea-e71b-4f9c-b4f2-f04f98e92d6c.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0300b4ea-e71b-4f9c-b4f2-f04f98e92d6c"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:28+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Why you should contribute to open-source software\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-11-04T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:28+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/11\/04\/why-you-should-contribute-to-open-source-software",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:28+00:00",
|
||||
"guid": null,
|
||||
"hash": "0f37079942ad6ce63ae32e8ea7c57c79",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.0316dfcf-b709-47e1-9622-9355b5ece6d9.json
Normal file
100
content/node.0316dfcf-b709-47e1-9622-9355b5ece6d9.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0316dfcf-b709-47e1-9622-9355b5ece6d9"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "You can deploy on Fridays"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-03-11T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/03\/11\/friday",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:00+00:00",
|
||||
"guid": null,
|
||||
"hash": "021827be7bf3f083020a0f2ff11066d8",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.0318e249-a9a8-476f-9bd4-432544369917.json
Normal file
100
content/node.0318e249-a9a8-476f-9bd4-432544369917.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0318e249-a9a8-476f-9bd4-432544369917"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:01+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "To patch or not to patch"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-02-24T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:01+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/02\/24\/patch",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:01+00:00",
|
||||
"guid": null,
|
||||
"hash": "e1882c079f5b933697958ec2ac91a1b7",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "031b38e7-5589-4f0a-9eaf-18621a4b0ea3"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:42+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "PHPUnit does more than unit testing\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-11-13T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:42+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/11\/13\/phpunit-does-more-than-unit-testing",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>As the name suggests, <a href=\"http:\/\/phpunit.de\">PHPUnit<\/a> is a unit testing framework for PHP.<\/p>\n\n<p>It's the defacto PHP testing framework used by the major PHP projects, such as Drupal, Symfony, Laravel.<\/p>\n\n<p>But unit testing isn't all that PHPUnit can do.<\/p>\n\n<p>These frameworks extend PHPUnit to give it more functionality.<\/p>\n\n<p>Drupal allows you to run functional\/browser tests to make requests to pages, check the response codes and content, as well as integration\/kernel tests to test real services instead of relying on mocking within unit tests.<\/p>\n\n<p>Symfony does the same with its web and kernel test cases.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>If you use a framework and want to more than unit testing, intsead of including another testing framework, try using some of the PHPUnit extensions that are provided by the framework.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>As the name suggests, <a href=\"http:\/\/phpunit.de\">PHPUnit<\/a> is a unit testing framework for PHP.<\/p>\n\n<p>It's the defacto PHP testing framework used by the major PHP projects, such as Drupal, Symfony, Laravel.<\/p>\n\n<p>But unit testing isn't all that PHPUnit can do.<\/p>\n\n<p>These frameworks extend PHPUnit to give it more functionality.<\/p>\n\n<p>Drupal allows you to run functional\/browser tests to make requests to pages, check the response codes and content, as well as integration\/kernel tests to test real services instead of relying on mocking within unit tests.<\/p>\n\n<p>Symfony does the same with its web and kernel test cases.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>If you use a framework and want to more than unit testing, intsead of including another testing framework, try using some of the PHPUnit extensions that are provided by the framework.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:42+00:00",
|
||||
"guid": null,
|
||||
"hash": "ebb678e6bfb989f0b14c1f494c92a1af",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.033f0b46-69f9-4ea0-9706-d930e67dd5d8.json
Normal file
100
content/node.033f0b46-69f9-4ea0-9706-d930e67dd5d8.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "033f0b46-69f9-4ea0-9706-d930e67dd5d8"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:08+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Merging unrelated histories"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-08-02T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:08+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/08\/02\/merging-unrelated-histories",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:08+00:00",
|
||||
"guid": null,
|
||||
"hash": "cc353a3343b4a9ed6dc01850a09c8f76",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "03653911-19e8-4f60-8baa-5165b8380d29"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-01T23:43:31+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Dependency-free PHP Collections"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-03-29T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-01T23:43:31+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/03\/29\/collections",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>A few months ago, <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/6-dan-leech-php-tui\">Beyond Blocks podcast guest Dan Leech<\/a> give another talk at the PHP South West user group.<\/p>\n\n<p>This talk was about <a href=\"https:\/\/www.youtube.com\/watch?v=UpyVAcWGQhg\">building an expression language from scratch<\/a>, but in one part of the talk, Dan showed how he creates Collection classes.<\/p>\n\n<p>I use Collection classes a lot, have <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/using-illuminate-collections-outside-laravel\">given talks about them<\/a> and <a href=\"https:\/\/www.drupal.org\/project\/collection_class\">wrote a Collections module for Drupal 7<\/a>.<\/p>\n\n<p>In Dan's talk, instead of using a Collection from Laravel or Doctrine, <a href=\"https:\/\/github.com\/dantleech\/onehourexpr\/blob\/8c4ee4a3c1680455118e16a3e1be2a08418ab207\/src\/Tokens.php\">he created his own<\/a>.<\/p>\n\n<p>His extended PHP's <code>IteratorAggregate<\/code> class so had no external dependencies.<\/p>\n\n<p>He could then add whatever additional methods and functionality he needed.<\/p>\n\n<p>Looking at other repositories on GitHub, I was able to find other examples.<\/p>\n\n<p>I've done this on projects since Dan's talk and like taking the minimalist approach - avoiding adding a dependency to my project and only adding the functionality I need and functionality that's more specific to my domain.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>A few months ago, <a href=\"https:\/\/www.oliverdavies.uk\/podcast\/6-dan-leech-php-tui\">Beyond Blocks podcast guest Dan Leech<\/a> give another talk at the PHP South West user group.<\/p>\n\n<p>This talk was about <a href=\"https:\/\/www.youtube.com\/watch?v=UpyVAcWGQhg\">building an expression language from scratch<\/a>, but in one part of the talk, Dan showed how he creates Collection classes.<\/p>\n\n<p>I use Collection classes a lot, have <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/using-illuminate-collections-outside-laravel\">given talks about them<\/a> and <a href=\"https:\/\/www.drupal.org\/project\/collection_class\">wrote a Collections module for Drupal 7<\/a>.<\/p>\n\n<p>In Dan's talk, instead of using a Collection from Laravel or Doctrine, <a href=\"https:\/\/github.com\/dantleech\/onehourexpr\/blob\/8c4ee4a3c1680455118e16a3e1be2a08418ab207\/src\/Tokens.php\">he created his own<\/a>.<\/p>\n\n<p>His extended PHP's <code>IteratorAggregate<\/code> class so had no external dependencies.<\/p>\n\n<p>He could then add whatever additional methods and functionality he needed.<\/p>\n\n<p>Looking at other repositories on GitHub, I was able to find other examples.<\/p>\n\n<p>I've done this on projects since Dan's talk and like taking the minimalist approach - avoiding adding a dependency to my project and only adding the functionality I need and functionality that's more specific to my domain.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-01T23:43:31+00:00",
|
||||
"guid": null,
|
||||
"hash": "94b06833489046a4c26442548eee3ca2",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.036a8839-c5f9-4206-a979-201e9dac1557.json
Normal file
100
content/node.036a8839-c5f9-4206-a979-201e9dac1557.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "036a8839-c5f9-4206-a979-201e9dac1557"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:46+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Software development is about solving problems and adding value\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-03-27T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:46+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/03\/27\/software-development-solving-problems-and-adding-value",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I've recently started as a Mentor for the School of Code, working with a student on their cohort that started last week. Whilst the Bootcamp is focussed on JavaScript and node, and is currently looking at front-end development and using APIs, we've already started talking about different back-end technologies and frameworks.<\/p>\n\n<p>Something that I've believed for a while is that software development is about solving problems and different languages and frameworks are tools to use to solve the problem and achieve the desired result. The programming fundamentals that he's learning now can be applied to different languages and some may be better depending on the problem that needs to be solved.<\/p>\n\n<p>I've also said when speaking with a client this week that development is about adding business value.<\/p>\n\n<p>Whilst there is some value to doing security updates and maintenance to keep an application running and secure, I'd much rather be working on tasks that directly add value for the client like some of the tasks I've done for them recently like improving eCommerce conversions and adding new payment methods or revenue streams.<\/p>\n\n<p>It's easier for the client to justify and see the results of the work, it improves the experience for their customers or users, and it's more interesting and fulfilling for me.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I've recently started as a Mentor for the School of Code, working with a student on their cohort that started last week. Whilst the Bootcamp is focussed on JavaScript and node, and is currently looking at front-end development and using APIs, we've already started talking about different back-end technologies and frameworks.<\/p>\n\n<p>Something that I've believed for a while is that software development is about solving problems and different languages and frameworks are tools to use to solve the problem and achieve the desired result. The programming fundamentals that he's learning now can be applied to different languages and some may be better depending on the problem that needs to be solved.<\/p>\n\n<p>I've also said when speaking with a client this week that development is about adding business value.<\/p>\n\n<p>Whilst there is some value to doing security updates and maintenance to keep an application running and secure, I'd much rather be working on tasks that directly add value for the client like some of the tasks I've done for them recently like improving eCommerce conversions and adding new payment methods or revenue streams.<\/p>\n\n<p>It's easier for the client to justify and see the results of the work, it improves the experience for their customers or users, and it's more interesting and fulfilling for me.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:46+00:00",
|
||||
"guid": null,
|
||||
"hash": "7256a5bb0e6800a548d88e2979344646",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.037796b8-42d8-4ea4-abec-f8c8de0d97e8.json
Normal file
100
content/node.037796b8-42d8-4ea4-abec-f8c8de0d97e8.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "037796b8-42d8-4ea4-abec-f8c8de0d97e8"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:28+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Drupal's Alternate Realities\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-11-17T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:28+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/11\/17\/drupal-s-alternate-realities",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:28+00:00",
|
||||
"guid": null,
|
||||
"hash": "4ddf140ca0555c2028d2bb2db394282f",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "03a28574-fa89-455a-8e83-81a276c0d658"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:25+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Code reviews are about the code, not code style"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-10-30T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:25+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/10\/30\/code-reviews-are-about-the-code-not-code-style",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>If you do code reviews, they should be about reviewing the code and not about the style of the code.<\/p>\n\n<p>There shouldn't be comments about whether tabs or spaces are used, how many spaces are on each line, where the braces are, or whether there should be semicolons.<\/p>\n\n<p>A code style should be defined upfront and checking code against it can be done automatically with tools such as phpcs or Prettier.<\/p>\n\n<p>You don't need to wait for a human to review the code style - automated tools can be run locally or in a CI pipeline and provide feedback much faster.<\/p>\n\n<p>And if people aren't reviewing the code style, they can focus on reviewing the code itself.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>If you do code reviews, they should be about reviewing the code and not about the style of the code.<\/p>\n\n<p>There shouldn't be comments about whether tabs or spaces are used, how many spaces are on each line, where the braces are, or whether there should be semicolons.<\/p>\n\n<p>A code style should be defined upfront and checking code against it can be done automatically with tools such as phpcs or Prettier.<\/p>\n\n<p>You don't need to wait for a human to review the code style - automated tools can be run locally or in a CI pipeline and provide feedback much faster.<\/p>\n\n<p>And if people aren't reviewing the code style, they can focus on reviewing the code itself.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:25+00:00",
|
||||
"guid": null,
|
||||
"hash": "9fe14e0414ae452819b91e9a2abc8403",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.03bbb03d-5963-477a-a904-19e2c1f1a581.json
Normal file
100
content/node.03bbb03d-5963-477a-a904-19e2c1f1a581.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "03bbb03d-5963-477a-a904-19e2c1f1a581"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:02+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Refactor, remove or replace"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-01-09T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:02+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/01\/09\/rrr",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>There are three things you can do with legacy code.<\/p>\n\n<p>Refactor it, remove it or replace it.<\/p>\n\n<p>You can refactor it to make it easier to maintain and change in the future.<\/p>\n\n<p>If it's not needed, you can remove it.<\/p>\n\n<p>If it's not used, there's no need to keep it.<\/p>\n\n<p>Or you can replace it with something else.<\/p>\n\n<p>There isn't one right answer and the correct approach will depend on the situation and objective.<\/p>\n\n<p>In a future email, I'll give some examples of how I refactor legacy code.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>There are three things you can do with legacy code.<\/p>\n\n<p>Refactor it, remove it or replace it.<\/p>\n\n<p>You can refactor it to make it easier to maintain and change in the future.<\/p>\n\n<p>If it's not needed, you can remove it.<\/p>\n\n<p>If it's not used, there's no need to keep it.<\/p>\n\n<p>Or you can replace it with something else.<\/p>\n\n<p>There isn't one right answer and the correct approach will depend on the situation and objective.<\/p>\n\n<p>In a future email, I'll give some examples of how I refactor legacy code.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:02+00:00",
|
||||
"guid": null,
|
||||
"hash": "a3ea19c23705f4574c9b1455cc2169bc",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.03c0a713-f32d-445b-9397-add68fbf2fe5.json
Normal file
100
content/node.03c0a713-f32d-445b-9397-add68fbf2fe5.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "03c0a713-f32d-445b-9397-add68fbf2fe5"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:04+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Homelabbing with NixOS"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-12-01T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:04+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/12\/01\/homelabbing-with-nixos",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:04+00:00",
|
||||
"guid": null,
|
||||
"hash": "ddffb71cbb4982c0c4d9ca78fecdcd4c",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "03c5cbcb-f7f6-49a1-b064-6a9a79b34b53"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:36+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Why do people still use Git Flow?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-02-25T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:36+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/02\/25\/why-do-people-still-use-git-flow",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/presentations\/git-flow\">The first conference talk I gave<\/a> was at DrupalCamp London 2014.<\/p>\n\n<p>The talk was about Git Flow - a popular branching scheme I was using to manage a project, where there are different branches for development and production versions of the software and separate branches for features, releases and hotfixes.<\/p>\n\n<p>It's been a standard approach as I've worked on different projects and teams, usually with pull or merge requests and code reviews.<\/p>\n\n<p>But why do people still use it?<\/p>\n\n<p>I was conducting technical interviews recently and every candidate explained how they used Git Flow or something inspired by it, and GitHub and GitLab have their own simplified versions.<\/p>\n\n<p>Vincent Driessen wrote the original Git Flow blog post in January 2010, though he updated it in March 2020 to add this note of reflection:<\/p>\n\n<blockquote>\n <p>This model was conceived in 2010, now more than 10 years ago, and not very long after Git itself came into being. In those 10 years, git-flow (the branching model laid out in this article) has become hugely popular in many a software team to the point where people have started treating it like a standard of sorts \u2014 but unfortunately also as a dogma or panacea.<\/p>\n \n <p>During those 10 years, Git itself has taken the world by a storm, and the most popular type of software that is being developed with Git is shifting more towards web apps \u2014 at least in my filter bubble. Web apps are typically continuously delivered, not rolled back, and you don't have to support multiple versions of the software running in the wild.<\/p>\n \n <p>This is not the class of software that I had in mind when I wrote the blog post 10 years ago. If your team is doing continuous delivery of software, I would suggest to adopt a much simpler workflow (like GitHub flow) instead of trying to shoehorn git-flow into your team.<\/p>\n \n <p>If, however, you are building software that is explicitly versioned, or if you need to support multiple versions of your software in the wild, then git-flow may still be as good of a fit to your team as it has been to people in the last 10 years. In that case, please read on.<\/p>\n \n <p>To conclude, always remember that panaceas don't exist. Consider your own context. Don't be hating. Decide for yourself.<\/p>\n<\/blockquote>\n\n<p>Since adopting trunk-based development and continuous integration and delivery, I've worked faster and avoided merge conflicts, which wasn't the case before, even when I was the only one working on a codebase.<\/p>\n\n<p>It's a simpler workflow.<\/p>\n\n<p>I don't need to think about whether this branch is a feature or a hotfix, and I've rarely seen release and hotfix branches used as described in the original blog post.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Do what works best for you and your team, but don't adopt something because it's the \"standard\" approach.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/presentations\/git-flow\">The first conference talk I gave<\/a> was at DrupalCamp London 2014.<\/p>\n\n<p>The talk was about Git Flow - a popular branching scheme I was using to manage a project, where there are different branches for development and production versions of the software and separate branches for features, releases and hotfixes.<\/p>\n\n<p>It's been a standard approach as I've worked on different projects and teams, usually with pull or merge requests and code reviews.<\/p>\n\n<p>But why do people still use it?<\/p>\n\n<p>I was conducting technical interviews recently and every candidate explained how they used Git Flow or something inspired by it, and GitHub and GitLab have their own simplified versions.<\/p>\n\n<p>Vincent Driessen wrote the original Git Flow blog post in January 2010, though he updated it in March 2020 to add this note of reflection:<\/p>\n\n<blockquote>\n <p>This model was conceived in 2010, now more than 10 years ago, and not very long after Git itself came into being. In those 10 years, git-flow (the branching model laid out in this article) has become hugely popular in many a software team to the point where people have started treating it like a standard of sorts \u2014 but unfortunately also as a dogma or panacea.<\/p>\n \n <p>During those 10 years, Git itself has taken the world by a storm, and the most popular type of software that is being developed with Git is shifting more towards web apps \u2014 at least in my filter bubble. Web apps are typically continuously delivered, not rolled back, and you don't have to support multiple versions of the software running in the wild.<\/p>\n \n <p>This is not the class of software that I had in mind when I wrote the blog post 10 years ago. If your team is doing continuous delivery of software, I would suggest to adopt a much simpler workflow (like GitHub flow) instead of trying to shoehorn git-flow into your team.<\/p>\n \n <p>If, however, you are building software that is explicitly versioned, or if you need to support multiple versions of your software in the wild, then git-flow may still be as good of a fit to your team as it has been to people in the last 10 years. In that case, please read on.<\/p>\n \n <p>To conclude, always remember that panaceas don't exist. Consider your own context. Don't be hating. Decide for yourself.<\/p>\n<\/blockquote>\n\n<p>Since adopting trunk-based development and continuous integration and delivery, I've worked faster and avoided merge conflicts, which wasn't the case before, even when I was the only one working on a codebase.<\/p>\n\n<p>It's a simpler workflow.<\/p>\n\n<p>I don't need to think about whether this branch is a feature or a hotfix, and I've rarely seen release and hotfix branches used as described in the original blog post.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>Do what works best for you and your team, but don't adopt something because it's the \"standard\" approach.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:36+00:00",
|
||||
"guid": null,
|
||||
"hash": "9b0cfa53767098dc8873acdefd4d5eba",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "03ce1ec7-c326-4e2a-94c9-a12efb9dfa89"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:23+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "How easily can you move changes between environments?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-12-24T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:23+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/12\/24\/moving-changes",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Regardless of <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/12\/23\/how-many-environments-do-you-need\">how many environments your application has<\/a>, you need to be able to move changes between them reliably.<\/p>\n\n<p>You don't want to configure each environment and make every change by hand.<\/p>\n\n<p>You want to automate this as much as possible so your changes are the same every time.<\/p>\n\n<p>In Drupal 7, the Features module was used to export changes once and apply them again using a <code>features revert<\/code> command - although its original use case was to extract reusable features for different applications.<\/p>\n\n<p>I've also written a lot of update of update hooks, like <code>mymodule_update_8001<\/code> to apply changes when database updates are applied.<\/p>\n\n<p>Since Drupal 8, we've had configuration management - a first-class way to export and import configuration changes - which I think was one of the best additions to Drupal 8, and something not available in some other CMSes, frameworks and applications.<\/p>\n\n<p>There's an ecosystem around configuration management, including Config Split for per-environment configurations and Config Ignore to ignore sensitive information or changes you don't want to manage via imported configuration.<\/p>\n\n<p>I recently worked on a project where we didn't have a CI pipeline running configuration imports on each change and things were very difficult to manage. Once that was in place, though, things were much easier, more consistent and changes were quicker to release.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Regardless of <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/12\/23\/how-many-environments-do-you-need\">how many environments your application has<\/a>, you need to be able to move changes between them reliably.<\/p>\n\n<p>You don't want to configure each environment and make every change by hand.<\/p>\n\n<p>You want to automate this as much as possible so your changes are the same every time.<\/p>\n\n<p>In Drupal 7, the Features module was used to export changes once and apply them again using a <code>features revert<\/code> command - although its original use case was to extract reusable features for different applications.<\/p>\n\n<p>I've also written a lot of update of update hooks, like <code>mymodule_update_8001<\/code> to apply changes when database updates are applied.<\/p>\n\n<p>Since Drupal 8, we've had configuration management - a first-class way to export and import configuration changes - which I think was one of the best additions to Drupal 8, and something not available in some other CMSes, frameworks and applications.<\/p>\n\n<p>There's an ecosystem around configuration management, including Config Split for per-environment configurations and Config Ignore to ignore sensitive information or changes you don't want to manage via imported configuration.<\/p>\n\n<p>I recently worked on a project where we didn't have a CI pipeline running configuration imports on each change and things were very difficult to manage. Once that was in place, though, things were much easier, more consistent and changes were quicker to release.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:23+00:00",
|
||||
"guid": null,
|
||||
"hash": "edb67464b9188fe49c1cef46dfa04ac8",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "03ec00a2-aea4-4454-bbe9-413f4c865596"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:17+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Static websites are easy to backup"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-03-14T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:17+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/03\/14\/backup",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:17+00:00",
|
||||
"guid": null,
|
||||
"hash": "cad56e3254ecbb16885c1f741f0776f9",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "03f8c551-dc44-4dde-ab7b-771c6244e9ac"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:22:02+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Useful Git configuration"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2022-09-19T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:22:02+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2022\/09\/19\/useful-git-configuration",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Here are some snippets from my Git configuration file.<\/p>\n\n<p>These days, I use a much simpler workflow and configuration since doing more trunk-based development, but in general, I rebase instead of merging by default, and prefer to use fast-forward merges that doesn't create a merge commit.<\/p>\n\n<p><code>branch.autosetuprebase = always<\/code> and <code>pull.rebase = true<\/code> configure Git to always rebase instead of pull. It does this for all branches, though I might override this for <code>main<\/code> branches.<\/p>\n\n<p><code>pull.ff = only<\/code> and <code>merge.ff = only<\/code> prevents creating a merge commit and will prevent the merge if it would create one. If I needed to override this, I could by using the <code>--no-ff<\/code> option on the command line.<\/p>\n\n<p>I use <code>checkout.defaultRemote = origin<\/code> to ensure that the <code>origin<\/code> remote is used if I have multiple remotes configured, and <code>push.default = upstream<\/code> to set the default remote to push to.<\/p>\n\n<p><code>merge.autoStash<\/code> allows for running merges on a dirty worktree by automatically creating and re-applying a stash of the changes, and <code>fetch.prune<\/code> will automatically prune branches on fetch - keeping things tidy.<\/p>\n\n<p>I also have and use a number of aliases.<\/p>\n\n<p>Some like <code>pl = pull<\/code> and <code>ps = push<\/code> are shorter versions of existing commands, and some like <code>aa = add --all<\/code>, <code>fixup = commit --fixup<\/code> and some additional arguments to commands.<\/p>\n\n<p>I also have some like <code>current-branch = rev-parse --abbrev-ref HEAD<\/code> and <code>worktrees = worktree list<\/code> which add simple additional commands, and some like <code>repush = !git pull --rebase && git push<\/code> which use execute shell commands to execute more complex commands or combine multiple commands.<\/p>\n\n<p>This is a snapshot of my Git configuration. The <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/7e935b12c09358adad480a566988b9cbfaf5999e\/roles\/git\/files\/.gitconfig\">full version is on GitHub<\/a>.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Here are some snippets from my Git configuration file.<\/p>\n\n<p>These days, I use a much simpler workflow and configuration since doing more trunk-based development, but in general, I rebase instead of merging by default, and prefer to use fast-forward merges that doesn't create a merge commit.<\/p>\n\n<p><code>branch.autosetuprebase = always<\/code> and <code>pull.rebase = true<\/code> configure Git to always rebase instead of pull. It does this for all branches, though I might override this for <code>main<\/code> branches.<\/p>\n\n<p><code>pull.ff = only<\/code> and <code>merge.ff = only<\/code> prevents creating a merge commit and will prevent the merge if it would create one. If I needed to override this, I could by using the <code>--no-ff<\/code> option on the command line.<\/p>\n\n<p>I use <code>checkout.defaultRemote = origin<\/code> to ensure that the <code>origin<\/code> remote is used if I have multiple remotes configured, and <code>push.default = upstream<\/code> to set the default remote to push to.<\/p>\n\n<p><code>merge.autoStash<\/code> allows for running merges on a dirty worktree by automatically creating and re-applying a stash of the changes, and <code>fetch.prune<\/code> will automatically prune branches on fetch - keeping things tidy.<\/p>\n\n<p>I also have and use a number of aliases.<\/p>\n\n<p>Some like <code>pl = pull<\/code> and <code>ps = push<\/code> are shorter versions of existing commands, and some like <code>aa = add --all<\/code>, <code>fixup = commit --fixup<\/code> and some additional arguments to commands.<\/p>\n\n<p>I also have some like <code>current-branch = rev-parse --abbrev-ref HEAD<\/code> and <code>worktrees = worktree list<\/code> which add simple additional commands, and some like <code>repush = !git pull --rebase && git push<\/code> which use execute shell commands to execute more complex commands or combine multiple commands.<\/p>\n\n<p>This is a snapshot of my Git configuration. The <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/7e935b12c09358adad480a566988b9cbfaf5999e\/roles\/git\/files\/.gitconfig\">full version is on GitHub<\/a>.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:22:02+00:00",
|
||||
"guid": null,
|
||||
"hash": "c064efff8a7c26a4e05fee32b076e0b2",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "04078ba0-6948-42fc-8417-0765f70d4482"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Is testing a chore?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-09-29T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/09\/29\/is-testing-a-chore",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/09\/28\/testing-personal-projects\">Do some Developers skip writing tests for their personal projects<\/a> because they think it's a chore?<\/p>\n\n<p>If they've written the code, so they then think it's too much work to write tests or need to move on to the next task?<\/p>\n\n<p>Is it boring to write tests for code that's already written and will pass straight away?<\/p>\n\n<p>This is why I do test-driven development and start with a failing test and then write code to make it pass.<\/p>\n\n<p>Then, I add more to the test until it fails and then get that to pass.<\/p>\n\n<p>When that test is finished, I'll move to a new test for a different piece of functionality.<\/p>\n\n<p>I like this approach of working in small feedback cycles and alternating between failing and passing tests.<\/p>\n\n<p>Testing this way isn't boring or a chore and much more interesting for me compared to writing all the code first and maybe writing the tests later.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p><a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/09\/28\/testing-personal-projects\">Do some Developers skip writing tests for their personal projects<\/a> because they think it's a chore?<\/p>\n\n<p>If they've written the code, so they then think it's too much work to write tests or need to move on to the next task?<\/p>\n\n<p>Is it boring to write tests for code that's already written and will pass straight away?<\/p>\n\n<p>This is why I do test-driven development and start with a failing test and then write code to make it pass.<\/p>\n\n<p>Then, I add more to the test until it fails and then get that to pass.<\/p>\n\n<p>When that test is finished, I'll move to a new test for a different piece of functionality.<\/p>\n\n<p>I like this approach of working in small feedback cycles and alternating between failing and passing tests.<\/p>\n\n<p>Testing this way isn't boring or a chore and much more interesting for me compared to writing all the code first and maybe writing the tests later.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "4b2d47376db0c887f15bedf49de35711",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "04174e15-cb3b-4d35-98be-9d2f5d89999a"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "How and why I started using PostCSS\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2022-12-09T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2022\/12\/09\/how-and-why-i-started-using-postcss",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I assume that, like many other Developers, when I started learning front-end development, I wrote normal, plain CSS and later discovered and adopted pre-processors like Less and Sass that added features such as variables and nesting to my stylesheets.<\/p>\n\n<p>This was the case when I first saw what became Tailwind CSS, which were some stylesheets written in Less and ported manually between projects.<\/p>\n\n<p>I remember watching one of those streams, and a fellow viewer suggested PostCSS, which Tailwind CSS would later be written in.<\/p>\n\n<p>PostCSS, a CSS post-processor rather than a pre-processor, has become my preferred way of writing CSS because of Tailwind.<\/p>\n\n<p>When I started using Tailwind in my projects, I was layering it on top of another CSS framework or styles that were written using Less or Sass, so I needed to pre-process them into CSS first and then run PostCSS - essentially running two build steps and adding to the build time.<\/p>\n\n<p>I moved to use PostCSS by default - removing one of the build steps.<\/p>\n\n<p>What I liked about it, as well as the quicker build times, was that I could start with plain CSS and add the extra features I needed. I didn't use all of Sass and Less' features, and now, if I needed nesting or real-time imports, I could add it via a PostCSS plugin or write my own.<\/p>\n\n<p>It's also quick and easy to use, using the PostCSS CLI tool and without more complex tools like Webpack.<\/p>\n\n<p>If you haven't tried PostCSS, I recommend taking a look.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I assume that, like many other Developers, when I started learning front-end development, I wrote normal, plain CSS and later discovered and adopted pre-processors like Less and Sass that added features such as variables and nesting to my stylesheets.<\/p>\n\n<p>This was the case when I first saw what became Tailwind CSS, which were some stylesheets written in Less and ported manually between projects.<\/p>\n\n<p>I remember watching one of those streams, and a fellow viewer suggested PostCSS, which Tailwind CSS would later be written in.<\/p>\n\n<p>PostCSS, a CSS post-processor rather than a pre-processor, has become my preferred way of writing CSS because of Tailwind.<\/p>\n\n<p>When I started using Tailwind in my projects, I was layering it on top of another CSS framework or styles that were written using Less or Sass, so I needed to pre-process them into CSS first and then run PostCSS - essentially running two build steps and adding to the build time.<\/p>\n\n<p>I moved to use PostCSS by default - removing one of the build steps.<\/p>\n\n<p>What I liked about it, as well as the quicker build times, was that I could start with plain CSS and add the extra features I needed. I didn't use all of Sass and Less' features, and now, if I needed nesting or real-time imports, I could add it via a PostCSS plugin or write my own.<\/p>\n\n<p>It's also quick and easy to use, using the PostCSS CLI tool and without more complex tools like Webpack.<\/p>\n\n<p>If you haven't tried PostCSS, I recommend taking a look.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "df6cac0e06b78b0e457c5d6f45c51e64",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.042e4d0c-f835-47dd-8075-745df0a7f8f2.json
Normal file
100
content/node.042e4d0c-f835-47dd-8075-745df0a7f8f2.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "042e4d0c-f835-47dd-8075-745df0a7f8f2"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:57+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "How I've configured Git"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2022-08-24T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:57+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2022\/08\/24\/2022-08-24",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>After yesterday's post on why I prefer using Git on the command line rather than using a GUI tool, today I thought that I'd post about how I've configured Git.<\/p>\n\n<p>First, I rarely ever run the <code>git<\/code> command - I usually run a <code>g<\/code> function that I've created within my zsh configuration.<\/p>\n\n<p>Rather than being an simple alias, it's a shell function that will run <code>git status -sb<\/code> to show the current status of the repository if there are no additional arguments. If there are, such as when running <code>g add<\/code>, then this is executed as a normal Git command. (This is something that I first saw from Thoughtbot, if I remember correctly).<\/p>\n\n<h2 id=\"using-.gitconfig\">Using .gitconfig<\/h2>\n\n<p>The main part of my configuration is within Git's <code>~\/.gitconfig<\/code> file, where I can configure Git to work how I want.<\/p>\n\n<p>For example, I like to avoid merge conflicts, so I always want to use fast-forward merges whilst pulling and also to rebase by default. I can do this by adding <code>ff = only<\/code> and <code>rebase = true<\/code> to the <code>[pull]<\/code> section of my <code>~\/.gitconfig<\/code> file.<\/p>\n\n<p>I can do this manually, or running <code>git config --global pull.rebase true<\/code> will set the option but also update the file automatically.<\/p>\n\n<p>Some of the tweaks that I've made are to only allow fast-forward merges by adding <code>merge.ff = only<\/code>, automatically squash commits when rebasing by setting <code>rebase.autosquash = true<\/code>, and automatically pruning branches by adding <code>fetch.prune = true<\/code>.<\/p>\n\n<h3 id=\"simple-aliases\">Simple aliases<\/h3>\n\n<p>Another way that I configure Git is using aliases, which are also within the <code>~\/.gitconfig<\/code> file.<\/p>\n\n<p>For example, if I ran <code>git config --global alias.b \"branch\"<\/code>, then running <code>git b<\/code> would just run <code>git branch<\/code> which shortens the command and saves some time and keystrokes.<\/p>\n\n<p>I have similar one- or two letter \"short\" aliases for pushing and pulling code, and some that also set some additional arguments such as <code>aa<\/code> for <code>add --all<\/code> and <code>worktrees<\/code> for <code>worktree list<\/code>.<\/p>\n\n<h3 id=\"more-complicated-aliases\">More complicated aliases<\/h3>\n\n<p>Aliases can be more complex if needed by prefixing it with a <code>!<\/code>, meaning that it executes it as a shell command.<\/p>\n\n<p>This means that I can have <code>repush = !git pull --rebase && git push<\/code> to chain two separate Git commands and combine them into one, and <code>ureset = !git reset --hard $(git upstream)<\/code> which executes the full command, including another alias as part of it.<\/p>\n\n<p>I also have <code>issues = !gh issue list --web<\/code> and <code>pulls = !gh pr list --web<\/code> to open the current repository's GitHub issues or pull requests respectively, which can be done as it's not limited to just running <code>git<\/code> commands.<\/p>\n\n<h3 id=\"custom-functions\">Custom functions<\/h3>\n\n<p>Finally, if an alias is getting too long or complex, then it can extracted to it's own file.<\/p>\n\n<p>Any executable file within your <code>$PATH<\/code> that starts with <code>git-<\/code> will automatically become a Git command.<\/p>\n\n<p>One example that I have is <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/2b20cd1e59ae3b1fa81074077e855cbdfa02f146\/bin\/bin\/git-cm\">git-cm<\/a> which, similar to the <code>g<\/code> function`, is a bash script that checks for any arguments passed to it and runs a slightly different command. It achieves the same thing as if it were an alias, but it does make it easier to write and maintain as it's in a separate file.<\/p>\n\n<p>These are just some examples. If you want to see my entire configuration, then check out <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/tree\/2b20cd1e59ae3b1fa81074077e855cbdfa02f146\/roles\/git\/files\">my dotfiles repository on GitHub<\/a>.<\/p>\n\n<p>How have you configured Git for your workflow? Reply to this email and let me know.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>After yesterday's post on why I prefer using Git on the command line rather than using a GUI tool, today I thought that I'd post about how I've configured Git.<\/p>\n\n<p>First, I rarely ever run the <code>git<\/code> command - I usually run a <code>g<\/code> function that I've created within my zsh configuration.<\/p>\n\n<p>Rather than being an simple alias, it's a shell function that will run <code>git status -sb<\/code> to show the current status of the repository if there are no additional arguments. If there are, such as when running <code>g add<\/code>, then this is executed as a normal Git command. (This is something that I first saw from Thoughtbot, if I remember correctly).<\/p>\n\n<h2 id=\"using-.gitconfig\">Using .gitconfig<\/h2>\n\n<p>The main part of my configuration is within Git's <code>~\/.gitconfig<\/code> file, where I can configure Git to work how I want.<\/p>\n\n<p>For example, I like to avoid merge conflicts, so I always want to use fast-forward merges whilst pulling and also to rebase by default. I can do this by adding <code>ff = only<\/code> and <code>rebase = true<\/code> to the <code>[pull]<\/code> section of my <code>~\/.gitconfig<\/code> file.<\/p>\n\n<p>I can do this manually, or running <code>git config --global pull.rebase true<\/code> will set the option but also update the file automatically.<\/p>\n\n<p>Some of the tweaks that I've made are to only allow fast-forward merges by adding <code>merge.ff = only<\/code>, automatically squash commits when rebasing by setting <code>rebase.autosquash = true<\/code>, and automatically pruning branches by adding <code>fetch.prune = true<\/code>.<\/p>\n\n<h3 id=\"simple-aliases\">Simple aliases<\/h3>\n\n<p>Another way that I configure Git is using aliases, which are also within the <code>~\/.gitconfig<\/code> file.<\/p>\n\n<p>For example, if I ran <code>git config --global alias.b \"branch\"<\/code>, then running <code>git b<\/code> would just run <code>git branch<\/code> which shortens the command and saves some time and keystrokes.<\/p>\n\n<p>I have similar one- or two letter \"short\" aliases for pushing and pulling code, and some that also set some additional arguments such as <code>aa<\/code> for <code>add --all<\/code> and <code>worktrees<\/code> for <code>worktree list<\/code>.<\/p>\n\n<h3 id=\"more-complicated-aliases\">More complicated aliases<\/h3>\n\n<p>Aliases can be more complex if needed by prefixing it with a <code>!<\/code>, meaning that it executes it as a shell command.<\/p>\n\n<p>This means that I can have <code>repush = !git pull --rebase && git push<\/code> to chain two separate Git commands and combine them into one, and <code>ureset = !git reset --hard $(git upstream)<\/code> which executes the full command, including another alias as part of it.<\/p>\n\n<p>I also have <code>issues = !gh issue list --web<\/code> and <code>pulls = !gh pr list --web<\/code> to open the current repository's GitHub issues or pull requests respectively, which can be done as it's not limited to just running <code>git<\/code> commands.<\/p>\n\n<h3 id=\"custom-functions\">Custom functions<\/h3>\n\n<p>Finally, if an alias is getting too long or complex, then it can extracted to it's own file.<\/p>\n\n<p>Any executable file within your <code>$PATH<\/code> that starts with <code>git-<\/code> will automatically become a Git command.<\/p>\n\n<p>One example that I have is <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/2b20cd1e59ae3b1fa81074077e855cbdfa02f146\/bin\/bin\/git-cm\">git-cm<\/a> which, similar to the <code>g<\/code> function`, is a bash script that checks for any arguments passed to it and runs a slightly different command. It achieves the same thing as if it were an alias, but it does make it easier to write and maintain as it's in a separate file.<\/p>\n\n<p>These are just some examples. If you want to see my entire configuration, then check out <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/tree\/2b20cd1e59ae3b1fa81074077e855cbdfa02f146\/roles\/git\/files\">my dotfiles repository on GitHub<\/a>.<\/p>\n\n<p>How have you configured Git for your workflow? Reply to this email and let me know.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:57+00:00",
|
||||
"guid": null,
|
||||
"hash": "4d3892ad51836bdd33e47e7043615d75",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "043d3014-82f2-445a-8bed-d576c51de576"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Passing tests doesn't mean a working application"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-11-03T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/11\/03\/passing-tests-doesnt-mean-a-working-application",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Having a passing test suite doesn't mean everything in your application is working.<\/p>\n\n<p>It means the functionality you previously tested is working.<\/p>\n\n<p>There may be edge cases you haven't covered or whole tests you haven't written yet, which may be working or could be broken.<\/p>\n\n<p>If you have tests that were passing that are now failing, you know you've broken something.<\/p>\n\n<p>Something that was previously working is broken and shouldn't be deployed.<\/p>\n\n<p>That's why having tests is important - they give you the ability to identify and fix regressions before they are released.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Having a passing test suite doesn't mean everything in your application is working.<\/p>\n\n<p>It means the functionality you previously tested is working.<\/p>\n\n<p>There may be edge cases you haven't covered or whole tests you haven't written yet, which may be working or could be broken.<\/p>\n\n<p>If you have tests that were passing that are now failing, you know you've broken something.<\/p>\n\n<p>Something that was previously working is broken and shouldn't be deployed.<\/p>\n\n<p>That's why having tests is important - they give you the ability to identify and fix regressions before they are released.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "ee9c7fdfadc92a583c9a83309b14f644",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "04b6be07-d875-4952-95cf-512c788b61cd"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Experimenting with the Nix package manager"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2022-09-26T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2022\/09\/26\/experimenting-with-the-nix-package-manager",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>After seeing it on some recent live streams and YouTube videos, I've recently been trying out the Nix package manager and looking into how I might use it for my local environment setup - potentially replacing some of my current Ansible configuration.<\/p>\n\n<p>Separate from the NixOS operating system, Nix is a cross-platform package manager, so instead of using <code>apt<\/code> on Ubuntu and <code>brew<\/code> on macOS, you could run Nix on both and install from the 80,000 packages listed on https:\/\/search.nixos.org\/packages.<\/p>\n\n<p>There is a community project called Home Manager which can be installed alongside Nix which, similar to Stow or what I'm doing with Ansible, can manage your dotfiles or even create them from your Home Manager configuration, and can manage plugins for other tools such as ZSH and tmux.<\/p>\n\n<p>There's also a Nix feature called \"Flakes\" which allow you to separate configuration for different operating systems. I currently have a flake for Pop!_OS which installs all of my packages and a minimal flake for my WSL2 environment as some of the packages are installed in Windows instead of Linux.<\/p>\n\n<p>I can see Ansible still being used to set up my post-setup tasks such as cloning my initial projects, but the majority of my current Ansible setup where I'm installing and configuring packages I think could be moved to Nix.<\/p>\n\n<p>I have a work-in-progress Nix-based version <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/tree\/7c3436c553f8b81f99031e6bcddf385d47b7e785\">in my dotfiles repository<\/a> where you can also see <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/7c3436c553f8b81f99031e6bcddf385d47b7e785\/home-manager\/modules\/git.nix\">how I've configured Git with Home Manager<\/a>.<\/p>\n\n<p>I may install NixOS on an old laptop to test that out too.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>After seeing it on some recent live streams and YouTube videos, I've recently been trying out the Nix package manager and looking into how I might use it for my local environment setup - potentially replacing some of my current Ansible configuration.<\/p>\n\n<p>Separate from the NixOS operating system, Nix is a cross-platform package manager, so instead of using <code>apt<\/code> on Ubuntu and <code>brew<\/code> on macOS, you could run Nix on both and install from the 80,000 packages listed on https:\/\/search.nixos.org\/packages.<\/p>\n\n<p>There is a community project called Home Manager which can be installed alongside Nix which, similar to Stow or what I'm doing with Ansible, can manage your dotfiles or even create them from your Home Manager configuration, and can manage plugins for other tools such as ZSH and tmux.<\/p>\n\n<p>There's also a Nix feature called \"Flakes\" which allow you to separate configuration for different operating systems. I currently have a flake for Pop!_OS which installs all of my packages and a minimal flake for my WSL2 environment as some of the packages are installed in Windows instead of Linux.<\/p>\n\n<p>I can see Ansible still being used to set up my post-setup tasks such as cloning my initial projects, but the majority of my current Ansible setup where I'm installing and configuring packages I think could be moved to Nix.<\/p>\n\n<p>I have a work-in-progress Nix-based version <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/tree\/7c3436c553f8b81f99031e6bcddf385d47b7e785\">in my dotfiles repository<\/a> where you can also see <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/blob\/7c3436c553f8b81f99031e6bcddf385d47b7e785\/home-manager\/modules\/git.nix\">how I've configured Git with Home Manager<\/a>.<\/p>\n\n<p>I may install NixOS on an old laptop to test that out too.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "951d2d9e9835481f997f95a29b18efdf",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.04ccaf9c-a0e4-4ca9-b96b-d32e3fc7f384.json
Normal file
100
content/node.04ccaf9c-a0e4-4ca9-b96b-d32e3fc7f384.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "04ccaf9c-a0e4-4ca9-b96b-d32e3fc7f384"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:36+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "More code, more problems\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-07-22T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:36+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/07\/22\/more-code-more-problems",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>The more code you have, the more potential problems you have.<\/p>\n\n<p>More code means more opportunities for bugs in your software.<\/p>\n\n<p>There's more code to maintain and more chance of encountering breaking changes as you update between major software versions of your project's dependencies, such as a CMS or framework.<\/p>\n\n<p>If you can keep your amount of code to a minimum and reduce the maintenance overhead, you are less likely to experience issues.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>The more code you have, the more potential problems you have.<\/p>\n\n<p>More code means more opportunities for bugs in your software.<\/p>\n\n<p>There's more code to maintain and more chance of encountering breaking changes as you update between major software versions of your project's dependencies, such as a CMS or framework.<\/p>\n\n<p>If you can keep your amount of code to a minimum and reduce the maintenance overhead, you are less likely to experience issues.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:36+00:00",
|
||||
"guid": null,
|
||||
"hash": "137f467c7894dcf4d534ab6c7572567a",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.050525d7-3275-486e-8f0e-9548aa81a156.json
Normal file
100
content/node.050525d7-3275-486e-8f0e-9548aa81a156.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "050525d7-3275-486e-8f0e-9548aa81a156"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:34+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Pull requests are great for open-source, but not for teams\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-08-27T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:34+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/08\/27\/pull-requests-are-great-for-open-source",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Code review with pull and merge requests is great for open-source but not for development teams or soloists.<\/p>\n\n<p>On an open-source project, the code changes are most likely being submitted by someone you don't know and don't work with regularly, so having a step to review the code prior to merging it and decide if you want to take on the responsibility of maintaining it is a big decision.<\/p>\n\n<p>On a development team, you work closely with the person submitting the change request and you have a shared responsibility and ownership of the code being added. The person isn't going to submit their change and not be seen again.<\/p>\n\n<p>It takes time for code to be reviewed, which means it takes longer for the change to be released to users.<\/p>\n\n<p>If you're a soloist, are you going to submit a request for you to review your own code?<\/p>\n\n<p>If you don't need to do code review on your team, do you need to create feature or topic branches?<\/p>\n\n<p>I'd suggest sticking to one canonical branch and doing trunk-based development instead.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Code review with pull and merge requests is great for open-source but not for development teams or soloists.<\/p>\n\n<p>On an open-source project, the code changes are most likely being submitted by someone you don't know and don't work with regularly, so having a step to review the code prior to merging it and decide if you want to take on the responsibility of maintaining it is a big decision.<\/p>\n\n<p>On a development team, you work closely with the person submitting the change request and you have a shared responsibility and ownership of the code being added. The person isn't going to submit their change and not be seen again.<\/p>\n\n<p>It takes time for code to be reviewed, which means it takes longer for the change to be released to users.<\/p>\n\n<p>If you're a soloist, are you going to submit a request for you to review your own code?<\/p>\n\n<p>If you don't need to do code review on your team, do you need to create feature or topic branches?<\/p>\n\n<p>I'd suggest sticking to one canonical branch and doing trunk-based development instead.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:34+00:00",
|
||||
"guid": null,
|
||||
"hash": "54fdebe3f9556a6d18a8f24c72f72652",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.050a5113-59bc-461e-ac78-420e16055303.json
Normal file
100
content/node.050a5113-59bc-461e-ac78-420e16055303.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "050a5113-59bc-461e-ac78-420e16055303"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:24+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "PHP TUIs, CLIs and open-source with Dan Leech\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-12-19T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:24+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/12\/19\/php-tui-dan-leech",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:24+00:00",
|
||||
"guid": null,
|
||||
"hash": "3cc8c054a1675b2ab1a1ec63dd5f49ad",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.05232b81-d945-4112-99bf-d1adb2552428.json
Normal file
100
content/node.05232b81-d945-4112-99bf-d1adb2552428.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "05232b81-d945-4112-99bf-d1adb2552428"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:12+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Why is everyone moving to SQLite?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-05-28T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:12+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/05\/28\/why-is-everyone-moving-to-sqlite",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:12+00:00",
|
||||
"guid": null,
|
||||
"hash": "91a7ebf19cb056c110911fc721129f1a",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "054fd9e2-70f0-4d27-ab7a-e90de9c66847"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Don't make assumptions"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-01-08T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/01\/08\/don-t-make-assumptions",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I was recently writing code for a project and found myself making assumptions about what I was writing.<\/p>\n\n<p>I was creating my own requirements.<\/p>\n\n<p>Something no-one asked for.<\/p>\n\n<p>I was assuming a value was always going to be a certain number of digits long.<\/p>\n\n<p>I was writing code that verified this was true or throw an Exception.<\/p>\n\n<p>Until I found out that that one of the values wasn't the same length as the others.<\/p>\n\n<p>This could be an error in the data or it could correct.<\/p>\n\n<p>No-one told me the lengths were always going to be the same.<\/p>\n\n<p>So why was I checking it?<\/p>\n\n<p>Why was I adding bugs to the code?<\/p>\n\n<p>I've reverted the code that checks the length of the value and gone to find clarification.<\/p>\n\n<p>If it's an issue, it'll be fixed in the source data.<\/p>\n\n<p>If the lengths should all be the same, I'll potentially re-add the check.<\/p>\n\n<p>Until I'm sure, I'll only write what's needed to deliver the feature and stop adding my own requirements and assumptions.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I was recently writing code for a project and found myself making assumptions about what I was writing.<\/p>\n\n<p>I was creating my own requirements.<\/p>\n\n<p>Something no-one asked for.<\/p>\n\n<p>I was assuming a value was always going to be a certain number of digits long.<\/p>\n\n<p>I was writing code that verified this was true or throw an Exception.<\/p>\n\n<p>Until I found out that that one of the values wasn't the same length as the others.<\/p>\n\n<p>This could be an error in the data or it could correct.<\/p>\n\n<p>No-one told me the lengths were always going to be the same.<\/p>\n\n<p>So why was I checking it?<\/p>\n\n<p>Why was I adding bugs to the code?<\/p>\n\n<p>I've reverted the code that checks the length of the value and gone to find clarification.<\/p>\n\n<p>If it's an issue, it'll be fixed in the source data.<\/p>\n\n<p>If the lengths should all be the same, I'll potentially re-add the check.<\/p>\n\n<p>Until I'm sure, I'll only write what's needed to deliver the feature and stop adding my own requirements and assumptions.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "2ddc207d69aba210aead45269c83988b",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0561e467-e490-405e-9a1a-4c54f969fac1"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "There is no perfect solution\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-10-03T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/10\/03\/there-is-no-perfect-solution",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Something I've said recently when mentoring bootcamp students and working with Junior Developers is that there isn't a perfect solution to each problem, and there are multiple ways to achieve the same result.<\/p>\n\n<p>Similarly, there isn't a perfect tool for every situation.<\/p>\n\n<p>You can use different tools and get the same outcome.<\/p>\n\n<p>In some of my early emails, I talked about <code>run<\/code> files and <code>just<\/code> - two ways to write project-specific commands or aliases that simplify complex commands or group multiple commands together.<\/p>\n\n<p>Both do the same thing, but each have pros and cons.<\/p>\n\n<p><code>run<\/code> files are files written in Bash, which are more verbose but can run anywhere.<\/p>\n\n<p>just is its own program that needs to be installed for it to be available, so Developers will need to have it installed, and it will need to be added to a CI pipeline to be available.<\/p>\n\n<p>I've had CI pipelines fail because they can't download just, and not because of anything in the application code.<\/p>\n\n<p>I like the simplicity of justfiles, though, and that the files are simpler.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>If there isn't a perfect solution, approach, or tool, it comes down to the pros and cons of each. Which option is best for you, your project, or your team?<\/p>\n\n<p>There isn't a \"one size fits all\" solution that works for everyone all the time.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Something I've said recently when mentoring bootcamp students and working with Junior Developers is that there isn't a perfect solution to each problem, and there are multiple ways to achieve the same result.<\/p>\n\n<p>Similarly, there isn't a perfect tool for every situation.<\/p>\n\n<p>You can use different tools and get the same outcome.<\/p>\n\n<p>In some of my early emails, I talked about <code>run<\/code> files and <code>just<\/code> - two ways to write project-specific commands or aliases that simplify complex commands or group multiple commands together.<\/p>\n\n<p>Both do the same thing, but each have pros and cons.<\/p>\n\n<p><code>run<\/code> files are files written in Bash, which are more verbose but can run anywhere.<\/p>\n\n<p>just is its own program that needs to be installed for it to be available, so Developers will need to have it installed, and it will need to be added to a CI pipeline to be available.<\/p>\n\n<p>I've had CI pipelines fail because they can't download just, and not because of anything in the application code.<\/p>\n\n<p>I like the simplicity of justfiles, though, and that the files are simpler.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>If there isn't a perfect solution, approach, or tool, it comes down to the pros and cons of each. Which option is best for you, your project, or your team?<\/p>\n\n<p>There isn't a \"one size fits all\" solution that works for everyone all the time.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "3579f9c1128a7333aacc2788d9b130b3",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "05952537-6bb6-408b-a417-73e91d310190"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:38+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Tim Lehnen and the Drupal Association"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-02-06T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:38+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/02\/06\/tim-lehnen-and-the-drupal-association",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Last week on the Beyond Blocks podcast, I spoke with Tim Lehnen - CTO and former colleague at the Drupal Association.<\/p>\n\n<p>We discussed what the Drupal Association is and what it does, how companies and individuals can contribute and support the Association, some recent and upcoming improvements to Drupal.org, Drupal 7's end-of-life, and more.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/9-tim-lehnen\">Listen now<\/a><\/p>\n\n<p>This Friday, I'm releasing an episode with Ryan Weaver from SymfonyCasts.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Last week on the Beyond Blocks podcast, I spoke with Tim Lehnen - CTO and former colleague at the Drupal Association.<\/p>\n\n<p>We discussed what the Drupal Association is and what it does, how companies and individuals can contribute and support the Association, some recent and upcoming improvements to Drupal.org, Drupal 7's end-of-life, and more.<\/p>\n\n<p><a href=\"https:\/\/www.oliverdavies.uk\/podcast\/9-tim-lehnen\">Listen now<\/a><\/p>\n\n<p>This Friday, I'm releasing an episode with Ryan Weaver from SymfonyCasts.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:38+00:00",
|
||||
"guid": null,
|
||||
"hash": "2a00495abcb2b4fb956be9ee3bf4582e",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "05c37db1-17f0-4be2-8fb6-2a2535aac23d"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:46+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Test to save your job\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-09-24T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:46+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/09\/24\/test-to-save-your-job",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I've recently been going through my YouTube \"Watch Later\" list and watching (or rewatching) videos of conference and meetup talks that I saved to watch later.<\/p>\n\n<p>Today's talk was by Matt Stauffer at one of the previous Laracon conferences.<\/p>\n\n<p>I've quoted Matt previously when explaining what to test on applications. The answer: \"The thing you'd lose your job for if it broke\".<\/p>\n\n<p>In this talk, Matt has a slide that goes further into this, titled \"Test to save your job\".<\/p>\n\n<h2 id=\"what-matt-said\">What Matt said<\/h2>\n\n<p>The best place to start your tests is by asking yourself: \"What part of this app, if broken, would make me worried for my job?\"<\/p>\n\n<ul>\n<li>What's most likely to break?<\/li>\n<li>What do I have the least control over?<\/li>\n<li>What are we about to refactor?<\/li>\n<li>What would make my clients stress out?<\/li>\n<li>What would make me stressed out?<\/li>\n<\/ul>\n\n<h2 id=\"what-about-you%3F\">What about you?<\/h2>\n\n<p>Do you have any other ways to decide what code to test? Reply and let me know, as I'd love to know.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I've recently been going through my YouTube \"Watch Later\" list and watching (or rewatching) videos of conference and meetup talks that I saved to watch later.<\/p>\n\n<p>Today's talk was by Matt Stauffer at one of the previous Laracon conferences.<\/p>\n\n<p>I've quoted Matt previously when explaining what to test on applications. The answer: \"The thing you'd lose your job for if it broke\".<\/p>\n\n<p>In this talk, Matt has a slide that goes further into this, titled \"Test to save your job\".<\/p>\n\n<h2 id=\"what-matt-said\">What Matt said<\/h2>\n\n<p>The best place to start your tests is by asking yourself: \"What part of this app, if broken, would make me worried for my job?\"<\/p>\n\n<ul>\n<li>What's most likely to break?<\/li>\n<li>What do I have the least control over?<\/li>\n<li>What are we about to refactor?<\/li>\n<li>What would make my clients stress out?<\/li>\n<li>What would make me stressed out?<\/li>\n<\/ul>\n\n<h2 id=\"what-about-you%3F\">What about you?<\/h2>\n\n<p>Do you have any other ways to decide what code to test? Reply and let me know, as I'd love to know.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:46+00:00",
|
||||
"guid": null,
|
||||
"hash": "c2095c4a1278959cfff849fb4f819ace",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "05fbebba-c68c-4066-9af7-bb8d8eee5501"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "TDD and \"Unexpected errors\"\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-08-30T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/08\/30\/tdd-and-unexpected-errors",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>When working on projects, it's common to see messages like \"The website encountered an unexpected error. Please try again later.\".<\/p>\n\n<p>Usually, this is the message shown to the user, whilst a more detailed error message is logged for Developers to diagnose and fix the underlying error.<\/p>\n\n<p>The wording \"unexpected error\" has been intriguing to me, though. When do you expect an error?<\/p>\n\n<p>The best example I can think of for an expected error is when doing test-driven development.<\/p>\n\n<p>When doing TDD, you want to see an error to start as you start with a failing test.<\/p>\n\n<p>Then, you write the code to remove the error and get the test passing.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>When working on projects, it's common to see messages like \"The website encountered an unexpected error. Please try again later.\".<\/p>\n\n<p>Usually, this is the message shown to the user, whilst a more detailed error message is logged for Developers to diagnose and fix the underlying error.<\/p>\n\n<p>The wording \"unexpected error\" has been intriguing to me, though. When do you expect an error?<\/p>\n\n<p>The best example I can think of for an expected error is when doing test-driven development.<\/p>\n\n<p>When doing TDD, you want to see an error to start as you start with a failing test.<\/p>\n\n<p>Then, you write the code to remove the error and get the test passing.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "d896323fbe54f5997b5e4edeb7c0c0dc",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.0610a25f-884a-48b6-8be0-e969749d316a.json
Normal file
100
content/node.0610a25f-884a-48b6-8be0-e969749d316a.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0610a25f-884a-48b6-8be0-e969749d316a"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:02+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Is it the application or implementation?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-01-28T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:02+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/01\/28\/application-or-implementation",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>With most things, it's easy to see where an issue is. There's only one way to build a car or a mobile phone, for example.<\/p>\n\n<p>With other things, such as software, it's not as clear.<\/p>\n\n<p>There are usually multiple ways to achieve the same result, but not all implementations are equal.<\/p>\n\n<p>It's important to understand if an issue is caused by the software itself or how it's been implemented.<\/p>\n\n<p>Some approaches may be quicker, better for end-user experience or more performant.<\/p>\n\n<p>Each has its own advantages and disadvantages.<\/p>\n\n<p>What was the correct solution then may not be the best one now.<\/p>\n\n<p>Priorities may have changed or new approaches could be available.<\/p>\n\n<p>You know more now about the problem that's being solved than you did at the time.<\/p>\n\n<p>One of the original discarded solutions could now be the best option, or a new option that wasn't previously available that solves the problem in a different way.<\/p>\n\n<p>The software may be capable of achieving what you want - it may just need to be configured in a different way.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>With most things, it's easy to see where an issue is. There's only one way to build a car or a mobile phone, for example.<\/p>\n\n<p>With other things, such as software, it's not as clear.<\/p>\n\n<p>There are usually multiple ways to achieve the same result, but not all implementations are equal.<\/p>\n\n<p>It's important to understand if an issue is caused by the software itself or how it's been implemented.<\/p>\n\n<p>Some approaches may be quicker, better for end-user experience or more performant.<\/p>\n\n<p>Each has its own advantages and disadvantages.<\/p>\n\n<p>What was the correct solution then may not be the best one now.<\/p>\n\n<p>Priorities may have changed or new approaches could be available.<\/p>\n\n<p>You know more now about the problem that's being solved than you did at the time.<\/p>\n\n<p>One of the original discarded solutions could now be the best option, or a new option that wasn't previously available that solves the problem in a different way.<\/p>\n\n<p>The software may be capable of achieving what you want - it may just need to be configured in a different way.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:02+00:00",
|
||||
"guid": null,
|
||||
"hash": "838a5e92a344c70d064478815bc8dd16",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.062c06ac-6ca0-4b03-8d5e-63a84eb8b9c2.json
Normal file
100
content/node.062c06ac-6ca0-4b03-8d5e-63a84eb8b9c2.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "062c06ac-6ca0-4b03-8d5e-63a84eb8b9c2"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:40+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Drupal is built by people\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-06-09T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:40+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/06\/09\/drupal-is-built-by-people",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>A quote I heard from DrupalCon, made by my former colleague Tim Lehnen - CTO at the Drupal Association - when talking about contribution:<\/p>\n\n<blockquote>\n <p>Contribution is what makes Drupal thrive.<\/p>\n \n <p>Drupal is built by people.<\/p>\n \n <p>No one entity, no one person builds Drupal.<\/p>\n \n <p>It's you who builds Drupal.<\/p>\n<\/blockquote>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>A quote I heard from DrupalCon, made by my former colleague Tim Lehnen - CTO at the Drupal Association - when talking about contribution:<\/p>\n\n<blockquote>\n <p>Contribution is what makes Drupal thrive.<\/p>\n \n <p>Drupal is built by people.<\/p>\n \n <p>No one entity, no one person builds Drupal.<\/p>\n \n <p>It's you who builds Drupal.<\/p>\n<\/blockquote>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:40+00:00",
|
||||
"guid": null,
|
||||
"hash": "957b36c5f9d9b70a87a9a60d1f31f9ab",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "063ea37a-fd11-4f5d-83dc-374e0f1caba7"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Strict typing in PHP"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-05-04T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/05\/04\/strict-typing-in-php",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I prefer writing and working with strictly typed code.<\/p>\n\n<p>One of the major improvements in PHP has been the option to enable strict types.<\/p>\n\n<p>For example, this code will usually not error and give the result:<\/p>\n\n<pre><code class=\"php\">function add(int $a, int $b): void\n{\n var_dump($a + $b);\n}\n\nadd(1, '1');\n<\/code><\/pre>\n\n<p>However, I'd prefer if it failed as I'm passing the function an integer and a string, but specifying they should both be integers.<\/p>\n\n<p>Fixing this is simple, by adding this line to the top of the file:<\/p>\n\n<pre><code class=\"php\">declare(strict_types=1);\n<\/code><\/pre>\n\n<p>I add this to every PHP file by default.<\/p>\n\n<p>I want my code to be as strict and predictable as possible, and to error when I want it to and make any bugs more explicit and easier to find and fix.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I prefer writing and working with strictly typed code.<\/p>\n\n<p>One of the major improvements in PHP has been the option to enable strict types.<\/p>\n\n<p>For example, this code will usually not error and give the result:<\/p>\n\n<pre><code class=\"php\">function add(int $a, int $b): void\n{\n var_dump($a + $b);\n}\n\nadd(1, '1');\n<\/code><\/pre>\n\n<p>However, I'd prefer if it failed as I'm passing the function an integer and a string, but specifying they should both be integers.<\/p>\n\n<p>Fixing this is simple, by adding this line to the top of the file:<\/p>\n\n<pre><code class=\"php\">declare(strict_types=1);\n<\/code><\/pre>\n\n<p>I add this to every PHP file by default.<\/p>\n\n<p>I want my code to be as strict and predictable as possible, and to error when I want it to and make any bugs more explicit and easier to find and fix.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "07d6a599d591e31580f215b484e9ae34",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "064bc838-fd38-47ab-9612-83e5df0843cc"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Writing tests is an investment\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-10-13T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/10\/13\/writing-tests-is-an-investment",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>It can take time to write automated tests and do test-driven development, but it is an investment in a project's future stability.<\/p>\n\n<p>Spending time to write tests upfront will save time as the project progresses, make the code easier to change, and result in better software, fewer bugs, and quicker changes.<\/p>\n\n<p>Even though it takes time, it's time well spent.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>It can take time to write automated tests and do test-driven development, but it is an investment in a project's future stability.<\/p>\n\n<p>Spending time to write tests upfront will save time as the project progresses, make the code easier to change, and result in better software, fewer bugs, and quicker changes.<\/p>\n\n<p>Even though it takes time, it's time well spent.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "b535eb52679173284d48e852e1dd8e86",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.066297b1-ab00-4769-afe1-d3831ed2a654.json
Normal file
100
content/node.066297b1-ab00-4769-afe1-d3831ed2a654.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "066297b1-ab00-4769-afe1-d3831ed2a654"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:12+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Writing assertions first"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-06-05T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:12+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/06\/05\/writing-assertions-first",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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->assertSession();\n $assert->pageTextContains('Post one');\n $assert->pageTextContains('Post two');\n $assert->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->drupalGet('\/blog');\n\n $assert = $this->assertSession();\n $assert->pageTextContains('Post one');\n $assert->pageTextContains('Post two');\n $assert->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()->setTitle('Post one')->getPost();\n PostBuilder::create()->setTitle('Post two')->getPost();\n\n $this->createNode([\n 'title' => 'This is not a post',\n 'type' => 'page',\n ]);\n\n $this->drupalGet('\/blog');\n\n $assert = $this->assertSession();\n $assert->pageTextContains('Post one');\n $assert->pageTextContains('Post two');\n $assert->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->assertSession();\n $assert->pageTextContains('Post one');\n $assert->pageTextContains('Post two');\n $assert->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->drupalGet('\/blog');\n\n $assert = $this->assertSession();\n $assert->pageTextContains('Post one');\n $assert->pageTextContains('Post two');\n $assert->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()->setTitle('Post one')->getPost();\n PostBuilder::create()->setTitle('Post two')->getPost();\n\n $this->createNode([\n 'title' => 'This is not a post',\n 'type' => 'page',\n ]);\n\n $this->drupalGet('\/blog');\n\n $assert = $this->assertSession();\n $assert->pageTextContains('Post one');\n $assert->pageTextContains('Post two');\n $assert->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
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:12+00:00",
|
||||
"guid": null,
|
||||
"hash": "3bdc81d1ff8f05f8b1beb3069dfdd370",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "067acf87-db7d-430d-8b8a-e38beb26f511"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:42+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Why I prefer integration tests to unit tests\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-11-14T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:42+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/11\/14\/why-i-prefer-integration-tests-to-unit-tests",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>With unit tests, you need to mock <strong>everything<\/strong>.<\/p>\n\n<p>If what you're testing has a dependency, you need to create and use a mock version.<\/p>\n\n<p>If the mock has its own dependencies, you need to mock those, too.<\/p>\n\n<p>I've written unit tests with mocks and accidentally only tested the mocks instead of the functionality I intended.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>With integration tests, you can use and test the real dependencies.<\/p>\n\n<p>Whilst they may be slightly slower to run, I prefer the simpler setup, less need for mocks, and knowing the real services work - not just the mocked versions.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>With unit tests, you need to mock <strong>everything<\/strong>.<\/p>\n\n<p>If what you're testing has a dependency, you need to create and use a mock version.<\/p>\n\n<p>If the mock has its own dependencies, you need to mock those, too.<\/p>\n\n<p>I've written unit tests with mocks and accidentally only tested the mocks instead of the functionality I intended.<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>With integration tests, you can use and test the real dependencies.<\/p>\n\n<p>Whilst they may be slightly slower to run, I prefer the simpler setup, less need for mocks, and knowing the real services work - not just the mocked versions.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:42+00:00",
|
||||
"guid": null,
|
||||
"hash": "b38408f033b23dc55649c0a05a3af78b",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.06b8d0b3-318a-4a06-902c-f42ce169774b.json
Normal file
100
content/node.06b8d0b3-318a-4a06-902c-f42ce169774b.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "06b8d0b3-318a-4a06-902c-f42ce169774b"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:16+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Newport City Council running LocalGov Drupal"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-03-25T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:16+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/03\/25\/newport-city-council-running-localgov-drupal",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Last week, it was announced that Newport City Council's (my local council) website is now running on LocalGov Drupal - a distribution for council websites.<\/p>\n\n<p>This increases the total to 44 councils in the UK and Ireland.<\/p>\n\n<p>Newport is the first Welsh council to use it and the first LocalGov website to be bilingual, serving content in both English and Welsh.<\/p>\n\n<p>It's great to see Drupal adoption continue to grow in Wales and within the Welsh public sector, and LocalGov being adopted by more councils across the UK and Ireland.<\/p>\n\n<p>I think LocalGov Drupal is a great project and one <a href=\"https:\/\/github.com\/localgovdrupal\/localgov_alert_banner\/pull\/225\">I've contributed to previously<\/a>, and I plan to do more in the future.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Last week, it was announced that Newport City Council's (my local council) website is now running on LocalGov Drupal - a distribution for council websites.<\/p>\n\n<p>This increases the total to 44 councils in the UK and Ireland.<\/p>\n\n<p>Newport is the first Welsh council to use it and the first LocalGov website to be bilingual, serving content in both English and Welsh.<\/p>\n\n<p>It's great to see Drupal adoption continue to grow in Wales and within the Welsh public sector, and LocalGov being adopted by more councils across the UK and Ireland.<\/p>\n\n<p>I think LocalGov Drupal is a great project and one <a href=\"https:\/\/github.com\/localgovdrupal\/localgov_alert_banner\/pull\/225\">I've contributed to previously<\/a>, and I plan to do more in the future.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:16+00:00",
|
||||
"guid": null,
|
||||
"hash": "2955d4cb562bc0a9ba0456bc040c629b",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0710efa0-c7f4-4254-afab-7c7a4f5b6959"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-01T23:43:31+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Generating presentation slides with Nix and rst2pdf"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-04-07T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-01T23:43:31+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/04\/07\/nix-rst2pdf",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Since switching to Nix and NixOS, I've been looking for opportunities to use Nix more in addition to managing my laptop and server configurations and creating development shells for projects.<\/p>\n\n<p>Nix is a build tool, so I've started to use it to build my slide decks which I create using rst2pdf.<\/p>\n\n<p>I write the rst (reStructuredText) file and compile it to a PDF file.<\/p>\n\n<p>I had a flake.nix file to add rst2pdf, pdfpc and other tools to my shell, but the compilation to a PDF file was done in a bash script which I've since removed.<\/p>\n\n<p>Here's how my flake.nix file looks now:<\/p>\n\n<pre><code class=\"nix\">{\n inputs.nixpkgs.url = \"github:NixOS\/nixpkgs\/nixos-unstable\";\n\n outputs = { nixpkgs, ... }:\n let\n system = \"x86_64-linux\";\n pkgs = import nixpkgs { inherit system; };\n\n inherit (nixpkgs.lib) makeOverridable;\n inherit (pkgs.stdenvNoCC) mkDerivation;\n\n shared = mkDerivation {\n name = \"talks-shared\";\n src = .\/src;\n\n installPhase = ''\n runHook preInstall\n\n mkdir $out\n cp -r fonts styles $out\n\n runHook postInstall\n '';\n };\n\n commonBuildInputs = with pkgs; [\n (python310.withPackages (p: with p; [ rst2pdf ]))\n ];\n\n mkTalk = makeOverridable ({ src }: mkDerivation {\n inherit shared src;\n\n name = builtins.head (builtins.attrNames talks);\n\n buildInputs = commonBuildInputs;\n\n buildPhase = ''\n runHook preBuild\n\n mkdir $out\n\n rst2pdf slides.rst \\\n --break-level 1 \\\n --fit-background-mode scale \\\n --font-path \"${toString shared}\/fonts\" \\\n --output \"$out\/slides.pdf\" \\\n --stylesheets bw,\"${toString shared}\/styles\/opdavies-light\"\n\n runHook postBuild\n '';\n });\n\n talks = {\n build-configs = mkTalk { src = .\/src\/building-build-configs; };\n sculpin = mkTalk { src = .\/src\/building-static-websites-sculpin; };\n tailwind-css = mkTalk { src = .\/src\/taking-flight-with-tailwind-css; };\n test-driven-drupal = mkTalk { src = .\/src\/test-driven-drupal; };\n };\n in\n {\n devShells.${system}.default = with pkgs; mkShell {\n packages = with pkgs; commonBuildInputs ++ [\n ghostscript\n just\n pdfpc\n texliveMedium # includes pdfjam\n ];\n };\n\n packages.${system} = {\n inherit shared;\n } \/\/ talks;\n };\n}\n<\/code><\/pre>\n\n<p>Each talk is its own derivation, so I can run <code>nix run .#test-driven-drupal<\/code> and it will generate the appropriate PDF file for me to present or share.<\/p>\n\n<p>The source code is available at <a href=\"https:\/\/code.oliverdavies.uk\/opdavies\/talks\">https:\/\/code.oliverdavies.uk\/opdavies\/talks<\/a> if you want to see how I use rst2pdf to create my presentations and I've even <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/building-presenting-slide-decks-rst2pdf\">given a presentation about how I create presentations<\/a>.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Since switching to Nix and NixOS, I've been looking for opportunities to use Nix more in addition to managing my laptop and server configurations and creating development shells for projects.<\/p>\n\n<p>Nix is a build tool, so I've started to use it to build my slide decks which I create using rst2pdf.<\/p>\n\n<p>I write the rst (reStructuredText) file and compile it to a PDF file.<\/p>\n\n<p>I had a flake.nix file to add rst2pdf, pdfpc and other tools to my shell, but the compilation to a PDF file was done in a bash script which I've since removed.<\/p>\n\n<p>Here's how my flake.nix file looks now:<\/p>\n\n<pre><code class=\"nix\">{\n inputs.nixpkgs.url = \"github:NixOS\/nixpkgs\/nixos-unstable\";\n\n outputs = { nixpkgs, ... }:\n let\n system = \"x86_64-linux\";\n pkgs = import nixpkgs { inherit system; };\n\n inherit (nixpkgs.lib) makeOverridable;\n inherit (pkgs.stdenvNoCC) mkDerivation;\n\n shared = mkDerivation {\n name = \"talks-shared\";\n src = .\/src;\n\n installPhase = ''\n runHook preInstall\n\n mkdir $out\n cp -r fonts styles $out\n\n runHook postInstall\n '';\n };\n\n commonBuildInputs = with pkgs; [\n (python310.withPackages (p: with p; [ rst2pdf ]))\n ];\n\n mkTalk = makeOverridable ({ src }: mkDerivation {\n inherit shared src;\n\n name = builtins.head (builtins.attrNames talks);\n\n buildInputs = commonBuildInputs;\n\n buildPhase = ''\n runHook preBuild\n\n mkdir $out\n\n rst2pdf slides.rst \\\n --break-level 1 \\\n --fit-background-mode scale \\\n --font-path \"${toString shared}\/fonts\" \\\n --output \"$out\/slides.pdf\" \\\n --stylesheets bw,\"${toString shared}\/styles\/opdavies-light\"\n\n runHook postBuild\n '';\n });\n\n talks = {\n build-configs = mkTalk { src = .\/src\/building-build-configs; };\n sculpin = mkTalk { src = .\/src\/building-static-websites-sculpin; };\n tailwind-css = mkTalk { src = .\/src\/taking-flight-with-tailwind-css; };\n test-driven-drupal = mkTalk { src = .\/src\/test-driven-drupal; };\n };\n in\n {\n devShells.${system}.default = with pkgs; mkShell {\n packages = with pkgs; commonBuildInputs ++ [\n ghostscript\n just\n pdfpc\n texliveMedium # includes pdfjam\n ];\n };\n\n packages.${system} = {\n inherit shared;\n } \/\/ talks;\n };\n}\n<\/code><\/pre>\n\n<p>Each talk is its own derivation, so I can run <code>nix run .#test-driven-drupal<\/code> and it will generate the appropriate PDF file for me to present or share.<\/p>\n\n<p>The source code is available at <a href=\"https:\/\/code.oliverdavies.uk\/opdavies\/talks\">https:\/\/code.oliverdavies.uk\/opdavies\/talks<\/a> if you want to see how I use rst2pdf to create my presentations and I've even <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/building-presenting-slide-decks-rst2pdf\">given a presentation about how I create presentations<\/a>.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-01T23:43:31+00:00",
|
||||
"guid": null,
|
||||
"hash": "83515e94d744b93f13eb7b8a56283bcc",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "074f251c-777b-44bc-ba68-87eb526d433b"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Software development is about solving problems and adding value\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-03-27T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/03\/27\/software-development-solving-problems-and-adding-value",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I've recently started as a Mentor for the School of Code, working with a student on their cohort that started last week. Whilst the Bootcamp is focussed on JavaScript and node, and is currently looking at front-end development and using APIs, we've already started talking about different back-end technologies and frameworks.<\/p>\n\n<p>Something that I've believed for a while is that software development is about solving problems and different languages and frameworks are tools to use to solve the problem and achieve the desired result. The programming fundamentals that he's learning now can be applied to different languages and some may be better depending on the problem that needs to be solved.<\/p>\n\n<p>I've also said when speaking with a client this week that development is about adding business value.<\/p>\n\n<p>Whilst there is some value to doing security updates and maintenance to keep an application running and secure, I'd much rather be working on tasks that directly add value for the client like some of the tasks I've done for them recently like improving eCommerce conversions and adding new payment methods or revenue streams.<\/p>\n\n<p>It's easier for the client to justify and see the results of the work, it improves the experience for their customers or users, and it's more interesting and fulfilling for me.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I've recently started as a Mentor for the School of Code, working with a student on their cohort that started last week. Whilst the Bootcamp is focussed on JavaScript and node, and is currently looking at front-end development and using APIs, we've already started talking about different back-end technologies and frameworks.<\/p>\n\n<p>Something that I've believed for a while is that software development is about solving problems and different languages and frameworks are tools to use to solve the problem and achieve the desired result. The programming fundamentals that he's learning now can be applied to different languages and some may be better depending on the problem that needs to be solved.<\/p>\n\n<p>I've also said when speaking with a client this week that development is about adding business value.<\/p>\n\n<p>Whilst there is some value to doing security updates and maintenance to keep an application running and secure, I'd much rather be working on tasks that directly add value for the client like some of the tasks I've done for them recently like improving eCommerce conversions and adding new payment methods or revenue streams.<\/p>\n\n<p>It's easier for the client to justify and see the results of the work, it improves the experience for their customers or users, and it's more interesting and fulfilling for me.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "7256a5bb0e6800a548d88e2979344646",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "075872d9-7af9-438a-960f-09e72e209e1f"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:21+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Anyone can use open source software"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-01-02T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:21+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/01\/02\/anyone",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Another great thing about open source software is anyone can use it, contribute to it or provide services for it.<\/p>\n\n<p>You don't need to be a large company like Acquia or Red Hat.<\/p>\n\n<p>I was a self-taught solo hobbyist Developer when I started building a website for my local Tae Kwon-Do club in 2007 with PHP.<\/p>\n\n<p>In 2008, I started learning Drupal, built my own website and started doing freelance Drupal development and consulting work.<\/p>\n\n<p>I became a full-time Drupal Developer in 2010 and haven't looked back since.<\/p>\n\n<p>I was able to this for free using open source software.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Another great thing about open source software is anyone can use it, contribute to it or provide services for it.<\/p>\n\n<p>You don't need to be a large company like Acquia or Red Hat.<\/p>\n\n<p>I was a self-taught solo hobbyist Developer when I started building a website for my local Tae Kwon-Do club in 2007 with PHP.<\/p>\n\n<p>In 2008, I started learning Drupal, built my own website and started doing freelance Drupal development and consulting work.<\/p>\n\n<p>I became a full-time Drupal Developer in 2010 and haven't looked back since.<\/p>\n\n<p>I was able to this for free using open source software.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:21+00:00",
|
||||
"guid": null,
|
||||
"hash": "3523efa30025b9ea53133ab91ddb3086",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.079f2e09-0827-458e-91d3-6dd5b8b80c56.json
Normal file
100
content/node.079f2e09-0827-458e-91d3-6dd5b8b80c56.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "079f2e09-0827-458e-91d3-6dd5b8b80c56"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:12+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Should you include issue IDs in your commit messages?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-05-15T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:12+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/05\/15\/should-you-include-issue-ids-in-your-commit-messages",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:12+00:00",
|
||||
"guid": null,
|
||||
"hash": "1029a860138fe970164e891ad1617d01",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "07cb61ba-669e-446c-a2e4-3ac4f4c6e0c2"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:44+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Is code coverage an objective or guideline?\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-11-02T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:44+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/11\/02\/is-code-coverage-an-objective-or-guideline",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Many development teams and projects use code coverage - e.g. how many lines of code are covered by automated tests - as an objective, and saying it must be 100% or another percentage.<\/p>\n\n<p>But is this an effective metric?<\/p>\n\n<p>In the same way as deleting failing tests to fix a pipeline, a code coverage amount can be faked.<\/p>\n\n<p>With this in mind, what if, instead of setting an objective such as 100% code coverage, you used it as a guideline?<\/p>\n\n<p>If you're working on a legacy project, what if you set a minimum code coverage amount as a guideline to ensure any new code has tests by not dropping under that level?<\/p>\n\n<p>Would that be better than saying every line of code needs to be covered?<\/p>\n\n<p>Code coverage is something I'm thinking of using more, so I want to know what you think.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Many development teams and projects use code coverage - e.g. how many lines of code are covered by automated tests - as an objective, and saying it must be 100% or another percentage.<\/p>\n\n<p>But is this an effective metric?<\/p>\n\n<p>In the same way as deleting failing tests to fix a pipeline, a code coverage amount can be faked.<\/p>\n\n<p>With this in mind, what if, instead of setting an objective such as 100% code coverage, you used it as a guideline?<\/p>\n\n<p>If you're working on a legacy project, what if you set a minimum code coverage amount as a guideline to ensure any new code has tests by not dropping under that level?<\/p>\n\n<p>Would that be better than saying every line of code needs to be covered?<\/p>\n\n<p>Code coverage is something I'm thinking of using more, so I want to know what you think.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:44+00:00",
|
||||
"guid": null,
|
||||
"hash": "37779b8be562eca580a1d3eb2ead9f83",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "07db4821-3295-42d6-bbc0-6026ba1c56cf"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Why I like pair and mob programming\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-05-11T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/05\/11\/why-i-like-pair-and-mob-programming",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>When working as part of a team, I like to do pair or mob programming as much as possible.<\/p>\n\n<p>I like being able to give and receive feedback in real-time; everyone can contribute to the solution and more shared knowledge, so there's less siloing, and it's much harder to block multiple people than a single person.<\/p>\n\n<p>Working in pairs or a mob is a great opportunity to onboard new team members, train and mentor, and share tips and tricks.<\/p>\n\n<p>It's usually more productive than working separately, and it's nice to speak and socialise with other team members whilst working on a task.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>When working as part of a team, I like to do pair or mob programming as much as possible.<\/p>\n\n<p>I like being able to give and receive feedback in real-time; everyone can contribute to the solution and more shared knowledge, so there's less siloing, and it's much harder to block multiple people than a single person.<\/p>\n\n<p>Working in pairs or a mob is a great opportunity to onboard new team members, train and mentor, and share tips and tricks.<\/p>\n\n<p>It's usually more productive than working separately, and it's nice to speak and socialise with other team members whilst working on a task.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "b0e612367a93931235c02addd4091033",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "07ddcb2f-b45d-4aa6-889a-ca9b0cb0ac82"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:22:04+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "What are Git hooks and why are they useful?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2022-08-16T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:22:04+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2022\/08\/16\/what-are-git-hooks-why-are-they-useful",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>In yesterday's email, I mentioned Git hooks but didn't go into any detail. So, what are they?<\/p>\n\n<p>Git hooks are Bash scripts that you add to your repository that are executed when certain events happen, such as before a commit is made or before a push to a remote.<\/p>\n\n<p>By default, the script files need to be within the <code>.git\/hooks<\/code> directory, have executable permissions, and be named to exactly match the name of the hook - e.g. <code>pre-push<\/code> - with no file extension.<\/p>\n\n<p>If it returns an error exit code then the process is stopped and the action doesn't complete.<\/p>\n\n<p>This is useful if, for example, you or your team use a specified format for commit messages and you want to prevent the commit if the message doesn't match the requirements.<\/p>\n\n<p>But, the main benefit that I get from Git hooks if from the <code>pre-push<\/code> hook.<\/p>\n\n<p>I use it to run a subset of the checks that are run within project's CI pipeline to limit failures in the CI tool and fix simple errors before I push the code.<\/p>\n\n<p>Typically, these are the quicker tasks such as ensuring the Docker image builds, running linting and static analysis, validating lock files, and some of the automated tests if they don't take too long to run.<\/p>\n\n<p>If a build is going to fail because of something simply like a linting error, then I'd rather find that out and fix it locally rather than waiting for a CI tool to fail.<\/p>\n\n<p>Also, if you're utilising trunk-based development and continuous integration where team members are pushing changes regularly, then you want to keep the pipeline in a passing, deployable state as much as possible and prevent disruption.<\/p>\n\n<p>But what have Git hooks got to do with the \"run\" file?<\/p>\n\n<p>Firstly, I like to keep the scripts as minimal as possible and move the majority of the code into functions within the <code>run<\/code> file. This means that the scripts are only responsible for running functions like <code>.\/run test:commit<\/code> and returning the appropriate exit code, but also means that it's easy to iterate and test them locally without making fake commits or trying to push them to your actual remote repository (and hoping that they don't get pushed).<\/p>\n\n<p>Secondly, I like to simplify the setup of Git hooks with their own functions.<\/p>\n\n<p>For security reasons, the <code>.git\/hooks<\/code> directory cannot be committed and pushed to your remote so they need to be enabled per user within their own clone of the repository.<\/p>\n\n<p>A common workaround is to put the scripts in a directory like <code>.githooks<\/code> and either symlink them to where Git expects them to be, or to use the <code>core.hooksPath<\/code> configuration option and change where Git is going to look.<\/p>\n\n<p>I like to lower the barrier for any team members by creating <code>git-hooks:on<\/code> and <code>git-hooks:off<\/code> functions which either set or unset the <code>core.hooksPath<\/code>. If someone wants to enable the Git hooks then they only need to run one of those commands rather than having to remember the name of the configuration option or manually creating or removing symlinks.<\/p>\n\n<p>There are other Git hooks that can be used but just using <code>pre-commit<\/code> and <code>pre-push<\/code> has saved me and teams that I've worked on both Developer time and build minutes, provides quicker feedback and fewer disruptions in our build pipelines, and I like how simple it can be by creating custom functions in a <code>run<\/code> file.<\/p>\n\n<p>Lastly, I've created <a href=\"https:\/\/github.com\/opdavies\/git-hooks-scratch\">https:\/\/github.com\/opdavies\/git-hooks-scratch<\/a> as an example with a minimal <code>run<\/code> file and some example hooks.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>In yesterday's email, I mentioned Git hooks but didn't go into any detail. So, what are they?<\/p>\n\n<p>Git hooks are Bash scripts that you add to your repository that are executed when certain events happen, such as before a commit is made or before a push to a remote.<\/p>\n\n<p>By default, the script files need to be within the <code>.git\/hooks<\/code> directory, have executable permissions, and be named to exactly match the name of the hook - e.g. <code>pre-push<\/code> - with no file extension.<\/p>\n\n<p>If it returns an error exit code then the process is stopped and the action doesn't complete.<\/p>\n\n<p>This is useful if, for example, you or your team use a specified format for commit messages and you want to prevent the commit if the message doesn't match the requirements.<\/p>\n\n<p>But, the main benefit that I get from Git hooks if from the <code>pre-push<\/code> hook.<\/p>\n\n<p>I use it to run a subset of the checks that are run within project's CI pipeline to limit failures in the CI tool and fix simple errors before I push the code.<\/p>\n\n<p>Typically, these are the quicker tasks such as ensuring the Docker image builds, running linting and static analysis, validating lock files, and some of the automated tests if they don't take too long to run.<\/p>\n\n<p>If a build is going to fail because of something simply like a linting error, then I'd rather find that out and fix it locally rather than waiting for a CI tool to fail.<\/p>\n\n<p>Also, if you're utilising trunk-based development and continuous integration where team members are pushing changes regularly, then you want to keep the pipeline in a passing, deployable state as much as possible and prevent disruption.<\/p>\n\n<p>But what have Git hooks got to do with the \"run\" file?<\/p>\n\n<p>Firstly, I like to keep the scripts as minimal as possible and move the majority of the code into functions within the <code>run<\/code> file. This means that the scripts are only responsible for running functions like <code>.\/run test:commit<\/code> and returning the appropriate exit code, but also means that it's easy to iterate and test them locally without making fake commits or trying to push them to your actual remote repository (and hoping that they don't get pushed).<\/p>\n\n<p>Secondly, I like to simplify the setup of Git hooks with their own functions.<\/p>\n\n<p>For security reasons, the <code>.git\/hooks<\/code> directory cannot be committed and pushed to your remote so they need to be enabled per user within their own clone of the repository.<\/p>\n\n<p>A common workaround is to put the scripts in a directory like <code>.githooks<\/code> and either symlink them to where Git expects them to be, or to use the <code>core.hooksPath<\/code> configuration option and change where Git is going to look.<\/p>\n\n<p>I like to lower the barrier for any team members by creating <code>git-hooks:on<\/code> and <code>git-hooks:off<\/code> functions which either set or unset the <code>core.hooksPath<\/code>. If someone wants to enable the Git hooks then they only need to run one of those commands rather than having to remember the name of the configuration option or manually creating or removing symlinks.<\/p>\n\n<p>There are other Git hooks that can be used but just using <code>pre-commit<\/code> and <code>pre-push<\/code> has saved me and teams that I've worked on both Developer time and build minutes, provides quicker feedback and fewer disruptions in our build pipelines, and I like how simple it can be by creating custom functions in a <code>run<\/code> file.<\/p>\n\n<p>Lastly, I've created <a href=\"https:\/\/github.com\/opdavies\/git-hooks-scratch\">https:\/\/github.com\/opdavies\/git-hooks-scratch<\/a> as an example with a minimal <code>run<\/code> file and some example hooks.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:22:04+00:00",
|
||||
"guid": null,
|
||||
"hash": "2dc52bfbe73534ab29285ff16486431f",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.08209d64-40fa-4771-9415-c23e962a5028.json
Normal file
100
content/node.08209d64-40fa-4771-9415-c23e962a5028.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "08209d64-40fa-4771-9415-c23e962a5028"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:28+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "It depends\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-11-07T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:28+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/11\/07\/it-depends",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Usually, in software development, there isn't always a definitive black-and-white answer to a question or situation.<\/p>\n\n<p>Most of the time, the answer is \"it depends\".<\/p>\n\n<p>How you approach a problem depends on context.<\/p>\n\n<p>How long do you have?<\/p>\n\n<p>Are you working on the final version or a prototype or minimum-viable product?<\/p>\n\n<p>Should you use a contributed module or write one yourself?<\/p>\n\n<p>What if an existing module hasn't been updated for some time or doesn't have tests or other quality checks included?<\/p>\n\n<p>Do you write custom CSS or use a framework like Tailwind CSS or Bootstrap?<\/p>\n\n<p>Should this project be written in this framework or CMS, or would a different one be better suited?<\/p>\n\n<h2 id=\"here%27s-the-thing...\">Here's the thing...<\/h2>\n\n<p>There are usually multiple approaches to achieve the same result.<\/p>\n\n<p>Decisions will depend on a combination of various factors. In a different situation, the answer could be different.<\/p>\n\n<p>This doesn't make any solution outright wrong.<\/p>\n\n<p>It was right given the situation.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Usually, in software development, there isn't always a definitive black-and-white answer to a question or situation.<\/p>\n\n<p>Most of the time, the answer is \"it depends\".<\/p>\n\n<p>How you approach a problem depends on context.<\/p>\n\n<p>How long do you have?<\/p>\n\n<p>Are you working on the final version or a prototype or minimum-viable product?<\/p>\n\n<p>Should you use a contributed module or write one yourself?<\/p>\n\n<p>What if an existing module hasn't been updated for some time or doesn't have tests or other quality checks included?<\/p>\n\n<p>Do you write custom CSS or use a framework like Tailwind CSS or Bootstrap?<\/p>\n\n<p>Should this project be written in this framework or CMS, or would a different one be better suited?<\/p>\n\n<h2 id=\"here%27s-the-thing...\">Here's the thing...<\/h2>\n\n<p>There are usually multiple approaches to achieve the same result.<\/p>\n\n<p>Decisions will depend on a combination of various factors. In a different situation, the answer could be different.<\/p>\n\n<p>This doesn't make any solution outright wrong.<\/p>\n\n<p>It was right given the situation.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:28+00:00",
|
||||
"guid": null,
|
||||
"hash": "f40826212e5c798e718edd8ad155d3c0",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.0843614b-645e-4d55-9e70-f960d504cadb.json
Normal file
100
content/node.0843614b-645e-4d55-9e70-f960d504cadb.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0843614b-645e-4d55-9e70-f960d504cadb"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:48+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Back after PHP Stoke\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-01-16T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:48+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/01\/16\/back-after-php-stoke",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:48+00:00",
|
||||
"guid": null,
|
||||
"hash": "c6186e7dbf6c19f8512dc083f70d7840",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "08578f5f-e9e2-4b3b-87e6-facee5b087af"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:19+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Should you have a separate front-end for your Drupal website?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-01-27T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:19+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/01\/27\/separate-front-end",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>A few years ago, \"decoupled\" or \"headless\" Drupal was a popular approach, leveraging Drupal's built-in JSON:API module to expose its data via an API which can be consumed by a separate front-end application.<\/p>\n\n<p>The front-end application would retrieve the data from Drupal via the API and generate the appropriate HTML.<\/p>\n\n<p>It's an approach I've used in the past and <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/decoupling-drupal-vuejs\">spoken about at conferences<\/a>, but it comes with pros and cons.<\/p>\n\n<p>In theory, as the Drupal (or back-end application) and front-end are completely separate, there can be two separate and independent teams working on them.<\/p>\n\n<p>This adds overhead and complexity and I've found that one team will commonly be blocking the other instead of both being able to work in parallel.<\/p>\n\n<p>As I said yesterday, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/01\/26\/layout-builder\">previewing content in Drupal can be an issue<\/a> - particularly with a decoupled approach which needs a front-end to be rebuilt before the changes can be seen.<\/p>\n\n<p>If you have a separate front-end, you'll need to create everything from scratch, such as writing accessible HTML markup and othe standard features that would normally be provided by Drupal and, because you've got two separate front-end and back-end applications, you've got twice the amount of maintenance.<\/p>\n\n<p>You could also be excluding yourself from any new features that will be available in future versions of Drupal or Drupal CMS, such as the new Experience Builder.<\/p>\n\n<p>Whilst decoupled\/headless builds are a viable option and can work well in some situations, it's not something I recommend often.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>A few years ago, \"decoupled\" or \"headless\" Drupal was a popular approach, leveraging Drupal's built-in JSON:API module to expose its data via an API which can be consumed by a separate front-end application.<\/p>\n\n<p>The front-end application would retrieve the data from Drupal via the API and generate the appropriate HTML.<\/p>\n\n<p>It's an approach I've used in the past and <a href=\"https:\/\/www.oliverdavies.uk\/presentations\/decoupling-drupal-vuejs\">spoken about at conferences<\/a>, but it comes with pros and cons.<\/p>\n\n<p>In theory, as the Drupal (or back-end application) and front-end are completely separate, there can be two separate and independent teams working on them.<\/p>\n\n<p>This adds overhead and complexity and I've found that one team will commonly be blocking the other instead of both being able to work in parallel.<\/p>\n\n<p>As I said yesterday, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/01\/26\/layout-builder\">previewing content in Drupal can be an issue<\/a> - particularly with a decoupled approach which needs a front-end to be rebuilt before the changes can be seen.<\/p>\n\n<p>If you have a separate front-end, you'll need to create everything from scratch, such as writing accessible HTML markup and othe standard features that would normally be provided by Drupal and, because you've got two separate front-end and back-end applications, you've got twice the amount of maintenance.<\/p>\n\n<p>You could also be excluding yourself from any new features that will be available in future versions of Drupal or Drupal CMS, such as the new Experience Builder.<\/p>\n\n<p>Whilst decoupled\/headless builds are a viable option and can work well in some situations, it's not something I recommend often.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:19+00:00",
|
||||
"guid": null,
|
||||
"hash": "780bda0044c53e6e45fb49f2037ac82e",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "0864f570-d766-488e-aa40-08896621dacc"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Upgrading from Drupal 9 is easier\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-07-31T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/07\/31\/upgrading-from-drupal-9-is-easier",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Upgrading from Drupal 7 to 8, 9 or 10 is a large task.<\/p>\n\n<p>You must create a new empty site, migrate your configuration and data, manually recreate anything else and rewrite any custom modules and themes.<\/p>\n\n<p>Since Drupal 8, things have been different.<\/p>\n\n<p>You can upgrade your site in place.<\/p>\n\n<p>No large code rewrite or data migration.<\/p>\n\n<p>Many contributed modules support multiple major Drupal versions simultaneously, so they may not need upgrading.<\/p>\n\n<p>Others may need small changes to remove deprecated code or be compatible with breaking changes, and some tools can automate some or all of the changes.<\/p>\n\n<p>The same applies to upgrading from Drupal 9 to 10, which will be the same for Drupal 11 next year.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Upgrading from Drupal 7 to 8, 9 or 10 is a large task.<\/p>\n\n<p>You must create a new empty site, migrate your configuration and data, manually recreate anything else and rewrite any custom modules and themes.<\/p>\n\n<p>Since Drupal 8, things have been different.<\/p>\n\n<p>You can upgrade your site in place.<\/p>\n\n<p>No large code rewrite or data migration.<\/p>\n\n<p>Many contributed modules support multiple major Drupal versions simultaneously, so they may not need upgrading.<\/p>\n\n<p>Others may need small changes to remove deprecated code or be compatible with breaking changes, and some tools can automate some or all of the changes.<\/p>\n\n<p>The same applies to upgrading from Drupal 9 to 10, which will be the same for Drupal 11 next year.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "062455710dfbfed24f6c650fa013d504",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "087fc4ed-53af-4f0c-9935-a808c2c84361"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:31+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Don't put HTML in your body field"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-05-24T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:31+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/05\/24\/dont-put-html-in-your-body-field",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I often see Drupal projects where people have put raw HTML code into their body or other rich-text fields.<\/p>\n\n<p>Whilst it can be useful for short-term prototyping, I don't think it should be done for content that will be reused or kept for a period of time.<\/p>\n\n<p>If you have structured HTML code in multiple nodes, you can't make changes without editing each instance.<\/p>\n\n<p>What if you need to fix a bug and have hundreds or thousands of instances?<\/p>\n\n<p>If you have inline styles, they won't be updated or affected by changes to your stylesheets, such as changing colour or font family.<\/p>\n\n<p>Instead, create first-class components that use templates that are easier to change and maintain and have a single source of truth that adheres to your design system.<\/p>\n\n<p>In Drupal, use structured data in fields with Paragraphs or Layout Builder and build the templates around them.<\/p>\n\n<p>This makes it easier to maintain and also for people to add and edit content.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I often see Drupal projects where people have put raw HTML code into their body or other rich-text fields.<\/p>\n\n<p>Whilst it can be useful for short-term prototyping, I don't think it should be done for content that will be reused or kept for a period of time.<\/p>\n\n<p>If you have structured HTML code in multiple nodes, you can't make changes without editing each instance.<\/p>\n\n<p>What if you need to fix a bug and have hundreds or thousands of instances?<\/p>\n\n<p>If you have inline styles, they won't be updated or affected by changes to your stylesheets, such as changing colour or font family.<\/p>\n\n<p>Instead, create first-class components that use templates that are easier to change and maintain and have a single source of truth that adheres to your design system.<\/p>\n\n<p>In Drupal, use structured data in fields with Paragraphs or Layout Builder and build the templates around them.<\/p>\n\n<p>This makes it easier to maintain and also for people to add and edit content.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:31+00:00",
|
||||
"guid": null,
|
||||
"hash": "c81fcb760babf4b27ac37f42d606aade",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "08829cf3-7798-417c-b71e-d619072bc4b6"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Running NixOS in the Cloud"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-11-28T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/11\/28\/running-nixos-in-the-cloud",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Yesterday I explained that Nix, or specifically NixOS, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/27\/nix-as-an-operating-system\">can be used to manage your entire operating system<\/a> in a declarative and reproducible way.<\/p>\n\n<p>My initial experience was running it on my laptop as a replacement for another Linux distribution, which I use to configure everything about my laptop and development environment, including my i3 window manager, Neovim and tmux configurations.<\/p>\n\n<p>I recently also started to use it on a new VPS to host several static websites, including this one and <a href=\"https:\/\/www.oliverdavies.uk\/blog\/uis-ive-rebuilt-tailwind-css\">various examples I've created as demos<\/a> or for presentations.<\/p>\n\n<p>Similarly to my laptop, I was able to declaratively install any required utilities, enable the Nginx web server, open firewall ports, add my virtual hosts and create and apply the required SSL certificates.<\/p>\n\n<p>And I can do this locally using <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/tree\/ec2767adfb6667184f884080a4f9b5d2a388a03d\/nix\/hosts\/hetznix\">the same NixOS configuration files<\/a> and applying it to the remote server.<\/p>\n\n<p>Now I'm running NixOS everywhere!<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Yesterday I explained that Nix, or specifically NixOS, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/11\/27\/nix-as-an-operating-system\">can be used to manage your entire operating system<\/a> in a declarative and reproducible way.<\/p>\n\n<p>My initial experience was running it on my laptop as a replacement for another Linux distribution, which I use to configure everything about my laptop and development environment, including my i3 window manager, Neovim and tmux configurations.<\/p>\n\n<p>I recently also started to use it on a new VPS to host several static websites, including this one and <a href=\"https:\/\/www.oliverdavies.uk\/blog\/uis-ive-rebuilt-tailwind-css\">various examples I've created as demos<\/a> or for presentations.<\/p>\n\n<p>Similarly to my laptop, I was able to declaratively install any required utilities, enable the Nginx web server, open firewall ports, add my virtual hosts and create and apply the required SSL certificates.<\/p>\n\n<p>And I can do this locally using <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/tree\/ec2767adfb6667184f884080a4f9b5d2a388a03d\/nix\/hosts\/hetznix\">the same NixOS configuration files<\/a> and applying it to the remote server.<\/p>\n\n<p>Now I'm running NixOS everywhere!<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "e7631b334d9daafcfa47e2f3cd60def6",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "08d34480-0983-4759-b06f-0fabab1b5a05"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Speaking at Reading College"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-05-04T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/05\/04\/college",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>After recently speaking at a PHP user group, I've been invited to be a guest speaker and speak to a group of students at Reading College.<\/p>\n\n<p>It will be a group of around 40 students who are currently studying Computing and IT with a current focus on web development.<\/p>\n\n<p>I'm planning to speak about my background in both hardware and software, how I started in software development and with open source, and some of the opportunities that I've had from that, including work opportunities, public speaking and mentoring.<\/p>\n\n<p>I'm also going to talk about the hobby side of computing for me - using ThinkPad laptops, Linux and managing a homelab and home server, which I think will be interesting and relevant to a group of Computing and IT students.<\/p>\n\n<p>I have a two hour slot, which I'm sure it will involve some demos, live coding and group programming, which usually happens when I'm giving presentations.<\/p>\n\n<p>This will be a bit different to all the talks and workshops I've done so far, but I'm looking forward to it and I'm sure will be open to doing similar presentations in the future.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>After recently speaking at a PHP user group, I've been invited to be a guest speaker and speak to a group of students at Reading College.<\/p>\n\n<p>It will be a group of around 40 students who are currently studying Computing and IT with a current focus on web development.<\/p>\n\n<p>I'm planning to speak about my background in both hardware and software, how I started in software development and with open source, and some of the opportunities that I've had from that, including work opportunities, public speaking and mentoring.<\/p>\n\n<p>I'm also going to talk about the hobby side of computing for me - using ThinkPad laptops, Linux and managing a homelab and home server, which I think will be interesting and relevant to a group of Computing and IT students.<\/p>\n\n<p>I have a two hour slot, which I'm sure it will involve some demos, live coding and group programming, which usually happens when I'm giving presentations.<\/p>\n\n<p>This will be a bit different to all the talks and workshops I've done so far, but I'm looking forward to it and I'm sure will be open to doing similar presentations in the future.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "745510ed0044be6758cbc74729ab3d08",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "08eb8c13-6259-4500-8829-e5d5854ef10c"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Don't run code formatting in your CI pipeline"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-07-29T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/07\/29\/dont-run-code-formatting-in-your-ci-pipeline",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Something I commonly used to see, and did myself, was running code formatting tools, such as PHP CS Fixer or prettier, automatically their CI pipeline.<\/p>\n\n<p>And not using it as a check to fail the pipeline if your code isn't formatted correctly.<\/p>\n\n<p>Running it, fixing any code and committing any updates.<\/p>\n\n<p>It wasn't long before I stopped doing this.<\/p>\n\n<p>Firstly, I wasn't comfortable with a CI pipeline have write access to my codebase. It's fine to be able to clone it and run checks against it, but making changes to my code and pushing it makes me nervous.<\/p>\n\n<p>Particularly if you're doing trunk-based development and everyone works on the same branch.<\/p>\n\n<p>This also causes additional upstream commits, because the pipeline has committed a change. If you don't remember to pull those commits, you can <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/07\/25\/only-have-one-url-per-git-remote\">end up in a tricky situation<\/a>.<\/p>\n\n<p>I'm also not a fan of having a lot of <code>php-cs-fixer fixes<\/code> or <code>prettier fixes<\/code> commits. I'd prefer the commits be correct when they're pushed, if possible, which is why I usually do micro commits locally and tidy things before pushing them.<\/p>\n\n<p>If you're working on a topic branch and creating a pull or merge request, you can squash commits when merging, but <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/11\/don-t-delete-my-commit-messages\">I'm not a fan of squashing commits<\/a>, either.<\/p>\n\n<p>Instead of relying on a CI pipeline to run code formatting, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">make it easy to run those tasks locally<\/a>.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Something I commonly used to see, and did myself, was running code formatting tools, such as PHP CS Fixer or prettier, automatically their CI pipeline.<\/p>\n\n<p>And not using it as a check to fail the pipeline if your code isn't formatted correctly.<\/p>\n\n<p>Running it, fixing any code and committing any updates.<\/p>\n\n<p>It wasn't long before I stopped doing this.<\/p>\n\n<p>Firstly, I wasn't comfortable with a CI pipeline have write access to my codebase. It's fine to be able to clone it and run checks against it, but making changes to my code and pushing it makes me nervous.<\/p>\n\n<p>Particularly if you're doing trunk-based development and everyone works on the same branch.<\/p>\n\n<p>This also causes additional upstream commits, because the pipeline has committed a change. If you don't remember to pull those commits, you can <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/07\/25\/only-have-one-url-per-git-remote\">end up in a tricky situation<\/a>.<\/p>\n\n<p>I'm also not a fan of having a lot of <code>php-cs-fixer fixes<\/code> or <code>prettier fixes<\/code> commits. I'd prefer the commits be correct when they're pushed, if possible, which is why I usually do micro commits locally and tidy things before pushing them.<\/p>\n\n<p>If you're working on a topic branch and creating a pull or merge request, you can squash commits when merging, but <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2024\/05\/11\/don-t-delete-my-commit-messages\">I'm not a fan of squashing commits<\/a>, either.<\/p>\n\n<p>Instead of relying on a CI pipeline to run code formatting, <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2022\/08\/15\/using-run-file-simplify-project-tasks\">make it easy to run those tasks locally<\/a>.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "d54ad8e941f721ec3bbb3abacd9ca123",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "08ed7d91-f12d-45fb-bef4-edc979ff46cf"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Small and fast"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-02-12T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/02\/12\/small-and-fast",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Due to an local outage, I've had no broadband connection and been mostly offline for the last few days.<\/p>\n\n<p>The only connection I've had is a weak 4G signal from my mobile phone that I've been able to tether from to check emails, etc.<\/p>\n\n<p>But this is slow and I struggled to load the majority of websites.<\/p>\n\n<p>Some would take a number of seconds or minutes to load, or fail.<\/p>\n\n<p>As websites and applications develop and grow, it's important to try and keep your codebase as lean and performant as possible.<\/p>\n\n<p>You never know what connection people will be using your code from.<\/p>\n\n<p>What if their broadband goes down or they're in an area with a poor mobile signal?<\/p>\n\n<p>They may not be able to download your large CSS or JS file, or execute the unoptimised database query.<\/p>\n\n<p>You can't assume everyone will be using a high speed Internet connection, so avoid feature bloat, optimise for performance and keep things small and fast.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Due to an local outage, I've had no broadband connection and been mostly offline for the last few days.<\/p>\n\n<p>The only connection I've had is a weak 4G signal from my mobile phone that I've been able to tether from to check emails, etc.<\/p>\n\n<p>But this is slow and I struggled to load the majority of websites.<\/p>\n\n<p>Some would take a number of seconds or minutes to load, or fail.<\/p>\n\n<p>As websites and applications develop and grow, it's important to try and keep your codebase as lean and performant as possible.<\/p>\n\n<p>You never know what connection people will be using your code from.<\/p>\n\n<p>What if their broadband goes down or they're in an area with a poor mobile signal?<\/p>\n\n<p>They may not be able to download your large CSS or JS file, or execute the unoptimised database query.<\/p>\n\n<p>You can't assume everyone will be using a high speed Internet connection, so avoid feature bloat, optimise for performance and keep things small and fast.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "f6c37d9d9fa156de34d1f69cd5c937cc",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.09073a81-2a1b-4200-905b-98b43152fe37.json
Normal file
100
content/node.09073a81-2a1b-4200-905b-98b43152fe37.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "09073a81-2a1b-4200-905b-98b43152fe37"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:26+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Frequency reduces difficulty\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-11-22T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:26+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/11\/22\/frequency-reduces-difficulty",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>\"Frequency reduces difficulty\" is a phrase I heard on a podcast today, though I have heard it before.<\/p>\n\n<p>It's a better way of saying, \"If it hurts, do it more often\".<\/p>\n\n<p>If software deployments and releases are large, risky, and contain bugs, break them into smaller, less-risky deployments and release them more often.<\/p>\n\n<p>If you get a lot of merge conflicts in Git, merge your code more frequently. Make your topic branches as short-lived as possible, or try trunk-based development and avoid topic branches by default.<\/p>\n\n<p>If writing tests is difficult and takes time, persevere. It will get easier the more you do it, and you'll save time in the future by releasing fewer bugs and being able to refactor safely.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>\"Frequency reduces difficulty\" is a phrase I heard on a podcast today, though I have heard it before.<\/p>\n\n<p>It's a better way of saying, \"If it hurts, do it more often\".<\/p>\n\n<p>If software deployments and releases are large, risky, and contain bugs, break them into smaller, less-risky deployments and release them more often.<\/p>\n\n<p>If you get a lot of merge conflicts in Git, merge your code more frequently. Make your topic branches as short-lived as possible, or try trunk-based development and avoid topic branches by default.<\/p>\n\n<p>If writing tests is difficult and takes time, persevere. It will get easier the more you do it, and you'll save time in the future by releasing fewer bugs and being able to refactor safely.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:26+00:00",
|
||||
"guid": null,
|
||||
"hash": "48855aeeae21e4c8f58c4898ddd9fea4",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.09097ac1-03ea-456c-a1bd-49bdc2bb9499.json
Normal file
100
content/node.09097ac1-03ea-456c-a1bd-49bdc2bb9499.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "09097ac1-03ea-456c-a1bd-49bdc2bb9499"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:36+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "What problem are we trying to solve?\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-08-03T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:36+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/08\/03\/what-problem-are-we-trying-to-solve",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>The Override Node Options module that I said yesterday is used on 35,000 websites isn't a complicated module.<\/p>\n\n<p>It doesn't add a lot of features.<\/p>\n\n<p>It solves a problem by adding additional permissions to Drupal that site administrators can assign to user roles and not need to give a more global permission like \"administer nodes\".<\/p>\n\n<p>The problem being solved is allowing users to set node options, like the created date or published status, in a secure way.<\/p>\n\n<p>If it wasn't solving a problem, it wouldn't be used on 35,000 Drupal websites.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>The Override Node Options module that I said yesterday is used on 35,000 websites isn't a complicated module.<\/p>\n\n<p>It doesn't add a lot of features.<\/p>\n\n<p>It solves a problem by adding additional permissions to Drupal that site administrators can assign to user roles and not need to give a more global permission like \"administer nodes\".<\/p>\n\n<p>The problem being solved is allowing users to set node options, like the created date or published status, in a secure way.<\/p>\n\n<p>If it wasn't solving a problem, it wouldn't be used on 35,000 Drupal websites.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:36+00:00",
|
||||
"guid": null,
|
||||
"hash": "1c6afa84bf0230b6fc71cdc42239c6e2",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "09407211-6afb-4f28-95b7-5a7c3f9235b8"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-01T23:43:32+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "How much would it cost to build Drupal?"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-03-03T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-01T23:43:32+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/03\/03\/cost",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Drupal comes with a lot of features available out of the box.<\/p>\n\n<p>It has a flexible system to create complex content models with different content types and fields, rich media management and Views - a visual query builder - to create lists of content.<\/p>\n\n<p>It has the JSON:API module to expose your content via an API for use by other systems, such as mobile apps.<\/p>\n\n<p>It has user management, authentication, password resets, roles and permissions.<\/p>\n\n<p>It has configuration management to easily manage settings and configuration between environments and to provide traceability.<\/p>\n\n<p>It has the Layout Builder to create page layouts with a drag and drop interface and a built-in WYSIWYG editor for entering rich content.<\/p>\n\n<p>These are just some of the features I could mention.<\/p>\n\n<p>Running cloc on Drupal's <code>core<\/code> directory shows 18,289 files and 1,095,970 lines of code.<\/p>\n\n<p>If you were to get someone to build a CMS from scratch with the same features, how long would that take?<\/p>\n\n<p>How much would it cost?<\/p>\n\n<p>This is what you get for free by using free and open source software like Drupal.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Drupal comes with a lot of features available out of the box.<\/p>\n\n<p>It has a flexible system to create complex content models with different content types and fields, rich media management and Views - a visual query builder - to create lists of content.<\/p>\n\n<p>It has the JSON:API module to expose your content via an API for use by other systems, such as mobile apps.<\/p>\n\n<p>It has user management, authentication, password resets, roles and permissions.<\/p>\n\n<p>It has configuration management to easily manage settings and configuration between environments and to provide traceability.<\/p>\n\n<p>It has the Layout Builder to create page layouts with a drag and drop interface and a built-in WYSIWYG editor for entering rich content.<\/p>\n\n<p>These are just some of the features I could mention.<\/p>\n\n<p>Running cloc on Drupal's <code>core<\/code> directory shows 18,289 files and 1,095,970 lines of code.<\/p>\n\n<p>If you were to get someone to build a CMS from scratch with the same features, how long would that take?<\/p>\n\n<p>How much would it cost?<\/p>\n\n<p>This is what you get for free by using free and open source software like Drupal.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-01T23:43:32+00:00",
|
||||
"guid": null,
|
||||
"hash": "3b2f48d28cdda255b884d631a4a170ad",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "09659c9b-a176-4ccb-916d-bab6ecfc102d"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Patching Drupal"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-01-14T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/01\/14\/patching-drupal",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Yesterday I wrote about <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/01\/13\/patches\">how I used a patch file to customise a project in my Nix configuration<\/a>.<\/p>\n\n<p>I'm familiar with patch files from my Drupal contributions, when we used to create and upload patch files and attach them to issues to contribute changes.<\/p>\n\n<p>Although patches aren't used to contribute to Drupal any more, you can still apply patches to Drupal code in your own projects if you need to.<\/p>\n\n<p>If there's a customisation or fix you need you need to apply, instead of altering and \"hacking\" the source files, you can apply changes with patch files.<\/p>\n\n<p>Instead of Nix, I use <a href=\"https:\/\/github.com\/cweagans\/composer-patches\">composer-patches<\/a> to automatically apply patches when running <code>composer install<\/code>.<\/p>\n\n<p>For example, in my composer.json file, I can add something like this:<\/p>\n\n<pre><code class=\"json\">\"extra\": {\n \"patches\": {\n \"drupal\/default_content\": {\n \"Issue #2698425: Do not reimport existing entities (https:\/\/www.drupal.org\/project\/default_content\/issues\/2698425#comment-15593214)\": \"patches\/default_content-2698425-do-not-reimport-196.patch\",\n \"Issue #3160146: Add a Normalizer and Denormalizer to support Layout Builder (https:\/\/www.drupal.org\/project\/default_content\/issues\/3160146#comment-14814050)\": \"patches\/default_content-3160146-53.patch\"\n }\n },\n},\n<\/code><\/pre>\n\n<p>This will apply these two patch files to the Default Content module (which are the same as running <code>git diff<\/code> between two commits), which I needed to do for a recent project.<\/p>\n\n<p>If the upstream issue is fixed and the patch is no longer needed, they can be removed and the module can be updated to the latest version.<\/p>\n\n<p>And this works for core and contrib projects.<\/p>\n\n<p>The same as the tmux-sessionizer example, this approach means I can apply any changes without needing to duplicate or alter the code, and it makes it easy to contribute by testing other people's patches or applying and contributing your own.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Yesterday I wrote about <a href=\"https:\/\/www.oliverdavies.uk\/daily\/2025\/01\/13\/patches\">how I used a patch file to customise a project in my Nix configuration<\/a>.<\/p>\n\n<p>I'm familiar with patch files from my Drupal contributions, when we used to create and upload patch files and attach them to issues to contribute changes.<\/p>\n\n<p>Although patches aren't used to contribute to Drupal any more, you can still apply patches to Drupal code in your own projects if you need to.<\/p>\n\n<p>If there's a customisation or fix you need you need to apply, instead of altering and \"hacking\" the source files, you can apply changes with patch files.<\/p>\n\n<p>Instead of Nix, I use <a href=\"https:\/\/github.com\/cweagans\/composer-patches\">composer-patches<\/a> to automatically apply patches when running <code>composer install<\/code>.<\/p>\n\n<p>For example, in my composer.json file, I can add something like this:<\/p>\n\n<pre><code class=\"json\">\"extra\": {\n \"patches\": {\n \"drupal\/default_content\": {\n \"Issue #2698425: Do not reimport existing entities (https:\/\/www.drupal.org\/project\/default_content\/issues\/2698425#comment-15593214)\": \"patches\/default_content-2698425-do-not-reimport-196.patch\",\n \"Issue #3160146: Add a Normalizer and Denormalizer to support Layout Builder (https:\/\/www.drupal.org\/project\/default_content\/issues\/3160146#comment-14814050)\": \"patches\/default_content-3160146-53.patch\"\n }\n },\n},\n<\/code><\/pre>\n\n<p>This will apply these two patch files to the Default Content module (which are the same as running <code>git diff<\/code> between two commits), which I needed to do for a recent project.<\/p>\n\n<p>If the upstream issue is fixed and the patch is no longer needed, they can be removed and the module can be updated to the latest version.<\/p>\n\n<p>And this works for core and contrib projects.<\/p>\n\n<p>The same as the tmux-sessionizer example, this approach means I can apply any changes without needing to duplicate or alter the code, and it makes it easy to contribute by testing other people's patches or applying and contributing your own.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "64930ff9734d8caf5d32c9d3840e4b0a",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.098d8367-a714-4e16-97b5-44f42a2a1cc2.json
Normal file
100
content/node.098d8367-a714-4e16-97b5-44f42a2a1cc2.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "098d8367-a714-4e16-97b5-44f42a2a1cc2"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:44+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Cleaner PHP code with promoted constructor properties\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-04-12T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T09:00:44+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/04\/12\/cleaner-php-code-with-promoted-constructor-properties",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>One of my favorite features that was introducted in PHP 8 was promoted constructor properties.<\/p>\n\n<p>If I'm passing arguments into a constructor, I can declare a visibility and it will be promoted to a property on the class.<\/p>\n\n<p>Here's an example of a value of a data transfer object that accepts a sort code and account number as strings:<\/p>\n\n<pre><code class=\"language-php\">class AccountDetails {\n\n public function __construct(\n public string $accountNumber,\n public string $sortCode,\n ) {}\n\n}\n<\/code><\/pre>\n\n<p>Without promoted constructor properties, I'd need to create the properties and assign them manually, and I'd have this:<\/p>\n\n<pre><code class=\"language-php\">class AccountDetails {\n\n public string $accountNumber;\n\n public string $sortCode;\n\n public function __construct(\n string $accountNumber,\n string $sortCode,\n ) {\n $this->accountNumber = $accountNumber;\n $this->sortCode = $sortCode;\n }\n\n}\n<\/code><\/pre>\n\n<p>Whilst text editors and IDEs can create the properties automatically, I prefer this as it's less code, more readable and easier to understand.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>One of my favorite features that was introducted in PHP 8 was promoted constructor properties.<\/p>\n\n<p>If I'm passing arguments into a constructor, I can declare a visibility and it will be promoted to a property on the class.<\/p>\n\n<p>Here's an example of a value of a data transfer object that accepts a sort code and account number as strings:<\/p>\n\n<pre><code class=\"language-php\">class AccountDetails {\n\n public function __construct(\n public string $accountNumber,\n public string $sortCode,\n ) {}\n\n}\n<\/code><\/pre>\n\n<p>Without promoted constructor properties, I'd need to create the properties and assign them manually, and I'd have this:<\/p>\n\n<pre><code class=\"language-php\">class AccountDetails {\n\n public string $accountNumber;\n\n public string $sortCode;\n\n public function __construct(\n string $accountNumber,\n string $sortCode,\n ) {\n $this->accountNumber = $accountNumber;\n $this->sortCode = $sortCode;\n }\n\n}\n<\/code><\/pre>\n\n<p>Whilst text editors and IDEs can create the properties automatically, I prefer this as it's less code, more readable and easier to understand.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T09:00:44+00:00",
|
||||
"guid": null,
|
||||
"hash": "6e7b86e1b92a964e048c10b4a1bb65da",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "09a0d65c-0169-4e0a-b890-fdf03dc66035"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:31+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Drupal 10.3 released"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-06-23T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:31+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/06\/23\/drupal-10-3-released",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Last week, Drupal 10.3 was released.<\/p>\n\n<p>It's the final feature release of Drupal 10, with Drupal 11 to be released this year.<\/p>\n\n<p>As it's a minor release, it provides improvements and new functionality and does not break backward compatibility (BC) for public APIs, so it should be easy to upgrade from Drupal 10.2.<\/p>\n\n<p>An interesting change is that you <strong>need to upgrade to Drupal 10.3 prior to upgrading to Drupal 11<\/strong>. This is similar to Symfony's upgrade cycle and will make upgrading to Drupal 11, which will be refined version of Drupal 10 with a very similar public API, much easier.<\/p>\n\n<h2 id=\"what-about-drupal-10.4\">What about Drupal 10.4<\/h2>\n\n<p>There will still be a Drupal 10.4 release in December, and will be the first maintenance minor version, receiving limited forward-compatible and security fixes only, and will be supported until the release of Drupal 12 in 2026.<\/p>\n\n<p>It's great to see the project evolve, and I'm looking forward to upgrading my projects to Drupal 10.3 and then 11 in the near future.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Last week, Drupal 10.3 was released.<\/p>\n\n<p>It's the final feature release of Drupal 10, with Drupal 11 to be released this year.<\/p>\n\n<p>As it's a minor release, it provides improvements and new functionality and does not break backward compatibility (BC) for public APIs, so it should be easy to upgrade from Drupal 10.2.<\/p>\n\n<p>An interesting change is that you <strong>need to upgrade to Drupal 10.3 prior to upgrading to Drupal 11<\/strong>. This is similar to Symfony's upgrade cycle and will make upgrading to Drupal 11, which will be refined version of Drupal 10 with a very similar public API, much easier.<\/p>\n\n<h2 id=\"what-about-drupal-10.4\">What about Drupal 10.4<\/h2>\n\n<p>There will still be a Drupal 10.4 release in December, and will be the first maintenance minor version, receiving limited forward-compatible and security fixes only, and will be supported until the release of Drupal 12 in 2026.<\/p>\n\n<p>It's great to see the project evolve, and I'm looking forward to upgrading my projects to Drupal 10.3 and then 11 in the near future.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:31+00:00",
|
||||
"guid": null,
|
||||
"hash": "9ab0b186e8be83ec48f221f864037954",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "09aec80d-9f5f-4ec1-96af-dd99d4f1da7b"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "The first test is the hardest"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2024-05-16T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T06:09:49+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2024\/05\/16\/the-first-test-is-the-hardest",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Whether you're writing tests before the implementation code or not, the first test is always the hardest to write.<\/p>\n\n<p>What will the arrange and act phases look like?<\/p>\n\n<p>What dependencies will you need?<\/p>\n\n<p>What do you need to mock or create fakes of?<\/p>\n\n<p>In a Drupal test, what other modules and configuration do you need to install?<\/p>\n\n<p>What installation profile and default theme do you need to use?<\/p>\n\n<p>What other unknown or complicated setup steps are there?<\/p>\n\n<p>Do you need to configure your environment to run the tests and get the expected output?<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>The hardest part is getting the arrange\/setup phase working and getting to when the test is running your business logic.<\/p>\n\n<p>Once you've got the first test running, adding more for similar use cases will be much easier.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Whether you're writing tests before the implementation code or not, the first test is always the hardest to write.<\/p>\n\n<p>What will the arrange and act phases look like?<\/p>\n\n<p>What dependencies will you need?<\/p>\n\n<p>What do you need to mock or create fakes of?<\/p>\n\n<p>In a Drupal test, what other modules and configuration do you need to install?<\/p>\n\n<p>What installation profile and default theme do you need to use?<\/p>\n\n<p>What other unknown or complicated setup steps are there?<\/p>\n\n<p>Do you need to configure your environment to run the tests and get the expected output?<\/p>\n\n<h2 id=\"here%27s-the-thing\">Here's the thing<\/h2>\n\n<p>The hardest part is getting the arrange\/setup phase working and getting to when the test is running your business logic.<\/p>\n\n<p>Once you've got the first test running, adding more for similar use cases will be much easier.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T06:09:49+00:00",
|
||||
"guid": null,
|
||||
"hash": "9932561d0945f63746a1bb5ddd951b0a",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "09ccfce7-e7be-4c14-85a1-5919afdf5a50"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:22:04+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "I wrote a Neovim plugin"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2022-08-13T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:22:04+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2022\/08\/13\/i-wrote-a-neovim-plugin",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>I enjoy writing and working with open-source software, starting back to when I started working with PHP and Drupal in 2007.<\/p>\n\n<p>Since then, I've written and maintained a number of Drupal modules and themes, PHP libraries, npm packages, Ansible roles and Docker images - all of which are available on my GitHub and Drupal.org pages.<\/p>\n\n<p>Just over a year ago, <a href=\"\/blog\/going-full-vim\">I switched to using Neovim full-time<\/a> for my development and DevOps work, and last week, I wrote my first Neovim plugin, written in Lua.<\/p>\n\n<p>I've used Lua to configure Neovim but this is the first time that I've written and open-sourced a standalone Neovim plugin.<\/p>\n\n<p>It's called <a href=\"https:\/\/github.com\/opdavies\/toggle-checkbox.nvim\">toggle-checkbox.nvim<\/a> and is used toggle checkboxes in Markdown files - something that I use frequently for to-do lists.<\/p>\n\n<p>For example, this a simple list containing both checked and unchecked checkboxes:<\/p>\n\n<pre><code class=\"markdown\">- [x] A completed task\n- [ ] An incomplete task\n<\/code><\/pre>\n\n<p>To toggle a checkbox, the <code>x<\/code> character needs to be either added or removed, depending on whether we're checking or unchecking it.<\/p>\n\n<p>This is done by calling the <code>toggle()<\/code> function within the plugin.<\/p>\n\n<p>In my Neovim configuration, I've added a keymap to do this:<\/p>\n\n<pre><code class=\"lua\">vim.keymap.set(\n \"n\",\n \"<leader>tt\",\n \"require('toggle-checkbox').toggle()\"\n)\n<\/code><\/pre>\n\n<p>This means that I can use the same keymap by running <code><leader>tt<\/code> to check or uncheck a checkbox. I could use Vim's replace mode to do this, but I really wanted to have one keymap that I could use for both.<\/p>\n\n<p>As it's my first Neovim plugin, I decided to keep it simple.<\/p>\n\n<p>The main <code>toggle-checkbox.lua<\/code> file is currently only 41 lines of code, and whilst there is an existing Vim plugin that I could have used, I was excited to write my own plugin for Neovim, to start contributing to the Neovim ecosystem, and add a Neovim plugin to my portfolio of open-source projects.<\/p>\n\n<p>You can view the plugin at <a href=\"https:\/\/github.com\/opdavies\/toggle-checkbox.nvim\">https:\/\/github.com\/opdavies\/toggle-checkbox.nvim<\/a>, as well as my Neovim configuration (which is also written in Lua) as part of <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/tree\/main\/roles\/neovim\/files\">my Dotfiles repository<\/a>.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>I enjoy writing and working with open-source software, starting back to when I started working with PHP and Drupal in 2007.<\/p>\n\n<p>Since then, I've written and maintained a number of Drupal modules and themes, PHP libraries, npm packages, Ansible roles and Docker images - all of which are available on my GitHub and Drupal.org pages.<\/p>\n\n<p>Just over a year ago, <a href=\"\/blog\/going-full-vim\">I switched to using Neovim full-time<\/a> for my development and DevOps work, and last week, I wrote my first Neovim plugin, written in Lua.<\/p>\n\n<p>I've used Lua to configure Neovim but this is the first time that I've written and open-sourced a standalone Neovim plugin.<\/p>\n\n<p>It's called <a href=\"https:\/\/github.com\/opdavies\/toggle-checkbox.nvim\">toggle-checkbox.nvim<\/a> and is used toggle checkboxes in Markdown files - something that I use frequently for to-do lists.<\/p>\n\n<p>For example, this a simple list containing both checked and unchecked checkboxes:<\/p>\n\n<pre><code class=\"markdown\">- [x] A completed task\n- [ ] An incomplete task\n<\/code><\/pre>\n\n<p>To toggle a checkbox, the <code>x<\/code> character needs to be either added or removed, depending on whether we're checking or unchecking it.<\/p>\n\n<p>This is done by calling the <code>toggle()<\/code> function within the plugin.<\/p>\n\n<p>In my Neovim configuration, I've added a keymap to do this:<\/p>\n\n<pre><code class=\"lua\">vim.keymap.set(\n \"n\",\n \"<leader>tt\",\n \"require('toggle-checkbox').toggle()\"\n)\n<\/code><\/pre>\n\n<p>This means that I can use the same keymap by running <code><leader>tt<\/code> to check or uncheck a checkbox. I could use Vim's replace mode to do this, but I really wanted to have one keymap that I could use for both.<\/p>\n\n<p>As it's my first Neovim plugin, I decided to keep it simple.<\/p>\n\n<p>The main <code>toggle-checkbox.lua<\/code> file is currently only 41 lines of code, and whilst there is an existing Vim plugin that I could have used, I was excited to write my own plugin for Neovim, to start contributing to the Neovim ecosystem, and add a Neovim plugin to my portfolio of open-source projects.<\/p>\n\n<p>You can view the plugin at <a href=\"https:\/\/github.com\/opdavies\/toggle-checkbox.nvim\">https:\/\/github.com\/opdavies\/toggle-checkbox.nvim<\/a>, as well as my Neovim configuration (which is also written in Lua) as part of <a href=\"https:\/\/github.com\/opdavies\/dotfiles\/tree\/main\/roles\/neovim\/files\">my Dotfiles repository<\/a>.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:22:04+00:00",
|
||||
"guid": null,
|
||||
"hash": "da50f1968f98fdd321596a74d98b2ec4",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
100
content/node.09d6a39f-ac99-44fc-b660-4f976132d813.json
Normal file
100
content/node.09d6a39f-ac99-44fc-b660-4f976132d813.json
Normal file
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "09d6a39f-ac99-44fc-b660-4f976132d813"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-05-11T08:59:58+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Building static websites with Drupal"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2025-04-18T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-05-11T08:59:58+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2025\/04\/18\/static-drupal",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"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 ",
|
||||
"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 ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-05-11T08:59:58+00:00",
|
||||
"guid": null,
|
||||
"hash": "2b68ef78311dde7624d8a9f3bf2aecd5",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
{
|
||||
"uuid": [
|
||||
{
|
||||
"value": "09daddb1-1715-4428-84b4-19653faf4744"
|
||||
}
|
||||
],
|
||||
"langcode": [
|
||||
{
|
||||
"value": "en"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
{
|
||||
"target_id": "daily_email",
|
||||
"target_type": "node_type",
|
||||
"target_uuid": "8bde1f2f-eef9-4f2d-ae9c-96921f8193d7"
|
||||
}
|
||||
],
|
||||
"revision_timestamp": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:58+00:00"
|
||||
}
|
||||
],
|
||||
"revision_uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"revision_log": [],
|
||||
"status": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"uid": [
|
||||
{
|
||||
"target_type": "user",
|
||||
"target_uuid": "b8966985-d4b2-42a7-a319-2e94ccfbb849"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"value": "Upgrading my Drupal example project to Drupal 10\n"
|
||||
}
|
||||
],
|
||||
"created": [
|
||||
{
|
||||
"value": "2023-02-17T00:00:00+00:00"
|
||||
}
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"value": "2025-04-21T01:21:58+00:00"
|
||||
}
|
||||
],
|
||||
"promote": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"sticky": [
|
||||
{
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"default_langcode": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"revision_translation_affected": [
|
||||
{
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
{
|
||||
"alias": "\/daily\/2023\/02\/17\/upgrading-my-drupal-example-project-to-drupal-10",
|
||||
"langcode": "en"
|
||||
}
|
||||
],
|
||||
"body": [
|
||||
{
|
||||
"value": "\n <p>Today I upgraded my <a href=\"https:\/\/github.com\/opdavies\/docker-examples\/tree\/main\/drupal\">Drupal Docker example<\/a> to Drupal 10.<\/p>\n\n<p>Admittedly, it's a simple project, but upgrading from Drupal 9 to 10 was a straightforward process.<\/p>\n\n<p>I had to remove the Examples module as there's no Drupal 10 compatible version yet, but updating to Drupal 10 only needed me to change the version constraints in the <code>composer.json<\/code> file and run the <code>composer update<\/code> command.<\/p>\n\n<p>After completing a number of Drupal 7 upgrade projects which involve migrating content, rewriting custom modules, and rebuilding themes, it's great to be able to upgrade between major modern versions with a few simple commands.<\/p>\n\n ",
|
||||
"format": "full_html",
|
||||
"processed": "\n <p>Today I upgraded my <a href=\"https:\/\/github.com\/opdavies\/docker-examples\/tree\/main\/drupal\">Drupal Docker example<\/a> to Drupal 10.<\/p>\n\n<p>Admittedly, it's a simple project, but upgrading from Drupal 9 to 10 was a straightforward process.<\/p>\n\n<p>I had to remove the Examples module as there's no Drupal 10 compatible version yet, but updating to Drupal 10 only needed me to change the version constraints in the <code>composer.json<\/code> file and run the <code>composer update<\/code> command.<\/p>\n\n<p>After completing a number of Drupal 7 upgrade projects which involve migrating content, rewriting custom modules, and rebuilding themes, it's great to be able to upgrade between major modern versions with a few simple commands.<\/p>\n\n ",
|
||||
"summary": null
|
||||
}
|
||||
],
|
||||
"feeds_item": [
|
||||
{
|
||||
"imported": "2025-04-21T01:21:58+00:00",
|
||||
"guid": null,
|
||||
"hash": "7648009a474298b1a14504ba7a413f7e",
|
||||
"target_type": "feeds_feed",
|
||||
"target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
|
||||
}
|
||||
]
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue