[SSS] Creating a sitemap

:  ~ 2 min read

Sitemaps are used by search engines to know what pages to crawl; they're basically a list of all the URLs available on a website. Last time we saw how to manually create an RSS feed by manually creating an XML document, and a sitemap is also just an XML document.

First, let's add the route to our droplet:

func addRoutes() -> Droplet {
	get("/sitemap.xml", handler: SitemapController.create)
	// [...]

As we saw in the previous post, we need a controller that has a method with the same signature as the handler:

struct SitemapController {

	static func create(with request: Request) throws -> Respon […]

Continue reading →

[SSS] Creating an RSS feed

:  ~ 1 min read

Back when the blog was written in Ruby, I wrote that I eventually went ahead and implemented an RSS feed, and that it was much easier than expected. Turns out I didn't even need a library to do it, it's only a matter of creating an XML document.

Sure, it might be prettier to assign properties (e.g rss.item.content = "content here") versus creating the document manually (e.g xml += <content>content here</content>), but with proper formatting, the latter can look pretty great too. Besides, printing the document, or looking at the source in a browser will be easier to track / spot bugs.

Let's start wit […]

Continue reading →

[SSS] Displaying posts and extending Queries

:  ~ 5 min read

This is a bit tricky, since my routes for posts and pages are the same, and I differentiate between the two if I can create an Int out of the lastPathComponent. I know it's not the best approach, but since URLs should be permanent, I never moved to a /page/x structure. I also kind of dislike that structure ¯\_(ツ)_/¯.

In the first post in this series, I briefly presented the Droplet extension, with a very basic addRoutes method, just to present the methods in the extension itself. Let's give it a few routes:

extension Droplet {

	func addRoutes() -> Droplet {
		get("/feed", handler: FeedController […]

Continue reading →

[SSS] PostgreSQL models

:  ~ 3 min read

Let's start by defining our Post model:

struct Post {

	let title: String
	var rawBody: String { // The original, markdown body.
		didSet {
			// For updating body, truncatedBody and readingTime automatically.
			// didSet doesn't get called on init too, sadly.
	fileprivate(set) var body: String // The html body.
	var truncatedBody: String // The html body, truncated to x chars.
	fileprivate(set) var readingTime: String
	let datetime: String // The date, in yyyy-MM-dd-HHmm format.
	let link: String // The link, created from the title, in post-title format.
	let date: String // The short […]

Continue reading →

[SSS] Setting the project up

:  ~ 2 min read

The first post in the Server Side Swift series will be about initializing the project, its structure, and configuring your Droplet. Running the vapor xcode -y command (although I always run swift build first) will download dependencies, build them, configure an Xcode project, and you will end up with a structure like this:

___ Config
   |___ secrets (optional) - This should be in your .gitignore.
   |___ production (optional)
   |_ app.json
   |_ servers.json
___ Localization - Translation files.
   |_ xx-YY.json
___ Packages - This is where Vapor installs your packages, and links them in Xcod […]

Continue reading →

Server side Swift with Vapor

I finally decided to migrate the blog from Node.js to Swift, and that's what I've been working on for the past weeks. It's been fun, and in the upcoming posts I will be writing about how it went. I will prefix them with [SSS], just like I did with [NJS]. The repo can be found here.

Hope you'll enjoy them as much as I did!

Breaking labeled scopes

:  ~ 1 min read

break is used to exit the current scope, for example a for loop:

for i in 1...10 {
	guard i < 9 else { break }
	// Code here.

But what if we have nested loops, and we want to break a specific one? Swift has us covered, with labels:

outer: for i in 1...10 {
	inner: for j in 1...10 {
		guard i < 9 else { break outer }
		guard j < 8 else { break inner }
		// Code here.

But today I found something interesting: you can label if blocks, as well:

// Works with non optional binding ifs as well.
abCheck: if let a = b() {
	guard a.condition else { break abCheck }
	// Code here.

This won't be th […]

Continue reading →

Assign if not nil; if nil, then assign

:  ~ 45 sec read

I always found Ruby's ||= operator interesting, which says (roughly) assign the right hand side to the left hand side, if the latter is nil (or false). But what about assigning the right hand side to the left hand side, if the former is not nil?

Here's my take on these two, with rather intuitive operators (if you ask me, of course):

infix operator ??= // If left is nil, then assign
func ??=<T>(lhs: inout T?, rhs: T?) {
	guard lhs == nil else { return }
	lhs = rhs

infix operator =?? // Assign if right is not nil
func =??<T>(lhs: inout T, rhs: T?) {
	guard let rhs = rhs else { return }
	lhs = rhs […]

Continue reading →

Vertical scrolling parallax

:  ~ 4 min read

If you're using WhatsApp, you probably saw the images have a small parallax effect, in the opposite scrolling direction. This gives the impression that the image is on a deeper level, and the "image container" is a window: if you climb on a chair, it's as if you lowered the window (you scrolled down), and now you can see more of the landscape below the window (it scrolled up); and crouching would have the opposite effect.

One of the biggest downsides to this, is that you need to force your image to be bigger than what the user sees: if you want to have a +/- 10px movement, you need to make it 20 […]

Continue reading →

Thinking outside of the box

:  ~ 1 min read

Recently, I stumbled upon a small problem: we have a product details controller which calls a factory method that creates a view with a few UITextViews that detect a website, a phone, and an address, respectively, but the latter was not working reliably. Said method only needs the product object to be passed in to properly create the view.

One simple solution would have been to also pass the controller as the target, and a local method as the selector, replace the UITextView with a button, set its title to the address and its target & action to the passed in params. Then, inside the product det […]

Continue reading →