<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0" xml:base="https://www.hashbangcode.com/">
  <channel>
    <title>Articles</title>
    <link>https://www.hashbangcode.com/</link>
    <description/>
    <language>en</language>
    
    <item>
  <title>Drupal 11: Building A Link Directory: Part 2</title>
  <link>https://www.hashbangcode.com/article/drupal-11-building-link-directory-part-2</link>
  <description>&lt;span class="field field--name-title field--type-string field--label-hidden"&gt;Drupal 11: Building A Link Directory: Part 2&lt;/span&gt;
            &lt;p&gt;In the last article in this series &lt;a href="https://www.hashbangcode.com/article/drupal-11-building-link-directory-part-1"&gt;I looked at creating a link directory on a Drupal site&lt;/a&gt;. In that article I looked at how I set up the links and took screenshots of the sites using a headless Chromium browser as the links were added.&lt;/p&gt;&lt;p&gt;The issue I had was that when I used headless Chromium to take screenshots of the sites the success rate was not very high. In these days of AI attacks, site captcha checks, and cookie popups it turned out to be quite difficult to take a clean screenshot of a site without being blocked either by a CDN or a cookie popup. In fact, most of the time the screenshot would be just a CDN error page.&lt;/p&gt;&lt;p&gt;I therefore looked for a different mechanism. Since I wanted to take a screenshot of a website it made sense to me to use a browser to do this, and because I am already using a browser why not get the browser I'm using to take the screenshot. After a bit of research I realised that creating browser extensions to do this was actually pretty simple. Plus once the screenshot has been taken I can post this to the Drupal site using a REST resource.&lt;/p&gt;&lt;p&gt;The only niggle was that I needed the screenshot to be at a set dimension, since all the link images on the site also have that dimension. That turned out to be slightly more challenging.&lt;/p&gt;&lt;p&gt;In this article we will look at setting up a rest resource to generate (or update) links, and then creating a Chrome extension to take a screenshot of a site at a set resolution.&lt;/p&gt;&lt;p&gt;First, let's look at creating the REST resource in Drupal.&lt;/p&gt;&lt;h2&gt;Creating A REST Resource&lt;/h2&gt;&lt;p&gt;This needs to accept the data from the Chrome extension and generate a Link content entity using that data.&lt;/p&gt;
      &lt;span class="field field--name-uid field--type-entity-reference field--label-hidden"&gt;&lt;span&gt;philipnorton42&lt;/span&gt;&lt;/span&gt;
&lt;span class="field field--name-created field--type-created field--label-hidden"&gt;&lt;time datetime="2026-06-07T19:15:26+01:00" title="Sunday, June 7, 2026 - 19:15" class="datetime"&gt;Sun, 06/07/2026 - 19:15&lt;/time&gt;
&lt;/span&gt;
</description>
    <pubDate>Sun, 07 Jun 2026 18:15:26 +0000</pubDate>
    <dc:creator>philipnorton42</dc:creator>
    <guid isPermaLink="false">14068 at https://www.hashbangcode.com</guid>
    </item>
<item>
  <title>Drupal 11: Building A Link Directory: Part 1</title>
  <link>https://www.hashbangcode.com/article/drupal-11-building-link-directory-part-1</link>
  <description>&lt;span class="field field--name-title field--type-string field--label-hidden"&gt;Drupal 11: Building A Link Directory: Part 1&lt;/span&gt;
            &lt;p&gt;A problem I've been struggling with for a while now is managing my bookmarks. Every time I come across an interesting article I want to read, a good resource I want to keep, or a neat tool I want to try I create a bookmark.&lt;/p&gt;&lt;p&gt;Over time I have collected a large collection of bookmarks so when I add a new one to the list it gets lots in the pile. I've tried to create directories to keep "new" bookmarks or organise them into sections, but I always end up scrabbling to find them.&lt;/p&gt;&lt;p&gt;The problem is that web browsers don't allow you to categorise or search bookmarks so I can never find them again. Also when I swap browsers (which I have done twice this year) I end up having to migrate them over and set up synchronising between computers. This always removes the favicons of the sites so I have even more trouble finding the right link.&lt;/p&gt;&lt;p&gt;After losing yet another bookmark again recently I decided to do something about it. I realised that &lt;a href="https://www.hashbangcode.com"&gt;#! code&lt;/a&gt; was the best place for it as I'm always logged into the site, so I set about creating a link directory on the site. I didn't just want a big list of links though. In my mind a good link directory takes a screenshot of the site when the link is created so that it is easy to see what links are there from the screenshot of the original site.&lt;/p&gt;&lt;p&gt;In this article I will go through how I set up the link directory, how links are added, and how the site is able to take screenshots of the links as they are added to the directory.&amp;nbsp;&lt;/p&gt;&lt;h2&gt;Creating The Link Content Type&lt;/h2&gt;&lt;p&gt;To store the links I created a content type called "Link" and added a few fields to it.&lt;/p&gt;
      &lt;span class="field field--name-uid field--type-entity-reference field--label-hidden"&gt;&lt;span&gt;philipnorton42&lt;/span&gt;&lt;/span&gt;
&lt;span class="field field--name-created field--type-created field--label-hidden"&gt;&lt;time datetime="2026-05-24T19:07:02+01:00" title="Sunday, May 24, 2026 - 19:07" class="datetime"&gt;Sun, 05/24/2026 - 19:07&lt;/time&gt;
&lt;/span&gt;
</description>
    <pubDate>Sun, 24 May 2026 18:07:02 +0000</pubDate>
    <dc:creator>philipnorton42</dc:creator>
    <guid isPermaLink="false">14066 at https://www.hashbangcode.com</guid>
    </item>
<item>
  <title>Drupal 11: Node Display Mode Preview Form Using HTMX</title>
  <link>https://www.hashbangcode.com/article/drupal-11-node-display-mode-preview-form-using-htmx</link>
  <description>&lt;span class="field field--name-title field--type-string field--label-hidden"&gt;Drupal 11: Node Display Mode Preview Form Using HTMX&lt;/span&gt;
            &lt;p&gt;This is part five of a series of articles looking at HTMX in Drupal. If you are interested in reading more then there will be a list of related articles at the end of this article.&lt;/p&gt;&lt;p&gt;When I was thinking about ideas on demonstrating HTMX in Drupal I implemented things like infinite scroll, a tabbed interface, and a cascading select form. I basically recreating some things that I had done in non-Drupal HTMX inside a Drupal module.&lt;/p&gt;&lt;p&gt;I then had an idea to create something that I might actually find useful in my day to day work as a Drupal developer. This was some way of displaying nodes in different view modes.&lt;/p&gt;&lt;p&gt;In this article we will look at creating a simple form that allows users to enter a node ID and a view mode and see the node rendered in that view mode.&lt;/p&gt;&lt;p&gt;All of the code contained in this article can be found in the &lt;a href="https://github.com/hashbangcode/drupal_htmx_examples"&gt;Drupal HTMX examples project on GitHub&lt;/a&gt;, but here we will go through what the code does and what actions it performs to generate content. &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Just like the other articles on HTMX, I'm going to start with the basics and define the route.&lt;/p&gt;&lt;h2&gt;The Route&lt;/h2&gt;&lt;p&gt;The route we need here just needs to point the path /htmx-examples/display-mode-preview at our form class.&lt;/p&gt;&lt;pre&gt;&lt;code class="language-yaml"&gt;drupal_htmx_examples_display_mode_preview_form:
  path: "/htmx-examples/display-mode-preview"
  defaults:
    _form: '\Drupal\drupal_htmx_examples\Form\DisplayModePreviewForm'
    _title: "HTMX Display Mode Preview Form"
  requirements:
    _permission: "access content"&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There isn't anything unusual about this route, it's just a regular form route.&lt;/p&gt;&lt;p&gt;Let's create the form for this route.&lt;/p&gt;&lt;h2&gt;The Form&lt;/h2&gt;&lt;p&gt;The form class has a couple of injected dependencies, which are as follows:&lt;/p&gt;
      &lt;span class="field field--name-uid field--type-entity-reference field--label-hidden"&gt;&lt;span&gt;philipnorton42&lt;/span&gt;&lt;/span&gt;
&lt;span class="field field--name-created field--type-created field--label-hidden"&gt;&lt;time datetime="2026-05-10T19:08:39+01:00" title="Sunday, May 10, 2026 - 19:08" class="datetime"&gt;Sun, 05/10/2026 - 19:08&lt;/time&gt;
&lt;/span&gt;
</description>
    <pubDate>Sun, 10 May 2026 18:08:39 +0000</pubDate>
    <dc:creator>philipnorton42</dc:creator>
    <guid isPermaLink="false">14059 at https://www.hashbangcode.com</guid>
    </item>
<item>
  <title>Drupal 11: Cascading Select Forms With HTMX</title>
  <link>https://www.hashbangcode.com/article/drupal-11-cascading-select-forms-htmx</link>
  <description>&lt;span class="field field--name-title field--type-string field--label-hidden"&gt;Drupal 11: Cascading Select Forms With HTMX&lt;/span&gt;
            &lt;p&gt;This is part four of a series of articles looking at HTMX in Drupal. In the last two articles we looked at using HTMX with controllers in different ways. This time I'll be venturing into the world of HTMX and forms.&lt;/p&gt;&lt;p&gt;Years ago on this site I wrote an article about &lt;a href="https://www.hashbangcode.com/article/drupal-9-cascading-ajax-select-forms"&gt;Cascading ajax select forms in Drupal&lt;/a&gt;, which I often refer back to when I'm trying to figure out something to do with select forms and ajax. In that article I take a year, month, and day select field and tie them together so that they influence each other during the selection process.&lt;/p&gt;&lt;p&gt;I've been writing Drupal sites for quite a number of years and I still need to take a deep breath before attempting to embark on implementing ajax in Drupal forms. I end up with form fields that have wrapper elements or custom attributes in an attempt to get things working. It always seems to be a painful experience.&lt;/p&gt;&lt;p&gt;When I was learning about HTMX and Drupal I sat down to re-implement this cascading select form and had something working in about half an hour. Most of that time was spend adding the form elements to the build form method. A stark difference between the old and the new ways of adding ajax to forms in Drupal.&lt;/p&gt;&lt;p&gt;In this article we will look at creating a form that contains multiple select elements and then use HTMX (and a little bit of the form states API) to tie them together so that selecting one element updates the others.&lt;/p&gt;&lt;p&gt;All of the code contained in this article can be found in the &lt;a href="https://github.com/hashbangcode/drupal_htmx_examples"&gt;Drupal HTMX examples project on GitHub&lt;/a&gt;, but here we will go through what the code does and what actions it performs to generate content. &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Just like the other articles on HTMX, I'm going to start with the basics and define the route.&lt;/p&gt;
      &lt;span class="field field--name-uid field--type-entity-reference field--label-hidden"&gt;&lt;span&gt;philipnorton42&lt;/span&gt;&lt;/span&gt;
&lt;span class="field field--name-created field--type-created field--label-hidden"&gt;&lt;time datetime="2026-04-26T18:58:36+01:00" title="Sunday, April 26, 2026 - 18:58" class="datetime"&gt;Sun, 04/26/2026 - 18:58&lt;/time&gt;
&lt;/span&gt;
</description>
    <pubDate>Sun, 26 Apr 2026 17:58:36 +0000</pubDate>
    <dc:creator>philipnorton42</dc:creator>
    <guid isPermaLink="false">14042 at https://www.hashbangcode.com</guid>
    </item>
<item>
  <title>Drupal 11: Creating A Tabbed Interface With HTMX</title>
  <link>https://www.hashbangcode.com/article/drupal-11-creating-tabbed-interface-htmx</link>
  <description>&lt;span class="field field--name-title field--type-string field--label-hidden"&gt;Drupal 11: Creating A Tabbed Interface With HTMX&lt;/span&gt;
            &lt;p&gt;This is part three of a series of articles looking at HTMX in Drupal. Last time I looked at &lt;a href="https://www.hashbangcode.com/article/drupal-11-building-load-more-feature-paginating-nodes-using-htmx"&gt;using HTMX to run a "load more" feature on a Drupal page&lt;/a&gt;. Before moving onto looking at forms I thought a final example of using HTMX and controllers to achieve an action.&lt;/p&gt;&lt;p&gt;One of the key examples that helped me understand HTMX was when it was used to create a tabbed interface, without reloading the page. This was quite simple to recreate in Drupal and can be done in a single controller.&lt;/p&gt;&lt;p&gt;In this article we will be creating a tabbed interface in Drupal, where HTMX is used to power loading the data in a tab like interface without reloading the page.&lt;/p&gt;&lt;p&gt;All of the code contained in this article can be found in the &lt;a href="https://github.com/hashbangcode/drupal_htmx_examples"&gt;Drupal HTMX examples project on GitHub&lt;/a&gt;, but here we will go through what the code does and what actions it performs to generate content. &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;The first task is to create the route for our controller.&lt;/p&gt;&lt;h2&gt;The Route&lt;/h2&gt;&lt;p&gt;The route we create here just points to an action in a controller.&lt;/p&gt;&lt;pre&gt;&lt;code class="language-yaml"&gt;drupal_htmx_examples_tabbed:
  path: '/drupal-htmx-examples/tabbed'
  defaults:
    _title: 'HTMX Tabbed'
    _controller: '\Drupal\drupal_htmx_examples\Controller\TabbedController::action'
  requirements:
    _permission: 'access content'&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When the user (assuming they have the access &lt;code class="plaintext"&gt;content permission&lt;/code&gt;) visits the path &lt;code class="plaintext"&gt;/drupal-htmx-examples/tabbed&lt;/code&gt; then they will trigger the &lt;code class="plaintext"&gt;action()&lt;/code&gt; method in the controller.&lt;/p&gt;&lt;p&gt;Let's build the controller that this route points to.&lt;/p&gt;
      &lt;span class="field field--name-uid field--type-entity-reference field--label-hidden"&gt;&lt;span&gt;philipnorton42&lt;/span&gt;&lt;/span&gt;
&lt;span class="field field--name-created field--type-created field--label-hidden"&gt;&lt;time datetime="2026-04-12T19:14:12+01:00" title="Sunday, April 12, 2026 - 19:14" class="datetime"&gt;Sun, 04/12/2026 - 19:14&lt;/time&gt;
&lt;/span&gt;
</description>
    <pubDate>Sun, 12 Apr 2026 18:14:12 +0000</pubDate>
    <dc:creator>philipnorton42</dc:creator>
    <guid isPermaLink="false">14027 at https://www.hashbangcode.com</guid>
    </item>
<item>
  <title>Drupal 11: Building A "Load More" Feature For Paginating Nodes Using HTMX</title>
  <link>https://www.hashbangcode.com/article/drupal-11-building-load-more-feature-paginating-nodes-using-htmx</link>
  <description>&lt;span class="field field--name-title field--type-string field--label-hidden"&gt;Drupal 11: Building A "Load More" Feature For Paginating Nodes Using HTMX&lt;/span&gt;
            &lt;p&gt;Following on from my last article, &lt;a href="https://www.hashbangcode.com/article/drupal-11-making-interactive-elements-htmx"&gt;an introduction to HTMX in Drupal&lt;/a&gt;, I wanted to start looking at examples of HTMX being used to power interactivity in Drupal in different ways.&lt;/p&gt;&lt;p&gt;I thought a good place to start this off would be to look at using HTMX in a simple controller. By creating a route to a controller we can render content and then inject HTMX attributes to perform actions with the same controller.&lt;/p&gt;&lt;p&gt;In this article I will put together a controller action to load some pages of content to display them as a list. An element containing HTMX attributes will be used to make a request back to the same controller action and generate more items in the list. These new items will be appended to the existing list along with another element containing HTMX attributes that we can use to request more items.&lt;/p&gt;&lt;p&gt;The HTMX element will act like a "load more" button, which will load more and more content as long as there is content to load.&lt;/p&gt;&lt;p&gt;All of the code contained in this article can be found in the &lt;a href="https://github.com/hashbangcode/drupal_htmx_examples"&gt;Drupal HTMX examples project on GitHub&lt;/a&gt;, but here we will go through what the code does and what actions it performs to generate content. &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;First, let's create the route to the controller.&lt;/p&gt;&lt;h2&gt;The Route&lt;/h2&gt;&lt;p&gt;The route we create here just links the path requested with the controller class. As we are only using a single action in this example we don't need to provide a second route for the HTMX request.&lt;/p&gt;
      &lt;span class="field field--name-uid field--type-entity-reference field--label-hidden"&gt;&lt;span&gt;philipnorton42&lt;/span&gt;&lt;/span&gt;
&lt;span class="field field--name-created field--type-created field--label-hidden"&gt;&lt;time datetime="2026-03-29T19:08:15+01:00" title="Sunday, March 29, 2026 - 19:08" class="datetime"&gt;Sun, 03/29/2026 - 19:08&lt;/time&gt;
&lt;/span&gt;
</description>
    <pubDate>Sun, 29 Mar 2026 18:08:15 +0000</pubDate>
    <dc:creator>philipnorton42</dc:creator>
    <guid isPermaLink="false">13962 at https://www.hashbangcode.com</guid>
    </item>
<item>
  <title>Drupal 11: Making Interactive Elements With HTMX</title>
  <link>https://www.hashbangcode.com/article/drupal-11-making-interactive-elements-htmx</link>
  <description>&lt;span class="field field--name-title field--type-string field--label-hidden"&gt;Drupal 11: Making Interactive Elements With HTMX&lt;/span&gt;
            &lt;p&gt;HTMX is a JavaScript library that allows you to make ajax calls and create CSS transitions without writing any JavaScript code. It works by adding attributes to HTML elements, which it then uses to set up and perform ajax requests, swap elements, and a few other things.&lt;/p&gt;&lt;p&gt;It was added to Drupal in version 11.3.0* and gives developers the ability to create interactive elements using render arrays and HTML attributes. The intent is to replace the entire ajax sub-system with one built around HTMX, and there is quite a lot of work ahead to accomplish this task.&lt;/p&gt;&lt;p&gt;* Technically, HTMX has been in Drupal since 11.2.0, but only as an experimental library. Drupal 11.3.0 features the full HTMX library and a number of helper classes to make life easy.&lt;/p&gt;&lt;p&gt;In this article we will look at how HTMX is integrated into Drupal, and what services exist to help you use it within the Drupal system.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Since this article is quite long I have created a table of contents to assist in scrolling to the relevant sections.&lt;/p&gt;
      &lt;span class="field field--name-uid field--type-entity-reference field--label-hidden"&gt;&lt;span&gt;philipnorton42&lt;/span&gt;&lt;/span&gt;
&lt;span class="field field--name-created field--type-created field--label-hidden"&gt;&lt;time datetime="2026-03-15T19:01:54+00:00" title="Sunday, March 15, 2026 - 19:01" class="datetime"&gt;Sun, 03/15/2026 - 19:01&lt;/time&gt;
&lt;/span&gt;
</description>
    <pubDate>Sun, 15 Mar 2026 19:01:54 +0000</pubDate>
    <dc:creator>philipnorton42</dc:creator>
    <guid isPermaLink="false">13817 at https://www.hashbangcode.com</guid>
    </item>
<item>
  <title>DrupalCamp England 2026</title>
  <link>https://www.hashbangcode.com/article/drupalcamp-england-2026</link>
  <description>&lt;span class="field field--name-title field--type-string field--label-hidden"&gt;DrupalCamp England 2026&lt;/span&gt;
            &lt;p&gt;The weekend of 28th February to the 1st March saw the second DrupalCamp England event with around 100 people attending the University of Salford, not far from Manchester, for the two day event.&lt;/p&gt;&lt;p&gt;I had submitted a talk and the camp organisers had accepted it and also decided to make me a featured speaker, which was an incredible honour. As such I was part of the communications being sent out in the weeks before the event.&lt;/p&gt;&lt;p&gt;Since this is more or less a local event for me I decided to travel in on both days rather than get a hotel or anything. The rain and wind of the previous week had abated and the Saturday morning saw some of the warmest (and driest) weather we had seen in the north west for a few months.&lt;/p&gt;&lt;h2&gt;Saturday&lt;/h2&gt;&lt;p&gt;The keynote on Saturday morning was &lt;strong&gt;The Augmented Future: Winning with AI&lt;/strong&gt; with &lt;strong&gt;Dr. Phininder Balaghan&lt;/strong&gt;, founder of &lt;a href="https://traversally.ai"&gt;Traversally&lt;/a&gt;. This was an look through the current state of AI, which Dr. Balaghan said changes every time he gives the talk.&lt;/p&gt;&lt;p&gt;Most companies these days have adopted an agile methodology, which has taken about 20 years to become widespread. Since the introduction of LLM AI systems a few years ago we have seen massive adoption across all industries.&lt;/p&gt;&lt;p&gt;Dr. Balaghan joked that we have reached the age of AI-gile, the new agile methodology.&lt;/p&gt;&lt;p&gt;At the moment we are using a collection of LLM agents that work together in a so-called "agentic" system to provide a coherent service. The next true advancement in AI systems will be thinking AI systems that are able to properly think about the input and respond. I think we are quite a long way from that yet and no amount of processing power or RAM is going to solve the problem that LLMs are just statistical word engines.&lt;/p&gt;
      &lt;span class="field field--name-uid field--type-entity-reference field--label-hidden"&gt;&lt;span&gt;philipnorton42&lt;/span&gt;&lt;/span&gt;
&lt;span class="field field--name-created field--type-created field--label-hidden"&gt;&lt;time datetime="2026-03-08T18:57:11+00:00" title="Sunday, March 8, 2026 - 18:57" class="datetime"&gt;Sun, 03/08/2026 - 18:57&lt;/time&gt;
&lt;/span&gt;
</description>
    <pubDate>Sun, 08 Mar 2026 18:57:11 +0000</pubDate>
    <dc:creator>philipnorton42</dc:creator>
    <guid isPermaLink="false">13807 at https://www.hashbangcode.com</guid>
    </item>
<item>
  <title>Running An LLM With Llama.cpp Using Docker On A Raspberry Pi</title>
  <link>https://www.hashbangcode.com/article/running-llm-llamacpp-using-docker-raspberry-pi</link>
  <description>&lt;span class="field field--name-title field--type-string field--label-hidden"&gt;Running An LLM With Llama.cpp Using Docker On A Raspberry Pi&lt;/span&gt;
            &lt;p&gt;I've been curious about integrating AI agents into my workflow recently, and so I started looking at how this could be done using my current equipment. Data sovereignty is important to me so sending all my data to train a remote AI agent doesn't appeal. I was expecting to need to buy a new gaming rig with a couple of high end graphics cards in it, but after some research I found that this wasn't the case.&lt;/p&gt;&lt;p&gt;I found a system called &lt;a href="https://github.com/ggml-org/llama.cpp"&gt;llama.cpp&lt;/a&gt;, which is an efficient LLM engine written in C++. The idea behind llama.cpp is that you can host small, efficient AI agents without having to throw thousands at equipment to get them running. As I have a Raspberry PI model 5, with 16GB of RAM in my office I thought this was a good candidate to get running.&lt;/p&gt;&lt;p&gt;In this article we will look at how to get an LLM running on a Raspberry PI via a docker container, and what sort of things we might be able to do with it.&lt;/p&gt;&lt;h2&gt;Building The Docker Container&lt;/h2&gt;&lt;p&gt;The docker file here is pretty simple. We need to start from a base model of Debian, install some dependencies, and then download and compile llama.cpp. Here is my docker file.&lt;/p&gt;&lt;pre&gt;&lt;code class="language-plaintext"&gt;FROM debian:trixie

ADD ./models /models

RUN apt update &amp;amp;&amp;amp; apt install -y build-essential cmake git libcurl4-openssl-dev

WORKDIR /opt/llama
RUN git clone https://github.com/ggerganov/llama.cpp.git &amp;amp;&amp;amp; cd llama.cpp

WORKDIR /opt/llama/llama.cpp
RUN cmake -B build -DLLAMA_CURL=OFF &amp;amp;&amp;amp; cmake --build build --config Release

ENTRYPOINT [ "/opt/llama/llama.cpp/build/bin/llama-server" ]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The build option we are sending to llama.cpp is "LLAMA_CURL", which is turned off to prevent llama.cpp from being able to download models.&lt;/p&gt;
      &lt;span class="field field--name-uid field--type-entity-reference field--label-hidden"&gt;&lt;span&gt;philipnorton42&lt;/span&gt;&lt;/span&gt;
&lt;span class="field field--name-created field--type-created field--label-hidden"&gt;&lt;time datetime="2026-03-01T19:19:38+00:00" title="Sunday, March 1, 2026 - 19:19" class="datetime"&gt;Sun, 03/01/2026 - 19:19&lt;/time&gt;
&lt;/span&gt;
</description>
    <pubDate>Sun, 01 Mar 2026 19:19:38 +0000</pubDate>
    <dc:creator>philipnorton42</dc:creator>
    <guid isPermaLink="false">13723 at https://www.hashbangcode.com</guid>
    </item>
<item>
  <title>Leaving Meetup.com And Extracting Past Event Data Without API Access</title>
  <link>https://www.hashbangcode.com/article/leaving-meetupcom-and-extracting-past-event-data-without-api-access</link>
  <description>&lt;span class="field field--name-title field--type-string field--label-hidden"&gt;Leaving Meetup.com And Extracting Past Event Data Without API Access&lt;/span&gt;
            &lt;p&gt;It's no secret that meetup.com have raised their prices over the last couple of years. Whilst this doesn't impact some of the larger user groups who have lots of members, it is basically killing smaller groups with no income streams.&lt;/p&gt;&lt;p&gt;I have no idea how tiny groups with less than 50 members can afford to pay £150+ every 6 months and pay for venues, refreshments, hosting space, and all the other things that a small group needs to pay for. That's not a fixed cost either, there's a good chance that meetup.com will increase their prices further.&lt;/p&gt;&lt;p&gt;The local Drupal user group I manage in Manchester is one of those groups affected. We just don't have the income or the user numbers to afford meetup.com any more. So, after 14 years we have stopped the subscription and the group will disappear from meetup within the next few weeks.&lt;/p&gt;&lt;p&gt;But what about those 14 years of events? They are stored in meetup.com and there is no way of getting hold of that data without API access; which costs a lot of money to get. I suppose I could just go through all those events and copy/paste the data into a CSV file, but surely there is a better way?&lt;/p&gt;&lt;p&gt;In this article I will show how I dug into the meetup.com site to see how the data was presented, and how I was able to MacGyver a solution in PHP to download the past data for the group as a CSV file.&lt;/p&gt;&lt;h2&gt;Digging Into The Data&lt;/h2&gt;&lt;p&gt;I can see a list of the old events on the page at &lt;a href="https://www.meetup.com/nwdrupal/events/?type=past"&gt;https://www.meetup.com/nwdrupal/events/?type=past&lt;/a&gt;, and as I scroll down the page the old events are loaded in as chunks. Note that this page might not exist when you read this article, but that's where the page &lt;em&gt;used&lt;/em&gt; to be.&lt;/p&gt;&lt;p&gt;If we look at what is going on in the browser I can see that the data is loaded from the path &lt;code class="plaintext"&gt;/gql2&lt;/code&gt; with a payload that requests the next chunk of data from some sort of API layer.&lt;/p&gt;
      &lt;span class="field field--name-uid field--type-entity-reference field--label-hidden"&gt;&lt;span&gt;philipnorton42&lt;/span&gt;&lt;/span&gt;
&lt;span class="field field--name-created field--type-created field--label-hidden"&gt;&lt;time datetime="2026-02-15T18:51:31+00:00" title="Sunday, February 15, 2026 - 18:51" class="datetime"&gt;Sun, 02/15/2026 - 18:51&lt;/time&gt;
&lt;/span&gt;
</description>
    <pubDate>Sun, 15 Feb 2026 18:51:31 +0000</pubDate>
    <dc:creator>philipnorton42</dc:creator>
    <guid isPermaLink="false">13792 at https://www.hashbangcode.com</guid>
    </item>

  </channel>
</rss>
