a brief walkthrough of setting up a b/rb blog
so, first things first, you'll need a blog directory.
start out with:
- `breb.yml`: your config file, defining the structure of your blog and where to find things
- `pages/`: the non-serialized pages that'll be on your blog (index, etc.)
- `posts/`: the serialized posts on your blog
- `static/`: simple static files your blog will need, most notably stylesheets
the distinction between "serialized" and "nonserialized" html --
respectively, "posts" and "pages" --
is very important to keep track of in b/rb.
the actual *technical* differences between them are fairly minor,
but i'm going to be talking about each as separate entities,
so i need to call the difference to your attention
so you don't think i'm simply being sloppy with language.
# the config file
copy/paste this into the `breb.yml` file,
but on the `name` and `url` lines, fill in your information:
```yml
# basic metadata about your blog
blog:
name: "my cool new blog"
url: "https://example.com/"
serves:
# we want to serve files as-is from `static/` with the base url `/`
- as-is: /
from: static/
# similarly: we want to serve *pages*, i.e. slightly munged html, from `pages/`, on the root
- pages: /
from: pages/
# and serialized blogposts, we serve under `/posts`
- posts: /posts
# (no `from` line needed -- it's inferred to match the url, by default)
```
this sets up perhaps the simplest possible site that can reasonably be called a blog:
you'll have a few non-serialized pages, for your blog index, about page, etc.,
plus a single directory with a single index of serialized posts.
we'll go into how you might extend this later. for now:
# the other files
create a few more files, and the directories as needed:
- `static/styles.css`
```css
/* (you can of course use simpler or more complex css) */
/* (this is just reasonably simple while looking reasonably good) */
body {
display: flex;
flex-direction: column;
margin: 0;
}
header {
text-align: center;
background-color: black;
color: white;
a { color: inherit; }
}
main {
padding: 1rlh;
.title {
background-color: lightgray;
text-align: center;
padding: 0.5rlh;
* { margin: 0.25rlh; }
}
}
```
- `pages/index.html`
```html
<p>welcome to my new blog!</p>
<p>learn more <a href="/about">about it</a>.</p>
<p>here are my posts:</p>
<ul>
{% for post in posts['posts'] %}
<li>
<strong><a href="/{{ post.url }}">{{ post.title }}</a></strong>:
{{ post.subtitle }}
{% for tag in post.tags %}<span class="tag">[{{tag}}]</span>{% endfor %}
<em>(published {{ post.published[:10] }})</em>
</li>
{% endfor %}
</ul>
```
- `pages/about.html`
```html
<p>this is my new blog!</p>
<p>nothing in particular to say here, yet.</p>
```
- `posts/my-first-post.html`
```html
title = 'my first post'
subtitle = 'at least, my first with b/rb'
published = '1970-01-01T00:00:00Z'
tags = ['testing', 'please hold']
---
<p>
cool! a blogpost!
</p>
```
this sets you up with the same directory structure as the `simple` example.
if you don't want to fiddle with any files,
you can also just clone the repo and poke around in that directory,
with `cargo run --example=simple` serving it,
including refreshing live when you save files.
whether you make it by hand or just run the example,
you can serve it with `breb serve -i ./path/to/the/directory`.
on most systems you can ctrl+click the url that shows up in your terminal,
but you might need to copy/paste it into your browser instead.
**one important note**:
you don't *currently* get an index page by default for any given `posts`.
the expectation is that you'll create a page for it yourself.
serves can overlap:
a `pages: /` can have a page named `posts.html`,
which will show up at `/posts`.
you **do**, however, get an atom feed by default,
in this example at `/posts/feed.xml`.
# publishing
if you're running linux on a vm or vps, `breb serve` might not work properly --
it serves on `localhost` specifically, so other machines can't talk to it.
`breb serve` is meant to run *locally on your machine*.
so how do you publish your blog to the world?
> that said: if you have a particularly compelling reason
> to let `breb serve` be accessible from other machines,
> [please get in touch](mailto:breb+docs@genderphas.ing).
well, there's two steps to the process:
- `breb build`, to get a directory you can serve as a website
- pushing that to your webserver
the first step is relatively simple.
you were just running `breb serve -i ./path/to/blog`;
now you'll run `breb build -i ./path/to/blog -o ./path/to/output`.
the output path can be anywhere you like,
but it usually makes sense to have it be next to the blog,
e.g. my blog uses `~/genderphas.ing` and `~/genderphas.ing/gen`.
that gives you a directory that you can upload to whatever hosting you like!
there are a *huge* number of options.
here are a few that i and my friends use, in no particular order:
- `rsync` to a self-hosted website:
```sh
rsync ./path/to/output your-website.example.com:/var/www/html/
```
- pushing to [neocities](https://neocities.org) via the cli:
```
neocities push ./some/other/path
```
- a gitlab repo can be set up with "gitlab pages",
and you can run `breb build` in your ci/cd to automatically turn
your blog's source code into your published website as soon as you push.
# where do we go from here?
now that you have a blog, you hopefully also have an insatiable itch to *do something with it*.
personally, i'd recommend writing a bunch, first.
it can be tempting to hold off on publishing anything until you're "good at it",
which more or less inevitably means you never actually will.
write badly and write often,
and you'll look back and realize you don't write so badly after all.
...oh, you probably meant, like, technically.
what other features of b/rb are worth noting in this introduction,
not life advice from a stranger.
uh, well, three:
## adjacent info
there are a bunch of pieces of "adjacent info",
which is... info you can put adjacent to a `serves` list,
which will be the default for all of them.
this includes a bunch of useful bits:
- `nav`: navbar elements, rendered into the html just below the site header
```yml
nav:
# notice this is a *list*, each element is prefixed with `-`,
# but each element is also a one-element map, `name: url`
- about: /about
- contact: /contact
```
- `styles`: selecting specific stylesheets,
rather than the default of "all of them in alphabetical order".
each line here is either selecting or removing some stylesheets,
matched by typical globs.
selecting is done by just having the filename glob;
removing is done by prefixing it with `!`.
if the first row is selecting, then the list starts empty
(before the first row adds the ones it selected, of course).
the inverse is true too: if the first row is removing,
the list starts full of everything.
```yml
# select every stylesheet except foo.css
styles:
- '!foo.css'
```
```yml
# select just foo.css and bar1.css, bar2.css
styles:
- foo.css
- bar*.css
```
these can be provided directly under relevant serves,
or as adjacent info, or both.
if there are multiple sources of the same info,
the closest one to the serve wins.
e.g.:
```yml
blog: # ...the usual metadata...
nav:
- about: /about
serves:
- pages: /
from: pages/
# this has the default nav, just `about`
- posts: /posts
nav: # but posts will have an extra `index` url
- about: /about
- index: /posts
```
## translations
if you maintain a multilingual website,
it can be helpful to automatically mirror the structure between the languages.
that's relatively simple to do in b/rb:
```yml
serves:
- # whatever serves you'd like to be available
languages:
- locale: en_US # the standard locale code for the language
on: / # the url prefix this language adds to the serves' urls
from: en/ # the folder this language is built from, similarly
# plus any adjacent metadata you want to add. commonly:
nav: # a localized navbar
- about: /about # the urls are *not* autotranslated!
- contact: /contact
- locale: es_ES
on: /es/
from: es/
nav: # you can link your localized navbars to untranslated pages
- sobre: /about
- contacta: /contact
```
## multiple sections
the config file you started with has `serves` at the root,
because it's the simplified, one-section version.
here's what a slightly fuller site might look like:
```yml
blog:
name: my blog
url: https://blog.example.com/
nav:
- about: /about
- contact: /contact
- projects: /projects
sections:
# most of the website is translated
- serves:
- pages: /
from: pages/
- posts: /posts
languages:
- locale: en_US
on: /
from: en/
- locale: es_ES
on: /es/
from: es/
nav:
- sobre: /es/sobre
- contacta: /es/contacta
- proyectos (en): /projects
# project pages are currently only in english
- serves:
- pages: /projects
- git: /projects/foo
source: /home/user/projects/foo
- git: /projects/bar
source: /home/user/projects/bar
# static assets are language-agnostic
- serves:
- as-is: /
from: static/
```
you can still have top-level adjacent info, as you can see,
but then each item in `sections` can *also* have adjacent info,
etc. etc.