diff --git a/config/sync/system.performance.yml b/config/sync/system.performance.yml index f08fe124d..61f4e1531 100644 --- a/config/sync/system.performance.yml +++ b/config/sync/system.performance.yml @@ -2,9 +2,9 @@ _core: default_config_hash: jtno5biznHZbrIgKwzq-ze-7XaQxLCGe6PeUOR7bRiQ cache: page: - max_age: 900 + max_age: 0 css: - preprocess: true + preprocess: false gzip: true fast_404: enabled: true @@ -12,5 +12,5 @@ fast_404: exclude_paths: '/\/(?:styles|imagecache)\//' html: '
The requested URL "@path" was not found on this server.
' js: - preprocess: true + preprocess: false gzip: true diff --git a/config/sync/views.view.daily_email_rss_feed.yml b/config/sync/views.view.daily_email_rss_feed.yml new file mode 100644 index 000000000..99c0f842c --- /dev/null +++ b/config/sync/views.view.daily_email_rss_feed.yml @@ -0,0 +1,194 @@ +uuid: de364a16-6052-402e-b7c0-52c243c8bfcf +langcode: en +status: true +dependencies: + config: + - node.type.daily_email + module: + - node +id: daily_email_rss_feed +label: 'Daily email RSS feed' +module: views +description: '' +tag: '' +base_table: node_field_data +base_field: nid +display: + default: + id: default + display_title: Default + display_plugin: default + position: 0 + display_options: + fields: + title: + id: title + table: node_field_data + field: title + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: title + plugin_id: field + label: '' + exclude: false + alter: + alter_text: false + make_link: false + absolute: false + word_boundary: false + ellipsis: false + strip_tags: false + trim: false + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: true + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + pager: + type: some + options: + offset: 0 + items_per_page: 1 + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + access: + type: none + options: { } + cache: + type: tag + options: { } + empty: { } + sorts: + created: + id: created + table: node_field_data + field: created + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: created + plugin_id: date + order: DESC + expose: + label: '' + field_identifier: '' + exposed: false + granularity: second + arguments: { } + filters: + status: + id: status + table: node_field_data + field: status + entity_type: node + entity_field: status + plugin_id: boolean + value: '1' + group: 1 + expose: + operator: '' + type: + id: type + table: node_field_data + field: type + entity_type: node + entity_field: type + plugin_id: bundle + value: + daily_email: daily_email + style: + type: default + options: + grouping: { } + row_class: '' + default_row_class: true + uses_fields: false + row: + type: fields + options: + default_field_elements: true + inline: { } + separator: '' + hide_empty: false + query: + type: views_query + options: + query_comment: '' + disable_sql_rewrite: false + distinct: false + replica: false + query_tags: { } + relationships: { } + header: { } + footer: { } + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - 'user.node_grants:view' + tags: { } + feed_1: + id: feed_1 + display_title: Feed + display_plugin: feed + position: 1 + display_options: + pager: + type: some + options: + offset: 0 + items_per_page: 1 + style: + type: rss + options: + uses_fields: false + description: 'A daily email newsletter about software development, DevOps, community, and open source.' + row: + type: node_rss + options: + relationship: none + view_mode: default + display_extenders: { } + path: rss/daily.xml + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - 'user.node_grants:view' + tags: { } diff --git a/content/feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76.json b/content/feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76.json index 338035ada..eb581e59a 100644 --- a/content/feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76.json +++ b/content/feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76.json @@ -34,17 +34,17 @@ ], "changed": [ { - "value": "2025-04-29T13:41:02+00:00" + "value": "2025-05-02T07:25:00+00:00" } ], "imported": [ { - "value": "2025-04-29T13:41:02+00:00" + "value": "2025-05-02T07:25:00+00:00" } ], "next": [ { - "value": "2025-04-30T01:41:02+00:00" + "value": "2025-05-02T19:25:00+00:00" } ], "queued": [ @@ -67,7 +67,7 @@ ], "item_count": [ { - "value": 811 + "value": 853 } ] } \ No newline at end of file diff --git a/content/meta/index.json b/content/meta/index.json index f746b37b9..0b33c8f74 100644 --- a/content/meta/index.json +++ b/content/meta/index.json @@ -3388,14 +3388,174 @@ "paragraph.e89e2456-b6b5-4c5f-922f-9f34f6e77e68", "paragraph.2f7f892b-75ff-48a0-9034-b9af048efd84" ], - "paragraph.e8a7c3c3-c07a-4545-8387-ab03b8f7f47a": [], - "paragraph.373fc0f2-717e-4fea-ae97-ec2c674834fd": [], - "paragraph.8828e7e1-466a-4086-a79a-e120899f0784": [], - "paragraph.34fea7ca-2458-448e-8991-495d69ee6836": [], - "paragraph.08be1735-e111-4a35-a270-2c56640f689f": [], - "paragraph.81b18409-0f9d-49de-a8ff-c75c7c4852c0": [], - "paragraph.e89e2456-b6b5-4c5f-922f-9f34f6e77e68": [], - "paragraph.2f7f892b-75ff-48a0-9034-b9af048efd84": [], + "node.6e6b15bc-6319-4392-ac07-7c38fb66e6a4": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.6900edff-5340-44ce-b328-9f3d24ab673b": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.43617141-40c9-4462-b130-60ee7697ab9d": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.d130088a-0c2c-4dfb-b65d-3b2ee8d6239c": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.0dc3cee6-40bf-4f95-8d25-4c32e95e7462": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.72729ed3-73ab-4e13-9115-fbf6d8ca6b08": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.6d520198-e187-44dd-b434-034f0f74d5c2": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.5cc406b1-f4ca-49c0-a296-d352086fc7f4": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.c4ee2105-bde9-49ad-89e2-2c06c215bdbb": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.0710efa0-c7f4-4254-afab-7c7a4f5b6959": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.2a8452d0-735c-41de-88ef-a9cc81f4035f": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.dc67f83a-6499-4b35-a040-3c7f89549cc7": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.00204e36-4f2d-4b4a-bcf6-c0140209e835": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.b09ccd35-261d-4fa5-99cc-52f781c52e87": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.3cbded61-45d4-46f7-95a0-a0ebb3da9847": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.641d773f-97cb-4da8-93e9-69df3c89261c": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.231b6fcb-38a4-4461-b0d4-63ab4c31806c": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.ecf2d8ff-f99c-4faf-899d-8e80e1b74287": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.03653911-19e8-4f60-8baa-5165b8380d29": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.197ba205-f2c2-4c14-8d71-ac01bf602861": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.cac7e909-60cc-48f1-9535-b1b3ea3347ad": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.d52128e8-0927-4232-8c77-e9c0d60578ca": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.e3631745-3190-45d0-b893-7e5315faeba3": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.d96c36ac-6f81-4a25-a5d1-b62c846680d1": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.3fa16a10-1230-498f-ad80-4cab3ae96a28": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.98e87c30-8dd5-4d80-aed3-53439673de97": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.4403292d-2b01-4681-afb2-0ab2113694a6": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.ed274b9c-e558-4ccb-a0e3-845fd4252c85": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.e3d951af-bba8-45f4-b249-c7e0f73e2a47": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.737d4134-6074-4498-b8d3-f51d7b71d006": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.ffcfe425-1787-4842-bbbf-0362a655a830": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.af5c2fcc-7f6c-4363-943c-f23dcdab51ca": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.f21de9a2-c741-4a12-9109-c7b5a452dccb": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.efea11de-28be-4cb0-9bad-9b04322c2126": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.9e166002-410b-4261-aac8-e47dbe1c04d8": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.d51a4843-892e-4d52-81ca-66c2af097478": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.bed02c02-476f-4f2f-8d21-0c8c45edb128": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.3d15dfe9-c530-40d6-8923-f5d7e7b3018b": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.c6ef991b-2262-4942-b1f9-34c8a3afced4": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.8c006484-b85e-4eb7-a2c2-f0094a331712": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.09407211-6afb-4f28-95b7-5a7c3f9235b8": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], + "node.dee73953-50c6-4afb-9c3d-09c53a5fd415": [ + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849", + "feeds_feed.90c85284-7ca8-4074-9178-97ff8384fe76" + ], "path_alias.ac3001e1-433d-40c7-bb9d-a4fb9e8d0544": [ "node.63032bf4-8a96-4e14-93b2-92f5b057184e" ], @@ -5955,9 +6115,143 @@ "path_alias.1a615955-1c23-4677-9839-1e29d2260179": [ "node.f9b17889-2531-4e1e-b120-a0f0e27fed83" ], + "path_alias.c0415faf-ca06-4f19-a31a-c7c1b3cf1e3f": [ + "node.6e6b15bc-6319-4392-ac07-7c38fb66e6a4" + ], + "path_alias.d395f86e-2911-4b1d-a49c-ca3dd1c32083": [ + "node.6900edff-5340-44ce-b328-9f3d24ab673b" + ], + "path_alias.0bc43805-583f-45cc-9604-2cb7a000af0b": [ + "node.43617141-40c9-4462-b130-60ee7697ab9d" + ], + "path_alias.aa4704f0-c8d1-4554-a133-fe2fca90c142": [ + "node.d130088a-0c2c-4dfb-b65d-3b2ee8d6239c" + ], + "path_alias.6898a61e-17b6-4103-9293-840d7a012850": [ + "node.0dc3cee6-40bf-4f95-8d25-4c32e95e7462" + ], + "path_alias.a7edd40d-18da-4a9b-ba0a-a8190cc6d104": [ + "node.72729ed3-73ab-4e13-9115-fbf6d8ca6b08" + ], + "path_alias.2dff4b65-61ed-46e9-94c9-71d479303461": [ + "node.6d520198-e187-44dd-b434-034f0f74d5c2" + ], + "path_alias.a0821366-eddb-4182-9987-d6d0caf0559a": [ + "node.5cc406b1-f4ca-49c0-a296-d352086fc7f4" + ], + "path_alias.dbd11573-f435-42c5-9fb2-eeff934fa7e1": [ + "node.c4ee2105-bde9-49ad-89e2-2c06c215bdbb" + ], + "path_alias.45376d45-20cf-41ca-84ab-8b50e6828666": [ + "node.0710efa0-c7f4-4254-afab-7c7a4f5b6959" + ], + "path_alias.04fe45c5-c54e-4110-9d33-b9681b32f3b5": [ + "node.2a8452d0-735c-41de-88ef-a9cc81f4035f" + ], + "path_alias.dc5689bd-8f0d-4c07-9a50-0bbc35a52c8f": [ + "node.dc67f83a-6499-4b35-a040-3c7f89549cc7" + ], + "path_alias.1e93c591-9fdc-415d-9ddd-ffe9ce2005f9": [ + "node.00204e36-4f2d-4b4a-bcf6-c0140209e835" + ], + "path_alias.82fb019d-185d-4b8f-a3ad-ed260b5c60e2": [ + "node.b09ccd35-261d-4fa5-99cc-52f781c52e87" + ], + "path_alias.cde23a5c-26c9-4cb1-9dc6-3de19ec7856f": [ + "node.3cbded61-45d4-46f7-95a0-a0ebb3da9847" + ], + "path_alias.a635bfb6-ac56-4a3e-87bb-e7487942d5a7": [ + "node.641d773f-97cb-4da8-93e9-69df3c89261c" + ], + "path_alias.3aad1a8d-456a-4f50-9dbd-c1073580e74e": [ + "node.231b6fcb-38a4-4461-b0d4-63ab4c31806c" + ], + "path_alias.1274b1fe-43b6-4277-bb7e-cfc25e8786ce": [ + "node.ecf2d8ff-f99c-4faf-899d-8e80e1b74287" + ], + "path_alias.ac2378ff-1de4-442b-9018-54c9c8322961": [ + "node.03653911-19e8-4f60-8baa-5165b8380d29" + ], + "path_alias.b0482047-f38c-41f4-9020-e5447d48ee1d": [ + "node.197ba205-f2c2-4c14-8d71-ac01bf602861" + ], + "path_alias.fcfbfce9-4005-4385-9904-527459c0193b": [ + "node.cac7e909-60cc-48f1-9535-b1b3ea3347ad" + ], + "path_alias.e2818d79-08ab-43de-a46a-611692fb21ad": [ + "node.d52128e8-0927-4232-8c77-e9c0d60578ca" + ], + "path_alias.b7ca03cd-c00c-404e-8efb-9c043c6c896d": [ + "node.e3631745-3190-45d0-b893-7e5315faeba3" + ], + "path_alias.8cdf0c15-fa61-4f6c-beba-6e2750a43add": [ + "node.d96c36ac-6f81-4a25-a5d1-b62c846680d1" + ], + "path_alias.a703bebc-ef85-4b26-9aca-8923ec103114": [ + "node.3fa16a10-1230-498f-ad80-4cab3ae96a28" + ], + "path_alias.66bb38d3-d7b4-43e4-875f-25afb877d1ce": [ + "node.98e87c30-8dd5-4d80-aed3-53439673de97" + ], + "path_alias.58d1c76c-54a4-4a93-8637-766e5bb2e598": [ + "node.4403292d-2b01-4681-afb2-0ab2113694a6" + ], + "path_alias.749b2e45-4c6f-4413-99a8-8bdb7295a36b": [ + "node.ed274b9c-e558-4ccb-a0e3-845fd4252c85" + ], + "path_alias.1ce9a885-2b61-4222-b340-08b54135eb2f": [ + "node.e3d951af-bba8-45f4-b249-c7e0f73e2a47" + ], + "path_alias.4b5dab9d-c0b7-47df-b2de-8f46fc45cb9c": [ + "node.737d4134-6074-4498-b8d3-f51d7b71d006" + ], + "path_alias.be97582e-4563-4f43-a6f2-c0a61b3832ce": [ + "node.ffcfe425-1787-4842-bbbf-0362a655a830" + ], + "path_alias.1e2d3a71-a014-477a-864c-d9c816b1c7a6": [ + "node.af5c2fcc-7f6c-4363-943c-f23dcdab51ca" + ], + "path_alias.0d5d3954-a5ea-4230-9508-c69a31e739d6": [ + "node.f21de9a2-c741-4a12-9109-c7b5a452dccb" + ], + "path_alias.3515d35d-aae2-46e9-9f2d-19482dd90011": [ + "node.efea11de-28be-4cb0-9bad-9b04322c2126" + ], + "path_alias.4071b156-9da4-4f65-a6ab-e390d9e955a0": [ + "node.9e166002-410b-4261-aac8-e47dbe1c04d8" + ], + "path_alias.d69bb36d-01d6-4dde-8b03-c01808447a14": [ + "node.d51a4843-892e-4d52-81ca-66c2af097478" + ], + "path_alias.fe4be376-f835-439b-9d6a-e281d8c8e6bc": [ + "node.bed02c02-476f-4f2f-8d21-0c8c45edb128" + ], + "path_alias.903ec0e9-3c6a-4279-b40f-620441e7d816": [ + "node.3d15dfe9-c530-40d6-8923-f5d7e7b3018b" + ], + "path_alias.450e40e9-6a07-4c26-a4fb-80f415e8af57": [ + "node.c6ef991b-2262-4942-b1f9-34c8a3afced4" + ], + "path_alias.7ffe966e-9311-4627-a058-e120afdfe341": [ + "node.8c006484-b85e-4eb7-a2c2-f0094a331712" + ], + "path_alias.22643036-3745-42ff-836e-86c2caafac72": [ + "node.09407211-6afb-4f28-95b7-5a7c3f9235b8" + ], + "path_alias.59cdaf2a-3e6c-4ca9-9816-83a5c59693ae": [ + "node.dee73953-50c6-4afb-9c3d-09c53a5fd415" + ], "shortcut.8cd79370-99a8-45fc-89a8-639ffc00bd1c": [], "shortcut.fd457304-bed3-4d38-926b-e190a05c37d3": [], "shortcut.0cabd243-2f9c-48ac-b0d9-f536d1cf1eaa": [], "user.42bd662a-80da-4069-9fb8-14db3a77bb8c": [], - "user.b8966985-d4b2-42a7-a319-2e94ccfbb849": [] + "user.b8966985-d4b2-42a7-a319-2e94ccfbb849": [], + "paragraph.e8a7c3c3-c07a-4545-8387-ab03b8f7f47a": [], + "paragraph.373fc0f2-717e-4fea-ae97-ec2c674834fd": [], + "paragraph.8828e7e1-466a-4086-a79a-e120899f0784": [], + "paragraph.34fea7ca-2458-448e-8991-495d69ee6836": [], + "paragraph.08be1735-e111-4a35-a270-2c56640f689f": [], + "paragraph.81b18409-0f9d-49de-a8ff-c75c7c4852c0": [], + "paragraph.e89e2456-b6b5-4c5f-922f-9f34f6e77e68": [], + "paragraph.2f7f892b-75ff-48a0-9034-b9af048efd84": [] } \ No newline at end of file diff --git a/content/node.00204e36-4f2d-4b4a-bcf6-c0140209e835.json b/content/node.00204e36-4f2d-4b4a-bcf6-c0140209e835.json new file mode 100644 index 000000000..71512eafd --- /dev/null +++ b/content/node.00204e36-4f2d-4b4a-bcf6-c0140209e835.json @@ -0,0 +1,100 @@ +{ + "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": "\nThere are many good resources and interesting articles online about how to write good messages when committing changes to a Git repository.<\/p>\n\n
The post I often refer to is How to Write a Git Commit Message<\/a> by Chris Beams.<\/p>\n\n In his post, he explains why good commit messages matter and gives these seven rules:<\/p>\n\n I'd recommend reading the article to get the full context.<\/p>\n\n Rules two and six suggest lengths for the subject line and body which is another reason why I rarely use 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 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 This additional feedback helps me create my commit messages how I intend.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n 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 The post I often refer to is How to Write a Git Commit Message<\/a> by Chris Beams.<\/p>\n\n In his post, he explains why good commit messages matter and gives these seven rules:<\/p>\n\n I'd recommend reading the article to get the full context.<\/p>\n\n Rules two and six suggest lengths for the subject line and body which is another reason why I rarely use 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 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 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"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.03653911-19e8-4f60-8baa-5165b8380d29.json b/content/node.03653911-19e8-4f60-8baa-5165b8380d29.json
new file mode 100644
index 000000000..39b71cbac
--- /dev/null
+++ b/content/node.03653911-19e8-4f60-8baa-5165b8380d29.json
@@ -0,0 +1,100 @@
+{
+ "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 A few months ago, Beyond Blocks podcast guest Dan Leech<\/a> give another talk at the PHP South West user group.<\/p>\n\n This talk was about building an expression language from scratch<\/a>, but in one part of the talk, Dan showed how he creates Collection classes.<\/p>\n\n I use Collection classes a lot, have given talks about them<\/a> and wrote a Collections module for Drupal 7<\/a>.<\/p>\n\n In Dan's talk, instead of using a Collection from Laravel or Doctrine, he created his own<\/a>.<\/p>\n\n His extended PHP's He could then add whatever additional methods and functionality he needed.<\/p>\n\n Looking at other repositories on GitHub, I was able to find other examples.<\/p>\n\n 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 A few months ago, Beyond Blocks podcast guest Dan Leech<\/a> give another talk at the PHP South West user group.<\/p>\n\n This talk was about building an expression language from scratch<\/a>, but in one part of the talk, Dan showed how he creates Collection classes.<\/p>\n\n I use Collection classes a lot, have given talks about them<\/a> and wrote a Collections module for Drupal 7<\/a>.<\/p>\n\n In Dan's talk, instead of using a Collection from Laravel or Doctrine, he created his own<\/a>.<\/p>\n\n His extended PHP's He could then add whatever additional methods and functionality he needed.<\/p>\n\n Looking at other repositories on GitHub, I was able to find other examples.<\/p>\n\n 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"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.0710efa0-c7f4-4254-afab-7c7a4f5b6959.json b/content/node.0710efa0-c7f4-4254-afab-7c7a4f5b6959.json
new file mode 100644
index 000000000..20c025042
--- /dev/null
+++ b/content/node.0710efa0-c7f4-4254-afab-7c7a4f5b6959.json
@@ -0,0 +1,100 @@
+{
+ "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 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 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 I write the rst (reStructuredText) file and compile it to a PDF file.<\/p>\n\n 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 Here's how my flake.nix file looks now:<\/p>\n\n Each talk is its own derivation, so I can run The source code is available at https:\/\/code.oliverdavies.uk\/opdavies\/talks<\/a> if you want to see how I use rst2pdf to create my presentations and I've even given a presentation about how I create presentations<\/a>.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n 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 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 I write the rst (reStructuredText) file and compile it to a PDF file.<\/p>\n\n 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 Here's how my flake.nix file looks now:<\/p>\n\n Each talk is its own derivation, so I can run The source code is available at https:\/\/code.oliverdavies.uk\/opdavies\/talks<\/a> if you want to see how I use rst2pdf to create my presentations and I've even 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"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.09407211-6afb-4f28-95b7-5a7c3f9235b8.json b/content/node.09407211-6afb-4f28-95b7-5a7c3f9235b8.json
new file mode 100644
index 000000000..ee2fb1ca2
--- /dev/null
+++ b/content/node.09407211-6afb-4f28-95b7-5a7c3f9235b8.json
@@ -0,0 +1,100 @@
+{
+ "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 Drupal comes with a lot of features available out of the box.<\/p>\n\n 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 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 It has user management, authentication, password resets, roles and permissions.<\/p>\n\n It has configuration management to easily manage settings and configuration between environments and to provide traceability.<\/p>\n\n 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 These are just some of the features I could mention.<\/p>\n\n Running cloc on Drupal's If you were to get someone to build a CMS from scratch with the same features, how long would that take?<\/p>\n\n How much would it cost?<\/p>\n\n This is what you get for free by using free and open source software like Drupal.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n Drupal comes with a lot of features available out of the box.<\/p>\n\n 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 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 It has user management, authentication, password resets, roles and permissions.<\/p>\n\n It has configuration management to easily manage settings and configuration between environments and to provide traceability.<\/p>\n\n 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 These are just some of the features I could mention.<\/p>\n\n Running cloc on Drupal's If you were to get someone to build a CMS from scratch with the same features, how long would that take?<\/p>\n\n How much would it cost?<\/p>\n\n 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"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.0dc3cee6-40bf-4f95-8d25-4c32e95e7462.json b/content/node.0dc3cee6-40bf-4f95-8d25-4c32e95e7462.json
new file mode 100644
index 000000000..b9c78226e
--- /dev/null
+++ b/content/node.0dc3cee6-40bf-4f95-8d25-4c32e95e7462.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "0dc3cee6-40bf-4f95-8d25-4c32e95e7462"
+ }
+ ],
+ "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": "Building static websites with Drupal"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-04-18T00: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\/18\/static-drupal",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n 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 Around that time, I discovered static site generators and built the next version of my website with Jekyll.<\/p>\n\n I liked how I could write content in simple plain files, export them to HTML and upload them to a server.<\/p>\n\n Static websites are fast and secure.<\/p>\n\n 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 I later switched to Sculpin, a static site generator written with PHP, which has a lot of similarities with Drupal.<\/p>\n\n But what if you want the power of Drupal with the benefits of a static website?<\/p>\n\n Tome<\/a> is a module that turns Drupal into a static site generator.<\/p>\n\n 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 Sam Mortenson, the creator of the Tome module discussed it on our episode of the Beyond Blocks podcast<\/a> where we also talked about single file components.<\/p>\n\n 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 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 Around that time, I discovered static site generators and built the next version of my website with Jekyll.<\/p>\n\n I liked how I could write content in simple plain files, export them to HTML and upload them to a server.<\/p>\n\n Static websites are fast and secure.<\/p>\n\n 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 I later switched to Sculpin, a static site generator written with PHP, which has a lot of similarities with Drupal.<\/p>\n\n But what if you want the power of Drupal with the benefits of a static website?<\/p>\n\n Tome<\/a> is a module that turns Drupal into a static site generator.<\/p>\n\n 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 Sam Mortenson, the creator of the Tome module discussed it on our episode of the Beyond Blocks podcast<\/a> where we also talked about single file components.<\/p>\n\n 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-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "2b68ef78311dde7624d8a9f3bf2aecd5",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.197ba205-f2c2-4c14-8d71-ac01bf602861.json b/content/node.197ba205-f2c2-4c14-8d71-ac01bf602861.json
new file mode 100644
index 000000000..2e85a0a40
--- /dev/null
+++ b/content/node.197ba205-f2c2-4c14-8d71-ac01bf602861.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "197ba205-f2c2-4c14-8d71-ac01bf602861"
+ }
+ ],
+ "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": "Work in sprints, deploy continuously"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-03-28T00: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\/28\/continuous",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n Agile and Scrum have become standard approaches in software development.<\/p>\n\n Work is planned and organised into iterations\/cycles\/sprints, usually lasting two weeks.<\/p>\n\n As one sprint is being worked on, the next is usually already planned and the following one is being discussed.<\/p>\n\n It's common for code deployments and releases to follow the same pattern.<\/p>\n\n When a sprint is finished, the changes are released.<\/p>\n\n But that means if a task is worked on at the start of the sprint, it won't be available for at least two weeks.<\/p>\n\n It may be longer if the sprint is longer or if there are steps like manual testing that also happen.<\/p>\n\n What if a change is needed or a bug is found?<\/p>\n\n Is that going to be at least another two weeks before it can be addressed?<\/p>\n\n Do you need to start using hotfixes and dealing with multiple branches and merge conflicts<\/a>?<\/p>\n\n I suggest separating your planning and work schedules from your deployments.<\/p>\n\n Deploy as often as possible, even during a sprint.<\/p>\n\n You want your feedback loop to be as small and quick as possible.<\/p>\n\n But, importantly, deploying code is different to releasing features<\/a>.<\/p>\n\n If you need to do manual testing, use feature flags to separate deploying the code from releasing the feature<\/a>.<\/p>\n\n Then, when it's ready to go live, you only need to enable the feature flag - no code deployment needed.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n Agile and Scrum have become standard approaches in software development.<\/p>\n\n Work is planned and organised into iterations\/cycles\/sprints, usually lasting two weeks.<\/p>\n\n As one sprint is being worked on, the next is usually already planned and the following one is being discussed.<\/p>\n\n It's common for code deployments and releases to follow the same pattern.<\/p>\n\n When a sprint is finished, the changes are released.<\/p>\n\n But that means if a task is worked on at the start of the sprint, it won't be available for at least two weeks.<\/p>\n\n It may be longer if the sprint is longer or if there are steps like manual testing that also happen.<\/p>\n\n What if a change is needed or a bug is found?<\/p>\n\n Is that going to be at least another two weeks before it can be addressed?<\/p>\n\n Do you need to start using hotfixes and dealing with multiple branches and merge conflicts<\/a>?<\/p>\n\n I suggest separating your planning and work schedules from your deployments.<\/p>\n\n Deploy as often as possible, even during a sprint.<\/p>\n\n You want your feedback loop to be as small and quick as possible.<\/p>\n\n But, importantly, deploying code is different to releasing features<\/a>.<\/p>\n\n If you need to do manual testing, use feature flags to separate deploying the code from releasing the feature<\/a>.<\/p>\n\n Then, when it's ready to go live, you only need to enable the feature flag - no code deployment needed.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "45f407c2e5e4e066da156bd49eb7991a",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.231b6fcb-38a4-4461-b0d4-63ab4c31806c.json b/content/node.231b6fcb-38a4-4461-b0d4-63ab4c31806c.json
new file mode 100644
index 000000000..89f73d214
--- /dev/null
+++ b/content/node.231b6fcb-38a4-4461-b0d4-63ab4c31806c.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "231b6fcb-38a4-4461-b0d4-63ab4c31806c"
+ }
+ ],
+ "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": "First pull request submitted to nixpkgs"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-03-31T00: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\/31\/nixpkgs",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n I've been using the Nix package manager for some time.<\/p>\n\n The first commit of a flake.nix file to my nixos-config repository<\/a> (formerly my dotfiles repository) was on the 26th of September 2022.<\/p>\n\n The following month, I started to experiment with NixOS - the operating system built on the Nix language and the package manager.<\/p>\n\n Rarely have I found a package missing within the 120,000+ available, but I have added some missing Vim plugins and some custom packages to my own configuration.<\/p>\n\n But I hadn't tried to contribute any package definitions back to nixpkgs until today.<\/p>\n\n I've submitted my first pull request to nixpkgs<\/a> to add a small script that I've added to my own configuration.<\/p>\n\n It's always nerve-racking contributing to a new projects, but let's see how it goes.<\/p>\n\n I'm thinking of it as a free code review<\/a>.<\/p>\n\n If it goes well, I can see me contributing more packages in the future.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n I've been using the Nix package manager for some time.<\/p>\n\n The first commit of a flake.nix file to my nixos-config repository<\/a> (formerly my dotfiles repository) was on the 26th of September 2022.<\/p>\n\n The following month, I started to experiment with NixOS - the operating system built on the Nix language and the package manager.<\/p>\n\n Rarely have I found a package missing within the 120,000+ available, but I have added some missing Vim plugins and some custom packages to my own configuration.<\/p>\n\n But I hadn't tried to contribute any package definitions back to nixpkgs until today.<\/p>\n\n I've submitted my first pull request to nixpkgs<\/a> to add a small script that I've added to my own configuration.<\/p>\n\n It's always nerve-racking contributing to a new projects, but let's see how it goes.<\/p>\n\n I'm thinking of it as a free code review<\/a>.<\/p>\n\n If it goes well, I can see me contributing more packages in the future.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "0e6a565b98631d7f71c7e8d4d68d0d26",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.2a8452d0-735c-41de-88ef-a9cc81f4035f.json b/content/node.2a8452d0-735c-41de-88ef-a9cc81f4035f.json
new file mode 100644
index 000000000..e1f5116c6
--- /dev/null
+++ b/content/node.2a8452d0-735c-41de-88ef-a9cc81f4035f.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "2a8452d0-735c-41de-88ef-a9cc81f4035f"
+ }
+ ],
+ "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": "Caching with decorators"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-04-06T00: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\/06\/caching",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n As well as working with different versions of an API<\/a>, I was able to use the same technique I wrote about yesterday to easily add a cacheable version of the API client.<\/p>\n\n As they all implement the same Here's an example based on the code I wrote:<\/p>\n\n Nothing in this instance is specific to either version of the API.<\/p>\n\n This client is only concerned with retrieving and saving cache data, and delegating any other logic to the original version.<\/p>\n\n With this approach, I can switch between But what if I don't want to interact with the API at all?<\/p>\n\n For local development, I have a The possibilities are endless.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n As well as working with different versions of an API<\/a>, I was able to use the same technique I wrote about yesterday to easily add a cacheable version of the API client.<\/p>\n\n As they all implement the same Here's an example based on the code I wrote:<\/p>\n\n Nothing in this instance is specific to either version of the API.<\/p>\n\n This client is only concerned with retrieving and saving cache data, and delegating any other logic to the original version.<\/p>\n\n With this approach, I can switch between But what if I don't want to interact with the API at all?<\/p>\n\n For local development, I have a The possibilities are endless.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "dd52b641b6c5a3e8eb19c47343f766c3",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.3cbded61-45d4-46f7-95a0-a0ebb3da9847.json b/content/node.3cbded61-45d4-46f7-95a0-a0ebb3da9847.json
new file mode 100644
index 000000000..426256cd1
--- /dev/null
+++ b/content/node.3cbded61-45d4-46f7-95a0-a0ebb3da9847.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "3cbded61-45d4-46f7-95a0-a0ebb3da9847"
+ }
+ ],
+ "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": "Dont commit changes with `-m`"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-04-02T00: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\/02\/commit",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n A common thing I see when reading posts or watch videos where people are using Git is using the If you think of a commit message as an email, the first line is the subject line which is followed by the body of the message.<\/p>\n\n If you don't use This includes the subject line and, more importantly, the body of the message where you can include as much additional information as you want.<\/p>\n\n The subject line summarises the change, but the body can be used to explain why it was needed.<\/p>\n\n You can describe the issue or requirements in more detail (don't just link to the issue or enter the issue number).<\/p>\n\n You can describe any other approaches you considered or tried.<\/p>\n\n You can describe any anticipated effects or consequences of this commit, any manual deployment steps or follow up tasks that will need to be created.<\/p>\n\n You can include any additional information you were aware of at the time of making the commit that could be useful to yourself or others in the future.<\/p>\n\n Think what information would you like to see when you next run A common thing I see when reading posts or watch videos where people are using Git is using the If you think of a commit message as an email, the first line is the subject line which is followed by the body of the message.<\/p>\n\n If you don't use This includes the subject line and, more importantly, the body of the message where you can include as much additional information as you want.<\/p>\n\n The subject line summarises the change, but the body can be used to explain why it was needed.<\/p>\n\n You can describe the issue or requirements in more detail (don't just link to the issue or enter the issue number).<\/p>\n\n You can describe any other approaches you considered or tried.<\/p>\n\n You can describe any anticipated effects or consequences of this commit, any manual deployment steps or follow up tasks that will need to be created.<\/p>\n\n You can include any additional information you were aware of at the time of making the commit that could be useful to yourself or others in the future.<\/p>\n\n Think what information would you like to see when you next run Now CSS supports variables<\/a> (aka custom properties) and Tailwind CSS v4 is configured using CSS<\/a> instead of JavaScript, I've been making heavy use of CSS variables in my front-end code.<\/p>\n\n I still use Tailwind to do the heavy lifting, but I can use CSS variables to extract themeable classes with variables like These variables can still use Tailwind's core variables by doing Tailwind has a arbitrary syntax to easily use CSS variables - e.g. CSS variables aren't specific to Tailwind CSS, so if I wasn't using Tailwind in a codebase, I'd use the new native CSS features instead of a preprocessor like Sass<\/a>.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n Now CSS supports variables<\/a> (aka custom properties) and Tailwind CSS v4 is configured using CSS<\/a> instead of JavaScript, I've been making heavy use of CSS variables in my front-end code.<\/p>\n\n I still use Tailwind to do the heavy lifting, but I can use CSS variables to extract themeable classes with variables like These variables can still use Tailwind's core variables by doing Tailwind has a arbitrary syntax to easily use CSS variables - e.g. CSS variables aren't specific to Tailwind CSS, so if I wasn't using Tailwind in a codebase, I'd use the new native CSS features instead of a preprocessor like Sass<\/a>.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:32+00:00",
+ "guid": null,
+ "hash": "5a6518d8c14841bf4d760dcc8afd3399",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.3fa16a10-1230-498f-ad80-4cab3ae96a28.json b/content/node.3fa16a10-1230-498f-ad80-4cab3ae96a28.json
new file mode 100644
index 000000000..0cb9a3f5f
--- /dev/null
+++ b/content/node.3fa16a10-1230-498f-ad80-4cab3ae96a28.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "3fa16a10-1230-498f-ad80-4cab3ae96a28"
+ }
+ ],
+ "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": "Legacy code is anything older than..."
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-03-22T00: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\/22\/legacy",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n How do you define legacy code?<\/p>\n\n Code that was written by someone else?<\/p>\n\n Code that doesn't have tests?<\/p>\n\n Any code that has been released to production?<\/p>\n\n Code that's more than a day old?<\/p>\n\n In a talk I recently watched, the speaker suggested that any code written more than thirty minutes ago is legacy code.<\/p>\n\n 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 This is the same approach for code that was written longer ago or written by someone else.<\/p>\n\n What do you think?<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n How do you define legacy code?<\/p>\n\n Code that was written by someone else?<\/p>\n\n Code that doesn't have tests?<\/p>\n\n Any code that has been released to production?<\/p>\n\n Code that's more than a day old?<\/p>\n\n In a talk I recently watched, the speaker suggested that any code written more than thirty minutes ago is legacy code.<\/p>\n\n 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 This is the same approach for code that was written longer ago or written by someone else.<\/p>\n\n What do you think?<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:32+00:00",
+ "guid": null,
+ "hash": "9983c859dafd94ec45282b7438b9cb59",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.43617141-40c9-4462-b130-60ee7697ab9d.json b/content/node.43617141-40c9-4462-b130-60ee7697ab9d.json
new file mode 100644
index 000000000..432cf59f5
--- /dev/null
+++ b/content/node.43617141-40c9-4462-b130-60ee7697ab9d.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "43617141-40c9-4462-b130-60ee7697ab9d"
+ }
+ ],
+ "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": "Automate Drupal deployments with configuration"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-04-20T00: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\/20\/config",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n Almost all Drupal projects have multiple environments - production and one or more pre-production environments.<\/p>\n\n A lot have development and staging, some have QA or UAT, or an environment per feature or sprint.<\/p>\n\n Each Developer has their own local environment to work on.<\/p>\n\n As new things are added, such as content types, fields and views, they need to be present on all environments.<\/p>\n\n When I started using Drupal, I needed to perform the same steps to manually recreate the changes on each environment.<\/p>\n\n Later, people started to use the Features module to export configuration into modules that could be committed and deployed as code.<\/p>\n\n This was accompanied by \"deploy\" modules that included update hooks to revert features or perform other tasks.<\/p>\n\n Since version 8, Drupal has had the Configuration Synchronization module.<\/p>\n\n Developers make changes once and export them to files using a simple command like Once the code has been deployed to each environment, run This will synchronise the configuration on the environment, making it the same as the exported configuration in an automated way - the same way every time.<\/p>\n\n Much quicker and more robust than doing it manually.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n Almost all Drupal projects have multiple environments - production and one or more pre-production environments.<\/p>\n\n A lot have development and staging, some have QA or UAT, or an environment per feature or sprint.<\/p>\n\n Each Developer has their own local environment to work on.<\/p>\n\n As new things are added, such as content types, fields and views, they need to be present on all environments.<\/p>\n\n When I started using Drupal, I needed to perform the same steps to manually recreate the changes on each environment.<\/p>\n\n Later, people started to use the Features module to export configuration into modules that could be committed and deployed as code.<\/p>\n\n This was accompanied by \"deploy\" modules that included update hooks to revert features or perform other tasks.<\/p>\n\n Since version 8, Drupal has had the Configuration Synchronization module.<\/p>\n\n Developers make changes once and export them to files using a simple command like Once the code has been deployed to each environment, run This will synchronise the configuration on the environment, making it the same as the exported configuration in an automated way - the same way every time.<\/p>\n\n Much quicker and more robust than doing it manually.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "a689477a80adb90fdbe7160be7d2450e",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.4403292d-2b01-4681-afb2-0ab2113694a6.json b/content/node.4403292d-2b01-4681-afb2-0ab2113694a6.json
new file mode 100644
index 000000000..e439edf93
--- /dev/null
+++ b/content/node.4403292d-2b01-4681-afb2-0ab2113694a6.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "4403292d-2b01-4681-afb2-0ab2113694a6"
+ }
+ ],
+ "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": "No-one is paying us to..."
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-03-19T00: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\/19\/effective",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n A great quote I recently heard whilst watching a conference talk was \"No-one is paying us to do something<\/em>, but we need to do it to work effectively\".<\/p>\n\n This talk was about decoupling, but the same quote could be re-used for various topics.<\/p>\n\n A common one is automated tests and test-driven development.<\/p>\n\n Tests aren't a line item<\/a> that should be billed for separately and clients and customers just want their software to work.<\/p>\n\n Generally, they aren't concerned that there are automated tests or whether the tests were written before the code.<\/p>\n\n If I need to give an estimate, I always include time to write automated tests.<\/p>\n\n It's part of my software development process.<\/p>\n\n Whether people know they're paying for me to write automated tests as part or not, I can work more effectively when I have tests and am doing test-driven development.<\/p>\n\n Both when writing the code, but also if it needs to be refactored or changed in the future<\/a>.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n A great quote I recently heard whilst watching a conference talk was \"No-one is paying us to do something<\/em>, but we need to do it to work effectively\".<\/p>\n\n This talk was about decoupling, but the same quote could be re-used for various topics.<\/p>\n\n A common one is automated tests and test-driven development.<\/p>\n\n Tests aren't a line item<\/a> that should be billed for separately and clients and customers just want their software to work.<\/p>\n\n Generally, they aren't concerned that there are automated tests or whether the tests were written before the code.<\/p>\n\n If I need to give an estimate, I always include time to write automated tests.<\/p>\n\n It's part of my software development process.<\/p>\n\n Whether people know they're paying for me to write automated tests as part or not, I can work more effectively when I have tests and am doing test-driven development.<\/p>\n\n Both when writing the code, but also if it needs to be refactored or changed in the future<\/a>.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:32+00:00",
+ "guid": null,
+ "hash": "4b75b46173ea0fe84b24f6e4c3cfcdb5",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.5cc406b1-f4ca-49c0-a296-d352086fc7f4.json b/content/node.5cc406b1-f4ca-49c0-a296-d352086fc7f4.json
new file mode 100644
index 000000000..d56bce576
--- /dev/null
+++ b/content/node.5cc406b1-f4ca-49c0-a296-d352086fc7f4.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "5cc406b1-f4ca-49c0-a296-d352086fc7f4"
+ }
+ ],
+ "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": "nix is like nvm, but for everything"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-04-15T00: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\/15\/nix-nvm",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n I was recently explaining and demonstrating Nix and direnv to a colleague and showing how, when I moved into a directory, new packages or different versions of packages became available.<\/p>\n\n If I left the directory, I was reverted back to my global packages and versions.<\/p>\n\n In this demonstration, I was showing how I can have different versions of PHP and node for a particular project - replacing a lot of what I'd previously used tools like Vagrant and Docker for.<\/p>\n\n I came up with a comparison between Nix and nvm - the node version manager - a tool that allows you to install multiple versions of nodejs and switch between them.<\/p>\n\n Using Nix and direnv is more seamless, but it works for everything.<\/p>\n\n I'm able to switch versions of PHP, MySQL, MariaDB, PostgreSQL or anything else I need with Nix.<\/p>\n\n Not just node, and without needing containers.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n I was recently explaining and demonstrating Nix and direnv to a colleague and showing how, when I moved into a directory, new packages or different versions of packages became available.<\/p>\n\n If I left the directory, I was reverted back to my global packages and versions.<\/p>\n\n In this demonstration, I was showing how I can have different versions of PHP and node for a particular project - replacing a lot of what I'd previously used tools like Vagrant and Docker for.<\/p>\n\n I came up with a comparison between Nix and nvm - the node version manager - a tool that allows you to install multiple versions of nodejs and switch between them.<\/p>\n\n Using Nix and direnv is more seamless, but it works for everything.<\/p>\n\n I'm able to switch versions of PHP, MySQL, MariaDB, PostgreSQL or anything else I need with Nix.<\/p>\n\n Not just node, and without needing containers.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "1f1938498491ff40c88d4e5b99fc617b",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.641d773f-97cb-4da8-93e9-69df3c89261c.json b/content/node.641d773f-97cb-4da8-93e9-69df3c89261c.json
new file mode 100644
index 000000000..efcebbe10
--- /dev/null
+++ b/content/node.641d773f-97cb-4da8-93e9-69df3c89261c.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "641d773f-97cb-4da8-93e9-69df3c89261c"
+ }
+ ],
+ "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": "Automated tests reduce debugging time"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-04-01T00: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\/01\/debugging",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n In my talk about automated testing and test-driven development<\/a>, I speak about a custom module I wrote for a client's Drupal project.<\/p>\n\n It was to integrate with a third-party job application system that they would log into and enter information via a form (similar to Drupal's node forms) that they wanted to appear on the Drupal website.<\/p>\n\n Once submitted, the system would send a POST request to an endpoint provided by the custom module. The module would process it and create the job node with the appropriate field values.<\/p>\n\n I wrote automated tests and did test-driven development.<\/p>\n\n Everything worked great for a few weeks or months.<\/p>\n\n Later, we had a message from the client saying the integration was broken and we needed to fix it.<\/p>\n\n I don't think I'd worked on this module for a while, but I was concerned that a Drupal core update or another change could have caused a regression.<\/p>\n\n The first thing I did was run the tests I'd written and verify they still passed, which they did.<\/p>\n\n This confirmed that as long as the data was being sent in the expected format, the node would be created and the integration would work.<\/p>\n\n Due to an upstream issue, the data was no longer in the expected format, which meant the node could not be created.<\/p>\n\n Once it was fixed, everything started working again.<\/p>\n\n My debugging time was practically zero as I was able to rely on my tests and that they were still passing.<\/p>\n\n I could confidently tell the client that the issue wasn't with our code and must've been an third-party issue.<\/p>\n\n Writing tests takes some time, but having tests saves time.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n In my talk about automated testing and test-driven development<\/a>, I speak about a custom module I wrote for a client's Drupal project.<\/p>\n\n It was to integrate with a third-party job application system that they would log into and enter information via a form (similar to Drupal's node forms) that they wanted to appear on the Drupal website.<\/p>\n\n Once submitted, the system would send a POST request to an endpoint provided by the custom module. The module would process it and create the job node with the appropriate field values.<\/p>\n\n I wrote automated tests and did test-driven development.<\/p>\n\n Everything worked great for a few weeks or months.<\/p>\n\n Later, we had a message from the client saying the integration was broken and we needed to fix it.<\/p>\n\n I don't think I'd worked on this module for a while, but I was concerned that a Drupal core update or another change could have caused a regression.<\/p>\n\n The first thing I did was run the tests I'd written and verify they still passed, which they did.<\/p>\n\n This confirmed that as long as the data was being sent in the expected format, the node would be created and the integration would work.<\/p>\n\n Due to an upstream issue, the data was no longer in the expected format, which meant the node could not be created.<\/p>\n\n Once it was fixed, everything started working again.<\/p>\n\n My debugging time was practically zero as I was able to rely on my tests and that they were still passing.<\/p>\n\n I could confidently tell the client that the issue wasn't with our code and must've been an third-party issue.<\/p>\n\n Writing tests takes some time, but having tests saves time.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "8f98e53db611d2a06dded4a390a73ab4",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.6900edff-5340-44ce-b328-9f3d24ab673b.json b/content/node.6900edff-5340-44ce-b328-9f3d24ab673b.json
new file mode 100644
index 000000000..4afbbe6f4
--- /dev/null
+++ b/content/node.6900edff-5340-44ce-b328-9f3d24ab673b.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "6900edff-5340-44ce-b328-9f3d24ab673b"
+ }
+ ],
+ "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": "With patches, I can change anything I want"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-04-21T00: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\/21\/patch",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n I've been a Drupal and Linux user for a long time, as well as using command-line tools and utilities like Neovim and tmux.<\/p>\n\n Since September 2022, I've used NixOS as my daily operating system on my computers.<\/p>\n\n Based on similar programs, in particular by ThePrimeagen, I wrote and use a program to automatically open tmux sessions and run initial commands for any project in my Code directory.<\/p>\n\n In October, he released tmux-sessionizer as its own package<\/a>.<\/p>\n\n There is a There was also this problem in the code:<\/p>\n\n These directories don't match what I use on my computers.<\/p>\n\n People have submitted pull requests, but these haven't yet been merged.<\/p>\n\n Either I change my directory structure or I can't use it.<\/p>\n\n But, in my derivation, I can apply my own patch files to make any changes I want - such as changing the directories to ones I'd want to use - making it usable for me.<\/p>\n\n I can also apply other people's patches, the same as I'm doing with dwm.<\/p>\n\n Someone has created a pull request to make the directories dynamic based on a configuration file.<\/p>\n\n I can apply these changes as a patch to my configuration and remove my custom one.<\/p>\n\n I can make any other changes I want or need to.<\/p>\n\n The possibilities are endless.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n I've been a Drupal and Linux user for a long time, as well as using command-line tools and utilities like Neovim and tmux.<\/p>\n\n Since September 2022, I've used NixOS as my daily operating system on my computers.<\/p>\n\n Based on similar programs, in particular by ThePrimeagen, I wrote and use a program to automatically open tmux sessions and run initial commands for any project in my Code directory.<\/p>\n\n In October, he released tmux-sessionizer as its own package<\/a>.<\/p>\n\n There is a There was also this problem in the code:<\/p>\n\n These directories don't match what I use on my computers.<\/p>\n\n People have submitted pull requests, but these haven't yet been merged.<\/p>\n\n Either I change my directory structure or I can't use it.<\/p>\n\n But, in my derivation, I can apply my own patch files to make any changes I want - such as changing the directories to ones I'd want to use - making it usable for me.<\/p>\n\n I can also apply other people's patches, the same as I'm doing with dwm.<\/p>\n\n Someone has created a pull request to make the directories dynamic based on a configuration file.<\/p>\n\n I can apply these changes as a patch to my configuration and remove my custom one.<\/p>\n\n I can make any other changes I want or need to.<\/p>\n\n The possibilities are endless.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "8a79fcd4efce6727224214430cc26505",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.6d520198-e187-44dd-b434-034f0f74d5c2.json b/content/node.6d520198-e187-44dd-b434-034f0f74d5c2.json
new file mode 100644
index 000000000..6257103a6
--- /dev/null
+++ b/content/node.6d520198-e187-44dd-b434-034f0f74d5c2.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "6d520198-e187-44dd-b434-034f0f74d5c2"
+ }
+ ],
+ "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": "Building fonts with Nix"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-04-16T00: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\/16\/fonts",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n I recently started using Nix to build my PDF presentation slides<\/a> that I create with rst2pdf<\/a>.<\/p>\n\n I removed the custom build script that was generating the PDF files and moved that code into a Nix derivation.<\/p>\n\n Now I can run 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 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 After some small changes, I was able to do it<\/a> and remove the font files from my repository.<\/p>\n\n The Inter font is available in nixpkgs, but it downloads an 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 I recently started using Nix to build my PDF presentation slides<\/a> that I create with rst2pdf<\/a>.<\/p>\n\n I removed the custom build script that was generating the PDF files and moved that code into a Nix derivation.<\/p>\n\n Now I can run 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 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 After some small changes, I was able to do it<\/a> and remove the font files from my repository.<\/p>\n\n The Inter font is available in nixpkgs, but it downloads an 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-05-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "663165d347672170986b3ba5d0f0ac13",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.6e6b15bc-6319-4392-ac07-7c38fb66e6a4.json b/content/node.6e6b15bc-6319-4392-ac07-7c38fb66e6a4.json
new file mode 100644
index 000000000..0759ea1a2
--- /dev/null
+++ b/content/node.6e6b15bc-6319-4392-ac07-7c38fb66e6a4.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "6e6b15bc-6319-4392-ac07-7c38fb66e6a4"
+ }
+ ],
+ "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": "Don't hack core"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-05-01T00: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\/05\/01\/hack",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n I've worked on a lot of Drupal projects and there have been times when previous Developers have \"hacked\" Drupal core or contrib modules by editing them to add or change functionality.<\/p>\n\n This is a short-sighted approach, as any changes to third-party code such as Drupal core or contrib modules would be lost when a new version is downloaded.<\/p>\n\n Most of the time, changes can be made within custom code that won't be overwritten and accidentally lost.<\/p>\n\n But in cases where the source code needs to be changed, you can patch files instead<\/a>.<\/p>\n\n You can commit the patch file to your project to save the changes, but you're responsible for maintaining it and ensuring it applies to any future updates of the code.<\/p>\n\n If you can, commit the changes upstream.<\/p>\n\n Then you won't need to patch files and others will benefit from the contribution.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n I've worked on a lot of Drupal projects and there have been times when previous Developers have \"hacked\" Drupal core or contrib modules by editing them to add or change functionality.<\/p>\n\n This is a short-sighted approach, as any changes to third-party code such as Drupal core or contrib modules would be lost when a new version is downloaded.<\/p>\n\n Most of the time, changes can be made within custom code that won't be overwritten and accidentally lost.<\/p>\n\n But in cases where the source code needs to be changed, you can patch files instead<\/a>.<\/p>\n\n You can commit the patch file to your project to save the changes, but you're responsible for maintaining it and ensuring it applies to any future updates of the code.<\/p>\n\n If you can, commit the changes upstream.<\/p>\n\n Then you won't need to patch files and others will benefit from the contribution.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "7ea5ffe7f98df1811de34c43a7caca75",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.72729ed3-73ab-4e13-9115-fbf6d8ca6b08.json b/content/node.72729ed3-73ab-4e13-9115-fbf6d8ca6b08.json
new file mode 100644
index 000000000..0bcce6ba9
--- /dev/null
+++ b/content/node.72729ed3-73ab-4e13-9115-fbf6d8ca6b08.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "72729ed3-73ab-4e13-9115-fbf6d8ca6b08"
+ }
+ ],
+ "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": "Upgrading incrementally"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-04-17T00: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\/17\/incrementally",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n Did you know you can have more than one version of your website in production at the same time?<\/p>\n\n If you're migrating to a new platform or upgrading to a new major version, such as Drupal 7 to Drupal 11, you don't need to do it all at once.<\/p>\n\n You can do it incrementally, and seamlessly for end users.<\/p>\n\n The MVP for your new website can be a particular section or a single page that is developed and launched to production alongside the current website.<\/p>\n\n Depending on the path someone goes to, they'll either see the new website or the old one.<\/p>\n\n Focusing on delivering a single page or section of a website is much faster compared to rebuilding the entire thing, it's a lot less risky as the feedback loop is much shorter and you get feedback from real users.<\/p>\n\n Once you have the new MVP deployed to a hosting environment, you can configure a proxy to assign traffic between it and the existing hosting based on path, request headers, or a combination of different options.<\/p>\n\n This is an approach I've taken with my website as I've upgraded between different versions of Drupal and also static site generators such as Jekyll, Astro and Sculpin.<\/p>\n\n Instead of waiting for months to deliver a new website to production, do it in days or weeks.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n Did you know you can have more than one version of your website in production at the same time?<\/p>\n\n If you're migrating to a new platform or upgrading to a new major version, such as Drupal 7 to Drupal 11, you don't need to do it all at once.<\/p>\n\n You can do it incrementally, and seamlessly for end users.<\/p>\n\n The MVP for your new website can be a particular section or a single page that is developed and launched to production alongside the current website.<\/p>\n\n Depending on the path someone goes to, they'll either see the new website or the old one.<\/p>\n\n Focusing on delivering a single page or section of a website is much faster compared to rebuilding the entire thing, it's a lot less risky as the feedback loop is much shorter and you get feedback from real users.<\/p>\n\n Once you have the new MVP deployed to a hosting environment, you can configure a proxy to assign traffic between it and the existing hosting based on path, request headers, or a combination of different options.<\/p>\n\n This is an approach I've taken with my website as I've upgraded between different versions of Drupal and also static site generators such as Jekyll, Astro and Sculpin.<\/p>\n\n Instead of waiting for months to deliver a new website to production, do it in days or weeks.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "36902cd3f90743c2ffd35168c819c294",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.737d4134-6074-4498-b8d3-f51d7b71d006.json b/content/node.737d4134-6074-4498-b8d3-f51d7b71d006.json
new file mode 100644
index 000000000..dde1f2f98
--- /dev/null
+++ b/content/node.737d4134-6074-4498-b8d3-f51d7b71d006.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "737d4134-6074-4498-b8d3-f51d7b71d006"
+ }
+ ],
+ "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": "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-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\/16\/what-s-the-correct-way-to-add-phpstan-to-an-existing-codebase",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n PHPStan is a static analysis tool for PHP.<\/p>\n\n It finds potential issues in PHP code without needing to run it, so Developers can find and resolve potential issues sooner.<\/p>\n\n I use it on all my projects including existing ones I've inherited.<\/p>\n\n 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 PHPStan has different levels of strictness.<\/p>\n\n Level 0 is the least strict and each level adds more rules and strictness, resulting in more errors.<\/p>\n\n Most of the time, people will start by running PHPStan on level 0, fixing any errors and committing the changes.<\/p>\n\n Then repeat the process as many times as needed until you reach the level you want to achieve.<\/p>\n\n I don't think this is the right approach.<\/p>\n\n This could mean that you need to edit the same files multiple times as you work through the levels.<\/p>\n\n 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 Another approach is to use a feature of PHPStan called the baseline.<\/p>\n\n 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 If you did this for an existing project, it would return no errors as everything would be included in the baseline.<\/p>\n\n 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 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 This I think is a better approach and how I add PHPStan to existing codebases.<\/p>\n\n To learn more about static analysis and PHPStan, listen to episode 22 of the Beyond Blocks podcast<\/a> with Dave Liddament.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n PHPStan is a static analysis tool for PHP.<\/p>\n\n It finds potential issues in PHP code without needing to run it, so Developers can find and resolve potential issues sooner.<\/p>\n\n I use it on all my projects including existing ones I've inherited.<\/p>\n\n 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 PHPStan has different levels of strictness.<\/p>\n\n Level 0 is the least strict and each level adds more rules and strictness, resulting in more errors.<\/p>\n\n Most of the time, people will start by running PHPStan on level 0, fixing any errors and committing the changes.<\/p>\n\n Then repeat the process as many times as needed until you reach the level you want to achieve.<\/p>\n\n I don't think this is the right approach.<\/p>\n\n This could mean that you need to edit the same files multiple times as you work through the levels.<\/p>\n\n 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 Another approach is to use a feature of PHPStan called the baseline.<\/p>\n\n 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 If you did this for an existing project, it would return no errors as everything would be included in the baseline.<\/p>\n\n 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 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 This I think is a better approach and how I add PHPStan to existing codebases.<\/p>\n\n To learn more about static analysis and PHPStan, listen to episode 22 of the Beyond Blocks podcast<\/a> with Dave Liddament.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:32+00:00",
+ "guid": null,
+ "hash": "9a7b258b69b97c51304c0aa8d6b87263",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.8c006484-b85e-4eb7-a2c2-f0094a331712.json b/content/node.8c006484-b85e-4eb7-a2c2-f0094a331712.json
new file mode 100644
index 000000000..c5fb79c63
--- /dev/null
+++ b/content/node.8c006484-b85e-4eb7-a2c2-f0094a331712.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "8c006484-b85e-4eb7-a2c2-f0094a331712"
+ }
+ ],
+ "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": "Feature branching slows delivery"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-03-05T00: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\/05\/slow",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n As well as causing merge conflicts<\/a>, feature branches slow the delivery of new features.<\/p>\n\n Someone needs to be responsible for merging the branches once they've been reviewed and approved, and any further merges into release branches.<\/p>\n\n This is typically the Lead Developer on the project, but this person then becomes a bottleneck.<\/p>\n\n They need to oversee all the branches and merges, and know what needs to be merged and where it needs to be deployed.<\/p>\n\n This slows down the speed of delivery.<\/p>\n\n In a trunk-based environment, there's only one branch and everyone can commit and push to it.<\/p>\n\n And, if you're doing continuous delivery<\/a>, any changes will be automatically deployed.<\/p>\n\n No more bottleneck.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n As well as causing merge conflicts<\/a>, feature branches slow the delivery of new features.<\/p>\n\n Someone needs to be responsible for merging the branches once they've been reviewed and approved, and any further merges into release branches.<\/p>\n\n This is typically the Lead Developer on the project, but this person then becomes a bottleneck.<\/p>\n\n They need to oversee all the branches and merges, and know what needs to be merged and where it needs to be deployed.<\/p>\n\n This slows down the speed of delivery.<\/p>\n\n In a trunk-based environment, there's only one branch and everyone can commit and push to it.<\/p>\n\n And, if you're doing continuous delivery<\/a>, any changes will be automatically deployed.<\/p>\n\n No more bottleneck.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:32+00:00",
+ "guid": null,
+ "hash": "abfbb6e640ea537c7cb537b44b7994ab",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.98e87c30-8dd5-4d80-aed3-53439673de97.json b/content/node.98e87c30-8dd5-4d80-aed3-53439673de97.json
new file mode 100644
index 000000000..343501e5c
--- /dev/null
+++ b/content/node.98e87c30-8dd5-4d80-aed3-53439673de97.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "98e87c30-8dd5-4d80-aed3-53439673de97"
+ }
+ ],
+ "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": "Extra PHPDoc types with PHPStan"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-03-21T00: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\/21\/phpdoc",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n Here are some examples of PHP code from Drupal core:<\/p>\n\n These use some of the standard PHPDoc types of Although they are comments, docblocks are checked by static analysis tools like PHPStan to parse the code and report any potential errors.<\/p>\n\n If you want to go deeper, PHPStan has its own PHPDoc types<\/a> that you can use to add more information and context.<\/p>\n\n Instead of specifying an argument must be a You can specify whether an integer is a You can define the shape of an array or object, whether an array is empty, or the types of keys and values in an array.<\/p>\n\n All of this is used by PHPStan when analysing the code and will give better results and find more potential bugs before anyone else does.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n Here are some examples of PHP code from Drupal core:<\/p>\n\n These use some of the standard PHPDoc types of Although they are comments, docblocks are checked by static analysis tools like PHPStan to parse the code and report any potential errors.<\/p>\n\n If you want to go deeper, PHPStan has its own PHPDoc types<\/a> that you can use to add more information and context.<\/p>\n\n Instead of specifying an argument must be a \n
\n
-m<\/code><\/a> when committing changes.<\/p>\n\n
\n
\n
-m<\/code><\/a> when committing changes.<\/p>\n\n
IteratorAggregate<\/code> class so had no external dependencies.<\/p>\n\n
IteratorAggregate<\/code> class so had no external dependencies.<\/p>\n\n
{\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
nix run .#test-driven-drupal<\/code> and it will generate the appropriate PDF file for me to present or share.<\/p>\n\n
{\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
nix run .#test-driven-drupal<\/code> and it will generate the appropriate PDF file for me to present or share.<\/p>\n\n
core<\/code> directory shows 18,289 files and 1,095,970 lines of code.<\/p>\n\n
core<\/code> directory shows 18,289 files and 1,095,970 lines of code.<\/p>\n\n
ApiClientInterface<\/code>, I can inject and decorate a client with another client, making one solely responsible for caching the result from the API whilst keeping the API interaction logic separate (aka the Decorator design pattern<\/a>).<\/p>\n\n
final class CacheableApiClient implements ApiClientInterface {\n\n \/**\n * The cache duration in seconds.\n *\/\n private const CACHE_DURATION = 3600;\n\n public function __construct(\n private readonly ApiClientInterface $client,\n private readonly TimeInterface $time,\n private readonly CacheBackendInterface $cache,\n ) {\n }\n\n public function getResults(): Collection {\n $key = $this->getCacheKey();\n\n $cache = $this->cache->get($key);\n\n if ($cache !== FALSE) {\n return $cache->data;\n }\n\n $result = $this->client->getResults();\n\n $this->cache->set(\n cid: $key,\n data: $result,\n expire: $this->time->getRequestTime() + self::CACHE_DURATION,\n );\n\n return $result;\n }\n\n}\n<\/code><\/pre>\n\n
V1ApiClient<\/code>,
V2ApiClient<\/code> or any other version with the same methods without having to reimplement caching as that's handled within the
CacheableApiClient<\/code>.<\/p>\n\n
FakeApiClient<\/code> that returns a static response that I can work with.<\/p>\n\n
ApiClientInterface<\/code>, I can inject and decorate a client with another client, making one solely responsible for caching the result from the API whilst keeping the API interaction logic separate (aka the Decorator design pattern<\/a>).<\/p>\n\n
final class CacheableApiClient implements ApiClientInterface {\n\n \/**\n * The cache duration in seconds.\n *\/\n private const CACHE_DURATION = 3600;\n\n public function __construct(\n private readonly ApiClientInterface $client,\n private readonly TimeInterface $time,\n private readonly CacheBackendInterface $cache,\n ) {\n }\n\n public function getResults(): Collection {\n $key = $this->getCacheKey();\n\n $cache = $this->cache->get($key);\n\n if ($cache !== FALSE) {\n return $cache->data;\n }\n\n $result = $this->client->getResults();\n\n $this->cache->set(\n cid: $key,\n data: $result,\n expire: $this->time->getRequestTime() + self::CACHE_DURATION,\n );\n\n return $result;\n }\n\n}\n<\/code><\/pre>\n\n
V1ApiClient<\/code>,
V2ApiClient<\/code> or any other version with the same methods without having to reimplement caching as that's handled within the
CacheableApiClient<\/code>.<\/p>\n\n
FakeApiClient<\/code> that returns a static response that I can work with.<\/p>\n\n
-m<\/code> option when committing changes.<\/p>\n\n
-m<\/code> allows you to specify the commit message inline or, more specifically, the first line of the commit message.<\/p>\n\n
-m<\/code>, Git will open an editor and you can type the full commit message into a file and save it.<\/p>\n\n
git log<\/code>.<\/p>\n\n ",
+ "format": "full_html",
+ "processed": "\n
-m<\/code> option when committing changes.<\/p>\n\n
-m<\/code> allows you to specify the commit message inline or, more specifically, the first line of the commit message.<\/p>\n\n
-m<\/code>, Git will open an editor and you can type the full commit message into a file and save it.<\/p>\n\n
git log<\/code>.<\/p>\n\n ",
+ "summary": null
+ }
+ ],
+ "feeds_item": [
+ {
+ "imported": "2025-05-01T23:43:31+00:00",
+ "guid": null,
+ "hash": "60ee5cbd523e01444113724332b468eb",
+ "target_type": "feeds_feed",
+ "target_uuid": "90c85284-7ca8-4074-9178-97ff8384fe76"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/content/node.3d15dfe9-c530-40d6-8923-f5d7e7b3018b.json b/content/node.3d15dfe9-c530-40d6-8923-f5d7e7b3018b.json
new file mode 100644
index 000000000..443a77489
--- /dev/null
+++ b/content/node.3d15dfe9-c530-40d6-8923-f5d7e7b3018b.json
@@ -0,0 +1,100 @@
+{
+ "uuid": [
+ {
+ "value": "3d15dfe9-c530-40d6-8923-f5d7e7b3018b"
+ }
+ ],
+ "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": "CSS variables everywhere"
+ }
+ ],
+ "created": [
+ {
+ "value": "2025-03-08T00: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\/08\/variables",
+ "langcode": "en"
+ }
+ ],
+ "body": [
+ {
+ "value": "\n
--color-primary<\/code> that can change value based on a data attribute or by something else.<\/p>\n\n
--color-primary: var(--color-red-500)<\/code>, rather than having to recreate all its colors, spacing or whatever variables I need to use.<\/p>\n\n
bg-(--color-primary)<\/code> - and you can define one-off variables with
[--box-spacing:30px]<\/code> or
[--box-spacing:--spacing(3)]<\/code> and using the standard arbitrary class syntax.<\/p>\n\n
--color-primary<\/code> that can change value based on a data attribute or by something else.<\/p>\n\n
--color-primary: var(--color-red-500)<\/code>, rather than having to recreate all its colors, spacing or whatever variables I need to use.<\/p>\n\n
bg-(--color-primary)<\/code> - and you can define one-off variables with
[--box-spacing:30px]<\/code> or
[--box-spacing:--spacing(3)]<\/code> and using the standard arbitrary class syntax.<\/p>\n\n
drush config:export<\/code>.<\/p>\n\n
drush config:import<\/code> to import the changes.<\/p>\n\n
drush config:export<\/code>.<\/p>\n\n
drush config:import<\/code> to import the changes.<\/p>\n\n
tmux-sessionizer<\/code> already in nixpkgs, but I wrote my own derivation<\/a> to use Prime's.<\/p>\n\n
# If someone wants to make this extensible, i'll accept\n# PR\nselected=$(find ~\/ ~\/personal ~\/personal\/dev\/env\/.config -mindepth 1 -maxdepth 1 -type d | fzf)\n<\/code><\/pre>\n\n
tmux-sessionizer<\/code> already in nixpkgs, but I wrote my own derivation<\/a> to use Prime's.<\/p>\n\n
# If someone wants to make this extensible, i'll accept\n# PR\nselected=$(find ~\/ ~\/personal ~\/personal\/dev\/env\/.config -mindepth 1 -maxdepth 1 -type d | fzf)\n<\/code><\/pre>\n\n
nix build .#test-driven-drupal<\/code> and it will generate the slides for that talk.<\/p>\n\n
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
nix build .#test-driven-drupal<\/code> and it will generate the slides for that talk.<\/p>\n\n
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
\/**\n * The weight of this role in administrative listings.\n *\n * @var int\n *\/\nprotected $weight;\n<\/code><\/pre>\n\n
\/**\n * Path of the image file.\n *\n * @var string\n *\/\nprotected $source = '';\n<\/code><\/pre>\n\n
\/**\n * Alter the list of mail backend plugin definitions.\n *\n * @param array $info\n * The mail backend plugin definitions to be altered.\n *\/\n<\/code><\/pre>\n\n
int<\/code>,
string<\/code> and
array<\/code>.<\/p>\n\n
string<\/code>, you can specify it's a
non-empty-string<\/code> or a
class-string<\/code>.<\/p>\n\n
positive-int<\/code> or
negative-int<\/code>, or within a certain range.<\/p>\n\n
\/**\n * The weight of this role in administrative listings.\n *\n * @var int\n *\/\nprotected $weight;\n<\/code><\/pre>\n\n
\/**\n * Path of the image file.\n *\n * @var string\n *\/\nprotected $source = '';\n<\/code><\/pre>\n\n
\/**\n * Alter the list of mail backend plugin definitions.\n *\n * @param array $info\n * The mail backend plugin definitions to be altered.\n *\/\n<\/code><\/pre>\n\n
int<\/code>,
string<\/code> and
array<\/code>.<\/p>\n\n
string<\/code>, you can specify it's a
non-empty-string<\/code> or a
class-string<\/code>.<\/p>\n\n