Skip to main content

Hello World Bicep

· 3 min read
John Reilly
OSS Engineer - TypeScript, Azure, React, Node.js, .NET

Bicep makes Azure Resource Management a great deal simpler than ARM templates. The selling point here is grokkability. This post takes a look at the "Hello World" example recently added to the Bicep repo to appreciate quite what a difference it makes.

hello world bicep

More than configuration

The "Hello World" added to the Bicep repo by Chris Lewis illustrates the simplest usage of Bicep:

This bicep file takes a yourName parameter and adds that to a hello variable and returns the concatenated string as an ARM output.

This is, when you consider it, the very essence of a computer program. Taking an input, doing some computation and providing an output. When I think about ARM templates, (and because Bicep is transpiled into ARM templates I mentally bracket the two together) I tend to think about resources being deployed. I focus on configuration, not computation

This is an imperfect mental model. ARM templates can do so much more than deploy by slinging strings and numbers. Thanks to the wealth of template functions that exist they have much more power. They can do computation.

The Hello World example focuses just on computation.

From terse to verbose

The Hello World example is made up of two significant files:

  1. main.bicep - the bicep code
  2. main.json - the ARM template compiled from the Bicep file

The main.bicep file amounts to 3 lines of code (I have omitted the comment line):

param yourName string
var hello = 'Hello World! - Hi'

output helloWorld string = '${hello} ${yourName}'
  • the first line takes the input of yourName
  • the second line declares a hello variable
  • the third line computes the new value of helloWorld based upon hello and yourName, then passes it as output

Gosh is it ever simple. It's easy to read and it's simple to understand. Even if you don't know Bicep, if you've experience in another language you can likely guess what's happening.

Let's compare this with the main.json that main.bicep is transpiled into:

"$schema": "",
"contentVersion": "",
"metadata": {
"_generator": {
"name": "bicep",
"version": "dev",
"templateHash": "6989941473549654446"
"parameters": {
"yourName": {
"type": "string"
"functions": [],
"variables": {
"hello": "Hello World! - Hi"
"resources": [],
"outputs": {
"helloWorld": {
"type": "string",
"value": "[format('{0} {1}', variables('hello'), parameters('yourName'))]"

The above ARM template expresses exactly the same thing as the Bicep alternative. But that 3 lines of logic has become 27 lines of JSON. We've lost something in the transition. Intent is no longer clear. We've gone from something easy to reason about, to something that is hard to reason about. You need to think a lot less to write the Bicep alternative and that's a good thing.

I was chatting to someone recently who expressed it well by saying:

ARM is the format that the resource providers understand, so really it’s the Azure equivalent of Assembler – and I don’t know anyone who enjoys coding in Assembler.

This is a great example of the value that Bicep provides. If you'd like to play with the Hello World a little, why not take it for a spin in the Bicep playground.