32-bit and 64-bit, what’s the difference?

Okay. Let’s clear this up once and for all, you nerds.

Distinction discussion

’32-bit’ and ’64-bit’ are adjectives that describe computer programs that target a specific version of the x86 instruction set architecture.

Okay, some definitions, I understand.

  • An instruction set architecture is a set of commands (opcodes, if you will) that tell specifically what thing a CPU chip should do.
  • x86 is a type of ISA. It is designed by Intel and AMD.

ISAs exists so that even if, for example, Intel and AMD manufacture different types of CPU chips, the programs that target the specific ISA they support would still be able to run in all those chips.

  • x86 is a family in general of ISAs that are supported by a number of CPU chips.
  • x86-64 is a specific version of x86 that is supported by 64-bit CPU chips.

64-bit here means that the memory is made available to consumers (programs) in blocks of 64 bits. That is, when you store an integer in a 64-bit chip, it has to be 64 bits long. The same analogy applies with 32-bit chips and 16-bit chips, which you might not have heard of, is a thing.

Programming nerds, discussion ends here. English nerds, the next section is for you.

Grammar and spelling points regarding x86 architectures

  • “64-bit” and “32-bit” are compound adjectives, so they should always have a hyphen in them. “Bit” should also be singular. All of these are wrong, please don’t do these:
    • “my 64 bit program”
    • “my 64bit program”
    • “Windows XP 64 bits”
    • “64-bits”
  • x86 is commonly used together with non-64-bit applications. x86-64 or, equivalently, amd64, is used together with 64-bit applications. ‘x64′ is just a thing popularized by Microsoft so they would look cool: they won’t. Please stop referring to x86-64 as such.

Miscellaneous

  • You will see applications distributed in either x86, amd64, or ia64. “ia64” is used to refer to the 64-bit Itanium (that is, not x86) ISA.

Definitely Not Dominion: migration from Dominion guide

Definitely Not Dominion is a new game mode in League of Legends based on Dominion. In this guide, I’ll lay out what you have to do in order to win this mode. I’ll assume prior knowledge with Dominion, so bear with me.

Layout

The Crystal Scar in this map has been changed. The starting points are the same as in Dominion, but the Quarry and the Boneyard capture points have been replaced by fountain-style towers that cannot be captured by the opponent. The bottom path between the Quarry and the Boneyard has been closed off, as well as nearby paths, up until the center of the map. The path that minions take is now linear, around the top of the map. There are more, but I’ll discuss these later.

There are three main points to know about this mode, but I have split them according to importance:

Primary objectives

There are three primary objectives in this mode.

  1. Capture and defend the Windmill. The Windmill is now the farthest location between the two teams’ starting points. There are three capture points, namely the Refinery, the Windmill, and the Drill. Because of its position, the Windmill is now more crucial than ever to hold.
  2. Capture the crystal relic. Crystal relics spawn in a location above the enemy’s base (Quarry/Boneyard) or “fountain” point. When captured, your base will spawn an ultra minion, which quickly captures points, is tanky, and deals a lot of damage. Try to capture the crystal relic when the enemy’s not looking: the crystal relic’s location is pretty dangerous.
  3. Capture the storm altar. The center area of the map has been replaced with a storm altar. You capture the storm altar by standing on it, and not taking damage within it for a few seconds. When captured, it will give your team a buff with 3 stacks that deals pure damage to your enemies whenever you damage them.

    Capturing the storm altar won’t give points to your nexus, but it’ll definitely make killing your enemies easier.

Secondary objectives

  • Capture the Refinery/Drill. You definitely need to capture the capture point closest to your base, but watch out for backdoors. Backdooring in this manner won’t do much though, capturing an ultra minion would be better.
  • Kill opponents. Killing an opponent will shave a couple of points from their nexus.
  • Defend the crystal relic near your base.
  • Lane. Laning is not that important, but clearing minion waves can be something.

Champions to pick (and ban)

  • Shaco – Shaco is the most annoying champion to deal with in DND. Make sure to ban this champion, otherwise be prepared to counter him.
    • W – Box can be used both as an escape and defense mechanism.
    • Q – Nope. He’s gone.
  • Teemo
    • R – Noxious Trap can be placed wisely in choke points and to defend the crystal relic.
  • Singed – Singed shines bright in DND thanks to his smoke.
    • Q – Singed’s Q can make following him pretty annoying.
    • Ghost – Ghost is very good on Singed and multiplies his degree of being annoying.
  • Nidalee
    • W – Nidalee can be pretty hard to chase.
    • Q – Nidalee’s long-range spears can disrupt capturing.
  • Heimerdinger
    • Q – Heimerdinger can pretty much defend any spot with some turrets.
    • RQ – Unleashing the super turret can be the ultimate defense your team needs.

Travellers

  • Evelynn
    • Passive – Evelynn can pretty much capture the crystal relic any time she wants.
  • Rammus
    • Q
  • Hecarim
  • Quinn
    • R – Quinn can quickly switch between objectives with her R. Because of her carry nature though, she’s not that viable.
  • Sona
    • E

Globals

Champions with global or near-global range abilities can always interrupt captures.

  • Pantheon
  • Ezreal
  • Jinx
  • Lux
  • Twisted Fate
  • Aurelion Sol
  • Taliyah
  • Gangplank

Assassins

  • Akali
  • Zed
  • Jax
  • Fiddlesticks

Mages

  • Zyra – Good defense
  • Swain
  • Ryze
  • Fizz
  • Ekko

Items to get

  • Crystal of Aeons – must-have for some mages.
  • Liandry’s Torment – the DoT can buy some time into preventing enemy captures.
  • Lightbringer and Arcane Sweeper – again a must-have for enemies with stealth and stealth wards such as Shaco, Teemo and Twitch.

Hosting user scripts on Github Gist

Since the main directory for GreaseMonkey user scripts went down years ago, there hasn’t been a more popular go-to place for user scripts. There are mirrors, yes.

But then there’s Github Gist.

Using Github Gist you can quickly brew up your user scripts and at the same time get an easy link to install it.

Note that I won’t go over the specifics of the GreaseMonkey header format here.

  1. A gist will usually only contain a single file with your code. When naming your code file, make sure to end it with .user.js. That way, GreaseMonkey and TamperMonkey will pick up your file as a user script when accessing it via a raw URL.
  2. When pushing updates to the file, you can just update the @version in your header.
  3. So that your GreaseMonkey or TamperMonkey client picks up your code file every time you edit it, you’ll need the raw URL of your code file, sans the Git commit hash. As of the time of writing, the format should be: https://gist.github.com/<your username>/<gist ID>/raw/<filename>.user.js. You should assign this URL as your @downloadUrl and/or @updateUrl.

Theoretically, you should be able to do this with Github, Bitbucket or any other similar Git hosting site as long as the file is publicly accessible. Just make sure the raw link points to the VCS branch you’re updating (master) and not linked to a specific commit.

I’m just mentioning TamperMonkey since that’s what I use. I use Chrome.

Building your web app on the fly with Heroku

We all know that Git is the only way to deploy apps to Heroku, right? (Nope!) But the thing is, as good Git users, we don’t want to add our compiled stuff to source control. But our apps won’t work without them existing on the deployed app, right? That’s why we’ll want to build the stuff on the fly in Heroku’s servers themselves with an npm postinstall script. In fact, Heroku recommends this in their node.js support and best practices articles.

But how do we get about doing this?

Creating a build pipeline

First, we need a functioning build pipeline. We might have this setup, which copies Bootstrap’s CSS files to a certain folder, for example:

// package.json
{
  "scripts": {
    "copy": "cp -r node_modules/bootstrap/dist/css app
  }
  ...
}

This requires that we have bootstrap as a devDependency:

// package.json
{
  "devDependencies": {
    "bootstrap": "4.0.0-alpha.2"
  }
  ...
}

But then, these dev dependencies won’t get installed when they get deployed to Heroku. Now we have a dilemma. We can’t build these on Heroku since they’re dev dependencies. But they are dev dependencies, we don’t need them in our backend. So should we make them dependencies?

What should we do now? One option is, definitely, to make bootstrap a non-dev dependency. That way we can make sure the bootstrap package is installed when our app is deployed to Heroku.

The answer I came to after sitting under a tree to attain Heroku/node.js nirvana is to make a build script to install these build dependencies on Heroku. And also introduce the concept of build dependencies.

And oh, there’s no tree.

Build dependencies

build dependency
A dev dependency that is used to build an app.

So before building, we should call this script to first install the build dependencies we need. The script installs the build dependencies we have. But first, we need to list what our build dependencies are. To do that, we can use ye olde package.json. We can do it in the same format as the standard format for dependencies and devDependencies but since I explicitly defined build dependencies as a subset of dev dependencies, we could just specify our build dependencies as an array.

// package.json
{
  "buildDependencies": [
    "bootstrap"
  ]
  ...
}

Now my script goes something like:

// install-build-dependencies.js
'use strict'

const pkg = require('./package')
const ChildProcess = require('child_process')

let bd = pkg.buildDependencies
bd = bd.map(dep => `${dep}@${pkg.devDependencies[dep]}`)
bd = bd.join(' ')

try {
  ChildProcess.execSync(`npm install ${bd}`)
}
catch (err) {
  console.error(err.message)
}

Putting it all together

Now we’re almost done. Do I still need to do this? Presumably, you’re already a Heroku dev.

// is-heroku.js
process.exit(isHeroku ? 0 : 1)

// package.json
{
  "scripts": {
    "postinstall": "node is-heroku && npm run heroku || exit 0",
    "heroku": "npm run install-build-dependencies && npm run build", // depending on your setup, you might have some other stuff here. I know I do.
    "build": "npm run copy",
    "install-build-dependencies": "node install-build-dependencies.js"
    ...
  }
  ...
}

Reducing your slug size

Now you’re using this flow and you might wonder: I don’t really need these build dependencies while the app is running, right? What we can do is actually uninstall them after building. Doing so might significantly reduce your slug size. It’s the same script as above, just replace install with uninstall. Here’s the updated heroku script:

// package.json
{
  "scripts": {
    "heroku": "npm run install-build-dependencies && npm run build && npm run uninstall-build-dependencies"
    ...
  }
  ...
}

Runtime dependencies (bonus!)

Maybe you have some “dependencies” that aren’t actually required dependencies. Maybe things like forever. Or maybe you’re just like me that likes using babel-cli on production code without caring about compiling them. I would like to define these runtime dependencies.

runtime dependency
A dev dependency that is required to run the app when deployed.

At this point, you should really know what to do with these now. Just do some copypasta on the things above. Only, obviously we shouldn’t really uninstall them after installing them.

Let’s finish this post

And that’s it! Hopefully you’ll gain enlightenment on some of the things I’ve shared on this post. This is the flow that I use myself on my latest project on Heroku. Which I totally forgot to share here. Anyway, thanks for reading, and I hope you’ll find Heroku/node.js development fun too.

Using npm config

Intro

I think most people (I don’t interact with most people so I don’t know really) don’t know about the various wonders npm does (or tries to do). One of them is that you can totally use npm as a build tool, an alternative to Grunt or Gulp.

In this post I’m going to discuss how you can use npm as a configuration system on top of your module written in (probably) node.js.

But first, let me discuss how people have been addressing the problem of configuration.

Popular config systems

Environment variables

Of course the most popular option would be to use environment variables. There are different ways to set environment variables in various operating systems but once set, these are passed onto your program whenever it is run. In node.js you can access an environment variable MY_AWESOME_VAR using process.env["MY_VAR"]. Environment variables can be considered per-user and thus has a consequence: conflicts can occur between programs. Some programs address this by adding a prefix. Many don’t.

.env files

Since setting environment variables on an operating system can be tedious, and have a huge scope with many possible conflicts (per-user scope), some have come up with .env files. Dot env files are files that you usually put on the root of your module directory, and when you run your module, it will import the .env file to your environment variable store. That way, you can both read from your OS’ environment variables and possibly override them in the .env file to provide a per-directory configuration. Packages enabling this functionality include dotenv.

Runtime command-line arguments

Of course you can always enable configuration setting via command-line arguments passed to your program. Just like mongo -u user -p=pass. This provides a very specific scope, specific to your program’s running instance. But if you’re typing this manually, it could be tedious. I mean, who here are still typing their usernames and passwords whenever they git push? Anyone?

From a database

What? Really? That’s a thing? I didn’t know that…

The awesome: npm config

The basics

What most people don’t know is that they could do all of these without using any dependencies, using just npm. (Except for the database thing. That’s so stupid… Why do that?)

Okay, let me clear this out of the way first. You’re probably reading this because you didn’t understand how npm config works, but here are all of the relevant documentation:

  • npm-config – Tells you what typing npm config should do, but not exactly why or how?
  • misc/config – Has some info but the bulk is npm’s own config
  • npmrc – Fair enough.

What I’m gonna teach here is how to create a configuration system that will be specific to your own module, and nothing else.

Supposing we’re done, let’s show first how you would read a configured variable such as password in a node.js app:

process.env.npm_package_config_password

Well, that’s easy enough. But wait. Aren’t you curious to know what all of that does? I know I am.

  • npm is just a prefix to all of the environment variables npm inserts. You know, to avoid conflicts.
  • package is a prefix to package-specific variables. If you have a package.json file (you should) a bunch of things from that will appear in your process.env prefixed with npm_package.
  • config is, specifically, your package-specific config. Which I am discussing right now.
  • password is the name of the config var.
  • _ (underscore) is the separator npm uses.

Suppose you are a module author authoring the module awesome-point-of-sale that requires a connection to a MySQL database. From the above you would know what to pass to create a connection:

const MySQL = require('mysql')
let connection = MySQL.createConnection({
  host: process.env.npm_config_package_host,
  user: process.env.npm_config_package_user,
  password: process.env.npm_config_package_pass,
  database: process.env.npm_config_package_db
})

Now, what you want to do is to ask your users to configure their system so they would have the correct configuration. One thing they can do is to set a per-user config:

npm config set awesome-point-of-sale:host 192.168.0.123

This will save the said config inside a .npmrc file in your $HOME directory. On Windows, this is the %USERPROFILE% directory. Don’t be shocked why they do this right there, it’s standard practice, really.

Alternatively, they can open a text editor using:

npm config edit

They would then append the following line in .env format:

awesome-point-of-sale:host=192.168.0.123

There are other places where you could put .npmrc config files. See the npmrc docs for details. With this it is possible to set config vars in different scopes: per-system, per-user, and per-directory. Hint: Try npm config edit -g!

Now, how would npm insert all this stuff in your program?

You should totally run your program using npm run-script. Google “npm as build tool” for ideas. (Although I’m considering blogging it myself. I have some personal opinions.)

And that’s it! We’re done. Wait, not yet? Yes, there’s more to it than it seems.

Defaults

Yes, definitely! You can set your project defaults in your config. Suppose you are able to run a MySQL database locally. We can use that.

package.json:

{
  "config": {
    "host": "localhost",
    "user": "admin",
    "pass": "",
    "db": "pos"
  }
  ...
}

Grouped configs

What if you want to group your config vars such that there’s a separate config for how to connect to your MySQL database and how to start your server? What you can do is group your configs into objects:

package.json:

{
  "config": {
    "mysql": {
      "host": "localhost",
      "user": "admin",
      ...
    },
    "server": {
      "host": "0.0.0.0",
      "port": 80
    }
  }
  ...
}

Now how would this reflect in your program? What npm does is it uses the underscore character (_) to indicate the path to the variable:

let serverHost = process.env.npm_package_config_server_host
let serverPort = process.env.npm_package_config_server_port
let mysqlHost = process.env.npm_package_config_mysql_host

How will users set this in the config though? The same way:

npm config set awesome-point-of-sale:server_host 0.0.0.0

And that’s a wrap!

Whoo! Aren’t you glad that’s over? Although if you have an absurd module name such as awesome-point-of-sale you might want to consider adding some config functionality. Something like npm init, even. (Whoa, that’s a really good suggestion right there that I could use myself.)

Upgrading to Babel 6 the awesome way

Upgrading to Babel 6.x can’t be that hard, right? Well, it can if you’re like me who wants maximum modularization. But it isn’t, really.

I love modularization. And making an effort to do so can really significantly reduce your own module size, if not where, when it counts. So yes, npm may not now dedupe by default (whether or not it does when you read this, then awesome) but if a module author decides to do so, then all’s good, right? I especially love lodash and how it’s divided into modules. That’s kinda what Babel does now.

So, how do we upgrade to Babel the awesome way?

Okay, first uninstall the babel package if you still have it: npm un -sD babel —we won’t need it anymore. If you have it installed globally, you might want to uninstall that too.

Next, install either babel-cli or babel-core depending on what you’re using. babel-cli is what you need when you need the CLI. (Good job, Sherlock) For a refresher or if you don’t know already, the CLI programs that come with it are babel, that transforms your code, and babel-node, that’s like a node.js proxy with both a runner and a REPL. Or install both if you need to. They’re modular anyway. I’m not much of a fan of require hooks, but if you swing that way, I can’t stop you.

Okay, at this point if you’re a n00b or a conformist you would now pick one of the presets to support ES2015 functionality, in which case I’m wondering why you’re reading this blog post when you could just go over to the website and follow the instructions. If you aren’t, you may continue reading.

Next, decide on the plugins you wish to include. Now here’s the trick to the awesome. If you’re not yet using node v5 or at least node v4 then you’re being out of the loop. The thing is, ECMAScript 2015 (say what??) has been released last June. So now we can use most of its features really. Support is flaky here and there but most of the usable ones have already arrived in various JavaScript environments. Now, I might be being a bad influence here but I’m only planning to support V8, but you can be better and support, I don’t know, SpiderMonkey? IE?

Anyway, if you’re like me, the point is if I see a feature is already supported by node and Chrome, I won’t have to transform it, right? So just pick plugins that you actually need. kangax’ compat tables might help. Basically, by doing this I have drastically reduced the number of plugins I needed for my code.

For module authors: If you’re not much of a polyfilling fan and would like to drop support for environments only compatible with ES5 or lower, consider not using the babel-runtime module and the babel-plugin-transform-runtime plugin anymore. Basically what it does is it ponyfills your code environment with babel-runtime which contains the JavaScript globals and functions you’ll need in an ES2015 environment, as well as regenerator, which works with generator functions. You’d then include babel-runtime to your dependencies. Not that I’m not a fan of core-js (it is seriously awesome) but native is better if it exists already.

Here’s my package.json for one of my projects using Babel:

{
  ...
  "devDependencies": {
    "babel-cli": "^6.1.2",
    "babel-plugin-transform-async-to-generator": "^6.0.14",
    "babel-plugin-transform-es2015-destructuring": "^6.0.18",
    "babel-plugin-transform-es2015-modules-commonjs": "^6.1.3",
    "babel-plugin-transform-es2015-parameters": "^6.0.18",
    "babel-plugin-transform-strict-mode": "^6.1.2",
    "babelify": "^6.3.0",
    "browserify": "^10.1.0",
    ...
  },
  "babel": {
    "plugins": [
      "transform-es2015-destructuring",
      "transform-async-to-generator",
      "transform-strict-mode",
      "transform-es2015-parameters",
      "transform-es2015-modules-commonjs"
    ]
  },
}

That’s just 5! Compare that to how many plugins I get when I actually used a preset.

You may ask: what’s with destructuring? Well, this project specifically has a lot of entry points and I don’t want to risk breaking anything, at least for now. If you didn’t already know, node already has support for destructuring via the --harmony_destructuring flag. If you’re still reading, you should definitely check out the node.js docs and see if you can further reduce the number of plugins you need simply by turning on a runtime flag. As for this specific project, it might be fine since it’s run on the server side, the catch is that it has front-end code. (Check out babelify!) And as of the time of writing, Chrome still does not have destructuring support (by default, anyway) hence the decision I made.

strict-mode is there because apparently I’m too lazy to add 'use strict' on top of all of the code. As you might have seen in kangax’ compat tables, V8 still doesn’t support some ES2015 features without seeing it.

Also, if anybody’s noticed: I put my babel config in my package.json file. This is just a personal preference. Personally, I don’t want so many files cluttering my project. So yeah, that’s why I don’t like Visual Studio Code.

If anyone has been reading my blog recently, this is the same project I had some trouble on.

Here’s one from a super-secret project that a reader has decided to bug me about:

{
  ...
  "devDependencies": {
    "babel-cli": "^6.1.1",
    "babel-core": "^6.1.2",
    "babel-plugin-transform-es2015-destructuring": "^6.0.18",
    "mocha": "^2.0.1"
    ...
  },
  "babel": {
    "plugins": [
      "transform-es2015-destructuring"
    ]
  }
}

Simple, right? Only one plugin. Here I have both babel-cli and babel-core installed because I use babel-cli for transforming my code and babel-core to test with Mocha.

TL;DR just read the bolded phrases.

Update: If you plan to support only node v4 and up and presets are totally fine with you then there’s this preset for node v4.

Do not use minification.constantFolding when using Babel on Heroku

I had a hard time debugging why my app on Heroku doesn’t work. It’s being run with babel-node. I encountered EACCES errors without any explanation of what’s going on. So apparently my port has not been changing. Apparently minification.constantFolding folds process.env. as constants. What I’m baffled about is that babel-node does not capture the value of process.env at the time it’s called, even though it should be at that time.

Anyway, for everybody’s guidance.

Trailing whitespace, Jade and Atom

Just a little aside here as I discovered that trailing whitespace is not automatically stripped from Jade files.

But why?

So apparently, more recent versions of Jade now has significant trailing whitespace. As one of the programmers who believe that whitespace is just there to brighten our days, it came to me as a shock and some disbelief.

They put it there so that people can do space things with their inline stuff. As for me, I’m perfectly okay with

= " "

if that’s the syntax that best suits my needs.

Of course most code languages we know are perfectly fine with stripping trailing whitespace, since they’re mostly insignificant to the language, save for the esoteric Whitespace programming language. It’s the first time I’ve seen anything like this. I’m shocked, yeah, but I’m not against it in any way. Jade is a beautiful language, and I hope it stays that way.

I also discovered that Jade’s filters is powered by jstransformer. I didn’t know what that was at first, but when I took a peek at the number of transformers enabled by jstransformer, I was in awe.

Yep. Nice segue. Anyway, bye.

Atom editor adventures

I’ve been using Atom a lot lately. It’s been my regular editor these past few weeks. Because who doesn’t love a text editor that always hangs, right!?

atom is not responding

But why did I get to use it anyway?

Okay, a brief for those who don’t know already: Atom is built on Electron. Electron uses WebKit. Chrome uses WebKit. WebKit uses V8. node.js uses V8.

I have Atom installed long ago. But I was a Sublime Text user. I even do my node.js projects on Sublime. Why the switch? I don’t really remember. Maybe there’s really no reason. It just clicked with me.

I have Jetbrains’ awesome web development application WebStorm. I think it’s the best node.js debugger out there. Well, there’s node-inspector, but it’s not working for me now.

But here I am now.

So how about I talk about my Atom haxx? Starting with some awesome packages!

  • Stylus – Stylus support. Stylus rules SASS sux LESS sux even more
  • api-docs – API documentation
  • file-icons – Distinguish between files. I can’t understand the reasoning behind the CSS icon though.
  • git-plus – Just git things. I don’t use it regularly but it’s awesome. Maybe I should use it regularly?
  • language-dots – .*ignore support
  • language-jade – Jade support
  • pigments – display colors. Heck it even displayed one in an ordinary text file.
  • source-preview – for transpilers
  • source-preview-babel – for Babel, specifically
  • language-babel – This is a deal-breaker. Jetbrains doesn’t have ES7 support. Maybe that’s the reason why I moved to Atom. Because even if I edit Javascript in WebStorm, it won’t highlight async and await. Atom doesn’t complain. It’s just a text editor, not an IDE. But this. This changed everything.
  • npm – npm I guess. Haven’t used it. (LOL)

I’ve also tinkered around and have some styles for the scrollbar. It was too dark and thin (curse Mac OS peeps! You really think this is good UX?) so I added some styles. Here’s the LESS code:

::-webkit-scrollbar,
.scrollbars-visible-always /deep/ ::-webkit-scrollbar {
width: 12px !important;
height: 12px !important;
}

.scrollbars-visible-always /deep/ ::-webkit-scrollbar-thumb {
background: rgba(100%, 100%, 100%, 0.2);
}

I’ve also created my own theme based on the custom one I have on WebStorm, which is in turn based on its own default dark syntax theme.

I also made it so that I have a background in my code editor area. I stole some ideas from editor-background (an Atom package), though. But that’s because that itself didn’t work as I expected.

Here’s the LESS code:

&:not(.mini) {
  background-color: transparent;
  background-image:
    radial-gradient(circle at 80% 35%, fade(@syntax-background-color, 85%) 0%, @syntax-background-color 80%),
    url('...');
  background-size: cover;
}

I think this requires a little explanation. The background-color should be transparent because code blocks actually cover the editor background. This defaults to @syntax-text-color, and you should keep it like this anyway because other text fields are created with the same atom-text-editor element (hence the :not(.mini)). The background is specified as-is. Only, I added a radial gradient. This is the idea I stole. It makes it look like the background is filtered in some way. I set it up so that the center is focused on the subject of the background (which I’ll discuss later) and to darken the area that’s supposed to be filled with code (i.e. the left side). The filter is actually kinda important because it kinda keeps me from being distracted with details of the background. That’s one way of mitigating the presence of a background. That’s the only one for me, though.

When I first thought of this, I first searched for a cool background to use. I came across a wallpaper with Yuuma Isogai in it that I apparently have no memory of saving or using so I went with that.

Well, that’s it, I guess. Atom is inconvenient in a way or two but that’s just that. We can’t really argue with the Mac OS peeps that made this. So yeah. The end.