Content Negotiation Plugin


i am currently writing a little Plugin which determines the device-type by request headers.
I want to achieve different templates and content-files for each device-type.

I tried to write my own Response and Template Component as descriped here.

I tried to get a different content-page by simply changing the page’s root property:

use Kirby\Component\Response;
class ContentNegotiationResponse extends Response {

   public function make($response) {
      $response->content()->root() // "/htdocs/content/1-home/home.en.txt";

      // is this possible?

      $response->content()->root = "/htdocs/content/1-home/home.en.desktop.txt";
      return $this->kirby->render($responsePage);

It doesn’t seem to have any effect even though a debug shows the correct value.
I guess that the read on the content file happens earlier, but i was not able to find it.

Is there a way i can achieve my plans or is this not possible via kirby at the moment?

Same Problem exists for changing the template. I am able to change it, but the Content-File doesn’t change.

Many thanks!

Since you can’t have multiple text files in a page folder, this does not really make sense? If anything, I’d try to switch to different content folders completely.

As it says in the documentation, the response class is at the end of the page creation process. So it is not the right place to switch to different content. It is, after all, the template that has to read the information from the content files in the first place. Only after that, the response is sent to the browser.

(Personally, I’m not a friend of different content for different devices (and it is not even reliable) but that’s a completely different story and I guess you have your reasons)

Are you designing for a very specific device for some reason? is this a Kiosk style site (like an ipad glued to a wall in a shop for customer use)?

I cant really think of another good reason to serve specific content to specific devices… and even thats not a good reason.

Whats your use case?

I agree with @jimbobrjames here. Device sniffing is usually a bad strategy which gets back at you later with a vengeance.

If it’s purely “layout”, try responsive design (CSS).

The layout is one thing. But different content is even more annoying. I really hate those websites that don’t give you the full experience on their mobile sites. It’s always just that bit missing for which you are visiting the website in the first place :scream:.

But let’s wait and see…

1 Like

Since you can’t have multiple text files in a page folder […]

How about the language files?
I thought about like this:


Anyways the mobile markup differs completely from the desktop markup.
The website is coded mobile first and is completely responsive (to get back to @bvdputte 's answer)

I also considered to have a second page content/home-desktop with another blueprint, another template etc, but i doesn’t seem to be a good idea, is it?

I don’t want to change the home-url obviously.
And i also would love to avoid a redirect.

So why do you need mobile specific content then? If it works already across devices?

Yes, you can have language files and you can have file meta files but nothing on top of that. You will get issues in the Panel if you add additional files, anyway.

Maybe you can switch to different content folders based on the request in a site.php, have never tried that.

I still don’t understand the use case for different content files.

I agree with @texnixe here: 1 URL should at least show the same information independent of which device you use.

If you would like to display different content, at least show your user a popup or something where they can choose to be redirected (to a different URL where the “other kind of information” lives).

Okay, after sleeping for solid 8 hours, i totally got the nonsense of creating multiple content files for the same page :smiley:
I don’t want the user to load the mobile-page first and then load the desktop page after clicking on any kind of interaction.

I know that recent tablets can have high resolutions where it might be wise to show the “desktop” page.

if(device == "mobile" && resolition >= "hd") { 

So you guys suggest creating two different pages and internally redirect to the other page before data gets send to the user?

domain.tld/en/home -> domain.tld/en/home-desktop

(I normally don’t create different markup, but this project (this customer) requires it to do so.)

The easiest way would be to use the same content but different markup. You can then use snippets together with mobile detect to define which snippet to use. If you really, really want different content on top of that, then the user should at least have an option to switch to another version.

Still trying to understand the use case of your client and why it would be necessary (other than the client wants it like this)

Client is always king, but it makes sense in this case.
So you would rather blow up the blueprint than making a different page?
I could imagine to use a plugin like kirby-tabs-field and name the tabs “mobile” and “desktop” for example. I could also think of “shared” (like title and SEO…), “mobile”, “desktop”.
Should be really self-explanatory for the customer.

Thanks for your thoughts and feedback!

It would at least be easier to maintain and probably avoid having to repeat stuff.

But of course, as @bvdputte already mentioned, different content under the same URL is at least questionable, especially from a SEO perspective (user uses Google search, but the page delivered to him depending on the device, does not contain the desired content). Maybe you can use routes or parameters to solve this problem.

Another option would be to use different domains with a multi-site setup.