Skip to main content
Penyaskito Blog

Main navigation

  • Home
Language switcher
  • English
  • Español
User account menu
  • Log in

Last articles

By penyaskito , 13 April, 2026
Image
Generic Feed icon, licensed GNU GPL-2.0-or-later

Droople Reader, my new way of consuming RSS feeds

In my last post, I explained how I leveraged the Dashboard and Aggregator modules for being up to date with the Drupal CMS ecosystem progress. And one of the keys there is that I lack a nice RSS feed reader.

If you've been in the internet long enough, and I ask you what's the product you miss the most, I'm pretty sure 80% of the people would answer Google Reader. It's been already 13 years since Google killed it. Google Reader was absolutely the best Feed reader, and was very successful in converting the reading experience into a social network. You could track your own feeds, but also create conversations around them and read what your friends found interesting. When it died, the communities spread into different alternatives, and for me, nothing compared at all. Google didn't only kill Google Reader, but also my interest in consuming feeds. While other social networks like Twitter became the de-facto (non)standard of connecting with ""feeds"", it never felt the same. And now even Twitter is gone (not dead, but dead in practice).

So for the last years, I've been using this site with the aggregator module. Of course, none of the social features were there anymore, but also the experience was far from ideal.

In the last weeks, I've been playing with LLM assisted code agents (Claude Code). I doubted if I should write a blogpost on my position on them before even hitting publish on this one, but others have done much better. The TL;DR: I don't like it, it's addictive gambling, I mostly don't feel good using it, but I've been getting shit done and my personal usage or non usage of it has zero impact while I have a burger for dinner and buy a new macbook every 5 years. I invite you to get informed about the pros and cons of LLMs and the consequences of adopting them. If those are a lot of links and you only have 1 hour to spare, this video I saw this weekend it's an excellent summary of how I feel about it: How to (Anti) AI Better, by Dr Fatima. The TL;DR of the TL;DR: shaming won't work, AI literacy and understanding the consequences will.

Even if I declare myself a hater-and-late-adopter, unless you've been hiding in a cave, you probably have read that the smaller the task and the more precise you are in your prompts, the better will be the results you get. For myself, adopting my friend Mateu open-source AI-task-manager has made a difference in being disciplined about it.

Here's how I started this weekend.


❯ /tasks:create-plan I'm planning to create a feed reader, as Google
Reader was in the time, where I can mark things as read, so it only
shows the non-read items. I want it to use the aggregator module
under the hood. Start drafting an overall plan.

One of the good things about these skills is that they will question you before moving further:

⏺ I have a few questions before drafting the plan:
⏺ User answered Claude's questions:
 ⎿  · Is this feed reader for you only (single-user, admin-only),
or should it support multiple users each with their own read/unread
state? → Single user (me only)
    · Where should the feed reader UI live? → Admin page only
    · How should marking items as read work? → Auto-read on view
    · Should items be grouped/filterable by feed source, or shown
as a single chronological stream? → Both (filterable)

I never YOLO, so I have the opportunity of giving feedback about every single step, even cancelling them.

❯ I want to track read per user, just in case. For ajax, I want to use the
new htmx api in core. The module name is Droople Reader (machine_name:
drooplereader), a wordplay of the defuct Google Reader. It will be its own
module, and its own git repo. For now create it in the "custom" folder though

This highlighted one of the problems I've found. Sometimes what you feel it's important, can be ignored by the agent. Even if I explicitly say this will be its own repo, it ignored it. And I didn't notice this again until when I was already done!

I had another opportunity though, as this will only draft a Markdown plan that you can ask Claude to edit, or edit manually. Before writing the plan, you will see a preview and you can give more feedback. One thing I had in mind, but I never prompted, is that I had in mind a Single-Page Application built in React. Sometimes hallucinations are not bad, it can actually get creative. One example here is that I didn't think of using the Views module, but it suggested it. I decided to follow that train and I gave this feedback:

❯ When the row scrolls into view I don't want to mark it as read, but at the
end of the post. I didn't say to use views, but that's a good suggestion.
However, we should load a reduced amount of items, and they should load the
next ones that belong to the existing filter dinamically. Each item should
allow me to mark as unread, as I might want to revisit later.

And it questioned me again:

⏺ Good clarifications. Let me make sure I understand the UX correctly
before rewriting the plan.
⏺ User answered Claude's questions:
 ⎿  · For the infinite scroll, how many items should load initially
and per subsequent batch? → 10 initially, 10 more
    · For 'mark as unread', should the item reappear immediately
in the list, or just be flagged for next visit? → Stay in place visually

After that, I get another preview of the plan, including how self-validation will work. Claude tends to create one-off scripts, so I was explicit about this. I could use AI-Task-Manager hook system instead, by editing POST_PLAN.md, but I haven't explored that yet.

❯ For self-validation, I like your suggestion, but it should be
FunctionalTests or KernelTests, as Drupal permits. No one-off tests.
Avoid FunctionalJavascript tests when possible, but you are allowed if
we want to test the htmx interactions.

After this, I get a new draft of the plan. As noted before, the smaller the tasks, the best outputs we will get. After I was satisfied with the overall plan at a high level, it found some minor inconsistencies and self-corrected the plan. Now I was ready to dump MarkDown into my folder, and go for the next step:

❯ /tasks:generate-tasks 5

(5 is this plan id for this project)

As noted before, the smaller the tasks, the better. This will not only divide and conquer, but associate tags to the tasks, so if you happen to use different skills or agents, it will pick the best agent for the job. Each task will be another Markdown file, that you can refine at any point.

⏺ Task generation complete. Created 8 tasks
in .ai/task-manager/plans/05--feed-reader/tasks/

I won't get into the details of each, but here's the summary it presented me with:

Task Group Skills Dependencies
01 - Module scaffolding + ReadTracker backend drupal-backend, database —
02 - Views integration backend drupal-backend 01
03 - Controller + routing backend drupal-backend, php 01, 02
04 - Frontend assets frontend js, css 03
05 - Kernel tests testing drupal-testing 01, 02
06 - Functional tests testing drupal-testing 03, 04
07 - FunctionalJavascript test testing drupal-testing, js 04, 06
08 - Documentation documentation docs 03

Here I found some things that I would have changed. Not lots of them relevant enough, and I was already impatient (remember the gambling mention before? Did you ever heard about tilt?) to see what it will come with. But the only thing that really annoyed me was the usage of twig templates for the UI. I asked Claude to use single-directory components (note I didn't say SDC) instead when possible. Another case where I could have defined extra guardrails with AI-Task-Manager hooks.

❯ For the front-end tasks, you should try to use single-directory
components, to avoid having too much rendering logic into the twig
templates themselves.

It read the necessary context, even to learn that we use the SDC acronym, and updated everything that was affected.

⏺ Now I have a clear picture of how SDC works in modules:
#type => 'component', #component => 'module_name:component_name',
#props, #slots. Let me update the affected tasks.
⏺ Now let me update the tasks. Task 2 no longer needs hook_theme()
since SDC handles that. Task 3 controller uses
#type => 'component' instead of #theme.
Task 4 is restructured around components/ directory.
⏺ Updated the plan and tasks 01, 02, 03, and 04 to use Single
Directory Components. Here's a summary of the changes:
- Plan: Module structure now shows components/reader-page/ and
components/reader-item/ instead of templates/ and css/ directories.
No hook_theme() mentioned.
- Task 01 (scaffolding): Libraries file simplified to just scroll-read
JS library. Directory structure shows components/ instead of
templates/ and css/.
- Task 02 (Views integration): Removed hook_theme() from acceptance
criteria and hooks — SDC auto-discovers components.
- Task 03 (controller): Uses ['#type' => 'component',
'#component' => 'drooplereader:reader-item',
'#props' => [...]] render arrays instead of #theme.
- Task 04 (frontend): Fully restructured around two SDC components
(reader-page and reader-item) with co-located .component.yml, .twig,
and .css files. The scroll-read.js behavior stays as a standalone
library since it's page-level, not component-scoped.

I was satisfied with this, so wanted to move ahead. 

❯ /tasks:refine-plan 04 <--- wrong one!

But I was even more impatient, so I even mistyped the plan id. 🤯 It assumed I meant 5 and asked me for confirmation 🤯 
Then started self-correcting and asked another round of clarification questions:

⏺ Issues found:
1. Plan still references drooplereader-item.html.twig (line 162) in the
"Reader Page and Infinite Scroll" section — should reference SDC
component instead.
2. HX-Location vs HX-Redirect: The plan says mark-all-read uses
HX-Location header, but the task files reference HX-Redirect. These
have different semantics in HTMX — HX-Redirect does a full page load,
HX-Location does an HTMX-driven navigation. For "mark all as read"
where we want a clean page refresh, HX-Redirect is the right choice.
3. Sentinel double-fetch: The buildSentinel() method in the controller
plan calls loadItems() to check if more items exist — this results in
executing the View twice per page load (once for the actual items, once
to check if a sentinel is needed). A simpler approach: always render
the sentinel, and have the load-more endpoint return empty content
(no sentinel) when there are no more items.

I re-triggered the task generation, and it did an analysis (to be fair, I haven't checked yes how it works) to see if it should divide further any task:

❯ /tasks:generate-tasks 05
⏺ Tasks already exist for this plan from the previous generation.
Let me check their current state and regenerate them with the
refinements applied.
⏺ Now running the POST_TASK_GENERATION_ALL hook — complexity review
and blueprint update.
 Complexity sanity check (all tasks ≤ 4):
 - Task 01 (scaffolding + ReadTracker): 2 skills, well-defined — ~3
 - Task 02 (Views integration): 1 skill, moderate — ~3
 - Task 03 (controller): 2 skills, 5 methods but pattern-based
   — 4 (documented)
 - Task 04 (SDC components + JS): 2 skills, 2 components
   + JS behavior — ~4
 - Task 05 (kernel tests): 1 skill, focused — ~3
 - Task 06 (functional tests): 1 skill, 4 test classes
   but formulaic — ~3
 - Task 07 (FunctionalJS): 2 skills, single test class — ~3
 - Task 08 (docs): trivial — ~1
 No task exceeds 5. No merging or splitting needed. The blueprint in
 the plan already reflects the correct 8 tasks and 6 phases. Let me
 verify it's still accurate after refinements.

Finally time to start creating some code... while I went for a hike with my dog 🐕. As it will create a new feature branch, I feel kinda safe, but I still never pre-accept anything:

❯ /tasks:execute-blueprint 05
✳ Create feature branch for plan 05… (49s · ↑ 589 tokens)
⎿ ◼ Create feature branch for plan 05
  ◻ Create module scaffolding
  ◻ Phase 1: Foundation - Task 01
  ◻ Phase 2: Data Layer - Task 02
  ◻ Phase 3: Application Layer - Tasks 03, 05
  ◻ Phase 4: Presentation - Tasks 04, 08
  ◻ Phase 5: Integration Testing - Task 06
  ◻ Phase 6: E2E Testing - Task 07
  ◻ Post-execution validation and archival
  ◻ Implement ReadTracker service › blocked by #5 … +8 pending, 8 completed

After I came back, I noticed that this should be its own git repo and Claude forgot. But I let it continue. 

I started to see some code patterns that, even if not bad per-se, it's not the best way to do things with Drupal Core 11.3. But I don't have any specific Claude skills for Drupal development, so it's definitely good enough. Definitely not worse than what most senior Drupal devs would write. As a simple example, it didn't use services auto-wiring and auto-configuration (Drupal Canvas is going to have a PHPStan rule for this!):

2 drooplereader.read_tracker:
3 class: Drupal\drooplereader\ReadTracker
4 - arguments: ['@database']
4 + arguments: ['@database', '@datetime.time']

When it can parallelize or reduce the required context needed, it will, and even launch subagents in the background.

⏺ Phase 2: Data Layer — Executing Task 02: Views integration. Let me
launch this as a subagent since it's a substantial implementation task.

I won't go into more details of the coding process. I will say though that the SDC components it generated were pretty bad compared to what even a junior Drupal developer might write. Fair enough, front-end is not my fort, I didn't give any details about which components I expected, and how their props and slots should look like. But at this point, I was good with it. I will iterate on this project anyway, and I was willing to see something working (will it work?). Also, in retrospect, there aren't many SDCs in this site, so probably the only examples it could inspect are the SDC core tests ones.

A more worrying matter though, after it finished all the tasks is this response:

❯ Did you ever run the tests?
⏺ No, I didn't. The plan's self-validation section explicitly called
for running the tests, and the POST_EXECUTION hook required it too.
Let me run them now.

It never attempted to run the tests it created! On the other hand, I had some composer dependencies that were blocking installing a phpunit version compatible with Drupal 11.3. It figured out by itself how to resolve the dependencies hell, always asking for my confirmation.

Those tests were good, and detected some issues in the views config it generated. Claude corrected that, and after self-correcting another last issue, all tests passed.

⏺ All 28 tests green across all three levels:
Level Tests Status
Kernel (ReadTrackerTest) 7 Pass
Kernel (ReadStatusFilterTest) 4 Pass
Functional (ReaderPageTest) 4 Pass
Functional (MarkReadEndpointTest) 4 Pass
Functional (InfiniteScrollTest) 4 Pass
Functional (MarkAllAsReadTest) 3 Pass
FunctionalJavascript (ScrollReadTest) 2 Pass
Total 28 All pass

I tested the result in my browser. Astonishing. A couple of bugs here and there, but let's be honest: remember my starting prompt?

❯ /tasks:create-plan I'm planning to create a feed reader, as Google
Reader was in the time, where I can mark things as read, so it only
shows the non-read items. I want it to use the aggregator module
under the hood. Start drafting an overall plan.

That's a pretty high level definition of the requirement! Probably it doesn't even know what Google Reader was (I don't recall Claude asking to search about it). I audited this for security issues, and even if I'm not 100% satisfied with e.g. how it handles controller arguments, there are no security issues.

You can see a quick video of the result here (showcasing some of the bugs too, as not marking as read the last element of the feed):

Remote video URL
Demo of Droople Reader first iteration, purposely including bugs! 🐛

I expected this to be my weekend proof of concept. I was done by Friday 10pm, with a full MVP that I can start using immediately. It took me longer to write this blogpost than the entire process. I didn't go even close to the token limits in the two session usage limit windows this spanned. 

Should you take into account all the ethical considerations before/while/after using LLMs? Definitely. 

Can you get quick good technical results with LLMs? Also true. 

What's next? During the next weeks I plan to solve all the bugs, review all the code again, then review it again one more time, and probably release this on Drupal.org. Would you use it?

Thanks a lot to Mateu "e0ipso" for technical review of this blogpost related to my usage of AI-Task-Manager. 

Disclaimer: Opinions are definitely my own, not Mateu's or my clients as a contractor.

Tags

  • Drupal
  • Drupal planet
  • Claude Code
  • RSS Feeds
  • Droople Reader
  • LLMs
  • AI-Task-Manager
By penyaskito , 11 April, 2026
Image
Screenshot of a Dashboard including the Digest feeds using aggregator

How I keep up with changes in Drupal

I started working with Drupal 15 years ago. I had previous experience contributing to open-source projects, but PHP wasn't my strength, and to be fair, it took me a bit to understand Drupal and most of my work could be done via site building. Some months later, I decided it had to change and attended the Drupal Developer Days 2012 at Barcelona (wow! the site is online! 🤩🤩). There were coding sprints planned on the Drupal 8 Multilingual Initiative, which actually was the beginning of this blog. I blogged about my own progress every day. 

Keeping track of what was going on in an initiative was affordable, thanks to the great job Gábor Hojtsy did leading it. We had IRC, our weekly meetings... I followed the D8MI tag on Drupal.org issues, but that was a manual process. I tried every single thing I could think of for tracking the issues I actively worked on, those that I had an interest in, and those where I would like to help if I had the time. Nothing really worked well for me.

On Jul 1st, 2013 (almost 13 years ago!) I decided to subscribe by email to ALL Drupal Core issues. All, because you cannot subscribe by email to a tag. So it was all, or missing information that I cared about. This was a huge game changer.

First, the filters + labels system I developed — using different tags with associated colors in Gmail — helped me keep track of every issue I was involved in or that had certain tags.

Second, because search is amazingly fast (and works even when there are Drupal.org outages).

And third, because I have a backup of Drupal.org core issues 😜

Image
Tracking Drupal issues with Google Mail tags
Tracking Drupal.org issues with GMail

But the real game changer is seeing things passing by. As you can see, I learnt quickly that infoxication was stressful, and assumed that Inbox-Zero wasn't for me, so I learnt to ignore the number of unread mails. But just by scanning those labels I could have a big picture of what was going on because of the email subject. If something catches my attention, I open the email, learn more about the issue, and there's a high chance I will follow it.

This, plus being on drupal.org and Slack, kept me pretty well informed. So good that this has worked for me for 13 years.

But priorities change, and that an issue exists doesn't always mean that it will land. Tracking what's actually making it into the project is a different beast. I was missing this piece of information between the noise of every single issue. Reading every commit for me was out of the question.

I think it was in 2023 when I met Marco Villegas (marvil07). What a great and passionate guy. So passionate that he shared that he would go through the last commits to Drupal Core, read them, and create and share a journal summarizing what was every commit about. He spoke about it in DrupalCon Barcelona 2024, and you can check his session Following Drupal core development: Is it possible to understand every added change? on YouTube.

But what's a blogpost these days without AI? Dries himself shared recently about his new process for following Drupal projects, and how AI is helping him to summarize the information for the increasing number of projects he needs to track. This is a huge resource. 

For the last month, I often visited his Drupal Digests, and looked around the repo to read the digests, but issue numbers are not super-helpful to keep track. Dries built this to scratch his own itch, so it's highly focused on RSS feeds. And my problem is that I don't really use RSS feeds anymore. Turns out, that wasn't entirely true.

I helped build the Dashboard module for Drupal CMS. There's an aggregator module (used to be, but no longer in Core) that I had installed in this blog, and where I already had some of the feeds I care about. And I visit this blog a lot to create drafts that go nowhere. 1+1 = 2.

So my email process is now complemented by a Dashboard, using the aggregator module provided blocks.
It didn't look pretty, so I had to include some custom CSS. This is how it looks now:

Image
Screenshot of a Dashboard including the Digest feeds using aggregator
Screenshot of a Dashboard including the Digest feeds using aggregator

If you want to replicate this, you'll need to inject a CSS similar to

/*
* Aggregator block theming
*/
.block-aggregator-feed-block {
  margin-block-start: var(--space-s);

  & .item-list ul {
    margin-block-start: 0;
    margin-inline-start: 0.875em;
    list-style-position: outside;

    li {
      list-style-type: none;
      margin: 0 0 0.25em 0.25em;
      padding: 0;
      padding-block-end: var(--space-m);
      padding-inline-end: var(--space-s);
    }
  }

  & a {
    text-decoration: none;
    color: var(--color-absolutezero);

    &:hover {
      text-decoration: underline;
      text-underline-offset: 2px;
    }
  }

  .more-link {
    margin-block-end: var(--space-m);
    margin-inline-end: var(--space-l);

    a {
      text-decoration: underline;

      &:hover {
        text-decoration: none;
      }
    }
  }
}

I considered including this in the Dashboard module styles itself, but might be too much opinionated. What do you think? Edited: created issue to discuss.

And how do you keep track of what's going on in Drupal?

 

Tags

  • Drupal
  • Drupal Core
  • Drupal planet
  • Dashboard Initiative
By penyaskito , 4 April, 2026

Quarterly Contributions summary for 2026 Q1

One year ago I started tracking my own contributions to Drupal.org and posting a report on my Mastodon account. See the last quarter of 2025 report as an example. The goal is not to flex (it would be cheating given that Acquia sponsors me for working on Drupal Canvas almost full time); and this is far from being a good way of tracking contributions or your own productivity, but it's better than nothing. 

Still, it helps me evaluate where I've been focusing (out of necessity, from being nerdsniped, or just for fun), and check if I need to balance that for my "volunteer" contributions. In this last year I've been appointed as Drupal CMS committer (which includes maintainership of 20+ projects 😱😱😱), and Drupal Core subsystem maintainer for Content Translation and Language modules. So tracking where my efforts go is really helpful for self-accountability.

And to be fair, I spent more time maintaining this blog than writing, so finding a new topic that is recurrent is a good way to force me to keep it up to date 😅.

In the last 4 quarters I've been tracking this, it's been ~1 credit per day among all projects. Last quarter I had credits at 1295 issues. As of now, it's 1376. So 81 new credits, vs 93 last quarter, which is a little below 1 credit/day.

Breaking those down:

Canvas: 143 (+61)
Core: 150 (+8)
CMS*: 42 (+4)
Dashboard: 61 (+3)

I also enjoy contributing to projects like DDEV, which helps me learn Golang and clear my mind from working on the same stack. Recently I've been working on Add --project/-p flag to ddev exec command to target a named DDEV project from any directory and it was just merged! 

And I've been pushing a bit this quarter to keep the Drupal Canvas development DDEV add-on up to date, with several improvements and releases.

Hope to write again before July 1st!

Happy coding! 🎉🎉

Tags

  • contributing
  • quarterly-report
  • Drupal
  • Drupal Core
  • Drupal Canvas
  • DDEV

Pagination

  • Page 1
  • Page 2
  • Page 3
  • Page 4
  • Page 5
  • Page 6
  • Page 7
  • Page 8
  • Next page
  • Last page

Monthly archive

  • April 2026 (3)
  • August 2025 (1)
  • April 2025 (1)
  • July 2023 (1)
  • December 2021 (1)
  • May 2021 (2)
  • April 2021 (1)
  • September 2014 (1)
  • November 2012 (1)
  • September 2012 (2)
  • August 2012 (3)
  • June 2012 (6)

Recent content

Droople Reader, my new way of consuming RSS feeds
8 hours ago
How I keep up with changes in Drupal
2 days 17 hours ago
Quarterly Contributions summary for 2026 Q1
1 week 2 days ago

Recent comments

Hell yeah!
1 week 1 day ago
I would recommend taking a…
2 years 7 months ago
This looks interesting
2 years 8 months ago

Blogs I follow

  • Mateu Aguiló "e0ipso"
  • Gábor Hojtsy
  • Pedro Cambra
  • The Russian Lullaby, davidjguru
  • Can It Be All So Simple
  • Maria Arias de Reyna "Délawen"
  • Matt Glaman
  • Daniel Wehner
  • Jacob Rockowitz
  • Wim Leers
  • Dries Buytaert
  • arcturus
  • Drupal Core AI digest
  • Drupal CMS AI digest
  • Drupal Canvas AI digest
  • Drupal AI AI digest
  • Drupal Patterns AI digest
  • Trisha Gee
Syndicate

Footer

  • Drupal.org
  • LinkedIn
  • GitHub
  • Mastodon
  • Twitter
Powered by Drupal

Free 🇵🇸