Well, if you've made it this far, I suppose we should start creating an app.

First, go here https://github.com/ahungry/puny-gui and clone the repo, or jump to the Releases section and download the one for your host OS.

In the future, if you invent something new, you'd likely repeat this same process in a fresh directory.

There are two main executable files to take note of, they are:

app.bin/app.exe

super-repl.bin/super-repl.exe

Essentially, they are pre-compiled Janet runtimes, packed full of useful C libraries that provide the features outlined for Puny GUI above.

"app" is the one you'd tend to distribute to users, and simply loads app.janet and calls it's (main) to start the application.

"super-repl" is the Janet runtime + Janet shell - if you've installed "janet" locally, it will seem very familiar (its just the "janet" binary with those C libs as builtins).

You can test out the dynamic nature of the REPL by making a new file such as "hello.janet"

Add this to it:

( defn main [ x ] ( print "Hello from Janet" ) )

Now run (in a terminal/CMD prompt):

./super-repl.bin hello.janet

See the pretty output? Neat right?

Next up, we'll try invoking the GUI. app.janet is already chock-full of GUI goodness, so just try running it:

./app.bin

Thats the kitchen-sink. It demos a lot of stuff at once (peek at app.janet if you're curious - you can see it imports from some other files).

Ok, back to this app. First off, if we're going to find cute puppies, we need a way to pull in their pics.

Lets implement that first.

Create yourself a file called dog-sdk.janet, and lets add some code.

First, we will implement a convenience wrapper written in Janet that makes working with C curl bindings more convenient:

( import lib/net/curl :as client )

Janet's module system is similar to the nodejs commonjs system. Had I not aliased it at the end, it would be under the "curl/" prefix.

Now, lets define some stuff:

# The remote endpoint we will request from - it returns a dog link ( def random-host "https://dog.ceo/api/breeds/image/random" ) ( defn get-random-dog [ host ] ( -> ( client/json-get host ) ( get "message" ) ) )

If you've used Clojure, that thread macro will not look very odd - if you haven't, it may be jarring. You can see the macro expansion in Janet via the macex call (similar to macro-expand-1 in Common Lisp).

Anyways, this small function will invoke json-get on the host argument, then use the Janet accessor to pull out the key in the json titled "message" (thats where the random dog image URL is stored).

Go ahead, try executing the code to make sure it works (if you use Emacs, you could set up inf-janet mode + janet-mode for a good REPL based workflow by now - if not, no big deal, you can do this all in Notepad even).

./super-repl.bin dog-sdk.janet

Oops! Nothing happened - that's because there is no 'main' in this file.

Ok, so you have two options - add a main, or call super-repl.bin without any arguments to have the REPL active.

If you chose to use the REPL, try this out next:

janet:1:> ( use dog-sdk ) nil janet:2:> ( get-random-dog random-host ) "https://images.dog.ceo/breeds/saluki/n02091831_3760.jpg"

Neat, it worked! If you wanted to add a main, you may have done so like this:

( defn main [ _ ] ( -> ( get-random-dog random-host ) pp ) )

Now when you run it with './super-repl.bin ./dog-sdk.janet', you see it prints out a URL.

Now lets get to the point of saving this as an image.

Fortunately, this is a trivial addition to what we already have.

Modify your code to look like this:

# Small SDK to get a random dog picture and save it to disk ( import lib/net/curl :as client ) ( def random-host "https://dog.ceo/api/breeds/image/random" ) ( defn get-random-dog [ host ] ( -> ( client/json-get host ) ( get "message" ) ) ) ( defn get-image-content "Fetches remote dog picture and saves to disk." [ url ] ( def img ( client/http-get url ) ) ( spit "dog.jpg" img ) ) ( defn main [ _ ] ( -> ( get-random-dog random-host ) get-image-content ) )

If you messed up or got confused, just peek at the "examples/dog-sdk.janet" file in the release you downloaded.

So, get-image-content is a new function - its job is to invoke the random url endpoint, and make a basic http request to the resultant image URL, then "spit" the code into a new file named dog.jpg.

Run this file and observe your new dog picture in dog.jpg