Sam Warnick

  1. About Me
  2. The Lily & Sam Show

Very Good Websites & Such

I setup a little business. A couple people wanted me to make websites for them. I’ve never built a website for someone else before before, and definitely not for money. While I’m proficient in HTML, CSS, and JS, I still feel like there is a steep learning curve for me. The first site is basically just a landing page, but there are things I haven’t had to worry so much about before, like SEO. There is definitely a lot I need to learn and understand.

Building sites for clients is definitely a new experience and challenge for me, but it’s been exciting! I’m by no means doing it full time (hardly part time at that) since I already have a great full time job. But the idea of working for myself has always appealed to me. So we’ll see what happens. So Very Good Websites & Such has been born and it’s been fun.

If you have good tips or resources on being a freelance web developer, especially part time, let me know!

Moving My Blog To GitHub Pages

My blog has moved around a lot. Most recently (and only for a couple months), I was using a self-hosted Ghost instance on DigitalOcean. As much as I liked Ghost, I was looking for something a little more hands off—I didn't love being greeted with a new update notification nearly every time I logged in, requiring me to SSH in and upgrade. I also wanted something I could manage a little more easily from my iPad. Not for any good reason; just for fun. A friend of mine has always suggested I try out GitHub Pages and Jekyll, so I decided to try it out. Now, I haven't been on GitHub pages for very long, so these are just my initial thoughts.

GitHub Pages and Jekyll

GitHub pages is a simple way to host a personal site. It just uses a repo on GitHub and Jekyll to build a static site. Basically, all you have to do is provide the files for Jekyll to build. At it's simplest, all you need is an index.html. Like they say on the GitHub Pages site:

Just edit, push, and your changes are live.

Here are a few pros and cons for me:

Pros

Cons

I enjoy being able to just push changes to my repo and not having to deal with SSH or Mosh or FTP or whatever. For me, it's by far the simplest solution I've come across. GitHub even emails you if there's a problem build the files you've just pushed.

Since Jekyll is a static site generator, it's obviously not going to be the right solution for every project, but for a simple blog, it's pretty perfect. I'm able to make page templates in HTML and the Liquid templating language, all my styling in SCSS, and write my posts in Markdown. Mostly, I followed the Jekyll docs to build my own theme. Since Jekyll sites don't come with a ton of bloat, it was quite easy to make a theme. Not a whole lot to worry about. I made a default layout and a post layout which extends the default. The default has all the <head> stuff, the header and footer, and a place to put the body content, so the other layouts I make don't have to worry about that stuff because they just extend it.

Jekyll can also have plugins. GitHub has several useful plugins whitelisted. They have some by default plugins like jekyll-optional-front-matter and jekyll-paginate in addition to some optional ones like jekyll-seo-tag and jekyll-sitemap. You just configure them in your _config.yml. Pretty cool. If you are developing locally, you need to make sure that you install them using gem install in addition to adding them to your _config.yml.

Long story short, I have found GitHub pages and Jekyll to be a simple way to make and manage my site. Win!

iPadability

I recently got an iPad Pro. Since I got it, it's been a mission of mine to figure out how to do more dev work. I'll write more about what I've found in another post, but let's just say, the iPad won't be replacing my laptop anytime soon. Despite this, GitHub Pages fits really well into an iPad workflow. iPads obviously can't run any fancy command line tools, but luckily GitHub Pages builds the Jekyll page for you! So, using the fantastic Working Copy, I can keep a local version of my repo on my iPad. For code changes, I can make small changes (usually in Textastic, push them, and boom—GitHub builds it for me and my changes are there. Yes, it's not as good as a feedback loop as running a local Jekyll server and making changes, but hey, its an iPad.

Writing posts on the iPad is even better. Jekyll has some rules for a post to be valid: the file needs to be in the format YYYY-MM-DD-post-title.md and the post needs valid frontmatter. I thought to myself, hey, that's something a computer should be able to do for me. Luckily Workflow on iOS has some pretty great automation tools. I was able to make a workflow that will take a markdown file, format it correctly for Jekyll, save it in Working Copy, commit it, and finally push it to GitHub. With a single tap, I can now do what would normally take several minutes and who knows how many taps. I don't know about you, but I think that's pretty cool. You can find it here.

So it's much easier to manage on my iPad than having to SSH into my DigitalOcean droplet to update things. Still not perfect, but with the current state of iOS, it's not too shabby.


There you have it—more than you'd ever want to know about me moving my blog to GitHub Pages! I recommend giving it a try sometime.

Making Send to Nowhere

For me, making Send To Nowhere was a fun process. I like making things. Send To Nowhere was a dumb and simple enough idea to experiment with some things. I’ll try to write a little bit about why and how I made this app. The entire project is up on GitHub.

Motivation

Life without the Interface Builder

Honestly, I didn’t miss the interface builder (IB) that much. The times I’ve used it, I feel like I was spending most of my time wrangling with constraints, and doing a lot of stuff that couldn’t be done in the IB programmatically anyways. This may be due to my inexperience with the IB. So, for me, it wasn’t a huge leap to doing everything programmatically. One of my CS classes had us doing a Java Swing interface without any IB, giving me a little experience using an UI framework programmatically. Needless to say, using Swift and UIKit is magnitudes better than using Java Swing.

Getting started with doing everything programmatically was fairly easy. I just had to delete Main.storyboard, add a couple lines to AppDelegate.swift, and change one project setting. The following code shows the necessary changes to AppDelegate.swift. Basically, you have to grab the window, instantiate your own view controller, and set it as the root.

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = YourFirstViewController()
        window?.makeKeyAndVisible()
        return true
    }

    // The rest of AppDelage.swift
}

In the project settings, you have to make sure that the project is not looking for any storyboards. Make sure that this setting is blank so that the app will not try to load a storyboard that does not exist. The app will crash if you don’t.

That was pretty much it to get going.

Actually building the interface programmatically wasn’t too difficult either. There are many ways to do this, but for me, I had a configureViews function that was called in the viewDidLoad function of my view controllers. In there, I would create all of the UI elements and constrain them to be in the right place.

func configureViews() {
    let authorLabel = UILabel()
    authorLabel.defaultStlye()
    authorLabel.text = "Created by Sam Warnick"

    let websiteButton = UIButton(type: .system)
    websiteButton.defaultStlye()
    websiteButton.setTitle("samwarnick.com", for: .normal)
    websiteButton.addTarget(self, action: #selector(STNCreditsViewController.didPressWebisteButton), for: .touchUpInside)
    websiteButton.sizeToFit()

    let twitterButton = UIButton(type: .system)
    twitterButton.defaultStlye()
    twitterButton.setTitle("@samwarnick", for: .normal)
    twitterButton.addTarget(self, action: #selector(STNCreditsViewController.didPressTwitterButton), for: .touchUpInside)
    twitterButton.sizeToFit()

    let contactLabel = UILabel()
    contactLabel.defaultStlye()
    contactLabel.font = UIFont.systemFont(ofSize: 12, weight: UIFontWeightThin)
    contactLabel.text = "Please get in touch on Twitter or my website with any feedback"

    let myDetailsStackView = UIStackView(arrangedSubviews: [authorLabel, websiteButton, twitterButton, contactLabel])
    myDetailsStackView.axis = .vertical
    myDetailsStackView.alignment = .center
    myDetailsStackView.distribution = .equalSpacing
    myDetailsStackView.spacing = 8
    myDetailsStackView.sizeToFit()

    view.addSubview(myDetailsStackView)

    myDetailsStackView.snp.makeConstraints { (make) -> Void in
        make.centerY.equalTo(view)
        make.left.equalTo(view).offset(40)
        make.right.equalTo(view).offset(-40)
    }

    view.backgroundColor = UIColor.white
}

The process was simple—make an UI element and add it as a subview. After that, you have to put it where you want using constraints. I used SnapKit for setting my constraints. It was pretty straightforward and it was easy enough to do everything I wanted. The only tricky thing was remembering to use negative numbers for the right and bottom constraints. For example, in the code above, I wanted the stack view to be 40 pts from the right edge of the view, so I had to give it an offset of -40.

I was initially a little worried about doing segues programmatically, but again, I found it to be simple enough.

let nextViewController = NextViewController()
nextViewController.modalPresentationStyle = .custom
nextViewController.modalTransitionStyle = .crossDissolve
present(nextViewController, animated: true, completion: nil)

You create an instance of the view controller you want to go to, set it up as needed (in my case I was setting the modal presentation and transition styles), and call present. These were simple segues that would present the view on top of my main view. I would just call dismiss to get rid of it. This project didn’t get me into using any navigation controllers. That’s something I want to try in the future.

I liked doing everything programmatically. Even with the IB, I was spending so much time in the code, so it makes sense to me to do everything in the code. It takes the mystery out of everything. I learned a lot about the UI elements I was using because it required spending a lot more time in the documentation. I built this app on my own, so I didn’t get the advantages of avoiding merge conflicts and such, but I can imagine how it’d be a blessing. I’d recommend giving it a try and see if it fits how you work.

Submitting to the App store

I won’t get into the details of actually submitting to the App Store (there are plenty of good tutorials), but I’ll say that I did have some trouble because I started the project before I had a real developer account. It caused some weird issues with the bundle identifier. It just took some time to work out, but I got it in the end, obviously.

I was about 80% sure my app would be rejected. One of the App Store’s criteria is:

If your app doesn’t offer much functionality or content, or only applies to a small niche market, it may not be approved.

So, I was worried that Send To Nowhere was too simple. It would have been fine if it had been rejected. I originally set out to just learn more about the whole process. But it was approved! After submitting, it took about a day and a half waiting to be reviewed and it took about 30 mins to be reviewed. It was very exciting. After that, it took about 6 hours to propagate to the App Store.

To date (about 6 days after it’s been released), Send To Nowhere has been downloaded an entire 18 times!

The Future

Luckily, Send To Nowhere is simple enough that bugs shouldn’t come up. I had a few people beta test it to get the kinks out. But we’ll see if anything pops up. It’s always possible. I have a few ideas for possible updates. So there will most likely be version 1.1. After that, who knows!

If you have any feedback, leave a comment or hit me up on Twitter.

CSS Variables?

I just found out, I think two days ago, that CSS has native "variables". I discovered this while looking through some generated code from Zeplin. CSS preprocessors like LESS and Sass give us this ability, and probably do it pretty well. I don’t really know. I haven’t used them much. For whatever reasons, I like writing plain CSS. So, without further ado, here’s an example of CSS variables:

:root {
  --lightblue: #65def1;
}

.nav-link {
  font-size: 20px;
  color: #65def1;
  color: var(--lighblue);
}

Apparently this has been around since 2014-ish, as far as I can tell. :root is a pseudo-class which, in most contexts, represents the <html> tag. More on :root can be found here. As you can see in the snippet, the variable starts with --. This sets it apart as a custom property. Custom properties can be used as variables using var()! How cool. Because the custom properties are defined in :root, they are global. There’s all sorts of inheritance things with that, for better or worse. Browser support is pretty good, with one notable exception (I’m looking at you IE…🙄). That’s why line 7 exists in the snippet. It defines the color just incase someone has no idea what to do with var(). Seems kinda redundant, but it’s not the end of the world. Just a minor/mild nuisance. It’s not CSS’s fault though. Maybe Edge supports it? I don’t know. Maybe no one will use IE again? Hopefully. I need to do more browser testing with it myself. Maybe there’s a gulp and/or webpack tool that can automatically insert that fallback line for you. I should look into that.

So that’s a brief overview of CSS variables. I think it’s pretty cool because it lessens our dependency on preprocessors and such. The end.

Hello, world!

var 😀 = "Hello, World!"

print(😀)