Merge branch 'master' of https://git.socklab.moe/chimchooree/blessfrey-bottle
@ -0,0 +1,186 @@
|
||||
<!--240219,230508-->
|
||||
<h1>The Making of Blessfrey.me in BottlePy</h1>
|
||||
#bottlepy #css #html #python #simpletemplate #webdesign #webdev<br>
|
||||
<br>
|
||||
<p>Welcome to Blessfrey.me, my webdev playground written in BottlePy! Twice a month, God willing, I share my gamedev projects, art, Bible study, and personal reflections. Originally in <a href="https://www.php.net/docs.php">PHP</a>, Blessfrey.me now thrives on the efficiency of the <a href="https://bottlepy.org/docs/dev/">Bottle</a> Python web framework. To celebrate my website, I'll share some of my front end and back end code, as well as the evolution of my design philosophy. </p>
|
||||
|
||||
<h2>Why not use a premade blogging platform like WordPress? </h2>
|
||||
<p>Generalized blogging platforms are overkill, as Blessfrey.me is mostly a few static pages and a blog. Unused features bog down the website and pose potential security vulnerabilities. And prominent blogging platforms like WordPress are flooded with features. </p>
|
||||
<p>There's also blogging platforms like Medium or Wattpad, which throw you into giant established communities and probably give you better chances of ending up on the front page of Google. There's something dreamy about having your own corner of the internet that is unabashedly you, though. No risk of losing everything due to some policy change or business restructuring. I'm not lost in the droves of social media nor pressured to follow their trends and positioning tactics. </p>
|
||||
<p>I just do what my friends and I think is cool, and maybe some people will stumble in through an old profile link or obscure keywords on a search engine and find this odd stash of personal projects and diaries. That's how the internet was in the 90s and into the 00s, and I'm really nostalgic for that mode of life. Even if it never amounted to fame or fortune, it was full of personality and discovery. I always daydreamed about having my own corner of the internet and what I could share on there. </p>
|
||||
<p>But anyway, Blessfrey.me is a programming portfolio, so it just seems obvious to write my own frontend and backend. Taking my website from initial sketches, to Hello World, to various prototypes, to something polished enough to show my friends has been a valuable chance to learn. It's probably just as valuable if not more to demonstrate working knowledge of WordPress, Bootstrap, or other popular webdev utilities since that's what clients crave, so obviously figure out what best suits you! </p>
|
||||
|
||||
<h2>Why Bottle? </h2>
|
||||
<p>Blessfrey.me was originally written in PHP. Designing the diary underscored how prohibitively repetitive raw HTML code is. It is not merely annoying; it's completely not scalable when managing years' worth of diary entries. HTML templates are a must for decoupling diary entries from the codebase and allowing for graphical redesigns. </p>
|
||||
<p>While searching for a templating engine, I stumbled upon Bottle's SimpleTemple. Bottle not only comes with <a href="https://bottlepy.org/docs/dev/stpl.html">SimpleTemplate</a> out of the box, but it also provides a lightweight and less verbose alternative to PHP. PHP may hold a place in my heart as the lingua franca of old petsites, but frankly, <a href="https://docs.python.org/">Python</a> is more enjoyable to use. </p>
|
||||
|
||||
<h2>How does Blessfrey.me work behind the scenes? </h2>
|
||||
<h3>The strength of SimpleTemplate in building a dynamic page without all that repetitive HTML</h3>
|
||||
<p>Blessfrey.me's pages aren't a static collection of <a href="https://www.w3schools.com/html/">HTML</a> pages hosted on my server but are dynamically constructed by a Bottle script upon request. </p>
|
||||
<p>Bottle's templating engine receives content from Bottle in the form of a dictionary and populates the given template. SimpleTemplate also allows Python code to be written directly onto the template, which is how Blessfrey.me displays random styles of bullets with each refresh, populates galleries and diary snippets, and calculates the required number of pages needed for the diary's navigation links. </p>
|
||||
<p>To stay consistent without copy-pasted code, every page is based upon the frame template below. Nested templates can be inserted into other templates through <code>{{!base}}</code> to create increasingly specific templates. (By the way, double curly brackets denote variables, and exclamation marks disable escaping.) </p>
|
||||
<pre><code>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
% include('header.tpl')https://wiki.blessfrey.me/view/Blessfrey
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="grid">
|
||||
|
||||
% include('logo-bar.tpl')
|
||||
|
||||
% include('nav.tpl')
|
||||
|
||||
<div class="body-row"> </div>
|
||||
|
||||
{{!base}}
|
||||
|
||||
</div>
|
||||
|
||||
% include('footer.tpl')
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</code></pre>
|
||||
|
||||
<p>There are a few variables in the header template below (incorporated into the main template at <code>% include('header.tpl')</code>). If Bottle doesn't provide a title, it defaults to 'blessfrey.me.' SimpleTemplate also allows for seamless integration of variables into paths and URLs, such as for Blessfrey.me's stylesheet links. </p>
|
||||
|
||||
<pre><code>
|
||||
<title>{{title or 'blessfrey.me'}}</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/{{css}}.css"/>
|
||||
</code></pre>
|
||||
|
||||
<p>Maybe I could feasibly copy-and-paste the header onto a couple of static pages, but the <a href="/diary">diary</a> has an ever-expanding backlog of entries and demands a more scalable solution. SimpleTemplate allows Python code to mingle with HTML on the same template and programmatically adjust to an variable amount of content. Below is an excerpt of the diary's template that shows how Blessfrey.me builds its previews using a <code>for loop</code>. </p>
|
||||
<p>Not shown is the template's first line <code>% rebase('frame.tpl')</code>, which tells the templating engine to insert this block of content at the <code>{{!base}}</code> variable in the main template. </p>
|
||||
<p>The <code>limit</code> (max number of snippets per page) is provided by Bottle script. The <code>snippets</code>variable is a list of lists. It contains all diary snippets, which are themselves packaged as a list containing the title, content, timestamp, and so on. By iterating over snippets, any information about the article can be pulled out as needed for the HTML. </p>
|
||||
|
||||
<pre><code>
|
||||
<div class="diary-pages">
|
||||
% for s in snippets[page * limit:page * limit + limit]:
|
||||
<div class="snippet">
|
||||
<div class="snippet-title">
|
||||
<a href={{s[3]}} rel="nofollow"><h1>{{!s[0]}}</h1></a>
|
||||
</div>
|
||||
<div class="snippet-content">
|
||||
{{!s[1]}}
|
||||
</div>
|
||||
<div class="snippet-info">
|
||||
<b>{{!s[2]}}
|
||||
• <a class="social-link social-twitter"
|
||||
href='http://twitter.com/share?text={{s[4]}}
|
||||
&url=https://blessfrey.me{{s[3]}}&via=lilchimchooree'
|
||||
target="_blank">tweet</a>
|
||||
• <a class="social-link social-fb"
|
||||
href='http://www.facebook.com/share.php?u={{s[3]}}'>
|
||||
facebook</a>
|
||||
% message = "Hey,+check+out+this+post:+" + s[1] + ".,+" + s[3]
|
||||
% message = message.replace('+','\+')
|
||||
% message = re.sub('\s+?','+', message)
|
||||
% message = message.replace('\\','')
|
||||
% message = re.sub('<.*?>','', message)
|
||||
• <a class="social-link social-email"
|
||||
href='mailto:?body={{message}}'>email</a></b>
|
||||
</div>
|
||||
<div class="snippet-link">
|
||||
<a href={{s[3]}} rel="nofollow"><b>read more</b></a>
|
||||
</div>
|
||||
</div>
|
||||
% end
|
||||
</div>
|
||||
</code></pre>
|
||||
|
||||
The <code>page</code> number comes from the Bottle script shown in the next section and is derived from the URL. </p>
|
||||
|
||||
<h3>What does Bottle look like on the backend? </h3>
|
||||
<p>Bottle takes URLs and generates the corresponding web page upon request. Each URL is coupled with a method, which returns a template and a dictionary of data to be used by SimpleTemplate. Since Bottle is a Python framework, it provides access to all the Python libraries out there. </p>
|
||||
<p>By the way, the <code>page</code> is ensured to be an <code>int</code> by a line of <code>assert isinstance(variable, datatyle)</code>. </p>
|
||||
|
||||
<pre><code>
|
||||
# Start on first Diary page if no page given
|
||||
@route('/diary')
|
||||
def diary():
|
||||
return diary(0)
|
||||
|
||||
# Diary Page - Diary Template - list all articles
|
||||
@route('/diary/<page:int>')
|
||||
def diary(page):
|
||||
"""diary"""
|
||||
loc = 'diary/entries/'
|
||||
assert isinstance(page, int)
|
||||
info = {'css': 'diary', 'title': 'chimchooree\'s diary', 'year': find_year(),
|
||||
'snippets': list_snippets(gather_and_sort(loc), loc),
|
||||
'latest': list_headlines(gather_and_sort(loc)[0:5], loc),
|
||||
'tags': fill_word_cloud(curate_files(gather_files(loc)), loc),
|
||||
'total': len(curate_files(gather_files(loc))), 'limit': 8, 'cluster': 3,
|
||||
'page': page, 'category': "diary"
|
||||
}
|
||||
return template('diary.tpl', info)
|
||||
</code></pre>
|
||||
|
||||
<p>This is how the methods for specific routes are structured. Every time you visit <a href="/diary">Blessfrey.me/diary</a>, one of the above methods is called, depending on whether any query parameters follow the URL. To collect all the data the template will need, it calls a medley of Python functions to access my folder of diary entries, convert them into previews for the snippets section and headlines for the sidebar, and count the total number of entries. </p>
|
||||
|
||||
<h3>The styling is nothing fancy, just CSS </h3>
|
||||
<p>The website is styled using <a href="https://www.w3schools.com/css/default.asp">CSS</a>, heavily relying on the <a href="https://www.w3schools.com/css/css_grid.asp">CSS Grid</a> and a bit of <a href="https://www.w3schools.com/css/css3_flexbox.asp">Flexbox</a>. CSS Grids can be used inside CSS Grids, so my pages are generally blocked out, with smaller internal grids managing specific content. </p>
|
||||
|
||||
<center>
|
||||
<img src="/static/img/ent/blessfrey_website_cssgrid.png" alt="(image: CSS Grid traced over screenshot of projects page.)" width="500" height="491"><br>
|
||||
<p>My 2021 design with the RPG skillbar nav pane...cute.</p>
|
||||
</center>
|
||||
|
||||
<p>The projects page (predates the current <a href="/games">games</a> page) is an example of nested grids. Almost every page uses the yellow general layout. The content unique to the projects page is mapped out in green, with a section for the header, featured projects, and other projects. The other projects use a 2-column grid in blue to evenly space out all the little thumbnails. </p>
|
||||
<p>Some CSS code for project's general grid and the nested 'more' grid are shown below. This code is very outdated, but you can always find my current stylesheets by right-clicking and choosing your browser's equivalent of "View Page Source" and examine the structure of my grids with the Inspector. </p>
|
||||
|
||||
<pre><code>
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: auto 800px auto;
|
||||
grid-template-rows: 25px 90px repeat(2, auto);
|
||||
grid-column-gap: 0px;
|
||||
grid-row-gap: 0px;
|
||||
}
|
||||
|
||||
.featured {
|
||||
grid-area: 2 / 1 / 3 / 3;
|
||||
}
|
||||
|
||||
.featured-desc {
|
||||
color: #F9B3D7;
|
||||
font-size: 25px;
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.more {
|
||||
grid-area: 3 / 1 / 4 / 3;
|
||||
width: 800px;
|
||||
display: grid;
|
||||
grid-template-columns: auto auto;
|
||||
}
|
||||
|
||||
.more-desc {
|
||||
color: #F9B3D7;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
margin-right: 10px;
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h2>Of course, design is its own beast you'll have to figure out on your own. </h2>
|
||||
<p>As I've attempted to emulate my favorite odd blogs and coding experiments from the 90s and 00s, Blessfrey.me has used <a href="https://www.w3schools.com/html/default.asp">HTML</a>, <a href="https://www.w3schools.com/css/default.asp">CSS</a>, <a href="https://www.php.net/docs.php">PHP<a/>, <a href="https://bottlepy.org/docs/dev/">BottlePy</a>, <a href="https://bottlepy.org/docs/dev/stpl.html">SimpleTemplate</a>, <a href="https://httpd.apache.org/">Apache</a>, <a href="https://www.nginx.com/">NGINX</a>, <a href="https://www.jenkins.io/doc/book/">Jenkins</a>, <a href="https://docs.ansible.com/">Ansible</a>, my husband's LazyWiki, and maybe other stuff, who knows? I think following a dream like that is a fun way to learn more than following a stuffy textbook or sticking to rigid website makers. After all, the more personal your requirements, the more likely you'll have to figure it out on your own. </p>
|
||||
<p>It also leads you to explore all those existential questions like "What is even the point of having a website?" The evolution of the overall design and content mix reflects that journey. I began by taking heavy inspiration from the most iconic promotional Japanese websites for 00s Playstation and PSP otome games. (All are now broken with the loss of <a href="https://www.adobe.com/products/flashplayer/end-of-life.html">Adobe Flash Player</a>.) It looked cool, but what's the point when I had no playable game for Blessfrey? Over time, I slowly adjusted to what actually suited my Godot RPG dream project, Blessfrey.</p>
|
||||
<p>As I actually used my website, I yearned to include a broader range of content. It took years to shake out all my preconceived notions of what makes a cool website and all the boring, samey advice shared by online husslers. A laser-tight focus might work for businesses, but it's lame to narrow your personal showcase into a niche. I much prefer having a cute, comfy little site that accomodates anything I might make. </p>
|
||||
<p>For example, the most random thing I've integrated is my <a href="https://wiki.blessfrey.me/view/Blessfrey">Bible study notes wiki</a>. Someone at church was unable to take a class that I had attended and wished to see my notes. My notes are comprehensive but unfortunately were completely inaccessible without setting up my family's private wiki software on a Linux computer and controlling it with the terminal. With a few changes, though, everyone can see my notes at Blessfrey.me's <a href="https://wiki.blessfrey.me/view/Blessfrey">wiki</a>! It's convenient to be able to access it on my phone and adds some value for other people, so why omit it? </p>
|
||||
<p>It's pivots like that that let me get all the mileage out of my server rent and really fall in love with webdev. It took about 4 years of janky CSS and meandering purpose, but Blessfrey.me is finally something I proudly show to other people. :) </p>
|
||||
|
||||
<h2>Now you know how to make your own website! </h2>
|
||||
<p>Or you can keep using blogging platforms or social media or whatever works for you. But at least admit it's cute to build your own playground! If you really decide to, be easy on yourself and open-minded while exploring webdev. Your site won't be perfect at first, but be honest about your needs and dreams, and you'll get there! See ya. </p>
|
||||
|
||||
<br>
|
||||
Last updated February 29, 2024 <br>
|
||||
<br>
|
@ -1,67 +0,0 @@
|
||||
<!--201224,200806-->
|
||||
<h1>making of blessfrey.me</h1>
|
||||
october 15, 2020<br>
|
||||
#bottle #css #html #simpletemplate #webdesign #webdevelopment<br>
|
||||
<br>
|
||||
Blessfrey.me is a personal website I use to showcase projects and blog my process. It was originally written in PHP, but now it uses <a href="https://bottlepy.org/docs/dev/">Bottle</a>, a Python web framework. <br>
|
||||
<br>
|
||||
<h2>why not use a premade blogging platform like WordPress? </h2><br>
|
||||
Blessfrey.me's needs are fairly simple - some static pages and a blog page. Generalized blogging platforms are overkill for my purposes. I don't need support for multiple authors, comments, localization, e-commerce, and so on. Unused features bog down the website at best and contribute to security vulnerabilities at worst. <br>
|
||||
<br>
|
||||
Also, it's fun to write my own platform. I'm learning a lot as I take my website from initial sketches, to Hello World, to various prototypes, to something polished enough to show my friends. Regardless, since it can be considered my programming portfolio, it makes sense that it itself should be something I programmed. <br>
|
||||
<br>
|
||||
<h2>why Bottle? </h2><br>
|
||||
I originally wrote Blessfrey.me in PHP. I switched to Bottle after looking for a templating engine. Bottle comes with SimpleTemplate and can do everything PHP can do but faster and with less verbosity. Plus, I get to write in Python, a much more enjoyable language. <br>
|
||||
<br>
|
||||
<h2>how does blessfrey.me work? </h2><br>
|
||||
<h3>SimpleTemplate </h3><br>
|
||||
Instead of existing as a static collection of HTML pages on my server, Blessfrey.me's pages are constructed upon request by the website's Bottle script from SimpleTemplate templates. <br>
|
||||
<br>
|
||||
Every page uses the frame template pictured below, so the basic skeleton is consistent without requiring copy-pasted code. Each page is individualize through bringing in a new template within <code>{{!base}}</code>. (Double curly brackets refer to variables, and exclamation marks disable escaping.) <br>
|
||||
<br><center>
|
||||
<img src="/static/img/ent/blessfrey_website_alltemplate.png" alt="(image: basic template code.)"><br>
|
||||
</center>
|
||||
(The code can be found on <a href="https://pastebin.com/mQuGX3Xa">Pastebin</a>.) <br>
|
||||
<br>
|
||||
The header template below (brought in at <code>% include('header.tpl')</code>) has some variables, too, which are supplied by the Bottle script. If Bottle doesn't provide a title, it defaults to 'blessfrey.me.' Variables can also be used in paths and URLs. <br>
|
||||
<br><center>
|
||||
<img src="/static/img/ent/blessfrey_website_headertemplate.png" alt="(image: header template code.)" width="500" height="54"><br>
|
||||
</center>
|
||||
(The code can be found on <a href="https://pastebin.com/JcEU4xTm">Pastebin</a>.) <br>
|
||||
<br>
|
||||
You can insert Python code into the templates for dynamic pages. Below is an excerpt of the template for the diary page. This code fills the page with diary entry previews using a for loop. Not shown is the first line <code>% rebase('frame.tpl')</code>, which tells SimpleTemplate to insert this content at the <code>{{!base}}</code> variable in the frame template. <br>
|
||||
<br><center>
|
||||
<img src="/static/img/ent/blessfrey_website_snippettemplate.png" alt="(image: diary snippet code from diary template.)" width="500" height="401"><br>
|
||||
</center>
|
||||
(The code can be found on <a href="https://pastebin.com/ckEj9Bf2">Pastebin</a>.) <br>
|
||||
<br>
|
||||
The Bottle script sends the max number of snippets per page (the <code>limit</code>) and a list of lists containing all the diary snippets. It receives the page number from the URL. For the snippets that will appear on the given page, it converts the list data into HTML code to be displayed in the browser. <br>
|
||||
<br>
|
||||
<br>
|
||||
<h3>Bottle </h3><br>
|
||||
Bottle takes URLs and generates the corresponding web page upon request. Each URL is tied to a method, which returns a template and a dictionary of data to be used in the template. Since Bottle is a Python framework, you have access to all the Python libraries you need. <br>
|
||||
<br><center>
|
||||
<img src="/static/img/ent/blessfrey_website_diaryscript.png" alt="(image: Bottle script excerpt for diary routes.)" width="500" height="288"><br>
|
||||
</center>
|
||||
(The code can be found on <a href="https://pastebin.com/Bf96F9Ha">Pastebin</a>.) <br>
|
||||
<br>
|
||||
This is what the methods for specific routes look like. So every time you go to Blessfrey.me/diary, one of the above methods is called, depending on whether also you supplied an integer. To generate the page content, it calls a lot of Python functions to find my diary entries, convert them into previews for the snippets section and headlines for the sidebar, and get the current time for the footer. <br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<h3>CSS </h3><br>
|
||||
The website is styled using CSS, heavily relying on the CSS Grid and a bit of Flexbox. CSS Grids can be used inside CSS Grids, so my pages are generally blocked out, with smaller internal grids managing specific content. <br>
|
||||
<br><center>
|
||||
<img src="/static/img/ent/blessfrey_website_cssgrid.png" alt="(image: CSS Grid traced over screenshot of projects page.)" width="500" height="491"><br>
|
||||
</center>
|
||||
<br>
|
||||
The projects page is an example of nested grids. Almost every page uses the yellow general layout. The content unique to the projects page is mapped out in green, with a section for the header, featured projects, and other projects. The other projects use a 2-column grid in blue to evenly space out all the little thumbnails. <br>
|
||||
<br>
|
||||
The CSS code for project's general grid and the nested unfeatured grid are shown below.<br>
|
||||
<br><center>
|
||||
<img src="/static/img/ent/blessfrey_website_projectcss.png" alt="(image: projects css code.)"><br>
|
||||
</center>
|
||||
(The code can be found on <a href="https://pastebin.com/pVgkmT5k">Pastebin</a>, but you can always see a web page's CSS by right-clicking and viewing the source.) <br>
|
||||
<br>
|
||||
Last updated June 8, 2021 <br>
|
||||
<br>
|
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 349 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 349 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 261 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 215 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 79 KiB |