Getting started
This guide assumes that you have successfully installed the Blog-Core framework.
The main file
We start by creating the main.pl
file. It creates the main
module and imports some useful modules.
:- module(main, []).
:- use_module(library(arouter)).
:- use_module(library(docstore)).
:- use_module(library(bc/bc_main)).
:- use_module(library(bc/bc_view)).
:- bc_main('site.docstore').
To start SWI-Prolog with this file we issue the command
swipl -q -s main.pl -- --port=8000
in the directory where the main.pl
file is. Arguments in the command have the following meaning:
-q
helps to keep the console clean by not displaying the SWI-Prolog banner.-s
sets the main source file.--
separatesswipl
arguments from the app arguments.--port=8000
selects the TCP port for serving requests.
After running the command, information about starting the server should be displayed:
Running in development mode!
% ... <lots of messages>
% Started server at http://localhost:8000/
Front page handler
An handler generates a response to an URL path (such as /example) that is requested with a specific HTTP method (GET, POST, PUT or DELETE). The
following code has to be added into the main.pl
file:
:- route_get(/, send_front).
send_front:-
( ds_find(entry, slug=about, [About])
-> bc_view_send(views/page, _{
html: About.html,
title: About.title
})
; bc_view_not_found).
Route setup starts with a directive route_get
. This connects the path expression to a predicate that will serve requests on the
matching path(s).
The predicate to serve the request should always produce a response. In the case when the predicate fails, an error page with the status 500 is sent as a response. Same happens when the predicate throws an exception.
In the predicate we attempt to find the entry with the slug about
. This is done by running the query against the docstore database:
ds_find(entry, slug=about, [About])
As we are interested in a single entry we explicitly unify the retrieved list with a list containing a single item.
When the entry is found, we render the front page view with the entry data:
bc_view_send(views/page, _{
html: About.html,
title: About.title
})
Otherwise the not-found page is shown.
After the changes have been saved into the file, run make.
in the SWI-Prolog console. This will load the changes.
Front page view
The next step is to create a view file for displaying HTML for the front page. This is done by saving the following template in the
views
subdirectory of the project. The file name must be page.html
.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{{= title }}</title>
</head>
<body>
<h1>{{= title }}</h1>
<div>{{- html }}</div>
</body>
</html>
The template consists of HTML with placeholders (instructions) for view variables. There are two instructions for displaying variable values:
{{= x }}
will escape the value ofx
with HTML entities;{{- x }}
will not escape the value ofx
.
Templates are automatically reloaded during rendering the response in the development mode.
About entry
An entry with slug about
has to be created in order to display the front page. Navigate to
http://localhost:8000/admin and log into the admin interface. The default username and password are
admin@example.com and admin.
Locate to Blocks list and add a new entry. Enter "About" (without the quotes) into the title field and "My first Blog-Core
site" into the content field. The form should place about
automatically into the slug field.
Navigate to http://localhost:8000 after the entry is saved. You should see the page with the entered contents.
Generic page handler
Now we are ready to add a generic page handler:
:- route_get(page/Slug, send_page(Slug)).
send_page(Slug):-
( ds_find(entry, slug=Slug, [Page])
-> bc_view_send(views/page, _{
html: Page.html,
title: Page.title
})
; bc_view_not_found).
The handler is similar to the front page handler except the entry slug is extracted from the URL path. For example, the URL path
/page/hello
would trigger the handler with the slug hello
. After we add a new page under the Pages section of the admin
UI and reload our changes with make.
we should see the new page when navigating to
http://localhost:8000/page/hello.
Note that there is no constraint in the ds_find/3
query which tells to retrieve a page. Posts, pages and blocks are internally
handled in the same way. The constraint for the entry to be a page can be added by modifying the query to be:
ds_find(entry, (slug=Slug, type=page), [Page])
Static files
No handlers have to be added for serving static files. Static files can be just added to the public
directory and are served
directly. A file path /style.css
corresponds to the file public/style.css
.
However, for including links to files inside the HTML code, a special technique known as cache busting is supported. This makes it possible to add long expire headers and have the browser still reload them when the site is updated. As an example, a link to the style file can be added as
<link rel="stylesheet" href="/t-{{= cache_token }}/style.css" />
The cache_token
is a special variable provided by the framework. The prefix containing the token is automatically removed by the
dispatcher.
Save the following file as public/style.css
:
h1 {
color: green;
}
Then modify the views/page.html
to have the following in the <head>
section:
<link rel="stylesheet" href="/t-{{= cache_token }}/style.css" />
After navigating to http://localhost:8000/page/hello you should see the title in green.
Files can also be uploaded to the public
directory using the "Files" section of the administration interface.
This concludes the current guide. Read the documentation for the further information. The project containing all files created during the guide can be found in this GitHub respository.