Skip to main content
View on YouTube to comment and like!

about 2 years ago Syntax Podcast

Hosting Private Fonts on the Edge With Cloudflare

Wes Bos

Wes Bos Host

Scott Tolinski

Scott Tolinski Host

Topic 0 06:37

Pages vs Workers for serverless functions

Scott Tolinski

And the first question might be, like, why not a bucket? Because the bucket seems like it makes a lot of sense. Right? You just dump the font in the bucket. You set up your access rules. You access the font. That's the easy way, I think. Yeah. And that works perfectly fine. In fact, I I actually did that at 1 point here JS part of my testing. It worked So Yes. So right. You know what? It it was a tough problem with this course, and I don't know if this is the final best,

Wes Bos

files. You know? And I always reach for, like, a Deno JS or or something like like SvelteKit just because you want the a little bit of baked in routing and some helpers.

Scott Tolinski

Yeah. Because when I did it with workers, this was it. You Node? You grab the path name. You're splitting the path name and checking the path for,

Wes Bos

something like SvelteKit. Right? Yeah. I was always surprised that Cloudflare Workers doesn't have the idea of, like, folder based routing, you know, like a very light routing where you wanna have a couple

Scott Tolinski

path server dot t s.

Scott Tolinski

So in something like SvelteKit with the routing system, you're you're just creating a route and that route is going to essentially function exactly like a CloudFlare function is because that's the way it bundles itself up given the CloudFlare adapter here. So it's not like I'm running a big old Node application to do this even though it is using And and I don't need to do that much with serverless functions, to be honest, was what's the difference practically between,

Scott Tolinski

And that can be done with a simple file store. It's a, like, a key value store.

Topic 1 17:33

Efficient caching for multiple origins?

Wes Bos

need to be used no way we sent the syntax domain ownership that I was like it was like a starter. Right? And then the people who own the the premium plug in, they're like, hey. They sent a DMCA. They didn't even ask me to take it down. They just DMCA'd it. Oh, yeah. I don't know if that takes it, like, out of the Git history. Probably that's why. Right? It probably scrubs Git history from from being in there, and I realized, oh, yeah. You probably shouldn't be doing that type of thing. The fonts 1 is is really tricky though because That's good. We should get that on,

Scott Tolinski

You're you're still breaking the license if you use it. So

Scott Tolinski

URL for each whitelisted site. Like, maybe that's it. Maybe you append something with the whitelisted site to the URL, and that's that's how you get around the caching there.

Scott Tolinski

the the long story about, like, stealing a font file is no one's ever going to prevent you from stealing a font file. There's an endless amount of ways to get to a font file even in these scenarios where you're you're trying to protect it. That's not gonna happen. You know? If if if font file JS being loaded, people can access it. So loading it up in local host and downloading the fonts, not a huge deal.

Wes Bos

they'll figure out

Wes Bos

based on 1 each.

Scott Tolinski

string. You parse part of that string, and then now you have a custom because all it would be doing would be appending a URL

Wes Bos

get you to buy it? And it's really interesting because you what you type in, like like,

Scott Tolinski

I don't know if this is the right solution to this. So if you're out there and you're a header whiz, individual functions, which are, you know, CloudFlare functions.

Scott Tolinski

Okay. So it it does allow it. Okay. Yeah. Which at that point, if you wanna load up our site and no one's gonna

Wes Bos

Can you put yeah. Oh, yeah. We got lots of it. Actually Oh, man. Oopsies. The loons are really interesting because that much. Like, I there's some of these font websites, and I was always really curious. Like, how do these font websites multiple URLs in and allow origin?

Wes Bos

it will

Wes Bos

people will

Wes Bos

Oh, I see.

Wes Bos

Okay.

Wes Bos

for, Oh, wow. Every time we hear, we're like, oh, no. And it's usually when there's, like, a sea dew or we just had Canada Day yesterday. They hate the fireworks. But and try to, like, repopulate it. It's very good at that. But the actual ownership of the domain name, you cannot go Cloudflare to Cloudflare account. Wow. Yeah. Thanks. We don't we don't have that issue with the syntax. Like, we

Scott Tolinski

Yep. Yeah. So, yeah, if you're out there and and you have a better solution for this for headers, let me know. I thought this was just an interesting project, an interesting idea. And if you wanna see, like, maybe what working inside of a a worker like this is like to accomplish something like this, the code is all public. We'll have it available in the show notes. That's all I have for you today, Wes.

Scott Tolinski

and I'm serving this to multiple different origins, the big question is, how do you efficiently cache this,

Wes Bos

And how does this work on, like, local host then? which can be tricky if you want to try to convert that back to something that works ESLint, like, a Figma, Yeah. The the way that people get around people stealing fonts is they do not serve up all of the weights.

Wes Bos

which is it's probably very frustrating

Scott Tolinski

yeah.

Scott Tolinski

accepting coding refer header comes in. Now Oh, okay.

Wes Bos

testing testing 123, characters and then bring it back. So there's some pretty tricky canvas too. Yeah.

Wes Bos

and only compile the font for Yeah. And they were able to, like, embed my videos or something like that. Yeah. And, I was like, oh, yeah. I have to actually check. And then I I moved it from just like a a checking strings. I moved it to, like, a proper I got the windows open right now. You guys got loons up there? Is that a thing? You got loons? Tons of loons. Yeah. You can JS that a thing? The we our money is called the loony. Oh, yeah. Like

Scott Tolinski

string URL per website.

Scott Tolinski

The last little thing might be just to use the fonts. You just load it up with think it's fonts.tolin.skiforward/thefontname, correct solution here. But this is currently working for us.

Scott Tolinski

to multiple different origins? I guess the answer might be, Wes, to have

Scott Tolinski

I don't think so. Maybe worth Googling. Yeah. Yeah. Let me the ENV PIN. Now as long as that ENV variable doesn't get leaked, I'm golden. Right? intelligence from the brightest minds in the space, check it out. We'll have a link in the show Node. You could sign up and, yeah, give it a watch. It's gonna be really neat. So let's get into the problem here. What's going on? What happened? Well, nothing really happened. We just have the fastest approach or something. Google Fonts is, like, crazy, crazy fast. But, ultimately, Taylor Otwell,

Scott Tolinski

a unique to work the way I want it to depending on how the variable font was created. So, I have a lot of, interesting things I learned about variable fonts involved in this. Okay. So I I put these into a worker. And what about the fonts themselves? I actually put those into Yeah. Yeah. That's a, a touchy topic right there. Ultimately, again, you're not gonna be able to prevent somebody from getting a font no matter what. So, hey. It's all about, you can your foundry.

Wes Bos

allow you to test it on the website but also

Wes Bos

They only serve up the WAF 2, Yeah. I I always hate that because you can't, like, select it, and you can't see the browser rendering, and it doesn't, like, wrap and things like that. So some of the the really nice websites allow you to, like, actually use it on there,

Topic 2 21:40

Project code available publicly

Wes Bos

all of the parts of the domain name also move over. So there's currently to transfer a domain name over. It will, like, suck up the DNS if you wanna, like, design with it. And then also,

Wes Bos

access control attached to a domain name. You can have, I forget what it was. Essentially, I was, like, checking if the domain name had, like, west Bos .com in it, but then somebody figured out that you could do, like, west boss.com.whatever.whatever.

Wes Bos

but we have to like, I have a couple workers on there, a couple subdomain names. I gotta move all that over, and that just doesn't seem at all. The registration I'm talking about the registration, not the, like Yeah. Not the being, not the, like, being in Cloudflare. So I had to transfer it Peace. Peace.

Wes Bos

You can obviously use it right away because you can still add it to Cloudflare, but it's a Why why would it use that? a course issue?

Wes Bos

fun. There's some some golden rule that should be there. It's like never do anything on your personal like, font boundaries with that. There's no there's nothing built in. Like, there's no DRM built into the browser for specific fonts.

Wes Bos

syntax domain. Oh, it's because we gotta move the syntax

Wes Bos

I'm betting that does a font face

Wes Bos

of

Wes Bos

out of Cloudflare to Vercel, and then you have to wait 60 days and then transfer it all back over to the Air Cloudflare.

Wes Bos

moving Cloudflare. Did I did I did I tell you that I had a domain name on Cloudflare, and I needed to transfer it to somebody else also on Cloudflare.

Wes Bos

Alright. Thanks everybody for tuning in. We will catch you later.

Wes Bos

Yeah. And it is not possible

Scott Tolinski

a pain. It always feels like the the right thing at the time. You're like, I just need to get this done. Oh, yeah. Yeah. Okay.

Wes Bos

But I think people probably assume that

Scott Tolinski

Pretty speedy.

Wes Bos

has so much to whatever Sanity uses, our hosted fonts and then just hotlinking them in their own website

Wes Bos

You know, Wrangler stuff. All of the stuff is attached to a domain Node, and it might be simple to think like, yeah, let's just move it over.

Wes Bos

account. Ever. Yeah. Just Yeah. Moving it over is Awesome.

Wes Bos

because Cloudflare

Wes Bos

like, the tunnels.

Scott Tolinski

Cloudflare over to the syntax. Yes. Yeah. Yes. This is a a major conversation while you were gone. I was huge pain

Topic 3 04:41

GitHub DMCA for licensed assets

Scott Tolinski

and I'll pop over to that code. As you can see, you know, workers are great for doing little things. But the moment I started writing HTML templates and strings that started to look like this Wes the moment I was like, yeah. You Node? Maybe

Wes Bos

Those are better to put in, like, a, like, a CDN or at least put a CDN in front of it.

Scott Tolinski

I wasn't taking a performance hit by turning this into a pages function.

Scott Tolinski

and a worker speed wise? And it turns out, functionally, there's no difference there. They both function the exact same as far as Cloudflare is concerned. So, bingo bango. As long as the access is good, you're good, and it loads like a normal font, caches it forever, like I said.

Wes Bos

things like fonts being served up by my compute.

Wes Bos

like, you're running out of bandwidth emails from them where I, like, just squeak in under the month, and I'm thinking, like, yeah, I probably shouldn't have fancy stuff around domain names, because, like, you can have workers attached to a domain name. You can have, because that was frustrating. But sorry. That wasn't your question, though. What was that? No. No. No. That wasn't my question. But, the question is, do you think because we're paying for the bandwidth and we're paying for So this is essentially

Scott Tolinski

III need routing. I need pages. I need a little bit more here.

Topic 4 08:19

Storing fonts in Buckets vs KV store

Wes Bos

to be clear, a bucket JS, what characters

Scott Tolinski

Yeah. And and this also was a big change for us too. We're not gonna get too much into this aspect on this episode, but we we went from how loading, like, 6 or 7 fonts, Wes. I don't even know if you because you were on vacation for this. We went from loading 6 or 7 fonts to 1 variable font.

Scott Tolinski

And, consistently, the the worker and the pages were faster than loading it from a bucket.

Scott Tolinski

So these things were able to be stored as an act they're small enough to be able to store as an actual value and then caches that value and send along as a string data. So what I made is a a quick little font server using Cloudflare Pages. Node, initially, I wrote this thing with just a straight up worker, Local host is just whitelisted.

Scott Tolinski

the I converted this into a SvelteKit repo, of course. Now it it does feel like that could be considered to be, like, overkill for something like this. But what you Scott understand is at the end of the day, ultimately, I had, like, a couple of pages. 1, to be able to manage the white list for the fonts, because I wanted to be able to choose where I'm serving these things to. But also, I wanted to be able to have Cloudflare workers in general,

Scott Tolinski

And what I learned is that variable fonts have a whole host

Scott Tolinski

and my ID, and then I just passed in the font. And guess what it did? It's up those right into KV. And to be clear, KV is not like a, Sometimes

Scott Tolinski

I did this approach just to see just to see how it would work. Right? And I gotta say, after tracking performance so I I loaded up from a bucket, Here we are.

Scott Tolinski

Yes.

Wes Bos

just fine. And a bucket you can't unless you were to change the file name of the font, which

Wes Bos

like, a place where you can dump files. Right? And Correct. Have control over. And so, like, a font file at what dot warp 2 is the 1 that we're all using right Node. That would be good to just throw into a bucket.

Scott Tolinski

KV, which is a key value store, Either Yeah. 12 Nobody knows what mountain time is. Either give us eastern or Pacific. Well, you know what? It's showing the time zone I'm in, and I I'm trying to do this on the fly here.

Scott Tolinski

whitelist, which was an interesting approach because I was able to upload No? and inside of our allow origin header? So, like, should I remove the white listing JavaScript and have white listing being done entirely through Cors instead?

Scott Tolinski

the caching part is something that I'm going to wanna get your advice on, Wes, because we had some weird issues with caching, and I was occasionally having to turn off the CDN cache or or dump the entire Cloudflare CDN cache at various points.

Scott Tolinski

and then I go on and serve it with some hard caching. Now

Topic 5 14:17

Use Cors instead of whitelist code?

Scott Tolinski

quitting early because they're not allowed, I don't know if that's hard fact. I ran Yeah. I ran refresh without cache a 100 couple couple 100 times and checked the results. It was always faster. That doesn't mean that it's necessarily

Scott Tolinski

here. I'm loading the font as an array buffer here. So, like, if I'm the Lambo man himself,

Wes Bos

Okay. But I think I I went into this once. I had somebody, like, submit, like,

Scott Tolinski

Yes. Very much so. Okay. Because a a script tag does not. It does because I had a quite a bit of issues different strings just in, you know, just in case. But with this, again, I could use the the various SvelteKit routing stuff, and it just worked really nice. So this was really super easy. CloudFlare has a SvelteKit starter, so you just start with that if you wanted to use that type of thing. But, again, there's there's starters for everything.

Wes Bos

Yeah.

Scott Tolinski

because I Wes, in this case, this here's a thought I'm just having right now live because I am loading the font

Scott Tolinski

the whitelisting stuff that I'm doing here in JavaScript is worth it, or would it be better off just to have that all being done with the whitelist Cloudflare Pages function the font itself with a Wrangler KV key put with my Node space ID

Wes Bos

That's a good question.

Scott Tolinski

refer, which was reliable enough for Safari here.

Scott Tolinski

which actually, that's a whole another thing. Apparently, Safari doesn't reliably set the origin has put together And I think the concern initially for me, considering I didn't have a ton of experience with

Wes Bos

respect

Wes Bos

like a bug bounty to me where I was

Wes Bos

URL parser, it will go off and compile a version of the font only for that amount of,

Scott Tolinski

header. I don't know if you knew this. Oh, really? listened to on syntax, the CEO and founder of Supabase, So I I decided to throw this into a worker and a function.

Topic 6 00:10

Licensed fonts hosted securely with custom font server

Scott Tolinski

Okay. So it's 9 Pacific, Welcome to Syntax on this Monday hasty treat. We're gonna be talking about how we solved a problem that we had using some interesting technology.

Wes Bos

So every summer, you you hope that, like, a loon stays in your area. Right? Because they're they're, like, mean.

Wes Bos

Loons like, if there's 2 loons in the area, they'll, like,

Wes Bos

kinda like area of the lake.

Wes Bos

beavers or something like that, that's that's probably just outside.

Scott Tolinski

So what is that? 9 o'clock? Mountain time.

Scott Tolinski

a behind the code discussion with back end experts. What's so cool about this is it's going to be coming up soon after you're listening to this. So July 16th. We'll have a link in the show notes. It's a Tuesday

Wes Bos

Yeah. We love apparently, that sound is when they Yarn stressed out.

Wes Bos

Hey. Not too much. Excited to be here. I'm up at the cottage now for for a good chunk of the summer, which I'm pretty excited about. So I Scott my

Wes Bos

there's only 1 loon per

Scott Tolinski

at 10 MST.

Scott Tolinski

And this is it's gonna be awesome because it has a bunch of folks that have been on the show, but, even some folks that haven't, just really brilliant people. So, Paul Copplestone,

Wes Bos

cottage office right on the rock. Yeah. So if you hear

Wes Bos

every year, we see, like, 2 little Loon babies just trailing the mom, and we're happy to see it.

Scott Tolinski

I love the sounds they make. They're fantastic.

Scott Tolinski

Wow. You know what else I'm happy to see? I'm happy to see that Sanity

Topic 7 03:51

Google Fonts tracking prompts self-hosting

Scott Tolinski

we don't wanna throw them into our Deno. And then everybody can just search GitHub for our licensed fonts and download them directly from there. So Yeah. I took this as a fun little challenge to make something. Have you ever gotten a DMCA from a company for having something licensed in a GitHub repo? I haven't, but I'm surprised I haven't because I'm starting to see a lot. A premium plug in at 1 point

Scott Tolinski

because our fonts are licensed, But this is pretty much the whole thing.

Scott Tolinski

because of using, So if you're out there and you you know your headers in and out, and you have a better solution for this, I I'm thinking as we talk through this, which I think is a good a good thing to do, I think maybe having a custom URL not having Google Fonts? What about just loading the font when there's a font that is licensed? Now that 1 of the problems that people don't often talk about with Google Fonts, and this is not necessarily related to the licensing issue, is that Google, they put tracking into those font scripts.

Scott Tolinski

Google Fonts, you didn't have to have a cookie banner. Just something to be aware of that hosting your own fonts, even if they're downloaded initially from somewhere else, can be a good thing. Now many times, it's just as easy as dropping that font into your static folder and loading that bad boy up directly on your server with some caching, whatever.

Topic 8 02:29

Behind the code discussion on July 16th

Scott Tolinski

licensed fonts in our application

Scott Tolinski

JS many of you do. You Node, you purchase a font license, Now for security, what I did is I hard coded an access PIN, which is an ENV

Scott Tolinski

and sometimes that

Scott Tolinski

and Yagiz Nizipli, who is on here, he's licensee has a way to serve that font itself, and you just use that. Other times, you're just using Google Fonts. Right? But, like, what about so like you mentioned, we are caching the origin forever, but I'm serving these things to several different websites. So that's where the very, That's correct. Yeah. And that that's the intention here. So was this a overkill approach to something that could have been solved with a bucket? Absolutely. But you know what? I think these types of projects Yarn, like, the ones that we have the most fun doing. Right? We have this fun little problem of font hosting. I'm gonna try to build a custom font hosting service. And how am I gonna do that? Well, I'm gonna throw the fonts into a key value store,

Scott Tolinski

the founder of Laravel, Yeah. Yeah. And there's a lot of, a lot of strategies here, and I'll I'll talk about some of the things that I thought about or tried. And we can talk about if the decision I went with was ultimately the right 1 because none of these decisions are permanent. You can always change things. So, We had some fonts in our application, and our app is open source as you Node, but these fonts are licensed. And you Scott keep these licensed fonts secure. So we built a miniature little font serving platform to help us serve fonts with a white list across any of the sites that I'm using personally. My name is Scott Tolinski. I'm a developer from Denver, and with me as always is Wes Bos. What's up, Wes? No.

Scott Tolinski

as you,

Scott Tolinski

Node TSC the white list page,

Scott Tolinski

member. He works for Century now and has made some really incredible Yeah. He's got some cool perks.

Topic 9 16:30

Confirm font face respects Cors

Wes Bos

control over that type of thing, especially because you're you're caching it forever

Wes Bos

also makes sense, I guess. Like, the the whole idea JS, like, cash forever. And if you update the font and change the font name, right, like, put a hash on it. Wes, so that's a whole another thing. So the 1 thing that we're saving by doing the white list is this line. That's it. Loading the array buffer. But in in JavaScript

Wes Bos

would it be enough just to use the allow origin? I would think, like, if the the platform has it built in, I would probably lean on that. And I think the only reason people Scott of would opt out of, I would think so Brains out. Yeah. There's there's some gnarly. If you ever wanna, like, go down a YouTube rabbit hole, like, search up, like, loons being aggressive.

Wes Bos

Yes. Which means that if you ever want to update the allow origin, no. You're right. It's, yeah, it's taking spear each other's Really?

Wes Bos

some of the platform features is because if they wanted a little bit more, Yes. I'm just trying to wonder. Like, does

Wes Bos

with Chorus in this. So Okay. Okay. Good. Man, I don't know. Like, sorry. The the question was, is this

Topic 10 11:26

Summary of font serving architecture

Scott Tolinski

And, basically, I'm loading up the whitelist. I'm fetching it with a normal fetch request, and I'm throwing it into the the key here is that we have a white list. Whitelist is stored as a key value in the same key KV.

Scott Tolinski

Because, you know, it's not a hash password that had that password's being encrypted already. It's being stored on on Cloudflare. I don't have to worry about that, becoming publicly available or anything. So this was a nice little super easy auth, just a easy way to to lock this white list down. But that's really it. You know? I I'm in here. I'm running a function. That function is really just hitting a fetch where I'm posting to the white list. I'm stringifying the white ESLint. And on that, So, therefore,

Scott Tolinski

PIN that only I know. So anytime I wanna update the white list instead of having auth yeah. I just type in my PIN and hit enter. It checks to make sure that PIN is correct with the,

Scott Tolinski

just a text area.

Scott Tolinski

is

Scott Tolinski

all I'm doing with that for the post request here that's stopping this font from being loaded as an array buffer before being passed into a request. So that is saving me some compute. Is it not? However,

Scott Tolinski

which is right here, When a request comes in, I I check to make sure the origin is in the allowed domains, which is in our KV, Yes. You can't rely on the origin header for Safari. So I just had to use, of crazy new properties that you have to learn, like new syntax. Like, if I just set, like, font weight 900 on a variable font, it's not guaranteed from KV via the worker, and then from KV via Cloudflare Pages.

Scott Tolinski

I'm running platform E and V Scott fonts put. I'm putting the fonts into the KV as domains, and I'm stringifying them. That's it. It it's this couldn't be pnpm any more simple application. There's no date database beyond the KV, which is just a few values.

Scott Tolinski

Now to manage the white ESLint, again, the white list is just a KV store. So what I did to manage the whitelist is I'll pop open.

Topic 11 13:00

Private font hosting with whitelist completed

Wes Bos

stopping anybody from

Scott Tolinski

and see how that performs. And the truth is it performed really well. So a lot of really interesting stuff, and I I have to solve this code public if you wanna give it a try or check it out. Now, Wes, I have some questions for you as being, the JavaScript dude around here.

Wes Bos

the origin request would not match your allow list, and it would it would not send it. Right?

Scott Tolinski

So 1 1 of the things that we're doing here is we're handling the white listing in code. A lot of it is there's an actual white list, and we're checking is allowed domain using the origin, Yeah. That should be a good 1. Yeah. If you wanna get get some, 12 ESLint.

Wes Bos

the actual font. So if somebody were to try and import the font directly into their own website, yeah, sometimes you do want it to be part of your your source code. Right? I have some fonts in my render, and I always get, like, these,

Share

Empowering developers for over 286200333510 milliseconds!