Vaunt
A cms with visual editor written in V that you can use to generate static sites.
Install / Use
/learn @Casper64/VauntREADME
Vaunt
[!IMPORTANT] This repository will no longer be maintained as it's built on vweb, vlang's old web module. It is not compatible with veb.
Current version: 0.2
Vaunt is a static site generator with built-in cms and visual block editor written in V.
Disclamer: Vaunt is still early software. There might be breaking changes until 0.3, but these changes will be minor.
License About the license: any website generated with Vaunt is license free since it doesn't contain any code used in this repository.

Features
- Static site generator
- easy to configure SEO (Search Engine Optimization)
- The CMS backend is optional
- Admin panel and visual block editor for content creation
- User configurable themes
- Image uploads automatically generate small, medium and large sizes
- Serve, include, import & edit markdown files
See only use static generator if you only want to convert your vweb application into a static website and don't need the admin panel.
Requirements
Make sure you have V installed. You can check out the documentation to install V.
If you have installed V make sure you have the latest version installed by running v up.
Installation
Run the following command to install Vaunt with the V package manager:
v install --git https://github.com/Casper64/vaunt
Now you are able to import Vaunt directly into your projects with import vaunt!
Database
Vaunt works with all databases in the db module.
Quick Start
Go to the Vaunt default theme to start making your website!
Themes
It is possible to create themes with Vaunt. Go to the Vaunt default theme example to get a quick start with Vaunt.
Usage
In the following example we start a basic Vaunt app.
module main
import vaunt
import vweb
import os
import db.sqlite
const (
template_dir = os.abs_path('templates') // where you want to store templates
upload_dir = os.abs_path('uploads') // where you want to store uploads
app_secret = 'my-256-bit-secret' // secret key used to generate secure hashes
)
// Your theme settings
struct Theme {}
// Base app for Vaunt which you can extend
struct App {
vweb.Context
vweb.Controller
vaunt.Util
pub:
template_dir string [vweb_global]
upload_dir string [vweb_global]
pub mut:
dev bool [vweb_global] // used by Vaunt internally
db sqlite.DB
theme Theme // Theme settings
}
fn main() {
// insert your own database
db := sqlite.connect('app.db')!
theme := Theme{}
// setup database and controllers
controllers := vaunt.init(db, template_dir, upload_dir, theme, app_secret)!
// create the app
mut app := &App{
template_dir: template_dir
upload_dir: upload_dir
db: db
controllers: controllers
}
// serve all css files from 'static' (optional)
app.handle_static('static', true)
// start the Vaunt server
vaunt.start(mut app, 8080, vaunt.GenerateSettings{})!
}
pub fn (mut app App) before_request() {
// copy database connection to Util
app.Util.db = app.db
}
pub fn (mut app App) index() vweb.Result {
content := 'Hello!'
app.s_html = content
return app.html(content)
}
Note The
Appstruct showed in the example contains all fields that must be present. They are used by Vaunt internally and your code won't work without them!
As you can see a Vaunt app is just a Vweb app with some predefined properties.
And you can add other properties and methods to App as it is a regular Vweb application.
The controllers that are generated control the api, admin panel and file uploads.
You can start the application with v watch run main.v for single files. If you have
multiple .v files you can put them in the src folder and run v watch run src.
Only static generator
You can also use Vaunt to generate a static version of your vweb app if you don't need the CMS backend.
You can still use the SEO utilities.
You only have to set app.s_html in the routes you want to generate.
See custom routes and generate for more information.
Example:
module main
import vaunt
import vweb
struct App {
vweb.Context
pub mut:
dev bool [vweb_global] // used by Vaunt internally
s_html string // used by Vaunt to generate html
}
fn main() {
mut app := &App{}
vaunt.start(mut app, 8080, vaunt.GenerateSettings{})!
}
pub fn (mut app App) index() vweb.Result {
// save html in `app.s_html` first before returning it
app.s_html = 'index'
return app.html(app.s_html)
}
Tips
If you don't want to add the Util struct to your app it's recommended to copy the
url function into your app so when generating your app .html get's added correctly
after the urls.
src/util.v
// url adds '.html' after the url if the site is being generated
// usage: `href="@{app.url('/my-page')}"`
pub fn (u &Util) url(url string) vweb.RawHtml {
if u.dev {
return '${url}'
} else {
if url.ends_with('/') {
return '${url}index.html'
}
return '${url}.html'
}
}
Admin panel
The admin panel is used to created articles via a visual editor. You can access the
admin panel by navigating to "/admin".
Create a user
To be able to access the admin you will need to create a superuser.
v run src --create-superuser
Follow the instructions after which you can log in with the created user and password.
Authentication settings
By default, the API and admin panel can only be accessed when authenticated. Vaunt includes 3 function with which you can protect your routes / app.
Only allow authenticated users, else redirect to login page:
vaunt.login_required(mut app.Context, app_secret)
Only allow authenticated users, else send HTTP 401:
login_required_401(mut app.Context, app_secret)
Or you can check if the current user is a superuser and set vaunt.Util.is_superuser
Example:
app.is_superuser = vaunt.is_superuser(mut app.Context, app_secret)
You can put either one of these functions in pub fn (mut app App) before_request()
to enable them for your whole app. Or call them in individual routes.
Authentitcation Caveats
When you generate the site all forms of authentication and middleware
(with the exception of before_request)will be skipped,
except if you return early.
Usage
The admin panel should be self-explanatory. You can press the create article button to
create a new article and get into the block editor. If you hit publish in the right nav
the html for your article will be generated.
Markdown
You can import any markdown file into Vaunt and edit it as "blocks". Just hit the
import markdown button and follow the steps.
The imported markdown is not properly sanitized! The end user is responsible.
Currently supported markdown elements
- paragraphs
- h1-h6
- Inline elements such as: links, bold/italic text, colored text
- images (the src and alt attributes will be copied)
- code blocks and inline code blocks
- non-nested lists
- blockquotes
- tables
- alerts from github's markdown notes:
> **Note**
Some raw html might slip by the basic sanitizer. If so you have to manually remove them in the editor.
Routing
When creating a route the html that is returned must be saved in app.s_html
before returning. If you forget to store the generated html in app.s_html
the generated output of the static site won't contain your html.
There are three dynamic routes that vaunt can generate html for:
Article with a category
A method with name category_article_page and dynamic route
"/articles/:category_name/:article_name". category_article_page is used to
generate the html page for each article that belongs to a category.
If you press the publish button in the admin panel the html will be generated
and outputted to "[template_dir]/articles/[category_name]/[article_name].html".
Example:
['/articles/:category_name/:article_name']
pub fn (mut app App) category_article_page(category_name string, article_name string) vweb.Result {
// save html in `app.s_html` first before returning it
app.s_html = app.category_article_html(category_name, article_name, template_dir) or {
return app.not_found()
}
return app.html(app.s_html)
}
Article without a category
A method with name article_page and dynamic route "/articles/:article_name".
article_page is used to generate the html page for each article.
If you press the publish button in the admin panel the html will be generated
and outputted to "[template_dir]/articles/[article_name].html".
Example:
['/articles/:article_name']
pub fn (mut app App) article_page(article_name string) vweb.Result {
// save html in `app.s_html` first before returning it
app.s_html = app.article_html(article_name, template_dir) or { return app.not_found() }
return app.html(app.s_html)
}
Tags
You can create tags in the admin panel and generate a html page for every tag.
Add atag_page method with dynamic route "/tags/:tag_name".
The html pages are generated in "[template_dir]/tags/[tag_name].html".
Example:
['/tags/:tag_name']
pub fn (mut app App) tag_page(tag_name string) vweb.Result {
tag := app.get_tag(tag_name) or { return app.not_found() }
content := 'tag: ${tag_name}'
// save html in `app.s_html` first before returning it
app.s_html = content
return app.html(app.s_html)
}
Custom Routes
All methods on your App that return vweb.Result are considered routes.
Vaunt will make sure to output files that are reachable the same way
as while running the dev server.
Example: A method
