Noun.ly
E1

Noun.ly

Raph: Hey friends, and welcome
to the Deep Stack Podcast.

I'm your host Raph.

Lio: I'm your host, Lio.

Raph: This is the Deep Stack,
the Deep Stack Podcast where we

explore everything in modern and
not so modern application stacks.

Today we're gonna be breaking
down Lio's old project Noun.ly.

So Lio, do you wanna tell us about Noun.ly

Lio: yeah, it's a, it's a fun little
project that I started while I was,

uh, working at Microsoft a decade ago.

Raph: Nice.

Lio: in, uh, this was 2000, um, Actually
more than a decade ago, like 2011.

And, and Microsoft had entered
with Azure there, the cloud space.

And so there was a hackathon to come
up with, uh, cloud projects and,

and so Noun.ly is the project that
I built in that hackathon and I kept

building on after leaving Microsoft.

Actually it started as
it started@stinkybad.com

and I think the URL still

Raph: Excellent name.

Lio: I, well, why it was funny was
was a website, or is a website?

It's, it's a URL shortener, but it
uses nouns instead of like weird codes.

Right.

So Bitly and a tiny URL were very
big back then, or maybe still are.

And I found them frustrating, uh, to
share URLs with people, uh, in, in real.

They're unusable, right?

Because you got a code with like eight
Q p r capital seven, so it doesn't work.

And so I, I had this idea of using noun
only and, uh, announced using nouns.

And because it was nouns, I took a
domain name that was like an adjective.

So everything was kind of funny.

I ended up with stinky back chair, stinky
horse, stinky bat, you know, uh, unknown.

Raph: Yeah.

Lio: Um, So I, I build that, uh, and.

I build them on, uh, a very early
Azure, right, the 2011 kind of Azure.

Interestingly, Azure was one of the first
that provided platform as a service before

they even had infrastructure at a service.

You, you didn't even have VMs yet.

And so it ended up being like a
Azure website, I think it was called.

It was running on

iis.

Raph: remember that, like that term.

Lio: It was kind of fun.

I thought.

Uh, the experience was cool.

You, uh, you had the command line, you
started a new Azure website project

and there was like a dash dash GI that
would give you, uh, like a get in edited

folder and as well as a, a remote repo.

And then any get push that
you did, uh, they had their.

Builder, uh, that I, I
forgot what it's called.

Like something with a K that would look
at your files and then figure out whether

it was like a Python or a, uh, C sharp.

I think the initial, the first version
I, I built was C Sharp, and then it

would build it and, and push it and host
it and, and that experience to go from,

um, you know, using the command line to
get a empty folder and then get, commit,

get, push, and it was up and running.

Uh, I think everybody was still
catching up to, to that behavior,

uh, to that ex deaf experience.

So I, I really liked it.

course, it was, it was very microsofty,
you know, like, it was like C sharp,

uh, only I s no, no Linux containers.

Uh, so, um, so, so that was the,
the first version of stinky bad.

But then when I, when I left
Microsoft, that's when I started using.

Like more open source tools.

So I, I rewrote the app and, uh, D Lang
like that, that was like the, the, the

thing, the language that.

I used for my hobby, hobby projects.

Um, and so I, I, I, I,
I wanted to use that.

Uh, I started using, uh, instead
of, of course d if you push decodes

to the, to the Azure websites, I
didn't know what to do with it.

So I had to build my own, uh, But then
by that time, Azure websites had docker

support, so you could actually, uh, it, it
could, uh, host containers as well as raw,

Raph: What year was that?

Lio: Sorry,

Raph: What year was that?

That they started to
support Docker containers.

Lio: uh, I don't know,
maybe, maybe 16 or something.

2016.

Raph: Okay.

Yeah.

Lio: I don't remember, but
that was some much later.

Raph: okay.

Yeah, I was, I was surprised.

I was like, wait, that the, the
timeline, I, I, I thought it was just

like maybe a, a few years after, and I
was like, that's, that's impressive of

the, or that, that early on the, the,

container train.

Lio: that particular feature with Docker
containers got renamed a bunch of times.

Uh uh.

Now it's, even now I think it's called.

Uh, Azure website for Docker or something.

I, I, I don't, I don't
keep up with the naming,

Raph: Yeah.

Lio: yeah, so, so that the whole
stack from Stinky Bad has been

completely rewritten around that time.

Like maybe five, six,
um, Or two, 2016 ish.

So that's when I also got
the domain name, noun.

Noun.

Actually, that was a little
earlier, I think maybe 2015, to be

honest, because people liked it.

You know, people started
using it, uh, stinky bad.

I actually got, I, I got like a bunch
of emails from users that said, Hey,

I, I want to use, Uh, stinky on my,
uh, presentation, but I, I cannot

show stinky bad.com on, on at work,
you know, so is there a way I can

have a, a different domain name?

Raph: Yeah.

Lio: Um, and actually it, it was,
presentations was the perfect use case

because yeah, URLs in a presentation are
pretty much pointless because people can't

get it and they'll have to wait until
you mail if, if you mail them the deck.

Raph: Yeah.

Lio: And so around that same time, I got
the domain noun.ly as well as Noun.ly.com.

And I, I added QR code, code generator
so that on your slide you could put both

the noun as well as the, the QR code, uh,
which because the nouns are short, the

QR code kind of had a, uh, didn't require
very high resolution, right, because you

didn't have a lot of bits to put in there.

Raph: Yeah.

Lio: at that time, the new,
well now old, but the new

stack, uh, was, uh, built right?

So the backend was rewritten in D Lang
using, uh, these vid, uh, web framework,

which was back then was state of the art.

It was like asynchronous, you
know, all the, all the, the

good stuff, uh, co routine.

All the stuff that, you know, uh, the,
the new modern web frameworks and no

js, python, uh, rust, they, they all use
that same kind of architecture right now.

Fived is very dated.

Uh, um, but yeah, so
that's what it's using now.

So if you go to now, that's
what it's using, it's using

the fived at the backend.

Uh, it, it's not using any,
any front end framework.

Everything is.

Uh, pretty raw, uh, handwritten,
uh, Java script and css.

I, I think it, it was using, what's
the Twitter CSS framework called again?

Raph: Oh, bootstrap.

Lio: I guess so.

Yeah, bootstrap.

I think it was using Bootstrap.

I kind of forgot cause I haven't touched,
I haven't touched it in a long time.

Raph: You know what I love,
so I just went to the website.

I like that you have a
little beta, beta banner on

the top left.

Lio: beta I got from Google, so I'm,
that's, that's like a disclaimer

Raph: It's a, it's a 12 year old beta.

Lio: of beta.

Raph: Yep.

Lio: so the, the, so talk
about deep stack, right?

So front end is, uh, handwritten
html, uh, with, uh, cs.

Raph: That's, that's, uh,
called that artisanal HTML

Lio: Oh yeah, exactly.

Exactly.

Um, which to be honest, for that kind of
single page app, I really think I don't

need a, i, I don't need a framework.

Right.

Raph: I agree.

Lio: The, the jQuery's biggest
feature, the dollar sign I just

built as a, you know, as a one-liner.

And, and so to reference, uh,
elements, you, you, I, I use that,

uh, that same kind of, uh, style.

Um, uh, I al and, and so.

There's only one rest call basically
there you can, uh, create a noun

and you can dereference a noun.

So that's, that's pretty much it.

Uh, I also built, uh, two, uh, two
native apps for iOS and Android

Raph: Oh,

Lio: in similar fashion.

I, I, I didn't use any
framework for those.

Raph: are they still up on the app stores?

Lio: They should be there,

Raph: All right, cool.

Lio: honestly, I, I,
I need to revamp them.

I, I wonder if they.

Still work because as the

Raph: Oh,

Lio: of times the, the operating
system, um, get revamped and, and if

you do not recompile and re-upload
your app, they'll, they'll just don't

make it show up on the newer devices.

And so it's possible that, uh, it's not

Raph: longer listed.

Lio: It could be.

Yeah.

Raph: Yeah.

Yeah.

It's gone.

Lio: so I, I didn't use a
framework for the native.

Raph: Yep.

Lio: Partly because that, that
is kind of how I learn things.

And same, same as, you know, not using
jQuery and using JavaScript and, and

writing CSS and html, if you don't know
the pain points of doing that, I, I,

I don't think you'll, you'll know the
value that frameworks provide or which

framework even to go for because you, you,
you, you want to address that pain and

if maybe the pain isn't even there, like
in the case of of of front end for noun.

Honestly, there is no pain in
using JavaScript and XML http.

There was no fetch api, right, so the
XML http request to talk to a backend.

Honestly, it's, it's, it's not a big deal.

Raph: Yeah.

Lio: Incidentally, my team and
Microsoft was in charge of XML H

G T P request, so I did not have a
problem with XML H G T P request.

Raph: Yep.

Yep.

Lio: One of my first tasks joining
that team was actually, uh, xml, H E T

p request had been added to Microsoft
Internet Explorer by the office team.

I became a standard afterwards,
and then people started complaining

that that Microsoft browser
didn't support the standard.

So my first task was to change
XML H G T P request and Internet

Explorer to follow the standard.

So that was kind of a fun task.

So for me to use XML, H G T P
request was, was not a big issue.

If you know the, the quirks, it's,
it's a, it was never intended as,

As a beautiful API for external use.

It just became the begin
beginning of Ajax, right?

Um, um, so that was the front end.

And again, doing that handwritten full
circle loop really makes you appreciate.

When to use a framework, what
framework you to use, which parts

to use it for instead of blindly
using every feature available.

Right.

Um, and so the same for,
for the native apps.

This is, again, a, a,
a one page application.

Um, I, I didn't feel the

need to

use, like,

Raph: and Java.

Lio: so I think I, I used Kotlin on
Android and I used, uh, well Swift on iOS.

Raph: Yeah.

Lio: And, and, and here's my biggest
takeaway from this project was that

once you design your model view, uh,
view model, right, your, your model

view controller, the, the new model
view, view model, M V V M architecture,

once you design that architecture,
uh, it's the same for both apps.

And, and so defining what your model looks
like, what your model view looks like.

What your views look like.

That is 80% of the job.

Then translating that into,
translating that twice, once into

Swift and once into, into Kotlin,

Raph: Not a

Lio: it's really negligible.

Like it's, it's like, um, like the, I
I always say like, in our profession,

typing is the least of my worry.

You know, like designing something
like good architecture and, and a

stable, uh, resilient architecture.

That, that is the hard part.

Right.

So,

Raph: so what you're saying is chat,
G P T is not taking our jobs just yet.

Lio: Well, un unless they get
into, in, into the designing

Raph: Yeah.

Yeah.

Lio: Yeah.

So typing the same architecture twice,
once in, in Kotlin, one's in Swift.

No problem at all.

In fact, both apps are open source.

So, and, and if you look at them,
it's kind of funny, I, all the files

on the folders have the same name.

Just one is written for iOS and the other
one is, is written in, uh, in Kotlin.

And then there, there's, of course,
there's 20% is, uh, different

in the operating system, right?

Yeah.

You, once you get to storage, for
example, they all have their, their own

way of doing, uh, local preferences,
local store, uh, stuff like that.

Their, their fetch api, you know, the
HTP API is a little different, but

honestly, you, you write small, thin
abstractions and then the rest of your

app looks the same and it's beautiful
because you end up at the same box in.

And you fix them in both as opposed
to if you used to, uh, web frameworks,

if you use a iOS framework or, or
like one of those phone gap things.

I, I'm not a fan.

You get their own, they have their own
quirks and now you're one step further

away from the, the source of the problem.

And I find debugging a higher
level problem, always harder

than debugging a low level one.

Raph: Yeah, I can see that.

I will in a, in a future episode,
perhaps I will push back on

a little bit of that, but,

Lio: Yeah, I, I, I know exactly when
to appreciate those, uh, frameworks

after having, you know, doing
the, the, the manual work.

Raph: Yep.

Lio: Um, so we, we are going
through the stack, right?

We, we have, uh, art Artisan
Know, H M l, JavaScript, css.

Uh, Uh, native apps, uh,
Kotlin and, and Swift.

Um, our, our REST api, very
straightforward rest API

with just crud, crud, nouns.

Basically, you know, you can post, you
get a noun, you can delete that noun, you

can get it to the reference, the noun.

Raph: What, uh, what
database are you using?

Lio: Um, yeah, okay.

That is still Azure table actually.

So I, I wanted to, in that new world of
cloud, uh, they had introduced Azure.

Uh, Azure Blob Store, Azure Table
Store, and uh, there was a third one.

The, the very Early Storage
Services or Azure queue.

Yeah, those were the first three high
level storage services that Azure

provided back in the, the early tents.

And so I, I used Azure Table,

Raph: Okay.

Lio: is kind of like a
precursor to Dynamo, right?

Dyna might have been around
actually because a Azure was

really catching up on, on a Amazon
in the early, early cloud years.

But Azure Table was perfect because
they have this key value kind of

behavior and and the key is the nouns.

Raph: Wait, but so you had
this, you had this back in 2011.

Lio: right?

Yep.

Raph: Okay.

Lio: So I was using Azure Table.

I, I'm still using Azure
Table as a key value store.

Um, so as stinky, bad, and now only got
more popular, I, I ran out of nouns.

And so the nouns became limited in time.

So after 24 hours, your link
might no longer be valid because

it, there's like a garbage, lazy
garbage collection that's happening.

And, but you can get, and, and as nouns
are taken, You end up with more nouns.

So instead of stinky bad chair, you would
end up with stinky bad horse chair, right?

And, and still was fun.

Oftentimes you end up with
very fun combinations.

Raph: Yeah.

Lio: Um, and, and key value
store was perfect, right?

You have a, you have a key and, and the
value becomes the URL that is being de

referenced, but plus a bunch of metadata.

Uh, interestingly, as soon as these,
the site was up and running, I, I

got a shitload of spam because all
of these bots, anytime they see a

added box, they just put links in it.

Right?

You get like a lot of spam.

So, so in, in the backend, I, I, I
think 60% of the backend code is anti.

So I, I do like the, the, i I do like
a honeypot in the HTML form, right?

So that means like a bogus field with
like a, a, a display non CSS class

that bots, if bots put something in
there, then you know, it's a bot.

I, I reference, uh,
two external honeypots.

So there is the honeypot project
actually, that, that was cloud flare.

First project, uh, cloud flares.

Uh, before it was called CloudFlare,
there was honeypot, uh, project.org,

I think, uh, where people would, uh,
volunteer to put a piece of form on

their website that cloud honeypot.

So the early CloudFlare would, uh, use
to detect, um, bots and, and keep a, a.

A blacklist of these, uh, of
these bots, of these IP addresses

that these bots were using.

And so that was called a rbl, I think.

Uh, RBL stood for, um, request
block list or something.

I forgot what the R stood for.

Raph: Yeah.

Lio: Um, And so, and, and there's
another one, uh, spam house.org.

So I, these, both of these have
public RBLs and these RBLs, you can

query them using DNS is actually kind
of funny, an API designed on dns.

So to, to query these databases,
you would craft a, uh, DNS request.

So you would ask, what is the IP
for, you know, for this domain.

But the domain was not,
not a real domain, right?

So basically the.

You the, the, the IP address
that you want to query,

Raph: Mm-hmm.

Lio: uh, you, you pre-end
it to their, uh, RBL domain.

So I think it was like rbl
dot spam house.org and rbl dot

uh, uh, project honeypot.org.

And so you, you repent the IP address
and then it would return an IP address.

If it says not found, like, you
know, an X domain, uh, IP, not,

uh, or domain address not found,
then, then it was not in the list.

If it returns an IP address,
then that IP address instead

of, it's not a real IP address.

In fact, it would always be
local host, always do 1 27 0 0

x, and then the last digit, uh,
of the IP address actually tells.

Some metadata about, you
know, why it was blocked.

Raph: Okay.

I feel like I vaguely remember
coming across this many

Lio: Yeah, it's kind funny.

Raph: Yeah.

Lio: Uh, and so, and, and so I,
I did that, I did, uh, the form

honeypot two, uh, RBL queries.

And then there's a little bit of, um,
because my now only doesn't have a login,

so it doesn't have an idea of a session
and I didn't want to get into that.

Um, that, that is like a rabbit hole.

I didn't wanna get,

Raph: Yeah.

Lio: so to prevent spam, I
did, um, kind of proof of work.

So, so the, the no only JavaScript
when you post the JavaScript

calculates a bunch of hashes with,
with, uh, with the current time.

Uh, and the, and the salt that
keeps changing until that hash

ends in a number, a bunch of zeros.

It's kind of like how, how the
early, well, so how, how Bitcoin,

but also the early, um, cash hash.

So cash hash was an anti-spam,
pre pret Bitcoin, right?

Uh, uh, anti-spam mechanism.

And so inspired by cash.

The, the website, when you do a post
on ly form it, it does a bunch of

these iterations until it has a hash
with a bunch of zeros, and then it's

very quickly to test backend, whether
there's zeros in the, in the hash.

So using these, that's why I mean,
60% is anti-spam in, in the, in

the backend because of the actual
key value is, is very simple.

Raph: Wild.

Lio: Uh, Um, yeah, so, uh, we, the
storage is just key value store.

It can, honestly, it can be
any key value store because I'm

not using any, any fanciness.

The only fancy feature, it's
not fancy anymore because

now every store provides it.

The on the only fanciness is
the optimistic locking, right?

So if you have multiple.

Uh, customers going to the website,
multiple users going to the

website, and they, because of the,
the algorithm is deterministic

when it returns a noun for a url,

Raph: Mm-hmm.

Lio: um, it's not random.

Raph: Okay.

Lio: And so it's there, there's a risk
that both would get the same noun.

And so how do you prevent
this kind of concurrency?

And I'm using optimistic locking.

Optimistic locking boils down to
every record keeping track of aversion

and when the record is updated.

So for in, in the noun only case, the
key is the, the noun or nouns that you.

That you're about to get right?

So when a record gets updated, it
has to provide the version that it's

of the record that it's updating.

So if somebody wins the race, Then
your version would no longer match.

And, uh, and there's an iteration
loop a second time where it picks

another noun and, and it would try
again until it, your browser wins the

race and, and you get the nouns, uh,
displayed in, in your browser window.

So optimistic locking is how you avoid
like locking database tables, locking

records, all this kind of locking, which.

If you do not unlock, you know, you,
you can get into a deadlock, you can

get into, uh, a lock that that has to
expire before somebody can do something.

So, locking to me is
something to be avoided.

Raph: Yeah,

Lio: And, and now a lot of these
key value stores, right, Redis,

uh, NATS Dynamo, they all have this
optimistic locking, uh, as a pattern.

Raph: Yep.

Lio: Um, so, and then, then the
last thing I was around the same

time, I, I got to know, uh, Nick's.

So the next package manager, I've
been using macros, but with the NS

package manager and, and the NS package
manager and can build Docker images.

And it's kind of cool because
if you use Nix to build a Docker

image, the Docker image will g.

only stuff that is referenceable, right?

The, the, the way Nix works,
everything has a hash based on the,

the sources that were used to generate.

And so when you start with
your binary, which is my noun,

only the language binary,

Raph: Yep.

Lio: basically scans that binary.

And if there's a hash to TC
data at dc, data will be pulled

in if there's a hash to gyps.

Which the, there probably isn't
because it was using D Lang, but

it would pull that in, right?

So everything because of this, this,
this, uh, tree of hashing, uh, It would

only pull in stuff that are, is actively
being referenced by that, uh, that binary,

the, the, the final, the final binary.

So you, you end up with very small, uh,
docker images from scratch, basically

the, the equivalent, uh, as writing
your own from scratch and copying only

the, the, the stuff that you would need.

Raph: Yep.

Lio: So that was kind of cool.

Uh, not only really let me
experiment with all these utility.

Yeah, it, it's, it's, it's an old website.

Uh, the, the apps might have
been delisted, so it needs some

love and I probably need to spend
some, some time to, to revamp it.

Raph: so, so how are you gonna do that?

Lio: That's a good question.

Like I probably wouldn't
use D Lang anymore.

Raph: No.

Lio: not, not because of the language.

I think the language is still being
actively developed, getting new features.

Dealing is, is not well
known, but it, it's, it.

A lot of the features make
it into the other languages.

Like Rust has, has features that,
that started in D Lang c plus plus.

The new c plus plus has
features that started in D Lang.

So I, I really feel it's, it's kind of
fun having followed that language and

the design and the discussions behind
the features that are being added.

Raph: Yeah.

Lio: It, it taught me a lot.

It's just that 5g, the web
framework is, is really old right

now.

Raph: Yeah, their, uh,

Lio: I, and I'm.

Raph: a little, a little dated.

Lio: it's very dated.

I don't think there's a new modern
alternative, so I would probably

use like a go or type script

Raph: Hey, the latest, latest commit
to Vibe D was eight hours ago.

So

Lio: Well,

Raph: maintained.

I don't know how actively.

Lio: Yeah.

I, I, I think it is being maintained.

Yeah.

But I wonder how much of those are just.

Fixing breakage, uh,
happening by the compiler.

The compiler features are

being added.

Raph: it, it still hasn't
gotten to a version one.

It's still at 0.9 0.6.

Lio: There you go.

Yeah.

Not great.

Raph: Yeah.

Lio: So, uh, I wouldn't use
Azure Table probably as another

one of those things that, that I
don't think it got any features.

In fact, I, I.

Considering the size of my
data set, it's not big, right?

Um, because the nouns
expire after 24 hours.

The number of keys that I have to
keep in memory is pretty constant.

Doesn't change much.

It's not very big.

I could probably keep the
whole thing in memory.

Uh, of course, I cannot use local
memory, right as I have multiple

instances of my backend up and running.

They, they need, uh, like
a consistent memory store.

A consistent store,

Raph: Yep.

Lio: but I could probably
do it in Redis or Nats.

So I would use either one of those two.

Perfect.

In-memory databases, I
don't need persistence.

Like the, what is the worst that
can happen if I, if I lose all

my instances and, and all the
keys and the values are gone,

Raph: Mm-hmm.

Lio: like only the active nouns would've
been affected and which are not that many.

So that's probably the better architecture
as opposed to doing like a round.

To a persistent database
like Azure Table, right?

It's a little bit overkill.

Um,

Raph: Would you, you wouldn't, you
wouldn't switch to a, to a, a full,

full blown front end framework with

Lio: I could be tempted.

No, I I actually, I would be tempted too.

Raph: Yeah.

What would be the value there?

Lio: so,

Raph: for fun?

Or would there be some value?

Lio: yeah, maybe, maybe just for fun to

Raph: fun is valuable.

Lio: To, to me, a project like
not only is perfect, uh, ground

to, to experiments with, right?

Like, uh, what would it look like using
View, what would it look like using React?

You know, how and how do you compare,
like how do you quantify the costs

and, and, and, and, uh, the value
of these, uh, of these frameworks.

Raph: Yeah,

Lio: So the one that.

Um, the one that I personally
haven't used yet, but would love to

try and maybe now only would be a
occasion to try it, it's felt kit.

So maybe I, I, I would try that for now.

Only 2.0.

Get it out Data.

Raph: Yeah.

Finally remove that, that little flag.

Lio: Yeah.

So yeah, it's a fun little project.

Um, I still use it in my presentations.

Uh, there is, it has some usage.

I mean, I'm not marketing it.

Um, you know, if people
like it, let me know.

If people think if, if it
doesn't work, let me know.

If, uh, there's a feature you
would like to see, let me know.

It's quite, quite fun for me to e.

Raph: That's noun ly, right?

Noun ly awesome.

Lio: So a little, uh, Easter egg.

Raph: Yeah.

Lio: Uh, if you go to noun mom, m o m,
it's goes to a five video that one of my

friends got me when I launched Stinky Bad.

And so it still references
stinky bad, but it's hilarious.

Like I, maybe I should do a ask
the same guy to do a new one.

So, uh,

Raph: Oops, that's my camera deciding.

It has been half an hour.

Alrighty.

Thanks for listening.

We are building projects that should
make it a lot easier for developers

to build projects like Noun.ly.

Lio: Yeah, check, check out Defang.io,
which is making building web apps

cheaper, easier, and more resilient.

Raph: And check out the
Chewy Stack at gochewy.io.

A deep stack framework that helps
developers build better products faster.

That's Defang defang.io.

And gochewy.io.

gochewy.io.

Thanks again for listening, and
we'll see you on the next episode.

Episode Video

Creators and Guests

Lionello Lunesu
Host
Lionello Lunesu
Wanderer. CEO of Defang.io, building a better Internet.
Raphaël Titsworth-Morin
Host
Raphaël Titsworth-Morin
Builder of the Chewy Stack. Co-founder of Éphémère Creative. Trying to do some good in the world with tech and design.