SkillAgentSearch skills...

Vaunt

A cms with visual editor written in V that you can use to generate static sites.

Install / Use

/learn @Casper64/Vaunt
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

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.

vaunt_2

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 App struct 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

View on GitHub
GitHub Stars71
CategoryDevelopment
Updated9mo ago
Forks2

Languages

V

Security Score

92/100

Audited on Jul 1, 2025

No findings