aboutsummaryrefslogtreecommitdiffstats

EZCMS - a minimal and simple way to manage a website

Requirements

  • Python 3.7+

  • git (for keeping track of your site updates)

Huh/What/Why?

EZCMS (or “Easy CMS” for those of you who call that “zed” instead) is a minimal and simple way of managing content and serving static files on a website. It was mostly made for my own website which I wanted to be as simple as possible, but with some ability to easily add new pages in a template I like.

I don’t really expect many people to use this, but I hope it might be useful for someone learning to use Flask, or someone who also likes the look of websites from the 90s.

Why not just neocities or wordpress?

Neocities is awesome! You should definitely host a site there.

https://neocities.org/

It’s easy to get a simple static site going there and it’s totally free, but it lacks server side scripting as far as I know.

I used to have wordpress blog, but I got bored of maintaining it. I felt like making something from scratch might make me more invested in making an interesting site.

Quickstart

It’s recommended to run each server in it’s own virtual environment. This program uses python 3.7, so change python to either python3 or python3.7 depending on your needs. First clone this repo (with git clone, or download the zip), change into the directory, then:

$ python -m venv env
$ source env/bin/activate
$ pip install -r requirements.txt
$ python server.py

Your server will (by default) be hosted on http://127.0.0.1:5000 and have the templates/site/ directory delivered to your users when they access http://127.0.0.1:5000/site/

You should see home.html render on the root directory.

Adding Pages

To add a new page, all you need to do is add a new file (or a folder and a group of files) somewhere under one of the folders in site. This folder in particular is special since it contains the top-level folders which will be used to navigate your site, but any folders beneath will be automatically indexed.

As an exercise, add a file to the templates/site/thoughts/rants folder called myrant.html and put the following content:

<p>I don't like spam!</p>

The new page will be rendered with your navbar on top and footer on the bottom when navigated to in the rants folder HTML files will by default be rendered in page, and all other types of files (like txt) will be returned without rendering.

An important note, since these HTML files are being rendered by Flask, you can make full use of the Jinja templating language! So in other words, any template you’ve developed for flask is fully usable here–but remember it will be rendered inside the templates/base.html template. If you need to make tweaks to the navbar or footer, you’ll want to edit that file instead.

Override base template

Have a page with custom CSS, or need to get rid of the navbar entirely? No worries! Just add a ‘!’ at the end of you html file and EZCMS will interpret it as it’s own Jinja template without adding everything from the base template. Tip: if you’re just changing the CSS, you can start with the following boilerplate that I provide in base.html:

{% extends 'base.html' %}
{% block css%}
//your cool css here
{% endblock %}
{% block content %}
//your cool content here
{% endblock %}

Configuration

This program comes with a configuration file with variables to tweak the display of your site called siteconfig.py. For example, by default this program makes the navbar out of the directories in the templates/site directory, but you might want include other directories, or even external sites. Examples of how to change these options are provided in the comments on that file. Customization is also provided through the use of specific files.

Be default, the top navbar is populated by indexing and sorting the top-level templates/site/ directory. You can override this to include any directories you want in any order, so long as they exist, but it’s advised to still keep them all in the site directory to avoid confusion.

Indexing

This program uses a single master index file which is used when navigating to any directory–instead of having to put in an ‘index.html’ in each folder, or using the default apache/nginx/httpd auto-indexer. In it’s place, you can optionally put a .description file to provide a short description of what’s in the directory or a .links file

The .description file should just be a text file with no formatting. If you want to add formatting, you can edit the templates\index.html file around the {{ description }} variable (for example, you could wrap it in for italics

The .links file is a pseudo-csv file which should contain a comma separated list containing a description and a relative or absolute URL to be linked. For example this line:

About,/about

Produces the following HTML on your index page:

<li><a href="/about" target="_blank" rel="noopener noreferrer>About</a></li>

You can of course link to external sites, but you must specify the protocol (i.e. https://google.com, not google.com). Otherwise, it will be interpreted as a relative path like example.net/google.com.

Making Secret Directories and Files

This program follows the Unix convention of placing a “.” before directories and files to make them hidden. Aside from the special files mentioned above, this program will not index any file or directory with a “.” prepended–and a user will receive a 404 error if they attempt to do so.

Mimetypes

Default mime types are primarily sourced from this page with some of my own additions for common source code files (like .c or .py):

You can add your own by editing the ‘mimetypes.csv’ file in the following format:

.file_extension,type/yourcoolmimetype

Otherwise, the default mime type is application/octet-stream, which (for most browsers) triggers the browser to download the file

License

The default license type is the same as this program’s: CC0. The HTML is from Creative Commons, with some modifications I like to add. You can of course replace the HTML with your own license (or none), by editing templates/site/license.html

RSS

This app comes packaged with an auto-RSS generator that makes a feed based on the files in the site directory, presuming you use git to keep track of your files. You can omit files by adding them to the omit file from the perspective of the site dir.

For example:

thoughts/rants/dontread.txt

or for files run under ‘site’

home.html

You can either continue to use the cloned ezcms repo as your git repo and git add and git commit files added to the templates/site/ directory. Or you can make your site into a local git repo with:

$ cd ./templates/site
$ rm -rf *
$ git init
<make some files>
$ git add .
$ git commit -m "new update"

Alternatively, you can make a new git repo elsewhere and add it to the main project as a submodule.

See here for more on submodules

Other Tips

There are a few special directories linked that are needed to customize your site. First the static directory, which holds your static files like CSS templates and images. Second the raw directory, which allows the user to access files the templates/site as raw files instead of HTML. You can disable it by deleting the code under send_file_from_site or send_file_from_static in server.py.

Deploying a server

If you do actually use this for anything on the open Internet, you should NOT run this server as in the quick start, but instead use something like UWSGI as the Flask project recommends.

Refer to https://flask.palletsprojects.com/en/2.0.x/deploying/ for options, but an easy option I use is uwsgi since it’s well documented. A quickstart looks like this:

$ sudo pip install uwsgi
$ sudo mkdir /var/path/to/your-flask/
$ sudo chown www-data -R /var/path/to/your-flask
$ uwsgi -s /var/path/to/your-flask.sock --manage-script-name --mount /=server:app --virtualenv ./env

Then point your main http daemon (nginx, apache, httpd) to the socket you made.

There are examples for a nginx configuration in the uWSGI and Flask docs:

I recommend making an ini file so you can run uwsgi --ini yourini.ini without all the extra arguments. A simple ini file, which I stole from here, looks like this (your socket path will be different depending on your environment):

[uwsgi]
socket = /var/www/run/flask-main/flask-main.sock
home = env
wsgi-file = server.py
callable = app
master = true
die-on-term = true
processes = 4
logger = file:/var/www/logs/uwsgi.log

Be sure to refer to all of those links above for a full explanation.