What bit of advice would you share with someone new to your field?

The most FA of all the FAQs.

Here’s Laura Kalbag:

Find what you love. Don’t worry about needing to learn every language, technique or tool. Start with what interests you, and carve your own niche. And then use your powers for good!

And my own:

Buy a domain name. Figure out how to put an HTML file up there. Isn’t that a powerful feeling? Now you’ve got table stakes. Build something.

Definitely, go read other A Book Apart author answers because they are all great. My other favorite is just three words.

Direct Link to Article — Permalink

The post What bit of advice would you share with someone new to your field? appeared first on CSS-Tricks.

Automate Your Workflow with Node

You know those tedious tasks you have to do at work: Updating configuration files, copying and pasting files, updating Jira tickets.

Time adds up after a while. This was very much the case when I worked for an online games company back in 2016. The job could be very rewarding at times when I had to build configurable templates for games, but about 70% of my time was spent on making copies of those templates and deploying re-skinned implementations.

What is a reskin?

The definition of a reskin at the company was using the same game mechanics, screens and positioning of elements, but changing the visual aesthetics such as color and assets. So in the context of a simple game like ‘Rock Paper Scissors,’ we would create a template with basic assets like below.

But when we create a reskin of this, we would use different assets and the game would still work. If you look at games like Candy Crush or Angry Birds, you’ll find that they have many varieties of the same game. Usually Halloween, Christmas or Easter releases. From a business perspective it makes perfect sense.

Now… back to our implementation. Each of our games would share the same bundled JavaScript file, and load in a JSON file that had different content and asset paths. The result?

The good thing about extracting configurable values into a JSON file is that you can modify the properties without having to recompile/build the game again. Using Node.js and the original breakout game created by Mozilla, we will make a very simple example of how you can create a configurable template, and make releases from it by using the command line.

Our game

This is the game we’ll be making. Reskins of MDN Breakout, based on the existing source code.

Gameplay screen from the game MDN Breakout where you can use your paddle to bounce the ball and destroy the brick field, with keeping the score and lives.

The primary color will paint the text, paddle, ball and blocks, and the secondary color will paint the background. We will proceed with an example of a dark blue background and a light sky blue for the foreground objects.

Prerequisites

You will need to ensure the following:

  • You have Git installed – https://git-scm.com/downloads
  • You have Node installed – https://nodejs.org/en/download
  • You have a GitHub account – https://github.com
  • You have cloned the repository locally – https://github.com/smks/nobot-examples.git
  • You have ran npm install in the root of the nobot-examples project.
  • Finally, you run the local server by running npm run gameServe in the root of the project via a terminal.

We have tweaked the original Firefox implementation so that we first read in the JSON file and then build the game using HTML Canvas. The game will read in a primary color, and a secondary color from our game.json file.

{ "primaryColor": "#fff", "secondaryColor": "#000"
}

We will be using example 20 from the book Automating with Node.js. The source code can be found here.

Open up a new command line (CMD for Windows, Terminal for Unix-like Operating systems) and change into the following directory once you have cloned the repository locally.

$ cd nobot-examples/examples/020

Remember the game server should be running in a separate terminal.

Our JSON file sits beside an index.html file inside a directory called template. This is the directory that we will copy from whenever we want to do a new release/copy.

<!DOCTYPE html>
<html>
<head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Paddle Game</title> <style> * { padding: 0; margin: 0; } canvas { background: #eee; display: block; margin: 0 auto; } </style>
</head>
<body> <canvas id="game" width="480" height="320"></canvas> <script type="text/javascript" src="../../core/game-1.0.0.js"></script>
</body>
</html>

You see above that every game we release will point to the same core bundle JavaScript file. Let’s have a look at our JavaScript implementation under the core directory.

Don’t look too much into the mechanics of how the game works, more so how we inject values into the game to make it configurable.

(function boot(document) { function runGame(config) { const canvas = document.getElementById('game'); canvas.style.backgroundColor = config.secondaryColor; // rest of game source code gets executed... hidden for brevity // source can be found here: https://git.io/vh1Te } function loadConfig() { fetch('game.json') .then(response => response.json()) .then(runGame); } document.addEventListener('DOMContentLoaded', () => { loadConfig(); });
}(document));

The source code is using ES6 features and may not work in older browsers. Run through Babel if this is a problem for you.

You can see that we are waiting for the DOM content to load, and then we are invoking a method called loadConfig. This is going to make an AJAX request to game.json, fetch our JSON values, and once it has retrieved them, it will initiate the game and assign the styles in the source code.

Here is an example of the configuration setting the background color.

const canvas = document.getElementById('game');
canvas.style.backgroundColor = config.secondaryColor; // overriding color here

So, now that we have a template that can be configurable, we can move on to creating a Node.js script that will allow the user to either pass the name of the game and the colors as options to our new script, or will prompt the user for: the name of the game, the primary color, and then the secondary color. Our script will enforce validation to make sure that both colors are in the format of a hex code (e.g. #101b6b).

When we want to create a new game reskin, we should be able to run this command to generate it:

$ node new-reskin.js --gameName='blue-reskin' --gamePrimaryColor='#76cad8' --gameSecondaryColor='#10496b'

The command above will build the game immediately, because it has the three values it needs to release the reskin.

We will create this script new-reskin.js, and this file carries out the following steps:

  1. It will read in the options passed in the command line and store them as variables. Options can be read in by looking in the process object (process.argv).
  2. It will validate the values making sure that the game name, and the colors are not undefined.
  3. If there are any validation issues, it will prompt the user to re-enter it correctly before proceeding.
  4. Now that it has the values, it will make a copy of the template directory and place a copy of it into the releases directory and name the new directory with the name of the game we gave it.
  5. It will then read the JSON file just recently created under the releases directory and override the values with the values we passed (the colors).
  6. At the end, it will prompt the user to see if they would like to open the game in a browser. It adds some convenience, rather than us trying to remember what the URL is.

Here is the full script. We will walk through it afterwards.

require('colors');
const argv = require('minimist')(process.argv.slice(2));
const path = require('path');
const readLineSync = require('readline-sync');
const fse = require('fs-extra');
const open = require('opn');
const GAME_JSON_FILENAME = 'game.json'; let { gameName, gamePrimaryColor, gameSecondaryColor } = argv; if (gameName === undefined) { gameName = readLineSync.question('What is the name of the new reskin? ', { limit: input => input.trim().length > 0, limitMessage: 'The project has to have a name, try again' });
} const confirmColorInput = (color, colorType = 'primary') => { const hexColorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/; if (hexColorRegex.test(color)) { return color; } return readLineSync.question(`Enter a Hex Code for the game ${colorType} color `, { limit: hexColorRegex, limitMessage: 'Enter a valid hex code: #efefef' });
}; gamePrimaryColor = confirmColorInput(gamePrimaryColor, 'primary');
gameSecondaryColor = confirmColorInput(gameSecondaryColor, 'secondary'); console.log(`Creating a new reskin '${gameName}' with skin color: Primary: '${gamePrimaryColor}' Secondary: '${gameSecondaryColor}'`); const src = path.join(__dirname, 'template');
const destination = path.join(__dirname, 'releases', gameName);
const configurationFilePath = path.join(destination, GAME_JSON_FILENAME);
const projectToOpen = path.join('http://localhost:8080', 'releases', gameName, 'index.html'); fse.copy(src, destination) .then(() => { console.log(`Successfully created ${destination}`.green); return fse.readJson(configurationFilePath); }) .then((config) => { const newConfig = config; newConfig.primaryColor = gamePrimaryColor; newConfig.secondaryColor = gameSecondaryColor; return fse.writeJson(configurationFilePath, newConfig); }) .then(() => { console.log(`Updated configuration file ${configurationFilePath}`green); openGameIfAgreed(projectToOpen); }) .catch(console.error); const openGameIfAgreed = (fileToOpen) => { const isOpeningGame = readLineSync.keyInYN('Would you like to open the game? '); if (isOpeningGame) { open(fileToOpen); }
};

At the top of the script, we require the packages needed to carry out the process.

  • colors to be used to signify success or failure using green or red text.
  • minimist to make it easier to pass arguments to our script and to parse them optionally. Pass input without being prompted to enter.
  • path to construct paths to the template and the destination of the new game.
  • readline-sync to prompt user for information if it’s missing.
  • fs-extra so we can copy and paste our game template. An extension of the native fs module.
  • opn is a library that is cross platform and will open up our game in a browser upon completion.

The majority of the modules above would’ve been downloaded/installed when you ran npm install in the root of the nobot-examples repository. The rest are native to Node.

We check if the game name was passed as an option through the command line, and if it hasn’t been, we prompt the user for it.

// name of our JSON file. We store it as a constant
const GAME_JSON_FILENAME = 'game.json'; // Retrieved from the command line --gameName='my-game' etc.
let { gameName, gamePrimaryColor, gameSecondaryColor } = argv; // was the gameName passed?
if (gameName === undefined) { gameName = readLineSync.question('What is the name of the new reskin? ', { limit: input => input.trim().length > 0, limitMessage: 'The project has to have a name, try again' });
}

Because two of our values need to be hex codes, we create a function that can do the check for both colors: the primary and the secondary. If the color supplied by the user does not pass our validation, we prompt for the color until it does.

// Does the color passed in meet our validation requirements?
const confirmColorInput = (color, colorType = 'primary') => { const hexColorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/; if (hexColorRegex.test(color)) { return color; } return readLineSync.question(`Enter a Hex Code for the game ${colorType} color `, { limit: hexColorRegex, limitMessage: 'Enter a valid hex code: #efefef' });
};

We use the function above to obtain both the primary and secondary colors.

gamePrimaryColor = confirmColorInput(gamePrimaryColor, 'primary');
gameSecondaryColor = confirmColorInput(gameSecondaryColor, 'secondary');

In the next block of code, we are printing to standard output (console.log) to confirm the values that will be used in the process of building the game. The statements that follow are preparing the paths to the relevant files and directories.

The src will point to the template directory. The destination will point to a new directory under releases. The configuration file that will have its values updated will reside under this new game directory we are creating. And finally, to preview our new game, we construct the URL using the path to the local server we booted up earlier on.

console.log(`Creating a new reskin '${gameName}' with skin color: Primary: '${gamePrimaryColor}' Secondary: '${gameSecondaryColor}'`);
const src = path.join(__dirname, 'template');
const destination = path.join(__dirname, 'releases', gameName);
const configurationFilePath = path.join(destination, GAME_JSON_FILENAME);
const projectToOpen = path.join('http://localhost:8080', 'releases', gameName, 'index.html');

In the code following this explanation, we:

  • Copy the template files to the releases directory.
  • After this is created, we read the JSON of the original template values.
  • With the new configuration object, we override the existing primary and secondary colors provided by the user’s input.
  • We rewrite the JSON file so it has the new values.
  • When the JSON file has been updated, we ask the user if they would like to open the new game in a browser.
  • If anything went wrong, we catch the error and log it out.
fse.copy(src, destination) .then(() => { console.log(`Successfully created ${destination}`green); return fse.readJson(configurationFilePath); }) .then((config) => { const newConfig = config; newConfig.primaryColor = gamePrimaryColor; newConfig.secondaryColor = gameSecondaryColor; return fse.writeJson(configurationFilePath, newConfig); }) .then(() => { console.log(`Updated configuration file ${configurationFilePath}`green); openGameIfAgreed(projectToOpen); }) .catch(console.error);

Below is the function that gets invoked when the copying has completed. It will then prompt the user to see if they would like to open up the game in the browser. The user responds with y or n

const openGameIfAgreed = (fileToOpen) => { const isOpeningGame = readLineSync.keyInYN('Would you like to open the game? '); if (isOpeningGame) { open(fileToOpen); }
};

Let’s see it in action when we don’t pass any arguments. You can see it doesn’t break, and instead prompts the user for the values it needs.

$ node new-reskin.js
What is the name of the new reskin? blue-reskin
Enter a Hex Code for the game primary color #76cad8
Enter a Hex Code for the game secondary color #10496b
Creating a new reskin 'blue-reskin' with skin color: Primary: '#76cad8' Secondary: '#10496b'
Successfully created nobot-examples\examples\020\releases\blue-reskin
Updated configuration file nobot-examples\examples\020\releases\blue-reskin\game.json
Would you like to open the game? [y/n]: y
(opens game in browser)

My game opens on my localhost server automatically and the game commences, with the new colors. Sweet!

Oh… I’ve lost a life already. Now if you navigate to the releases directory, you will see a new directory called blue-reskin This contains the values in the JSON file we entered during the script execution.

Below are a few more releases I made by running the same command. You can imagine if you were releasing games that could configure different: images, sounds, labels, content and fonts, you would have a rich library of games based on the same mechanics.

Even better, if the stakeholders and designers had all of this information in a Jira ticket, you could integrate the Jira API into the Node script to inject these values in without the user having to provide any input. Winning!


This is one of many examples that can be found in Automating with Node.js. In this book, we will be looking at a more advanced example using “Rock Paper Scissors” as the basis of a build tool created from scratch.

  • Color Print: http://amzn.eu/aA0cSnu
  • Kindle: https://amzn.to/2JPTk7q
  • Kobo: https://www.kobo.com/gb/en/ebook/automating-with-node-js
  • Leanpub: https://leanpub.com/automatingwithnodejs

The post Automate Your Workflow with Node appeared first on CSS-Tricks.

CSS-in-JS: FTW || WTF?

I enjoyed Bruce Lawson’s talk on this holiest of wars. It’s funny and lighthearted while being well researched and fairly portraying the good arguments on both sides.

The post CSS-in-JS: FTW || WTF? appeared first on CSS-Tricks.

Render Children in React Using Fragment or Array Components

What comes to your mind when React 16 comes up? Context? Error Boundary? Those are on point. React 16 came with those goodies and much more, but In this post, we’ll be looking at the rendering power it also introduced — namely, the ability to render children using Fragments and Array Components.

These are new and really exciting concepts that came out of the React 16 release, so let’s look at them closer and get to know them.

Fragments

It used to be that React components could only return a single element. If you have ever tried to return more than one element, you know that you’ll will be greeted with this error: Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag. The way out of that is to make use of a wrapper div or span element that acts as the enclosing tag.

So instead of doing this:

class Countries extends React.Component { render() { return ( <li>Canada</li> <li>Australia</li> <li>Norway</li> <li>Mexico</li> ) }
}

…you have to add either an ol or ul tag as a wrapper on those list items:

class Countries extends React.Component { render() { return ( <ul> <li>Canada</li> <li>Australia</li> <li>Norway</li> <li>Mexico</li> </ul> ) }
}

Most times, this may not be the initial design you had for the application, but you are left with no choice but to compromise on this ground.

React 16 solves this with Fragments. This new features allows you to wrap a list of children without adding an extra node. So, instead of adding an additional element as a wrapper like we did in the last example, we can throw <React.Fragment> in there to do the job:

class Countries extends React.Component { render() { return ( <React.Fragment> <li>Canada</li> <li>Australia</li> <li>Norway</li> <li>Mexico</li> </React.Fragment> ) }
}

You may think that doesn’t make much difference. But, imagine a situation where you have a component that lists different items such as fruits and other things. These items are all components, and if you are making use of old React versions, the items in these individual components will have to be wrapped in an enclosing tag. Now, however, you can make use of fragments and do away with that unnecessary markup.

Here’s a sample of what I mean:

class Items extends React.Component { render() { return ( <React.Fragment> <Fruit /> <Beverages /> <Drinks /> </React.Fragment> ) }
}

We have three child components inside of the fragment and can now create a component for the container that wraps it. This is much more in line with being able to create components out of everything and being able to compile code with less cruft.

Fragment Shorthand

There is a shorthand syntax when working with Fragments, which you can use. Staying true to its fragment nature, the syntax is like a fragment itself, leaving only only empty brackets behind.

Going back to our last example:

class Fruit extends React.Component { render() { return ( <> <li>Apple</li> <li>Orange</li> <li>Blueberry</li> <li>Cherry</li> </> ) }
}

Question: Is a fragment better than a container div?

You may be looking for a good reason to use Fragments instead of the container div you have always been using. Dan Abramov answered the question on StackOverflow. To summarize:

  1. It’s a tiny bit faster and has less memory usage (no need to create an extra DOM node). This only has a real benefit on very large and/or deep trees, but application performance often suffers from death by a thousand cuts. This is one less cut.
  2. Some CSS mechanisms like flexbox and grid have a special parent-child relationship, and adding divs in the middle makes it harder to maintain the design while extracting logical components.
  3. The DOM inspector is less cluttered.

Keys in Fragments

When mapping a list of items, you still need to make use of keys the same way as before. For example, let’s say we want to pass a list of items as props from a parent component to a child component. In the child component, we want to map through the list of items we have and output each item as a separate entity. Here’s how that looks:

const preload = { "data" : [ { "name": "Reactjs", "url": "https://reactjs.org", "description": "A JavaScript library for building user interfaces", }, { "name": "Vuejs", "url": "https://vuejs.org", "description": "The Progressive JavaScript Framework", }, { "name": "Emberjs", "url": "https://www.emberjs.com", "description": "Ember.js is an open-source JavaScript web framework, based on the Model–view–viewmodel pattern" } ]
} const Frameworks = (props) => { return ( <React.Fragment> {props.items.data.map(item => ( <React.Fragment key={item.id}> <h2>{item.name}</h2> <p>{item.url}</p> <p>{item.description}</p> </React.Fragment> ))} </React.Fragment> )
} const App = () => { return ( <Frameworks items={preload} /> )
}

See the Pen React Fragment Pen by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

You can see that now, in this case, we are not making use of any divs in the Frameworks component. That’s the key difference!

Render Children Using an Array of Components

The second specific thing that came out of React 16 we want to look at is the ability to render multiple children using an array of components. This is a clear timesaver because it allows us to cram as many into a render instead of having to do it one-by-one.

Here is an example:

class Frameworks extends React.Component { render () { return ( [ <p>JavaScript:</p> <li>React</li>, <li>Vuejs</li>, <li>Angular</li> ] ) }
}

You can also do the same with a stateless functional component:

const Frontend = () => { return [ <h3>Front-End:</h3>, <li>Reactjs</li>, <li>Vuejs</li> ]
} const Backend = () => { return [ <h3>Back-End:</h3>, <li>Express</li>, <li>Restify</li> ]
} const App = () => { return [ <h2>JavaScript Tools</h2>, <Frontend />, <Backend /> ]
}

See the Pen React Fragment 2 Pen by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

Conclusion

Like the Context API and Error Boundary feature that were introduced in React 16, rendering children components with Fragment and multiples of them with Array Components are two more awesome features you can start making use of as you build your application.

Have you started using these in a project? Let me know how in the comments so we can compare notes. 🙂

The post Render Children in React Using Fragment or Array Components appeared first on CSS-Tricks.

PSA: Yes, Serverless Still Involves Servers.

You clever dog. You’ve rooted it out! It turns out when you build things with serverless technology you’re still using servers. Pardon the patronizing tone there, I’ve seen one-too-many hot takes at this point where someone points this fact out and trots away triumphantly.

And yes, because serverless still involves servers, the term might be a bit disingenuous to some. You could be forgiven for thinking that serverless meant technologies like web workers, which use the client to do things you might have otherwise done on a server and is where the term serverless was headed. Alas, it is not.

What serverless really means:

  • Using other people’s servers instead of running your own. You’re probably already doing that, but serverless takes it to another level where you have no control over the server outside of telling it to run a bit of code.
  • You don’t need to think about scaling — that’s the serverless provider’s problem.
  • You are only paying per execution of your code and not some fixed cost per time.
  • You only worry about your code being misused, but not the security of the server itself.
  • We’re mostly talking about Cloud Functions above, but I’d argue the serverless movement involves anything that allows you to work from static hosting and leverage services to help you with functionality. For example, even putting a Google Form on a static site is within the serverless spirit.

Serverless is about outsourcing a little bit more of your project to companies that are incentivized to do it well. My hope is that someday we can have a conversation about serverless without having to tread this ground every time and spat about the term. I suspect we will. I think we’re almost over the term the cloud as an industry and we’ll jump this hurdle too. It’s worth it when a single word successfully evokes a whole ecosystem.

Wanna know more about serverless? Here’s the tag on CSS-Trick where we’ve talked about it a bunch.

The post PSA: Yes, Serverless Still Involves Servers. appeared first on CSS-Tricks.

Create your own Serverless API

If you don’t already know of it, Todd Motto has this great list of public APIs. It’s awesome if you’re trying out a new framework or new layout pattern and want to hit the ground running without fussing with the content.

But what if you want or need to make your own API? Serverless can help create a nice one for data you’d like to expose for use.

Serverless really shines for this use case, and hopefully this post makes it clear why. In a non-serverless paradigm, we have to pick something like express, we have to set up endpoints, we have to give your web server secured access to your database server, you have to deploy it, etc. In contrast, here we’ll be able to create an API in a few button clicks, with minor modifications.

Here’s the inspiration for this tutorial: I’ve been building a finder to search for new cocktails and grab random one. I originally started using ae public API but realized quickly that I found the contents limiting and wanted to shape my own.

I’m going to use Azure for these examples but it is possible to accomplish what we’re doing here with other cloud providers as well.

Make the Function

To get started, if you haven’t already, create a free Azure trial account. Then go to the portal: preview.portal.azure.com.

Next, we’ll hit the plus sign at the top left and select Serverless Function App from the list. We can then fill in the new name of our function and some options. It will pick up our resource group, subscription, and create a storage account from defaults. It will also use the location data from the resource group. So, happily, it’s pretty easy to populate the data.

Next, we’ll create a new function using HTTP Trigger, and go to the Integrate tab to perform some actions:

What we did was:

  • Give the route template a name
  • Change the authorization level to “Anonymous”
  • Change the allowed HTTP methods to “Selected Method”
  • Select “GET” for the selected method and unchecked everything else

Now, if we get the function URL from the top right of our function, we’ll get this:

https://sdras-api-demo.azurewebsites.net/api/hello

The initial boilerplate testing code that we’re given is:

module.exports = function (context, req) { context.log('JavaScript HTTP trigger function processed a request.'); if (req.query.name || (req.body && req.body.name)) { context.res = { // status: 200, /* Defaults to 200 */ body: "Hello " + (req.query.name || req.body.name) }; } else { context.res = { status: 400, body: "Please pass a name on the query string or in the request body" }; } context.done();
};

Now if we go to the URL below, we’ll see this:

https://sdras-api-demo.azurewebsites.net/api/hello/?name=TacoFace
Says hello TacoFace

There’s more information in this blog post, including API unification with Function Proxies. You can also use custom domains, not covered here.

OK, now that that initial part is all set up, let’s find a place to host our data.

Storing the data with CosmosDB

There are a number of ways to store the data for our function. I wanted to use Cosmos because it has one-click integration, making for a pretty low-friction choice. Get a free account here. Once you’re in the portal, we’ll go to the plus sign in the top left to create a new service and this time select “CosmosDB.” In this case, we chose the SQL version.

We have a few options for how to create our documents in the database. We’re merely making a small example for demo purposes, so we can manually create them by going to Data Explorer in the sidebar. In there, I made a database called CocktailFinder, a collection called Cocktails, and added each document. For our Partition Key, we’ll use /id.

creating a collection

In real practice, you’d probably either want to upload a JSON file by clicking the “Upload JSON” button or follow this article for how to create the files with the CLI.

We can add something in JSON format like this:

{ "id": "1", "drink": "gin_and_tonic", "ingredients": [ "2 ounces gin", "2 lime wedges", "3–4 ounces tonic water" ], "directions": "Add gin to a highball glass filled with ice. Squeeze in lime wedges to taste, then add them to glass. Add tonic water; stir to combine.", "glass": [ "highball", "hurricane" ], "image": "https://images.unsplash.com/photo-1523905491727-d82018a34d75?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=52731e6d008be93fda7f5af1145eac12&auto=format&fit=crop&w=750&q=80"
}

And here is the example with all three that we’ve created, and what Cosmos adds in:

Have the function surface the data

OK, now we’ve got some dummy data to work with, so let’s connect it to our serverless function so we can finish up our API!

If we go back to our function in the portal and click Integrate in the sidebar again, there’s a middle column that called Inputs. Here, we can click on the plus that says “+ New Inputs” and a few options come up. We’ll click the CosmosDB option and “Create.”

Showing in the portal the button to create a connection with CosmosDB

A prompt will come up that asks us to provide information about our Database and Collection. If you recall, the databaseName was CocktailFinder and the collectionName was Cocktails. We also want to use the same partitionKey which was /id. We’ll use all the other defaults.

Now if we go to our function.jso, you can see that it’s now been updated with:

{ "type": "documentDB", "name": "inputDocument", "databaseName": "CocktailFinder", "collectionName": "Cocktails", "partitionKey": "/id", "connection": "sdrassample_DOCUMENTDB", "direction": "in"
}

We’re going to use that inputDocument to update our testing function to reflect that’s what we’re trying to access. I also add in the status and log frequently, but that’s optional.

module.exports = function (context, req) { context.log('JavaScript HTTP trigger function processed a request.'); if (context.bindings) { context.log('Get ready'); context.res = {status: 200, body: context.bindings.inputDocument}; context.log(context.res); } else { context.res = { status: 400, body: "Something went wrong" }; } context.done();
};

Now you can see our function at work!

CORS!

Can’t forget the axios call. I have a really barebones CodePen implementation so that you can see how that might work. In Vue, we’re hooking into the created lifecycle method and making the GET request, in order to output the JSON data to the page.

See the Pen Show API Output, beginning of Vue.js integration by Sarah Drasner (@sdras) on CodePen.

From here, you have all that data to play with, and you can store whatever you like in whatever form you fancy. You can use something like Vue, React, or Angular to create interfaces with the content we stored in our database, and our serverless function creates the API for us. The sky is the limit to what we can create! 🎉

The post Create your own Serverless API appeared first on CSS-Tricks.

Remote Conferences; Bridging the Gap, Clearing the Odds

A few weeks back, I saw one of my esteemed mentors decry the psychological traumas he had experienced, following series and series of refusals at certain embassies.

little girl surprised
“A child concentrating hard at school” by Les Anderson on Unsplash

You would think he went for a contract he did not have the capacity for, but then, you would have been wrong. He needed to impart knowledge. He opted to do so across borders, but then, some realities were harsh.

Borders and geographical constraints can cause a lot of havoc. However, it can only do so, when the full discovery of a better way to impart knowledge across borders has not been made. Video conferencing technology has become handy at times like this. Hence, your traditional seminars, conferences, and talks can easily be achieved from anywhere, regardless of your role.

man on a couch with a computer
Photo by DESIGNECOLOGIST on Unsplash
On a lighter note, these pillows are dope.

Maybe we should not be too ambitious. Maybe we could simply make this article about a one-sided ‘remoteness’, where the attendees are gathered in an offline venue, but then the speakers have a 100% flexibility to speak from anywhere.

For this kind of arrangement, the advantages are many, same as the disadvantages. Let’s start with the disadvantages. For a place not having a very fast internet, the video and audio quality might be abysmal. But that is about that!

For the advantages: a herd of developers or writers are gathered, waiting for a speaker to impart knowledge. So many things would have gone wrong if the speaker was to travel from one location to another. Think about the racism, the mishaps or the thefts. What about the man-hours lost in commuting from one place to the other?

All of these are greatly minimized to a lazy trudge from your bed or kitchen to your computer. Then, the speaker has 5 minutes to the conference, and they are washing their face and checking their teeth. Now he or she is out of time and rushes up with a neatly ironed shirt, on a light brown underpants. Of course, the camera is only built to see the face of the speaker. Convenience is the word!

Visa problems are a thing here in Africa. While a public ban has not been laid on some countries, a lot of resource persons find it difficult to get visa to speak in countries they have a large following, or not.

man putting his head in his hands, looking frustrated, sitting on a pier
Photo by Bruno Aguirre on Unsplash

However, this conferencing arrangement might make your dream come true, if and only if you are able to get up from that cozy bed and turn on your computer in time. You could reach more audience than you expect.

Such an easy life.

For the attendees, it is a Win. Look at it this way; your favorite speakers are just a click away from you! That sounds alluring. There are plenty reasons why your favorite speakers might not make it to you in a totally offline conference, but then everything has been simplified and he or she is simply a button and a good internet-connection away. This offers more mentorship chances and enhances progress. In sum, it makes things easier for your favorite speakers.

a person's hands at a meeting
Photo by Headway on Unsplash

Are you a writer, a developer or a random conference crasher, then you should look out for the next online conference in town. You might just be surprised at the quality of speakers you would be hearing from.

Concatenate is a free conference for Nigerian developers, happening the 9th and 10th of August. The attendees will be in person and the speakers and MC will be both in person and remote from around the world. If you’re near Lagos, register here!

The post Remote Conferences; Bridging the Gap, Clearing the Odds appeared first on CSS-Tricks.

The div that looks different in every browser

It’s not that Martijn Cuppens used User Agent sniffing, CSS hacks, or anything like that to make this quirk div. This is just a plain ol’ <div> using the outline property a la:

div { outline: inset 100px green; outline-offset: -125px;
}

It looks different in different browsers because browsers literally render something differently in this strange situation.

I happened upon Reddit user spidermonk33’s comment in which they animated the offset to understand it a bit more. I took that idea and made this little video to show them behaving even weirder than the snapshots…

Direct Link to Article — Permalink

The post The div that looks different in every browser appeared first on CSS-Tricks.

itty.bitty

Mark this down as one of the strangest things I’ve seen in a good long while. Nicholas Jitkoff has made a tool called itty.bitty that creates websites with all of the assets being contained within their own link. You can create a website without any HTML or CSS resources at all because it’s all been base64 encoded into the URL itself.

Take this crazy looking URL, for example:

https://itty.bitty.site/#How_it_works/XQAAAAJdDAAAAAAAAAAeHMqHyTY4PyKmqfkwr6ooCXSIMxPQ7ojYR153HqZD3W+keVdvwyoyd+luwncAksxo8PWJs+831jtAVty8rDpGXmyebtxMTP3PSa4g8/593sWue8WaPjJZKXPqJ+G6ffUrBFhdclCfPRZ1gVobusxdd5g4xI5328XhoOoeADUFQZMeRzfBVzcSlEdUqLcxhD5c7kYCBo79g1FR9+rRyw0U3Jyc+5Axt5HWUqKPcEBfQpO35dwvNhCOOZQ/83PRzl51VrpqJ+zwl7UT1JUUK24g/b9zCUO6EIGg1bcZW0VBL53SSK4LE+UkJNv3WKY04UQnISAISa4WghBZjXT5ID0S61leAohaQ9Kqkv6fGfZKI+RFa0bqnsYAHjZZQce8enN9zmfqYR/KIuNnoHmpY9M0W0okWY00CsBUYMdGh1tuE9dypij8nGhJnV61wgkafLJGNsg71mZFmumJRFRdjhuoORlUot67GJomgzUTr5dksBkTokx2zOQKMVW3M1yIQfy3ylY4txUf1icCDjf+Xs2Zhcm51cFucwhLfPIMfGfvlDOh4LtSQxlTu9YfZl4+H6fBMeVed/EqzEOwXAH21SiHUWBzxU8iwSNdHa48CvP41ozlThFVKKpWP290FN8UAcKd8smsf4YKLuDFHqoMyZILv1+k4ZhqEfXKO0Ky7oHaI7xLacv0mihhxK6Kz2jYlwFIsi3E8Mo8miWTIGcyZXCpwmsYzuKDigv5ZFGkw/VhOrQV/wLyqoa707i7PKnJE9BT1mhWpzonBLME6S7afa1CB3FqcPp7+/vRJbrKH9LqXpwUgzbdIl67YqgXBls5enwQ5mWgU23HC3Es60D0mBCALFNIsm/5HPLPWBwJrkfmx/JNPvnt2YLLeopCva1nY3cINXEfpGRtm2/j/F19PWFNJ0BW98k9KqaQNYduYlQN6Xjctewe2mRNM8k9CKaVet5pJ/eWshL8iMwje5sIX8MI09TGetVqAsgw6U+2F6UcqJPXFyJrGvdxeK6P5Zi9tSLQr5hByMK9mgXUfPuAL+Sazf/jt2UTMmHtr0yCaYTgw8bu/+Bzdo+eaE3J/ZVlTPPr2alSi6SmVSWGlYbcTIQZMA5KpF4GZFGowyxQUbndHhP/J1yY1SZ9G8YBktTaoGkXL2CDo6u498VrB6f7+oS5MOe3pK2/YzghZKLtMq1yzdnFlyekKyOSjppwbwkYJlLn96JOOpFxPHC2AZmUhfRbyYLNTrEQottY5z2Y/ERJTXMhTOtkE2Ba5LIrkrR3/7zjQTY5EF2plyx8xKwd07hrzZJ5tjUL3o2Hz+TsTs7glon64LbdmEZ6gH0acX7GrzdedQPdcElyDx+ByFW6l+IXDxShmeWlOBsMh0EOT5LC2y9UO9ZsNvdq21EAIiqTEOCf8xqm88r22q/A+uDmQHNhPG9s6zjoLmIaWugZWSy4Ab9wGC0+iTriRnLiePMQayw6bJ03G5Hoq+VKIF5y7OV2ijQtUkqqjDpGwkFSjwgirudMVeVhekZf7uMcCyT3JDLaTbMUVEtji2eL3fugR+yx8WYE99rczKeSpH7KBW4Vvs2cdy+42YZkZC9Ajnm3y1g6ljqE5/a3amHTXs4SH5TutdTeXKYI9fD6MHjmSWG2G8/JRjMGYVFhKpQs93CSaINQ3vGJYki5FP9aGDWqS7RlxXnUKgImK5upLy4XgmYQxQwoMYhj5JbfGyz5jqw+JlxK8XUkr+AQApWG/9suBe6BCgoAQRdgRjkMJGVdNwbCCCNs5ri/8kDwKahl6TAI4cO5B8QNg9KF1UalldlyMd3ITCHrcKkof1ZLGpHULGHvCcTC3IFANcd1hhNwyapdQPQQjiEqSBqP63kae39ehNXpbEjLk3vPypTX73p3D5/NxBUUqJgDSkKvs2zkKSfIXproiyqFQIxJgu+NFBYppkjkxQUzPRfhaojDES5jFdPMQGGCUG+en0zDihgNSJFnim/WHnUw89LXCQS96tbuW3Ym8RoGUIOzw9IjpWq8DJq3YY26TZu3WtqHUaSEUN0BBnUjAz+SR/hI3ellqVIK069hk8zGu7cdsRlGuRtUDnVeqMPX3M9VqGd7Qw8A9dV6XbjUP0DZTp4Xiqyj2IfXOG+qGAqCfPkKzaSW//XuArU=

This link contains all of the HTML and CSS that makes up the website. The really cool thing about this is that you don’t need a server to make an itty.bitty site — once you paste the link above into the browser it’ll fetch some code from the itty bitty domain then extract and inflate the data from there.

I’m not entirely sure how useful this is but it’s certainly a novel concept to me! Go ahead and start making your own itty.bitty sites.

Direct Link to Article — Permalink

The post itty.bitty appeared first on CSS-Tricks.

Little Tip: Draw Your Grid in ASCII in Your CSS Comments for Quick Reference

Say you declared a grid like this:

body { display: grid; grid-template-columns: min-content 1fr; grid-template-rows: min-content auto min-content;
}

This depends on content, for sure, but how it’s likely to play out is like this:

+---+-------------+
| | |
| | |
+-----------------+
| | |
| | |
| | |
| | |
| | |
| | |
+-----------------+
| | |
+---+-------------+

That’s really easy to draw out quick in ASCIIFlow Infinity.

Now you want to place elements in that grid, and arguably the easiest way to do that is to specify the grid rows/columns they should start/end at.

/* grid-area: row-start / column-start / row-end / column end */ .logo { grid-area: 1 / 1 / 2 / 2;
} .site-header { grid-area: 1 / 2 / 2 / 3;
} .sidebar-nav { grid-area: 2 / 1 / 3 / 2;
} .main-content { grid-area: 2 / 2 / 3 / 3;
} .site-footer { grid-area: 3 / 1 / 4 / 3;
}

There are other ways to do this. You could use longhand CSS properties. You could name the areas. But say you like doing it this way because it is succinct or whatever. That’s where the ASCII is useful! Leave it in a CSS comment and number the lines.

/* 1 2 3
1 +---+-------------+ | | | | | |
2 +-----------------+ | | | | | | | | | | | | | | | | | |
3 +-----------------+ | | |
4 +---+-------------+
*/

Now you’ve got an visual reference to pick out those grid numbers from.

If you like native apps and wanna get real fancy, there is Monodraw.

The post Little Tip: Draw Your Grid in ASCII in Your CSS Comments for Quick Reference appeared first on CSS-Tricks.