17 comments

[ 4.8 ms ] story [ 44.4 ms ] thread
If you want the same thing with more controls and less building/maintenance, you can run Ghost on Digital Ocean for $5 a month
https://sendy.co/ is also a fantastic option in this area. It wasn't quite for us in the end (we have quite complex needs) but I gave it a good workout and it's pretty neat.
Digital Ocean can eat dirt for buying CSS Tricks just to send it to the graveyard.

Use Vultr, or Linode if you have to :)

I saw Google App Engine when skimming and had to check the date. The last time I launched a GAE project was in 2012.
Hello, author here! I used GCP as it was familiar and quick to set up on that basis — we use it as our cloud provider at my day job — but I’ve got no special allegiance otherwise. I’m curious what you would’ve expected in its place? A corresponding AWS offering? A more ‘bare’ hosted VM from a commodity provider?
If you are using GCP Cloud Run services are very nice
Hey if it works, it works. GAE still has a generous free tier. Most new stuff I’ve seen has been migrating to Cloud Run for more configuration and options.
Sorry for drive-by (accidental) criticism, it was really more of a joke than anything. I haven't kept up to date at all and I think I missed that GAE is now a general-purpose hosting platform now (iirc in 2012 it was specific to a Google-provided framework). I think I'd use GAE now on further looks, or I guess something like Render if I didn't want to use GCP.
Anyone know of any good cheap options for making a newsletter frontend that looks nearly professional-media quality? The closest thing I can find is Ghost and Wordpress templates that are nearly $100 to license.
Try Ghost's free headline theme, or if you want something really good splurge for a Ghost theme from Bright Themes.
> Some JavaScript on this site that’ll ask the backend to sign up a new user.

This makes me sad. The browser has perfectly good form submission stuff that doesn’t need JavaScript, and there’s seldom any actual reason to require JavaScript. Yet I find it increasingly common that web developers, despite perhaps (hopefully!) still using <form> and <input type=submit>, are somehow unaware of this and assume JavaScript must be used, and use JSON encoding, and trip up over CORs, and… and… Whereas in fact, you only need JavaScript to support seamless content changes based on the form submission (providing feedback or whatever without loading a new version of the page with just that alteration), and it’s normally perfectly reasonable to support normal form submission with just a slight enhancement if JavaScript runs.

Here’s an alteration of the newsletter form, which assumes that /subscribe is a regular HTTP form submission endpoint, accepting application/x-www-form-urlencoded form data and returning a basic message as an HTML fragment (or even plain text):

  <div class="hover-div blog-post-container pastel-depth-4 lift-on-hover" id="newsletter_signup" style="border-radius: 14px;">
  <h3 style="margin-top: 6px">Newsletter</h3>
  <form id="sign_up_for_newsletter_form" method="post" action="https://axleos-blog-newsletter.ew.r.appspot.com/subscribe" target="_blank">
  [… seven unchanged lines omitted for brevity …]
  </form>
  <script>
      sign_up_for_newsletter_form.addEventListener("submit", async function(event) {
          event.preventDefault();
          let response = await fetch(this.action, {
              method: "POST",
              body: new URLSearchParams(new FormData(this)),
          });
          newsletter_signup.innerHTML =
              response.ok
                  ? "<p>Signup successful!</p>"
                  : `<p>Signup failed: ${response.statusText} / ${await response.text()}<p>`;
      });
  </script>
A few notes:

• I’ve added the method, action and target attributes to the <form> element. The consequence of this is that regular form submission, if the JavaScript isn’t run for whatever reason, will submit the data to that URL in a new window, the idea being that the user just gets a new page containing “signup successful” and nothing else. (By contrast, on the current page, submitting the form will submit to the current URL with ?email=… added, appearing to the user as though the page has just reloaded, and it won’t be clear whether or not it worked.)

• I’ve shifted the <script> element from before the form to after it, so that the form exists when the script is run, so that it can do its thing immediately rather than being deferred until the page finishes loading by wrapping it in $(document).ready(function(){…}) (or addEventListener("DOMContentLoaded", function(){…}) would be non-jQuery equivalent, so long as it’s still an inline script). This is very desirable if the scripts are inline anyway, and quantities like this should basically always be inline for the best performance (seriously, inlining all your JS and CSS yields the best performance until surprisingly large sizes—far past 100 KB in practically all deployment and access scenarios, even with a warm cache). You only want ready dances if you’re deliberately loading the script asynchronously (which I will also defend as not unreasonable for something like this: the document is fully interactive without it, it can run later or even not at all and cause no problem).

• I’ve removed jQuery usage because it’s simply not necessary ($("#…") → document.getElementById("…"), .on() → .addEventListener(), $.ajax() → fetch()); all the native alternat...

Really interesting and actionable, thanks for the information and for the example code!

I don't have any web development expertise, and it's not where my interests lie, so I've been following a "google it and move on as quickly as possible" approach. That said, since I'm now making web tools, I do have an intellectual responsibility to learn the platform. I reached for jQuery just because I had a vague sense that it was a "web development thing", and didn't bother to learn the fundamentals of what exactly it was bridging, and whether those bridges were still relevant in today's browser landscape. I appreciate the callout, and will use it as an opportunity to learn more about the web platform.

Like you realised, I thought JavaScript was appropriate because I wanted to ensure that the user wouldn't be navigated to a new page when they submitted the form. I appreciate the quite tidy approach you've shared that achieves this when JS is available, and still does something reasonable when it's not!

You might like HTMX which essentially does the above with some declarative tags and a small JS library. It’s surprisingly powerful.
(comment deleted)