Pyco is a simple, not very fast, flat file CMS base on Python Flask. It is design to simulation our Could Content Service, will help developers make Themes from localhost.
Pyco build with plugin supported and custom able config settings, that mean is you can also host a website with own needs, but it is not design for large portal site, so please make sure is not very big traffic.
This project NEVER testing on Windows, if you are use windows only, We are sorry.
- Make sure you have
python 3.7
or later andpip
. - Clone this github repo http://github.com/soopro/pyco.
- Make sure current branch is
master
. - Get the project root folder, run
pip install -r requirements.txt
. (you might needsudo
). - Check all install result was succeed.
- Done.
First, you have to enter the pyco folder obviously, then you can run pyco in multiple ways.
-
sh start.sh
: Run as backend. you will needsh stop.sh
to stop it, or kill the system progress manually. -
python pyco.py
: Run as develop.
You can modify the config.py
to change base settings.
Those settings below is for simulate the cloud platform settings. please do not chagne it if you want use pyco to develop a cloud base theme.
-
DEBUG
: [ bool ] Switch of debug mode. The debug mode will showing up some additional information and reload theme very request. you can also access fromcurrent_app.debug
. Defualt isTrue
. -
HOST
: [ str ] Host local ip address. Default is"0.0.0.0"
. -
PORT
: [ int ] Host port. Default is5500
. -
THEMES_DIR
: [ str ] Themes dir will be"themes"
. -
THEME_NAME
: [ str ] Theme name slug. Default is"default"
. -
UPLOADS_DIR
: [ str ] Uploads dir will be"uploads"
. -
BACKUPS_DIR
: [ str ] Backups dir will be"backups"
. -
PLUGINS_DIR
: [ str ] Plugin dir will be"plugins"
. -
BASE_URL
: [ str ] Site base url. Default is"http://localhost:5500"
. -
API_URL
: [ str ] Site api baseurl for ajax request. Default is"http://localhost:5500/restapi"
. -
THEME_URL
: [ str ] Theme url of Site. It is base onBASE_URL/STATIC_PATH/THEME_NAME
. -
UPLOADS_URL
: [ str ] uploads url of Site. default isBASE_URL/UPLOADS_DIR
. -
RES_URL
: [ str ] res url of Site. default isUPLOADS_URL/res
. Change it to online url if you need. -
PLUGINS
: [ list ] all plugins packpage name here.
Pyco supported plugins. Plugins use several hooked functions, and order by the request work flow. Some data could be customlize, you have to print out to understand attributes. Hooks such as:
-
config_loaded(config)
: While config, site date, theme_meta loaded.config
: [ dict ] read-only. includeconfig
,theme_meta
andsite_meta
.
-
request_url(request)
: While the request is confirmed.request
: [ dict ] a flask request object.
-
get_page_content(content)
: After content parsed.content
: [ dict ]content
: parsed content string.
-
get_page_meta(page_meta, redirect)
: After read page meta.page_meta
: [ dict ] All page readed attrbiutes.redirect
: [ dict ] or [ None ] redirect information. for rest api this param will be None, because there is no way to redirect.url
: [ str ] redirect url, default isNone
.
-
get_pages(pages, current_page_id)
: While query contents.pages
: all contents. Print out for attributes.
-
before_render(context, template)
: Before render (not support restapi).context
: [ dict ] context for the rendering.template
: [ dict ] template information.name
: [ str ] template name.
-
after_render(rendered)
: After render (not support restapi).rendered
: [ dict ] rendered output.output
: [ str ] the content return to browser.
Attation: Our cloud platform might not support your plugins modify.
Pyco is flat file CMS, there is no database. All content host as .md
markdown file in content
folder.
The type of contents is base on folder name. The files in the root of content
folder is static page type, call page
. Add other content types just create a folder then put .md
inside, the folder name will be slug
of this content type.
There is global content data for whole site is host in a json file in root of content
folder, call site.json
.
DO NOT USE ANY NON ASCII CODE ON FILE NAME OR DIR NAME
the markdown parse support is turn of by default, you have you turn it on if you need, otherwise only support text/html.
Global content data for whole site. some data is simulation for cloud service, if you don't know what is it, leave it alone.
-
app_id
: [ str ] simulation anapp_id
(could be encrypted). -
slug
: [ str ] site slug, simulation app slug. -
type
: [ str ] site type, simulation app type. -
content_types
: [ dict ] content types is define by folder name, but those folder name is always aslug
, given a Text title for content type here.{"page": "Pages"}
etc. -
menus
: [ dict ] define multiple menus. Followmenu
structure exactly.< menu_slug >
: [ list ] a menu.
slug
: [ str ] menu item slug.title
: [ str ] menu item title.link
: [ str ] menu link, system will generateurl
bylink
.target
: [ str ] menu link target, such as_blank
,_self
.related_type
: [ str ] menu item related content type slug.meta
: [ dict ] menu item meta, put custom data as you wish.nodes
: [ list:dict ] children menu items
-
categories
: [ dict ] All categories host here.name
: [ str ] Category name.content_types
: [ list ] list of supported content types.terms
: [ list:dict ] terms of this category.key
: [ str ] term key.name
: [ str ] term name.meta
: [ dict ] term data in meta. leave it empty if you don really need it. *class
: [ str ] term sytle class. *pic
: [ str ] pic for term display. 5parent
: [ str ] mark parent term key.
-
slots
: [ dict ] All widget slots host here.< slot_key >
:name
: [ str ] slot label.src
: [ str ] slot media src.route
: [ str ] slot route.scripts
: [ str ] slot scripts.data
: [ dict ] slot data key/value map.status
: [ str ] slot on (1) or off (1).
-
meta
: Site metatitle
: [ str ] site title, aka app title.logo
: [ str ] media src of logo.favicon
: [ str ] media src of favicon.bg
: [ dict ] media dict of site level background.contact
: [ str ] contact info.copyright
: [ str ] copyright.description
: [ str ] description text.license
: [ str ] license.locale
: [ str ] language locale.seo
: [ str ] seo codes here.analytics
: [ str ] third part analytic codes here.languages
: [ list ] languages switcher if you need.[ {"key": "zh_CN", "name":"汉语", "url":"http://....."}, {"key": "en_US", "name":"English", "url":"http://....."} ]
Example
{
"app_id": "pyco_app_id",
"slug": "pyco",
"type": "ws",
"content_types": {
"post": "Posts",
"page": "Pages"
},
"menus": {
"primary": [
{
"key": "home",
"meta": {},
"nodes": [],
"title": "Home",
"link": "/"
},
{
"key": "page",
"meta": {},
"nodes": [],
"title": "Static Page",
"link": "/page"
}
]
},
"categories": {
"name": "Category",
"content_types": ["post"],
"terms": [
{"key": "daily", "meta":{"name": "Daily"}},
{"key": "food", "meta":{"name": "Food"}},
{"key":"daily-2", "meta":{"name": "Daily"}, "parent":"daily"},
{"key":"food-2", "meta":{"name": "Food"}, "parent":"food"}
]
},
"slots": {
"event": {"script": "<div style='background:#ccc;max-width:200px;padding:16px;'>This is EVENT wdiget slot.</div>"}
},
"meta": {
"locale": "en_US",
"favicon": "",
"logo": "",
"bg": "",
"contact": "<a href='mailto:redy@imredy.com'>redy@imredy.com</a>",
"copyright": "2015 Made by Pyco.",
"description": "...",
"license": "MIT",
"title": "Sample",
"socials":[
{"key": "facebook", "name": "Facebook", "url": "#", "code": "facebook"},
{"key": "twitter", "name": "Twitter", "url": "#", "code": "twitter"}
],
"languages": [
{"key": "zh_CN", "name":"汉语", "url":"http://....."},
{"key": "en_US", "name":"English", "url":"http://....."}
]
}
}
All Content is host by .md
file put in content
folder.
Use folder to define different content types
. (folder and file name could be latin, dash -
, underscore _
or number)
The default content type is page
, every .md
in root of content
folder is page
, that's why don't have a folder named it.
Each content file .md
, separated with 2 parts, meta
and content
.
Pyco also support shortcode
for people who need write data file manually. shortcode
will generation dynamic value in your data. BUT, shortcode is only work for manual operation. When you saved data in Admin Panel, those shortcode will be replace to what they should be.
Shortcode is a str as this format [%<shortcode_name>%]
. if you really want a text exactly the same as shortcode, you must use html entity to replace the %
to %
. Remember You have to quote it while using in meta
, such as '[%uploads%]/your_pic.jpg'
because YAML can not read %
.
We provide one default shortcode:
[%uploads%]
: A shortcode for uploads url.
You can modify or add your shortcodes form config.py. but keep in your mind, too many shortcode always slow down data loading time.
Multiple line between /* ... */
is meta. you can define attribute whatever you want. It's YAML format. google it to learn YAML format.
Some attribute will be reserved:
date
: [ str ] Input date format with yyyy-mm-dd.priority
: [ int ] Priority of content, the smaller the front, default is0
.parent
: [ str ] Parent content slug, default is empty str.terms
: [ list:str ] host term's key of category, such as['term-key-1', 'term-key-2']
.tags
: [ list ] A list of str for tags.redirect
: [ str ] Redirect url.template
: [ str ] Template name.status
: [ int ] Publish status,1
- published,0
- draft, default is published.
In the .md file, the attributes's first letter is capitalized, it just for good looking, will automatice lowercase after the file is loaded.
After /* ... */
is Content, must be simple HTML with inline styles or markdown format (make sure markdown parse is turn on in config settings). Complex html with layout styles and classes is NOT recommend, those content will very difficult to maintain after sync to cloud service. Any complex content you might have to depend on theme's layout design.
Example
/*
Date: '2014-01-01'
Priority: 0
Status: 1
Terms:
- term-key-1
- term-key-2
- some-key
Template: page
Title: Static Page
Featured_img:
src: '[%uploads%]/cover_img.png'
title: 'cover image'
*/
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
<p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores consequatur aut perferendis doloribus asperiores repellat.</p>
You can create own themes for pyco with Jinja2 template language.
After your got a new theme, put intro themes folder and change settings in config.py
to activated your owen theme.
Learn Jinja2 from here Jinja2 Docs
Learn more about template context.
https://github.com/Soopro/rafiki/blob/master/jinja2_template.md