A Hopper is “a curated list of source URLs on a topic, plus a scheduled brief from them”. This guide walks through setting one up end-to-end, from creating the Hopper to seeing the first article published unattended.

Hopper is a Premium-tier feature. Trial and Standard tiers see the menu hidden. This guide assumes you're on Premium or Enterprise.


The Hopper concept

A Hopper has three moving parts:

1. A topic + watch source

Name, description, keywords. Plus a watch: a Search query, an RSS feed URL, or a fixed URL set. The watch is what gets harvested when you click Generate / Refresh candidates.

2. A curated list of sources

The Candidates tab. Each harvested URL is fetched and verified — the page body has to actually mention the words from the search snippet, or the row is marked Bad. You curate: Mark good / Mark bad / Delete. The Good rows are the Hopper's source list.

3. A cadence

Manual (Run Now from the tab), or daily / 3x weekly / 2x weekly / weekly with a time of day in your site timezone. Each cadence cycle produces ONE brief whose sources are every Good URL.

What the Hopper produces is briefs — one brief per cycle. The article-gen pipeline then runs on each brief the same way it runs on a one-off. Optional Auto-generate and Auto-publish settings make the whole loop unattended.


Step 1 — Create a Hopper

  1. Go to Components > Article Generator > Hoppers and click New.
  2. Topic tab — fill in:
    • Name — the editorial label, e.g. “UK politics — Andy Burnham”.
    • Description — a short topic frame the AI uses when synthesising the brief title. Keep it crisp.
    • Keywords — comma-separated. Inherited by every brief this Hopper emits.
    • Always-include source URLs — URLs that ride on every emitted brief alongside whatever the watch finds. Leave empty for most cases.
    • Authoritative sources for this topic — per-Hopper authoritative-domain hints (e.g. bbc.co.uk, nature.com). Sub-domains match. Used to prefer publisher-grade results in the candidate cluster step.
  3. Editorial Defaults tab — tone, reading level, target word count, content structure, citation mode, banner icon, banner theme. These ride on every brief the Hopper emits, so you set them once.
  4. Production tab — the watch + cadence:
    • What to watch — Search query / RSS feed / URL set.
    • Watch value — the actual query / feed URL / URL list.
      • Search query: the words you'd type into Google. Hopper expands this internally with “latest news” / “this week” time-bias variants, plus a Serper news-endpoint variant if Serper is your provider.
      • RSS feed: a single http(s):// URL. RSS 2.0 and Atom 1.0 both supported.
      • URL set: one URL per line, up to 20. Each URL becomes one candidate.
    • Cadence — Manual, Daily, 3x weekly, 2x weekly, or Weekly. Manual fires only from the Run Now button on the Candidates tab; the rest are driven by the scheduled task.
    • Time of day — shown when cadence is non-manual. Site-timezone HH:MM at which the cadence fires. Daily fires AT that time each day; weekly variants use it as a not-before floor on the gap.
    • Articles per run — left as 1 for the simplified Hopper model.
    • Monthly cap — soft self-imposed ceiling on briefs per month. 0 = unlimited (your tier's monthly article cap still applies).
    • Approval modeManual = emitted briefs land as drafts for your review; Auto = published immediately as drafts ready for the tick pipeline.
    • Auto-generate articles — off by default. See Auto-generate & auto-publish below.
    • Final article state — shown when Auto-generate is on. Draft (you review before publishing) or Published (live immediately).
  5. Click Save & Close. The Hopper appears in the list.
If you pick a non-manual cadence and the scheduled task isn't set up yet, the form shows a yellow warning card at the top of the Topic tab with a one-click link to System > Scheduled Tasks > New. Easier to do it before you save the Hopper, but you can come back to it any time.

Step 2 — Generate & curate candidates

Open the Hopper you just created and switch to the Candidates tab.

Generate the first batch

On a brand-new Hopper the tab shows a centred “No candidates yet” card with a Generate candidates button. Click it. What happens behind the scenes:

  1. Harvest — the watch type is dispatched. Search queries hit your configured search provider (Serper / Tavily / Google); RSS feeds are fetched and parsed; URL sets are fetched directly. Search queries also try a Serper news endpoint variant for journalist sources.
  2. Dedupe — URLs are deduped by host+path so the same article doesn't enter twice.
  3. Inline verification — each candidate URL is fetched (5s timeout per URL, 45s overall budget) and the body checked. The verifier requires the page to actually load, be long enough to be a real article, and contain at least 2 keywords drawn from the search title+snippet. URLs that fail are marked Bad. URLs whose verification timed out are marked Unverified.
  4. Persist — rows land in the Candidates tab already badged Good / Bad / Unverified.

The Run Now message after harvest tells you the breakdown: e.g. “Ran 1 Hopper(s) — 21 new candidate(s) found, 1 brief(s) emitted. (3 source(s) dropped by inline verifier — see the Candidates tab.)”

Curate the list

Each row carries a Status badge:

  • Good — in the source list. Every Run Now / scheduled run uses this URL as a source.
  • Bad — excluded. Verifier dropped it (or admin marked it Bad). The row stays so you can audit.
  • Unverified — harvest budget ran out before checking. Click Verify on the toolbar to clear the residue.

Toolbar buttons:

  • Run Now — produce ONE brief from the current Good list. See the next section.
  • Refresh candidates — harvest again. Duplicates skip on signature; new URLs land verified.
  • Create brief from selected sources — tick rows then click. Literal selection, no filter. One brief with exactly the URLs you ticked as sources.
  • Always include — promotes the URLs of selected rows to the Hopper's default-sources list, so every future emitted brief inherits them.
  • Mark good / Mark bad — admin override on the verifier verdict. Use when you know the URL is good but the verifier was over-strict (or vice-versa).
  • Delete — hard delete of the row. Confirmation appears inline (Joomla framework dialog — no browser modals). The URL signature is kept, so a future Refresh could rediscover the URL.
  • Verify (N) — runs the verifier across Unverified rows. Visible only when there are unverified rows to act on.

Click row titles to open the source URL in a new tab. Hover the snippet for the full text.


Step 3 — Run Now: the first brief

When you have at least one Good row, click Run Now on the Candidates tab.

The Hopper:

  1. Loads every Good row's URL.
  2. Calls the AI to synthesise a title, topic statement, and keyword list from the cluster.
  3. Creates ONE brief whose sources field includes those URLs plus the Hopper's Always-include source URLs.
  4. Stamps the Hopper's last_run so the cadence doesn't fire again immediately.
  5. Redirects you to the new brief's edit screen.

From there, click Generate Article on the brief's toolbar to run the article-gen pipeline. The pipeline researches across all the source URLs and writes a piece that cross-references them — not a paraphrase of any single source.

If Run Now reports an empty pool — the message breaks down the row counts. Common causes:
  • All rows are Unverified — click Verify first.
  • All rows are Bad — use Mark good on any you trust, or refresh candidates with a better watch value.
  • The Hopper has just been created and you haven't generated candidates yet.

Step 4 — Cadence & time of day

Manual cadence (the default) is fine for one-off topics. For ongoing coverage, set a cadence and a time of day.

Cadence options

CadenceMinimum gapRuns per 7d
Daily 23 hours 7
3x weekly 55 hours 3
2x weekly 83 hours 2
Weekly 167 hours 1

How the time of day works

The time-of-day field is the “earliest the Hopper becomes eligible to fire today”. The scheduled task checks each Hopper on every tick:

  1. If today's site-timezone clock hasn't reached the configured HH:MM, the Hopper isn't due. Wait.
  2. Once the time of day has passed AND the last run is older than the cadence's minimum gap, the Hopper fires on that tick.

So a Hopper set to Daily at 02:00:

  • The 01:00 cron tick: not due (haven't reached today's 02:00 target yet).
  • The 02:00 cron tick: due (we're at the target and last run was ≥23h ago). Fires.
  • The 02:05 cron tick: not due (just ran, <23h gap).

If your cron runs less frequently than the time-of-day target — say once daily at 05:00 — the 02:00 Hopper still fires at 05:00 (it's the next tick after the target). The cadence drift problem of pure gap-based scheduling is gone, but you do still need the scheduled task to be running often enough to actually hit your target window.


Step 5 — Scheduled task setup

The unified Article Generator scheduled task drives every Hopper's cadence (plus on-demand batch jobs and the unattended generation phases). Create it once and leave it running.

Create the task

  1. Go to System > Scheduled Tasks > New.
  2. Pick task type Article Generator.
  3. Give it a name (e.g. “Article Generator”).
  4. On the Execution Rule tab, choose Interval, in minutes, set to 5. This is the recommended cadence: it keeps the Hopper time-of-day accurate to within 5 minutes, and the auto-generate phase ticks the article-gen pipeline forward 20 briefs per run.
  5. On the Options tab, set Status to Enabled.
  6. Save.

What the task does on each tick

  1. Hopper discovery (30s budget) — runs every Hopper whose cadence is due. Calls produceBriefs; new briefs land as drafts (or as state=1 if the Hopper's Approval mode is Auto).
  2. Auto-generation (90s budget, max 20 briefs) — for briefs whose Hopper has Auto-generate articles on, ticks the article-gen pipeline forward one step. The same step machine the browser drives, headless. A brief that takes 5 ticks to finish will progress one step per scheduled tick.
  3. Auto-publish (30s budget) — briefs that finished generation with Final article state = Published get their Joomla article flipped to state=1.
  4. Batch queue (30s budget) — services on-demand jobs from the Generate All Steps button.
Upgrade note (3.5.56). If you had any of the older task types — artigen.batch_queue, artigen.news_beat, or artigen.hopper_sweep — delete them and create one with the new Article Generator type. The old type strings don't resolve any more.

Logs

Each task's log lives at administrator/logs/task_{id}.log.php. Phase-level events also mirror to administrator/logs/com_artigen.error.php. A healthy run looks like:

2026-06-25T02:05:01+00:00  INFO  task9  Running task#09 'Article Generator'.
2026-06-25T02:05:01+00:00  INFO  task9  Task> Hopper #1 "AI ethics watch": 4 source(s) used, 1 brief(s) emitted
2026-06-25T02:05:01+00:00  INFO  task9  Task> Hopper discovery phase: 3 due, ran 1, skipped 2 (not yet due)
2026-06-25T02:05:02+00:00  INFO  task9  Task> Auto-generation phase: ticked 1 brief(s), 0 completed, 0 failed
2026-06-25T02:05:02+00:00  INFO  task9  Task> Auto-publish phase — no completed briefs awaiting publish
2026-06-25T02:05:02+00:00  INFO  task9  Task> Batch queue phase — no pending batch jobs
2026-06-25T02:05:02+00:00  INFO  task9  Successfully finished task#09 in 0.14 seconds.

Step 6 — Auto-generate & auto-publish (optional)

If you want the loop fully unattended, switch on the two automation knobs on the Hopper edit form (Production tab):

  • Auto-generate articles — when on, briefs this Hopper emits are picked up by the scheduled task's auto-generation phase. Each cron tick advances a brief one step. A typical article finishes in 5–7 ticks (5 to 35 minutes wall-clock at the recommended 5-minute cadence).
  • Final article state
    • Draft — article generates fully but stays unpublished. You review and click Publish in Joomla's article editor. Recommended for new Hoppers.
    • Published — article goes live as soon as the pipeline completes. Use only when you trust the Hopper's source curation completely; the article never gets a human review pass.

Briefs inherit the Hopper's auto_publish_state at emit time, so changing the Hopper's setting only affects briefs emitted from that point on. Previously-emitted briefs keep whatever was set when they were created.

Recommended flow for a new Hopper: start with Auto-generate OFF and Approval mode = Manual. Run the Hopper a few cycles by hand from the Candidates tab, review the briefs and articles, refine the source list. Once the output is consistently good, flip Auto-generate ON and pick Draft or Published.

Troubleshooting

Three things have to be true:

  1. The Article Generator scheduled task exists, is enabled, and is set to run at least as often as the Hopper's Time of day requires.
  2. The Hopper's Time of day is in your site timezone (the value you typed in the field). If your scheduled task only runs once a day at, say, 09:00, a Hopper set to fire at 02:00 will fire at 09:00 — not 02:00.
  3. The Hopper has at least one Good candidate row. Run Now and the cadence both use the same Good-rows pool.

Pre-3.5.66 Hoppers used pure gap-based scheduling (24h since last run), which silently drifted each day. If you upgraded from earlier, the migration set every Hopper's Time of day to 02:00; edit and change as needed.

3.5.66's cadence_time column was VARCHAR(5) but browsers (Safari for one) submit <input type="time"> as HH:MM:SS. Upgrade to 3.5.67 or later — the column widens to VARCHAR(8) automatically via the migration + postflight ensure helper.

Common causes:

  • Search query Hoppers — no search provider configured. Check Components > Article Generator > Options > Search Provider. Serper is the recommended provider.
  • Search query Hoppers — the query is too narrow or the configured Excluded source domains blocklist is stripping every result. Check com_artigen.error.php for per-variant log lines.
  • RSS feed Hoppers — the feed URL returns HTML or a non-XML body. The verifier surfaces “RSS XML parse failed”.
  • URL set Hoppers — URLs aren't http(s):// prefixed, or the watch_value is blank.

The verifier requires the fetched body to actually contain words from the search snippet. If every candidate fails, the search engine is returning low-quality results that don't match what they're titled (parasite SEO, cached spam). Refine the search query, switch search provider, or use Mark good manually on URLs you trust.

Check, in order:

  1. The Hopper has Auto-generate articles set to On.
  2. The brief was emitted AFTER you flipped Auto-generate on (it's inherited at emit time, not retroactively).
  3. The brief's pipeline_state is idle or running. Open the brief and check the Status stepper — if it's failed or cancelled, the auto phase skips it. Click Regenerate to reset.
  4. The scheduled task is running. Check the task's last-run timestamp on System > Scheduled Tasks.

The brief's inherited auto_publish_state needs to be published AND its pipeline_state needs to be completed. Open the brief and check both. Briefs emitted before you set Final article state to Published won't auto-publish — manually publish them in Joomla's article editor or regenerate to inherit the new value.

Full documentation index: Article Generator documentation. Changelog: artigen-changelog.html.

Licences, trademarks, source code licences and attributions

928uk® is a trademark of Multizone Limited, registered in the UK. Multizone and this site is not affiliated with or endorsed by The Joomla! Project™. Any products and services provided through this site are not supported or warrantied by The Joomla! Project or Open Source Matters, Inc. Use of the Joomla!® name, symbol, logo and related trademarks is permitted under a limited licence granted by Open Source Matters, Inc. AdMob™, AdSense™, AdWords™, Android™, Chrome OS™, Chromebook™, Chrome™, DART™, Flutter™, Firebase™, Firestore™, Fuchsia™, Gmail™, Google Maps™, Google Pixel™, Google Play™, Pixelbook Go™, and Pixel™ and other trademarks listed at the Google Brand Resource center are trademarks of Google LLC and this site is not endorsed by or affiliated with Google in any way. Apple and the Apple logo are trademarks of Apple Inc., registered in the U.S. and other countries. App Store is a service mark of Apple Inc. The OSI logo trademark is the trademark of Open Source Initiative. Any other product or company names may be trademarks™ or registered® trademarks of their respective holders. Use of these trademarks in articles here does not apply affiliation or endorsement by any of them.

Where the source code is published here on multizone.co.uk or on our GitHub by Angus Fox, Multizone Limited it is licenced according to the open source practice for the project concerned.

BSD 3-Clause "New" or "Revised" Licence
Original source code for mobile apps are licenced using the same licence as the one used by "The Flutter Authors". This Licence, the BSD 3-Clause "New" or "Revised" Licence (bsd-3-clause) is a permissive licence with a clause that prohibits others from using the name of the project or its contributors to promote derived products without written consent.
GNU General Public Licence v3.0 or later
Original source code for Joomla! published here on multizone.co.uk by Angus Fox, Multizone Limited is licenced using the GNU General Public Licence. This Licence, the GNU General Public Licence Version 3 or later (gpl-3.0+) is the most widely used free software licence and has a strong copyleft requirement. When distributing derived works, the source code of the work must be made available under the same licence.

Please respect the licences and dont use the name of this site or our company to promote derived products without written consent. I mean, why would you? You're not us!

Amazon Associate
As an Amazon Associate we earn from qualifying purchases.
Logo
Our Logo Image is by Freepik. We chose it because its an M and also the letter A twice - and that represents us.
Graphics
Our images representing user experience and interface design are from Freepik here and here and here and here and here.