Basic Load More AJAX Example


I am building a site using Kirby for the first time.

I am trying to load more content with Ajax but I am having trouble understanding how that works. I understand the tutorial Load more with Ajax but I haven’t found a good explanation of how the HTML is generated from the .json file.

Does anyone just have a very minimal, bare bones example of this? Something just as bare as clicking the ‘load more’ button and some content shows up on the page.

Thanks a lot for your help.

Simple example:

In your home.php template:

<div class="test" data-page="<?= $page->url() ?>"></div>
<button class="load-more">Load more</button>

In your home.json.php template:


$html = '<div>Hello again</div>';

echo json_encode($html);

In your script:


  var element = $('.test');
  var url     ='page') + '/.json';

  $('.load-more').on('click', function(e) {

    $.get(url, function(data) {





Thanks for this – it’s working.

My only follow-up question for now is the structure of formatting projects for them to be recognized in the Ajax call. Right now, I have

– alexander
– colin
– jack
– sam
– moran
– projects.txt

Within each person’s file is a file called project.txt.

When I load the projects page and click ‘load more’ it doesn’t recognize that there are any projects and it disappears because the project count is 0.

Not sure I get what you mean. Could you please post your current code?

Sure – it’s the same as from the cookbook Load More With Ajax example.

In a similar way to the small example you gave, right now I am just trying to get the program to recognize that there are projects and to load one on each click. Right now I click ‘load more’ and the button disappears because it thinks there are no projects to display.


– alexander
– – project.txt
– – picture.jpg
– beth
– – project.txt
– – picture.jpg
– jake
– – project.txt
– – picture.jpg
– james
– – project.txt
– – picture.jpg
– moran
– – project.txt
– – picture.jpg
– sam
– – project.txt
– – picture.jpg
– projects.txt


Title: Alexander Project





return function($site, $pages, $page) {

  $projects = $page->children()->visible();
  $count    = $projects->count();

  if(r::ajax() && get('offset') && get('limit')) {

    $offset = intval(get('offset'));
    $limit  = intval(get('limit'));

    $projects = $projects->offset($offset)->limit($limit);

    $more = $count > $offset + 1;

  } else {

    $offset   = 0;
    $limit    = 2;
    $projects = $projects->limit($limit);


  return compact('offset', 'limit', 'projects', 'more');



  echo js([


<li class="project">
  <a href="<?= $project->url() ?>" class="project-link">
    <?php if($image = $project->image()): ?>
    <img src="<?= $image->url() ?>" alt="<?= $image->alt_text()->html() ?>" />
    <?php endif ?>
    <div class="project-caption">
      <h2 class="project-title"><?= $project->title()->html() ?></h2>


<?php snippet('header') ?>

  <main class="main" role="main">
    <h1><?= $page->title()->html() ?></h1>
    <?= $page->text()->kirbytext() ?>

    <ul class="projects" data-page="<?= $page->url() ?>" data-limit="<?= $limit ?>">

      <?php foreach($projects as $project): ?>
      <?php snippet('project', compact('project')) ?>
      <?php endforeach ?>

    <button class="load-more">Load more</button>


<?php snippet('footer') ?>



$html = '';

foreach($projects as $project) {

  $html .= snippet('project', compact('project'), true);


$data['html'] = $html;
$data['more'] = $more;

echo json_encode($data);



  var element = $('.projects');
  var url     ='page') + '.json';
  var limit   = parseInt('limit'));
  var offset  = limit;

  $('.load-more').on('click', function(e) {

    $.get(url, {limit: limit, offset: offset}, function(data) {

      if(data.more === false) {


      offset += limit;




Do the first two projects appear on the page?


Well, then your subpages are probably not visible but you are filtering by visible.

Okay great – it’s working now. Thanks so much!