~~Italic text~~
--Centered text--
Internal Hyperlink: [wiki_article_name]
Internal Anchor Hyperlink: [#anchor_name]
External Hyperlink: [the.website.domain]{and the link's description}
Image with alt description: #[tomodashi.com/images/bug.png]{an illustration of a bug}
>>>Blockquoted text>>>
''' Preformatted text '''
``` Lines of code ```
Getting Started
Now that you've got kiki installed, it's time to write your first page/post/article.Let's assume that you've decided to write your pages in a text editor, and you're not using kiki's wiki editor.
To create a new page, go to your /pages folder, make a copy of sample_post.bug, and name it to whatever you want.
You'll notice that the sample post is split up into two sections:
((header))
title:my first post
date:2025-01-26
author:[www.dialup.cafe/]{a little black cat}
tags: post, cats
((content))
Hi. This is my first blog post using bug markup formatting.
--This line is centered.--
~~This line is in italics~~.
**This line is in bold.**
The Header Section
The ((header)) section lets you set some important variables used in displaying the page. There are some built-in variables that you'll probably want to use on most pages, like title: and tags: and author:, but they're all entirely optional.The title: variable lets you set the page's name that will be shown in the browser's titlebar.
The date: variable lets you set the publishing date for the page. This must be written in YYYY-MM-DD format.
The author: variable lets you display the author's name on the page.
Most important, the tags: variable lets you use a comma-separated list of names that describe the post. These might be the type of page it is, or the category or theme or mood of the page.
In this case, I've added a tag called "post". This allows me to show a list of pages that all have the "post" tag.
Note: None of the variables in the header are shown on the page's content, unless you explicitly request them. They're all hidden from view by design.
(ps: Want to do more cool stuff with variables, like using them in the content area? Visit the User Guide's Dynamic Pages section for more information.)
You don't have to have the header section, but it is recommended.
The Content Section
The ((content)) section is where you'll write the actual blog post. Anything below that line will be shown on the page.You might have noticed that the first blog post uses some of the bug markup language tags, like italic, centered, and bold. Go ahead and play around with the bug formatting tags, and write your post. If you want help with using the tags, refer to the bug markup page for help writing in bug.
Done writing? Save the file, and voila - your first kiki page is now being served live on the web!
Want to learn how to write pages using the Bug markup language? Continue here.
Or go straight to the User Guide which will help you get the most out of customizing your instance.
A Quick (Re-)Programmer's Guide
For the folks who can handle a bit of simple scripting, I recommend using some of kiki's built-in variables and scripting keywords - you can learn how to use those in the User Guide.
If you're still here, it's probably because you've decided to add a feature that kiki doesn't come with out of the box, and you're happy to get your hands dirty with some PHP.
This documentation is written a bit differently than most programming documentation, which I find truly useless (don't let programmers write programming docs!). Instead of giving you a big list of function names and parameters, this is a walking tour of the source code.
It is not meant to be exhaustive, but is like a map of the territory. It helps you track down the right files to make the kinds of changes you want to make.
The files listed below are in (chronological) processing order: files at the top are processed first, and files at the end are processed last.
When a user visits your site, index.php is the browser's first and last stop. All processing begins and ends in this file.
index.php does a few important things (in this order, from top to bottom):
* Stores any information the browser has sent as "POST" or "GET" requests, like the page name, uploaded file, tag, sort style, published content and password.
* Determines whether the requested page exists, and if it does, loads that page.
* When wiki mode has been enabled, create a new page when a non-existent page has been requested.
* When a tag is requested, load and display all pages with that tag.
* Loads a 404 error page when none of the above are possible.
* Rebuilds the RSS feed every time the page is loaded.
When a page (or more than once page) is loaded by the index, it calls get_page() from /library/page.php. That's our next stop.
How Pages Are Loaded
get_page():
* gets and returns a single page, fully formatted into HTML. Calls load_page, and when that is successful, builds the page with build_page. This is really just an API function to offer a clean/simple way of using load_page().
load_page(): this is where almost all of the page parsing and loading happens. A single page is loaded into an array, and returns that array. The page loading process happens in this order:
* Begin building the page and storing the HTML output in $pageOutput. While I've tried to avoid putting any hardcoded HTML in php scripts, there is unfortunately some left in this script.
* Process any $action sent by the user. At the current time, all "commands" such as publish, edit, delete, or new are wiki-related commands. If you'd like to add new functionality to your wiki, like handling new input types, this is where you would make the modifications.
* The heavy duty work starts when data has been loaded into $page_source (usually from the page's file):
* The source data is extracted by extract_header_and_content() into an array with two keys: header and content.
* All data (variables, text) from the header is turned into $dynamic_content.
* Searches the header for any key:value pair using parse_keys(), and returns the value.
* Looks for any menuitems specified in the header, and builds a menu from them if they are present.
* Looks for the page's title in the header, and adds it to $dynamic_content.
* Gets the time and date from the file and header (if present), and adds them to $dynamic_content.
* Gets any tags present in the header, and adds them to $dynamic_content.
* Checks the header for a custom stylesheet and if present uses it as the page's stylesheet.
* Checks the header for a specified markup language, and if present uses that instead of the default markup language.
* Interpret any keywords used in either the header or content part of the page, display them inline on the page.
* When wiki mode is enabled and the page is in editing mode, load the page content into a Textarea.
* Parse any markup in the page content using the markup language currently selected, and return it as formatted HTML.
* Store the completely formatted page in a $pageData array composed of a few different keys:
* content: the written body of the page found in the source page's ((content))
* header: any key-value pairs found in the source page's ((header)).
* stylesheet: a custom stylesheet specified for this page.
* title: a custom title specified for the page.
* menu: a custom menu specified for the page.
When the page has been loaded, get_page() sends that pageData to build.php where that data is built into an HTML-formatted page using a template.
The first stop when building a page is build_page(), which is just a friendly function that calls all of the different steps of building a page, one at a time:
build_page_header(): builds the HTML header of the document, most importantly including the specified stylesheet.
build_page_content(): this is where the content key of the pageData is loaded into.
* This is where the bulk of the page formatting work happens. The document's content is inserted into $theme_content_layout which is really the file /themes/current_themename/page_layout.php. If you want to make any formatting changes to the document's HTML output, make modifications to the theme's page_layout.php.
* The menu building function is also called here.
build_page_footer(): the footer file, specified in settings.php, is turned into HTML here.
build_document_end(): closes the HTML document tags.
When the entire document has been built, it returns the whole document as a large string full of HTML.
That document HTML is returned through the (above) chain of functions, back to index.php where it is displayed on the browser.
One of kiki's most powerful features is being able to add dynamically-generated content to a page on the fly, instead of manually writing everything into the content section.
This works great when you use one of the many built-in dynamic page variables. But what if you want to use a variable of your own?
To do that, you'll have to modify page.php's load_page() function. Here's where you can make any variable you want available to a document:
For instance, say I've written a really cool function that retrieve today's forecast called get_todays_weather() which generates today's weather outlook as HTML. How do I add the output of that function to the dynamic variables list? Modiying page.php's load_page function like this:
if ($page_source)
{
... snip ...
// the $dynamic_content array is accessible when a document is parsed for variables.
// this line adds a new weather variable
$dynamic_content["weather"] = get_todays_weather();
... snip ...
}
Now, any page can use the $$weather$$ variable in the ((content)) section to show today's forecast.
The help area is split up into a few different pages:
First Time Users
The Getting Started Guide shows you how to write your first page, and how to use bug markup/formatting.
The Bug Markup Quick-Reference page shows you how to write pages using bug.
Getting the Most out of your Instance
The User Guide goes into detail with getting the most out of your kiki instance by modifying the settings, selecting a markup language, using RSS feeds, and generating dynamic pages.
The Theme and Templating Guide explains how themes work, and how you can build your own.
Programming
The Programming Guide is for the coder who wants to make modifications to how kiki works under the hood, including sketches of the program flow and tips on where to make your modifications.
Building Themes
If you're here, it's because you want to modify one of the built-in themes, or build your own.
Themes are made of a minimum of two files with the following folder structure:
/themes/themename/style.css /themes/themename/page_layout.php
style.css
* A cascading stylesheet that contains all of the formatting, fonts, colours and alignment.
* The easiest change is to modify the colours used. Colours are stored in a few variables at the top of the sheet: color_main, color_contrast, color_highlight, color_highlight2, color_shadow.
* While I've tried to avoid hardcoding named HTML elements such as <div> in the page building code, there are a few places where there are hardcoded names that your stylesheet can use:
Classes used in library/page.php
div.page_content: contains all of the page's ((content))
div.page_title: title used at the top of each page.
div.error: contains any kind of feedback to the user, such as error messages.
Classes used in library/build.php
div.footer: contains the content of footer.bug
Classes used in library/wiki.php
div.edit_form: contains the wiki's page editing form.
div.textarea: contains the textarea within the wiki's page editing form.
button.submit: buttons used on the wiki page editing form.
(I'd love to get rid of these hardcoded names, but for the time being they simplify page generation code.)
page_layout.php
When kiki builds a page, it uses the current theme's page_layout.php as a template for building each page. This is the document you'll want to modify if you want to change the layout of your page, such as moving around the menu or page content.
Work through most basic built-in layout, themes/onecolumn/page_layout.php, one chunk at a time:
<?php
// a basic one-column layout
global $current_page, $public_wiki, $theme_basename;
$htmlOutput = '<div id="container">';
if ($title)
$htmlOutput .= ' <div class="title"><span>' . $title . '</span></div>';
In the above chunk, we first define the page as a php script, and then let the script access a bunch of kiki's global variables.
$current_page: defined in /index.php, keeps track of the name of the page we're on.
$public_wiki: defined in /settings.php, checks if kiki is running in public wiki mode.
$theme_basename: defined in /library/page.php, gets the URL of the theme.
Notice how all HTML output is stored in the variable $htmlOutput: that's because when this script is done processing, it will return all of its output to the calling function build_page_content() in build.php.
Wonder where the $title variable was defined? One of php's (weird) variable scope features: it is defined in the calling function build_page_content(), and page_layout.php automatically gets access to the variable.
// add each navmenu item to the navmenu
$htmlOutput .= '<div id="navmenu">';
foreach ($menu_items as $menu_item)
{
$htmlOutput .= '<div class="navmenu-item"><span>' . $menu_item . '</span></div>';
}
$htmlOutput .= '</div>'; // close navmenu
Next, let's deal with menu display. Just like with $title, $menu_items is an array of menu items that are inherited from the function build_page_content() in build.php.
Because $menu_items is an array, we loop through each item in the list and then wrap each $menu_item in a div.
// only show the edit link when wiki mode is enabled
if ($current_page && $public_wiki)
{
$htmlOutput .= ' <div id="page_menu">';
$edit_link = build_local_permalink($current_page, "Edit Page", "edit");
$htmlOutput .= '<span class="edit_button">' . $edit_link . '</span>'; // add edit option at top of page
$htmlOutput .= ' </div>'; // close page_menu
}
The above chunk first checks if wiki mode is enabled, and if the user is visiting a page named $current_page, which is defined in index.php.
(The $current_page check is necessary, because we don't show this link in static generation mode, and when a user is viewing many pages at the same time.)
The build_local_permalink call creates an internal link to the $current_page with a name called "Edit", and an $action called "edit".
$htmlOutput .= ' <div id="content">';
$htmlOutput .= $content;
return $htmlOutput;
?>
Now, we add the $content - the actual content of the entire document. Just like with $title and $menu_items, this variable is inherited from the calling function build_page_content().
And finally, we return the generated HTML to the calling function build_page_content in build.php so it can build the rest of the document.
If you're building your own theme, I strongly suggest just copying one of the existing page_layout.php files, and modifying it to your taste.
Customizing Your kiki Instance
Getting the most out of kiki involves modifying these settings, so you can do some of these really cool things: * Have wiki pages that can only be modified by you, open to the public, or editable only with a password.
* Use an alternate markup language like Markdown.
* Use "SEO-friendly" permalink URLs like https://yoursite.com/mypage
* Generate an RSS feed.
* Generate static HTML pages.
* Use a different theme.
* Display dynamic data on pages like the post date, tags, article author, or page title.
* Show specific pages on menus.
* Show pages that have a specific tag.
* Customizing the navigation menu
Sub-Folders
Organizing your pages into sub-folders is a good idea when you're building a large site, or have dozens of pages, of different kinds, such as a blog.To create a sub-folder, just add a folder to your /pages/ folder. For example:
/homepage/pages/blog/
Now, to create a permalink to a blog post called "my first post", use the internal permalink code [blog/my_first_post], where 'blog' is the name of the sub-folder you created.
Wiki Mode
To turn on wiki mode, modify settings.php:
$public_wiki = true;
$wiki_password = "wiki"; // change this to something you'll remember
$wiki_delete_allowed = false; // set true if you want to allow page deletion from the editing interface
When wiki mode is enabled, loading an existing page will show the page with an "Edit" button on the menu.
Clicking on the Edit button launches the page editor in the browser. If $wiki_delete_allowed is enabled, a delete button allows you to delete a page.
When a page is deleted in wiki mode, its filename is changed to (some_pagename).deleted. This is a safety feature to prevent accidental deletions.
Hitting the Publish button publishes the page with any modifications made. Clicking Cancel exits editing mode.
In wiki mode, loading a non-existing page automatically creates a new empty page using the page template found in /layout/page_template.bug. When the Publish button is clicked, the new page is added to the wiki. If you click Cancel, the page is not added to the wiki.
Creating a new page is as simple as adding an internal link on any page to the new page. For example, add a [cats] link on a page. After the page has been published, load it in your browser. Click on the [cats] link, and you'll automatically enter editing mode for that page.
Using Markup Language Plug-ins
kiki supports any markup language that accepts a string (or array of lines) of markup, and returns a string of formatted HTML. Michel Fortin's PHP-Markdown and Parsedown are supported with no modifications necessary. Just unzip the file to the /plugins/ folder.To use Parsedown, modify settings.php like this:
$markup_interpreter = "parsedown";
To use PHP-Markdown, modify settings.php like this:
$markup_interpreter = "php-markdown";
If you'd like to use a different markup parser, you'll have to make modifications to utils.php. Refer to this section in utils.php for more information:
// these lines automatically run when utils.php is loaded
// and set the default interpreter according the one
// in Settings
SEO-Friendly Permalinks
Turning on SEO-friendly URLs is not something that can be done with kiki alone. This is a job done by your HTTP server, like Apache or nginx.If you're running Apache, you can modify your site's .htaccess file like so:
<VirtualHost *:80>
ServerName my-site.com
DocumentRoot /var/www/mypages
<Directory /var/www/mypages>
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
allow from all
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</Directory>
</VirtualHost>
If you're running nginx, you'll have to modify your server's configuration file. Use one of these two configurations to suit your particular directory:
## For a kiki site running in the root folder
location / {
index index.html index.htm index.php;
rewrite ^/([^\.]+)$ /index.php?page=$1$args;
}
Or:
## For a kiki site running in a subfolder called "homepages"
location /homepages/ {
index index.html index.htm index.php;
rewrite ^/homepages/([^\.]+)$ /homepages/index.php?page=$1$args;
}
Once your server has been configured properly, turn on "easy" permalinks in kiki by modifying settings.php:
$permalink_style = "easy";
With "easy" permalinks on, instead of visiting http://my-site.com/index.php?page=home, you can now visit http://my-site.com/home and kiki will find the right page automagically.
Note: both classic and easy permalinks are valid URLs when kiki is set to the "easy" permalink style.
Generating an RSS Feed
RSS feeds can be generated from all pages, or only specific pages that have a "tag" set in the header.First, turn on RSS feeds by modifying settings.php:
$rss_enabled = true;
By default, all pages are automagically added to the RSS feed. That might not be desirable if you only want specific pages added, like blog posts. To change this behaviour, modify settings.php:
$rss_tags = "post"; // now, any page that has "tag: post" will be added to the rss feed, and all others excluded.
You can include multiple tags by adding a comma between each tag.
By default, the RSS feed is generated as rss.xml in kiki's top (root) folder. You can set the path or filename to whatever you'd like in settings.php:
$rss_file = "rss.xml";
$rss_document = "rss/"; // sets the folder to the rss subdirectory
If the file and folder do not already exist, they will be automatically created when the file is generated.
Programmer's Tip:
The HTML layout of the RSS feed can be modified in rss.php to suit your specific needs, in the following functions:
build_rss_feed_header()
build_rss_feed_item()
Static Site Generation
Some folks don't like serving dynamic pages on the net, and kiki fully supports static site generation. (If you're unfamiliar with the term: it just means spitting out .html files instead of serving pages from index.php).To turn on SSG mode, modifying settings.php:
$static_generation = true;
To generate the site, you can browse to index.php and all of the .html files will be generated. Note that kiki overwrites any .html file with the same name.
Alternately, you can generate the HTML files from the command line/terminal by typing:
php /your-kiki-site-directory/index.php
By default, the .html files are generated in the "static/" folder. You can change this behaviour by modifying settings.php:
$static_pages_dir = "new_html_pages/";
Switching Themes
Themes installed in the /themes folder should follow this format:
/themename/content.php // contains a layout to show the page $title, $menu_items and $content
/themename/style.css // to style that layout
To change the theme, update settings.php:
$theme = "themename"; // note that themename MUST match the name of the folder in /themes/
If you'd like to build your own kiki theme, make a copy of one of the existing pre-installed themes and hack away at it!
Dynamic Pages
One of kiki's major features that sets it apart from many static site generators is the ability to create dynamic pages, just as you would with PHP, without all of the gnarly PHP code. There are two options that you can integrate into each page: variables and keywords.
Using Variables
kiki allows you to include all kinds of variables that are generated on-the-fly, such as the page author, publishing date, or any other kind of information you've added to the ((header)) section of a document. For instance, say that you don't want to have to type out the publishing date on every single page you write. kiki has a date variable that you can include in your document, and it will show the date specified in the header.To add a date variable, add this line to your document's ((header)) section:
date:2025-01-19 // note the date MUST be in the YYYY-MM-DD format!
Now, to show that date variable in the document, add this line to your document's ((content)) section:
This article was published on: $$date$$
See the $$ double dollar-sign tags? Wrap those around a word, and kiki will check if that variable exists. If the variable exists, it will return whatever value was stored in it.
There are many built-in kiki variables that you can use. Here's a list:
$$title$$: displays the article's title, when included in the header.
$$date$$: displays the date, when included in YYYY-MM-DD format in the header; allows for page to be sorted by date.
$$time$$: automatically displays the file's original creation time.
$$tags$$: displays any tags included (separaed by commas) in the header as hyperlinks.
$$menutitle$$: lets you use a specific title name when displaying the menuitem for this page.
You can add any variable you want by adding it to the header, and then wrapping it in $$ tags.
Want to add a custom variable not built-in to kiki, or specified in the header? Head over to the programming page to learn how.
Using Keywords
Okay, but what about displaying more complex information - such as providing a list of links to all pages? This is where kiki's keywords come in handy. This is almost like a scripting language, except that it relies on keywords like you'd see in a very simple adventure game's text parser.Let's say you want to show a list of links to all of the pages on your site. Normally you'd have to manually type in the links, and update the links as you create new pages. That's too much work. Instead, we can use the show links keyword to do the same job, and it will automatically add links to any new pages you create.
((header))
title:my pages
((content))
!{show page links}
Notice the bug tags !{ and }: these tell kiki that whatever is inside of the curlybraces is a set of keywords.
The keywords !{show page links} provides a list of links to every page on the site. Try it out!
You'll probably notice that the link descriptions are just the names of the pages. Prefer to use the page title as the link description instead? Try using !{show page links with titles}, and you'll see much nicer output.
What if these are blog posts, and you want to see their dates instead? Try !{show page links with dates} instead, and any posts with the date variable set in the header will show their date.
Showing Pages with a Specific Tag
Tags are one of the most important categorization tools that kiki offers. You might have noticed that kiki doesn't make a distinction between "blog posts" or "pages", as is common in content management systems like Wordpress.
We can make our own categories of pages by adding tags to them. For instance, this page uses tags:
((header))
title:my first blog post is about cats
date:2025-01-19
tags: post, cats
((content))
... snip ...
The above page uses two tags: post and cats. Notice that they're separated by a comma: all tags must be separated by commas. Now if you add the "post" tag to any pages that you want to show as blog posts, we can show only pages with the post tag.
To show only pages with the "post" tag, create an internal link using [?tag=post]{My Posts}.
Or, you can show the pages using the permalink URL: https://my-site.com/index.php?tag=post (classic permalinks) or https://my-site.com/?tag=post (easy permalinks)
By default, the pages are displayed in the order the files are found in their directories. If you'd like to sort them, see the next section.
Sorting Tagged Pages
Tags also support sorting the pages by date. In order for a page to be sortable by date, they must contain a date entry in the header in YYYY-MM-DD format:
((header))
title:my blog post
date:2025-01-01
... snip ...
To sort tagged pages by date using the url &sort=newest or &sort=oldest, create an internal link like:
[?tag=post&sort=newest]{My Posts Sorted from Newest To Oldest}
[?tag=post&sort=oldest]{My Posts Sorted from Oldest To Newest}
Custom Navigation Menus
By default, menu_auto_add_pages = true; and kiki automatically adds menu items for each page on your siteSecurity Considerations
You can prevent others from downloading your .bug (or .md or any other markup format files) by adding these lines to your server configuration file.nginx example:
location ~* \.(bug|md)$ {
deny all;
}
apache example:
<Files ~ "\.(bug|md)$">
Order allow,deny
Deny from all
</Files>