Trouble integrating Netlify CMS and Flask Frozen

I’ve got a personal site that I’ve deploy with Flask-Frozen, which currently saves the static site to the …/build directory. I would like to give Netlify CMS a shot and got it configured. Currently it saves all the .MD files in _posts/blog in the root. This feels a bit hackey, but in order to get it all stitched together I created an admin blueprint that served the index.html and config.yml files:

admin_bp = Blueprint('admin_bp', __name__, template_folder='templates')

# Custom Views
@admin_bp.route('/config.yml')
def config():
    return render_template('config.yml')

@admin_bp.route('/')
def admin():
    return render_template('index.html')

I’ve got a few questions.

  1. Is this blueprint approach a recommended method?

  2. Perhaps I’m misunderstanding the functionality, but I can’t seem to preview the blog article with blog/{{slug}} as in the config.yml. Is this built in or do I need to add a route perhaps to a blog blueprint?

  3. If I create a blog blueprint, is there a good way to serve the content? Right now it’s saved to the root directory. I would think it makes more sense to be saved to the blueprint’s static folder, but this wouldn’t work with Flask-Frozen. Right now it seems I should use something like this to list all the markdown files?

os.listdir('{}/_posts/blog'.format(os.getcwd()))

Again this feels a bit hackey.

Here’s my config.yml

backend:
  name: github
  repo: myusername/myrepo
  branch: master # Branch to update (optional; defaults to master)

# This line should *not* be indented
publish_mode: editorial_workflow

# This line should *not* be indented
media_folder: "/static/img/uploads" # Media files will be stored in the repo under images/uploads

collections:
  - name: "blog" # Used in routes, e.g., /admin/collections/blog
    label: "Blog" # Used in the UI
    folder: "_posts/blog" # The path to the folder where the documents are stored
    create: true # Allow users to create new documents in this collection
    preview_path: blog/{{slug}}
    slug: "{{year}}-{{month}}-{{day}}-{{slug}}" # Filename template, e.g., YYYY-MM-DD-title.md
    fields: # The fields for each document, usually in front matter
      - {label: "Layout", name: "layout", widget: "hidden", default: "blog"}
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Publish Date", name: "date", widget: "datetime"}
      - {label: "Featured Image", name: "thumbnail", widget: "image"}
      - {label: "Body", name: "body", widget: "markdown"}

Answering my own question…To get Netlify CMS and Flask-FlatPages and Flask-Frozen to play together you need to do the following:

  1. Do not put Flask-FlatPages into a Blueprint. This appears to be a known issue

  2. Set your build and pages directories to the root directory if you are following the application factory model

    app.config["FREEZER_DESTINATION"] = "../build"
    app.config["FLATPAGES_AUTO_RELOAD"] = True
    app.config["FLATPAGES_EXTENSION"] = ".md"
    app.config["FLATPAGES_ROOT"] = "../pages"
  1. Serve your Netlify CMS config.yml and index.html in a blueprint or as you like
admin_bp = Blueprint('admin_bp', __name__, template_folder='templates')

# Custom Views
@admin_bp.route('/config.yml')
def config():
    return render_template('config.yml')

@admin_bp.route('/')
def admin():
    return render_template('index.html')
  1. Create a /posts directory in your config.yml

folder: "posts"

  1. Shuttle newly created files from Netlify CMS to your Flask-FlatPages folder via freeze.py and modify the markdown, because otherwise you’ll get errors. See here.
import os
from flask_frozen import Freezer
from app import create_app

app = create_app()
freezer = Freezer(app)

if __name__ == '__main__':
    pages = os.listdir('pages')
    for post in os.listdir('posts'):
        if post not in pages:
            # Read in the file
            with open('{}/posts/{}'.format(os.getcwd(), post), 'r') as f:
                filedata = f.readlines()

                with open('{}/pages/{}'.format(os.getcwd(), post), 'w') as f:
                    for n, line in enumerate(filedata):
                        # Need to remove the first line if it's ---
                        if n == 0:
                            line = line.replace('---\n', '')
                        # All --- get replaced with empty spaces but we keep the \n
                        line = line.replace('---', '')
                        f.write(line)
    freezer.freeze()

Wow, you’re fast :slight_smile: Thank you for following up with the solution!

1 Like