Before you can add new pages via the Panel, you have to set up a pages section in your page or site blueprint, with the status set to
Click on the "Add" button in the top right corner of a pages section. Every new page in the Panel is created as a draft first. This prevents accidental publishing of a page that is not ready yet.
Drafts are stored in a
_drafts subfolder for every page. These drafts are only accessible when you are logged in.
If you want to automatically publish new pages created via the Panel, you can set up a
page.create:after hook in your
Pages are stored as subfolders of the
/content folder. To create a new page manually, create a new folder and add a text file with the extension
.txt (default) or
.md (optional configuration setting).
A simple folder structure could look like this:
If you want to create a site with different languages using Kirby's built-in multi-lang feature, you need to add language code extensions for each language, e.g.
The naming of these content files is important, because it defines which template is used to render the content.
|Content filename||Template filename|
If there is no corresponding template, the
default.php template is used to render the page.
Each page folder is accessible via its URL, e.g. you can access the projects folder by entering the domain name followed by the UID of the folder into your browser's address bar:
https://example.com/projects. If your projects folder contains subpages, the subpage
project-a would therefore be accessible via
URLs can be modified using Kirby's router.
If you want to create a draft manually in the content folder you can create a
_drafts subfolder in the parent page folder (if it's not there yet) and inside create your draft page folder.
Pages can also be created via Kirby's API methods in a controller, template, plugin, hook etc. This is useful if you want to create pages from form data, external files (like an Excel or
.csv file), or from an external API.
The basic syntax for creating a page using the
$page->createChild() method looks like this:
The above code only works if you are either logged in and have the necessary permissions for the action, or if you authenticate the user programmatically to perform the action Learn more about permissions and impersonating users.