Landing Pages With Clojure and Firebase
This tutorial will demonstrate a workflow for creating a landing page (with email signup form) for a new project. Part of The Solo Hacker's Guide To Clojure. Prerequisites: First Steps With Clojure.
Demo
Clone the Mystery Cows
repository and checkout the landing-page
branch. Run ./task setup
to
install a couple npm deps and download the Bootstrap source (if you don't have
npm installed, do that first). Then run ./task dev live
to start a
development server.
(I'm going to assume your environment has the ability to run shell scripts. I figure this is a reasonable assumption since Windows 10 has the Windows Subsystem for Linux. But if you can't run shell scripts, you can just look inside the files and run the individual commands yourself. I won't be doing much shell scripting anyway.)
A landing page (like this one) should open in
your web browser. Whenever a Clojure file changes on disk, the task we ran
will regenerate the public/index.html
file and reload the page in your web
browser. Try it out: open src/cows/core.clj
and change the nav bar so it says
"Mystery Sows" instead of "Mystery Cows" (which is a real
thing
in case you're wondering).
(By the way, the email form will give you console errors if you try to use it because it has a Firebase dependency which we haven't set up yet. More on that later.)
The code
This file uses Rum server-side rendering to generate the html. Things you may not have seen yet:
(for ...)
- destructuring (both sequential and associative)
Always worth a look.
Note that clj -m cows.core
calls the -main
function from src/cows/core.clj
.
This is where you can customize Bootstrap's CSS.
Do it yourself
Now, create a separate project for your own landing page:
-
Set up a skeleton for the project. Copy over
deps.edn
,task
andbootstrap/custom.scss
, then add a bare-bonessrc/yourproject/core.clj
file with just a "hello world" div. Also include a head section with the title and meta elements. Run./task setup
, then start the dev server and make sure it works. -
Generate a favicon (favicon.io). Place the generated files in
public/
and link to them fromyourproject.core
. -
Add links to Bootstrap from
yourproject.core
. Change the theme colors inbootstrap/custom.scss
(unless you want to leave it as "cowpie brown"). You can use use coolers.co or something similar to help you pick some colors. -
Write the HTML/CSS in
cows.core
. You could do it from scratch without too much effort, but I searched for "free bootstrap themes" and ended up on this one. If you take that route, use this site to convert the HTML to Clojure data structures. Wrap the output in a(defc landing-page [] ...)
as incows.core
. You'll have to do a little editing.For one thing, Rum is slightly different from Hiccup. Hiccup uses only strings for inline CSS, so you can't write something like
[:p {:style {:background-color "green"}} ...]
. Instead, you'd have to write[:p {:style "background-color: green;"}]
. Rum is the opposite way, so if you get any compilation errors, you may need to convert the strings to maps by hand.Also stick any images and CSS files from the theme you copied somewhere under
public/
, adding the appropriate links to the head section. I'd recommend rewriting the CSS intoyourproject.core
in most cases, but some things (like media queries) can't be written inline, so feel free to leave those in a separate CSS file. (See Garden if you want a 100% Clojure solution.)Finally, you can break up the HTML structures into separate variables and components like I've done in
cows.core
. For example, the "testimonial items" were originally three separate blocks of HTML, but I consolidated them into a component and afor
. -
For stock photos, I recommend pexels.com (that's where I got all the cows).
Once your landing page is looking good, the next step is to make the signup form actually work. We'll need to set up Firebase as we'll be using that for storing the email addresses (and for hosting).
-
Go to firebase.google.com and set up a new project.
-
From that website, create a Firestore database. After it's provisioned, click "Start collection" and set the ID to
signups
. Add a single string field calledemail
. -
Follow this guide to install the Firebase CLI. Once you get past the
firebase login
part, runfirebase init firestore
. -
Replace the the new
firestore.rules
file with the one from Mystery Cows. Those rules will let your signup form add new email addresses, and it will prevent users from reading or modifying the saved addresses. Runfirebase deploy --only firestore:rules
. -
In
cows.core
, you'll notice three Firebase:script
elements. Add those elements toyourproject.core
.The
:src
values are special "Hosting URLs" that Firebase can use to add the dependencies for you along with project-specific configuration. See here. -
Run
./task dev
(not./task dev live
). This will serve your app using the Firebase dev server instead of the npm live server. This is necessary so that the Hosting URLs will work. Unfortunately, you'll have to manually refresh the page whenever you regenerate theindex.html
file.
Now all that's left is to hook up some JS to your signup form and then deploy
the landing page. See public/js/main.js
and the signup form elements in
cows.core
to see how I did the former. Once you set that up, test out the
signup form. You can check the Firebase console to make sure that the email was
saved.
Finally, run firebase init hosting
and then firebase deploy
. Your landing
page should be live. You can hook up a custom domain now if you want, or just
use one of the provided domains. Later, when you set up a mailing list, you can
import the emails you get from Firebase. (I use Mailgun with some custom code
myself, but Firebase somewhat recently made a convenient extension for adding
new users to Mailchimp, so that could be a decent option. We'll go more into
that eventually.)
Next, add authentication.
Published 10 Feb 2020