Skip to content
View in the app

A better way to browse. Learn more.

ernestdefoe.online

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
ernestdefoe.online

Extensions, themes & support for Flarum and Invision Community

Vibe coding for the community web. Report a bug, request a feature, or dig into the source — this is where the tools you use get built, in the open.

We do custom Bespoke Invision Community apps. If you have an idea for something you want then use the contact form to get in touch with us.
Knowledge base

Things that cost me a day, so they cost you none

Working notes from building Invision Community and Flarum applications. Mostly the failures that give no error at all — the ones where everything installs cleanly and quietly does the wrong thing.

92 articles

Invision Community 5

86 articles

Extensions and contracts

39

What each extension point is for, what it must declare, and what happens when it is wrong — which is usually nothing visible.

Languages and text

5

The string table, translation, and the places where text does not appear where you expected it to.

Theming, templates and forms

9

Theme hooks, CSS that survives both colour schemes, and building forms that do not throw on render.

Background work and scheduled tasks

5

The queue system, work that has to happen after the response, and jobs that finish without doing anything.

Data, settings and storage

11

The database layer, settings, tags, file storage, and backing up a live site.

AI features and expectations

5

What these features do, what they cost, and what buyers reasonably but wrongly assume they do.

Application structure and releases

11

The JSON files an application is made of, versioning and upgrade steps, and testing from the command line.

Realtime, chat and calls

1

WebSocket gateways, relays and the server-side pieces live features depend on — where "it works when I test it" and "it works for your members" are different claims.

Nothing matches that.

A Pages category created in code sends every article into a redirect loop

Create a Pages category from code, move some records into it, and every one of those records becomes unreachable. The browser reports too many redirects; the server is issuing a 301 to the same URL over and over. The category itself is fine — it lists correctly, the AdminCP shows nothing unusual, and the records are present and approved.

The cause is one column that nothing asked you to fill in: category_full_path.

Why it loops rather than 404s

Pages builds a record's canonical URL from the category's stored full path, not by walking the parent chain at request time. With the column empty, the path segment is empty, and the URL comes out with a doubled separator:

/kb//how-to-do-the-thing-r7/

Pages then does what it always does with a non-canonical URL — redirects to the canonical one. Which it rebuilds from the same empty column. Which is the same URL it just rejected. The loop is not a bug in the redirect; the redirect is working perfectly and being handed a broken destination forever.

This fails after everything appears to have worked. The category saves, the records move, the category listing renders, and the AdminCP is entirely normal. The damage only shows on the record route — so a check that stops at "the category page loads" passes while every article underneath is dead.

The fix

Write the column when you create the category. It is the parent's full path, plus a slash, plus this category's furl name — and for a top-level category it is simply the furl name:

$category->save();

\IPS\Db::i()->update( 'cms_database_categories', array(
    'category_full_path' => $parent['category_full_path'] . '/' . $slug,
), array( 'category_id=?', $category->id ) );

It has to happen after save(), because until then there is no id to update. To repair categories that already exist, walk the parent chain once and write the assembled path to each row, then clear the caches:

\IPS\Data\Store::i()->clearAll();
\IPS\Data\Cache::i()->clearAll();

How to catch it

After creating any category in code, request an actual article URL and check the redirect count, not just the status code. A loop and a healthy page both look like success if you only ever follow redirects and read the final status:

curl -s -o /dev/null -L -w '%{http_code} hops=%{num_redirects}\n' <article-url>

A healthy record answers 200 hops=0. Anything reporting dozens of hops is this.

Related

The same shape of problem — a Pages category that saves cleanly and is then quietly broken — also applies to permissions: a category with no row in core_permission_index is invisible on the front end and raises nothing at all. See Creating a Pages database and categories in code.


User Feedback

Recommended Comments

There are no comments to display.

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.