Baking the Perfect Website: A Deep Dive into Pie-Site-Baker

September 08, 2023 | "Güvenç Usanmaz"

Hey there, fellow web enthusiasts! 👋 Today, we're going to roll up our sleeves and dig into the delicious world of Pie-Site-Baker, our homemade static site generator. If you've ever wanted to create your own website but found other tools too complex or inflexible, you're in for a treat! 🥧

The Recipe: Understanding Pie-Site-Baker's Structure

Before we start mixing our ingredients, let's take a look at what's in our kitchen (aka the project structure):

pie-site-baker/
├── config/   └── config.yaml (our recipe card)
├── content/   ├── blog/   ├── assets/   ├── index.md   └── resume.json
├── output/ (where our baked goods end up)
├── siteforge/   ├── processors/      ├── base_processor.py      ├── blog_processor.py      ├── page_processor.py      └── resume_processor.py   ├── config.py   ├── generator.py   ├── markdown_extensions.py   └── utils.py
├── templates/   ├── base.html   ├── blog_index.html   ├── landing.html   ├── page.html   ├── post.html   └── resume.html
└── main.py (our oven switch)

Think of this structure as your well-organized kitchen. Each folder and file has its place and purpose, just like your mixing bowls, measuring cups, and cooking utensils.

The Secret Sauce: How Pie-Site-Baker Works Its Magic

Templating: The Pie Crust

At the heart of Pie-Site-Baker is our templating system, powered by Jinja2. It's like the crust of our pie – it holds everything together and gives our site its structure.

Here's a taste of how it works:

<!-- In base.html (our pie crust) -->
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}{{ config.site_name }}{% endblock %}</title>
</head>
<body>
    <nav><!-- Navigation items --></nav>
    <main>
        {% block content %}{% endblock %}
    </main>
    <footer><!-- Footer content --></footer>
</body>
</html>

<!-- In post.html (a slice of our pie) -->
{% extends "base.html" %}

{% block title %}{{ post.title }} - {{ config.site_name }}{% endblock %}

{% block content %}
<article>
    <h1>{{ post.title }}</h1>
    <div class="post-content">
        {{ post.content | safe }}
    </div>
</article>
{% endblock %}

Just like how you can fill a pie crust with different fillings, we can fill our base.html template with different content for each page. Neat, right?

Processors: The Filling Makers

Our processors are like the chefs that prepare different fillings for our pie. Each processor (BlogProcessor, PageProcessor, ResumeProcessor) knows how to handle a specific type of content.

For example, the BlogProcessor takes your Markdown blog posts and transforms them into tasty HTML:

class BlogProcessor(BaseProcessor):
    def process(self):
        blog_posts = self.get_blog_posts()
        self.generate_blog_index(blog_posts)
        self.generate_blog_posts(blog_posts)

URL Generation: The Serving Directions

Ever wondered how Pie-Site-Baker knows where to place each slice of pie on the serving platter? That's where our URL generation comes in:

def get_url(self, path):
    return '../' * self.current_depth + path.lstrip('/')

This clever little function makes sure that no matter where a page is in your site structure, it can always find its way to other pages. It's like having a map of your pie, ensuring you can always find that cherry in the corner!

Let's Get Baking: Customizing and Expanding Pie-Site-Baker

Now that we understand the basics, let's talk about how you can customize Pie-Site-Baker to make it truly your own. After all, the best pies are the ones that have your personal touch!

Adding a New Section: More Slices for Your Pie

Let's say you want to add a new "Projects" section to your website. Here's how you'd do it:

  1. Create a new processor in siteforge/processors/project_processor.py:
from .base_processor import BaseProcessor

class ProjectProcessor(BaseProcessor):
    def process(self):
        projects = self.get_projects()
        self.generate_project_index(projects)
        self.generate_project_pages(projects)

    def get_projects(self):
        # Logic to get project data
        pass

    def generate_project_index(self, projects):
        # Logic to generate project index page
        pass

    def generate_project_pages(self, projects):
        # Logic to generate individual project pages
        pass
  1. Create a new template in templates/project.html:
{% extends "base.html" %}

{% block content %}
<h1>{{ project.title }}</h1>
<p>{{ project.description }}</p>
<img src="{{ project.image }}" alt="{{ project.title }}">
<!-- Add more project details as needed -->
{% endblock %}
  1. Update siteforge/generator.py:
from siteforge.processors.project_processor import ProjectProcessor

def generate_site(config):
    # ...
    project_processor = ProjectProcessor(config)
    project_processor.process()
    # ...
  1. Add project content in content/projects/.

  2. Update config/config.yaml:

navigation:
  - name: Home
    url: index.html
  - name: Blog
    url: blog/index.html
  - name: Projects
    url: projects/index.html
  - name: Resume
    url: resume.html

Voila! You've just added a whole new section to your website. It's like adding a new flavor to your pie menu!

Styling Your Pie: Making It Look Delicious

Want to give your site a unique look? It's as easy as adjusting the frosting on your pie:

  1. Modify content/assets/css/custom.css:
body {
    font-family: 'Roboto', sans-serif;
    background-color: #f5f5f5;
}

.navbar {
    background-color: #ff6b6b;
}

.blog-post {
    background-color: white;
    border-radius: 10px;
    padding: 20px;
    margin-bottom: 20px;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
  1. Update templates/base.html to include your custom CSS:
<head>
    <!-- ... other head elements ... -->
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="{{ get_url('assets/css/custom.css') }}">
</head>

Now your site has a fresh, modern look with rounded corners, subtle shadows, and a punchy color scheme!

Adding Sprinkles: Implementing New Features

The beauty of Pie-Site-Baker is that you can keep adding features to make your site even more delightful. Here are a few ideas to get your creative juices flowing:

  1. Comment System: Integrate a comment system like Disqus into your blog posts.
  2. Search Functionality: Implement a JavaScript-based search for your static site.
  3. Image Gallery: Create a new processor and template for handling beautiful image galleries.
  4. Tag System: Add a tagging system for your blog posts and generate tag pages.
  5. RSS Feed: Generate an RSS feed for your blog to keep your readers updated.

For example, let's add a simple tag system:

  1. Update BlogProcessor to handle tags:
class BlogProcessor(BaseProcessor):
    def process(self):
        blog_posts = self.get_blog_posts()
        self.generate_blog_index(blog_posts)
        self.generate_blog_posts(blog_posts)
        self.generate_tag_pages(blog_posts)

    def generate_tag_pages(self, blog_posts):
        tags = {}
        for post in blog_posts:
            for tag in post['metadata'].get('tags', []):
                if tag not in tags:
                    tags[tag] = []
                tags[tag].append(post)

        for tag, posts in tags.items():
            self.generate_tag_page(tag, posts)

    def generate_tag_page(self, tag, posts):
        # Logic to generate a page for each tag
        pass
  1. Create a new template templates/tag.html:
{% extends "base.html" %}

{% block content %}
<h1>Posts tagged with "{{ tag }}"</h1>
<ul>
    {% for post in posts %}
    <li><a href="{{ get_url(post.url) }}">{{ post.title }}</a></li>
    {% endfor %}
</ul>
{% endblock %}

Now you have a tag system that creates pages for each tag used in your blog posts. It's like adding a sprinkle of organization to your content pie!

Serving Your Pie: Deployment

Once you've baked your perfect website, it's time to serve it to the world. Here are a few ways to do that:

  1. GitHub Pages: Perfect for project websites and personal blogs.
  2. Netlify: Offers continuous deployment from your Git repository.
  3. Amazon S3: Scalable and cost-effective for larger sites.

For example, to deploy to GitHub Pages:

  1. Create a new repository on GitHub.
  2. Push your output/ directory to the gh-pages branch of your repository.
  3. Enable GitHub Pages in your repository settings.

And just like that, your website is live and ready for the world to enjoy!

The Cherry on Top: Continuous Improvement

Remember, Pie-Site-Baker is your tool, and you can always improve it. Maybe you want to add support for custom post types, or perhaps you want to implement a caching system for faster builds. The possibilities are endless!

Here are a few advanced ideas to take your Pie-Site-Baker to the next level:

  1. Asset Pipeline: Implement a system to minify and bundle your CSS and JavaScript files.
  2. Incremental Builds: Only rebuild pages that have changed since the last build.
  3. Plugin System: Create a plugin architecture to allow for easy extension of Pie-Site-Baker's functionality.
  4. Multi-language Support: Add support for multiple languages in your static site.

Conclusion: Your Website, Your Way

And there you have it, folks! We've taken a deep dive into the world of Pie-Site-Baker, from its basic structure to advanced customizations. Remember, the key to a great website is the same as the key to a great pie – start with a solid base, fill it with quality content, and don't be afraid to experiment with new flavors!

Pie-Site-Baker gives you the tools to create a website that's truly your own. It's flexible enough to adapt to your needs, yet simple enough that you can understand and modify every part of it. Whether you're baking a simple personal blog or a multi-layered portfolio site, Pie-Site-Baker has got you covered.

So what are you waiting for? Fire up your Python oven, grab your favorite text editor, and start baking your perfect website today! And remember, in the world of web development, there's always room for dessert. Happy coding, and may your websites always be delicious! 🥧💻✨