Search by

chatixy / kirby-chatixy

JanchaLV

Chatixy AI support agent for Kirby - site-wide install with no template changes.

Package info

github.com/Devoflex/kirby-chatixy

Homepage

Issues

Type:kirby-plugin

pkg:composer/chatixy/kirby-chatixy

Statistics

Installs: 7

Dependents: 0

Suggesters: 0

Stars: 0

v1.0.2 2026-08-19 20:15 UTC

This package is auto-updated.

Last update: 2026-08-19 20:16:33 UTC


README

Adds the Chatixy AI support agent to every rendered HTML page of a Kirby site. Install it, put your widget key in site/config/config.php, done. No template changes, no snippet to include, no js() call to add.

Requirements

Kirby 4 and 5
PHP 8.0+ (composer.json requires "php": ">=8.0")
Composer optional - the plugin loads its own classes when dropped in by hand

Install

Composer (recommended)

composer require chatixy/kirby-chatixy

Manual

Unzip the package into site/plugins/chatixy/ in your Kirby project, so that index.php sits at site/plugins/chatixy/index.php. The plugin require_onces its own two classes, so it works with no Composer autoloading at all.

Configure

Add the widget key to site/config/config.php. The exact option keys are chatixy.chatixy.widgetKey and chatixy.chatixy.enabled - Kirby namespaces plugin options as <vendor>.<plugin>.<option>, and this plugin registers itself as chatixy/chatixy:

<?php

return [
    'chatixy.chatixy.widgetKey' => 'a1b2c3d4...', // 64-hex key from your Chatixy dashboard, Install tab
    'chatixy.chatixy.enabled'   => true,          // optional, defaults to true
];

The key option accepts any of the three shapes the dashboard hands out:

  • the bare 64-character key,
  • <key>.js,
  • the whole <script src="https://chatixy.com/source/<key>.js" async></script> snippet.

The key is extracted from whatever you paste. Anything that does not contain a 64-hex key - including leaving the option out entirely - injects nothing at all rather than emitting a broken tag.

Set chatixy.chatixy.enabled to false to switch the support agent off without deleting the key. The check is a strict comparison against boolean true, so give it a real boolean; any other value counts as off.

No Chatixy account yet? Start at https://chatixy.com/register.

What it does

On every rendered HTML page it splices one tag in before the closing </body>:

<script src="https://chatixy.com/source/<key>.js?platform=kirby" async></script>

That is the whole payload. Nothing is added to <head>, no CSS, no extra requests from the server side.

The injection point is Kirby's page.render:after hook, which is handed the finished document and uses whatever it returns as the response body. That is what makes site-wide injection possible from a third-party plugin: your templates and snippets never have to cooperate.

What it rewrites, and what it leaves alone

The rewrite is deliberately total - for every input it returns either a correctly modified document or the original string unchanged:

Situation Behaviour
Content type is not html (JSON, XML, txt) returned byte-identical
Widget key missing, or not a 64-hex key injects nothing
Document has no </body> returned unchanged, never appended to
The loader for this key is already on the page returned unchanged, no second tag

The content-type gate matters most: Kirby serves JSON and XML representations (sitemap.xml, a feed, any .json.php template) through the very same hook, and appending a <script> to those would produce an unparseable payload. The gate runs before anything else, so a </body> inside a JSON string cannot trigger a splice.

The </body> search takes the last occurrence, so an escaped &lt;/body&gt; inside a code sample on the page cannot win over the real end of the document. Idempotence is keyed on the loader path rather than on a marker attribute, so a snippet someone pasted into a template by hand counts as "already present" too - exactly one support agent per page, ever.

Security: the origin is pinned

The widget key is public; the host is not configurable. There is no host option and no constant to override, because the stored host would build a first-party <script src> on every page of the site - i.e. site-wide stored XSS if it could be influenced, and config.php is a plain PHP file that a deploy pipeline or a stray include can write. ChatixyKey::sanitizeHost() accepts only an https origin whose host is chatixy.com or a subdomain of it, and returns the canonical origin for anything else. The pattern is anchored at both ends and only grows the host to the left of a literal dot, so evilchatixy.com, chatixy.com.evil.example, chatixy.com@evil.example and http://chatixy.com are all rejected. The finished src is HTML-escaped into the attribute on top of that.

Support

MIT licensed. See LICENSE.