Lucky Logo

# Swapping out the HomePage

It’s nice that we can boot our application and see a home page, but we know that page won’t stick around. We will swap it out for our own Home page to make this site a little more ours.

First, we should create a new Page. We will use the gen.page CLI task. Enter lucky gen.page Home::IndexPage.

lucky gen.page Home::IndexPage

This will generate a new Page class in src/pages/home/index_page.cr which we will need to make a small change in. Open that file, and update this code:

# src/pages/home/index_page.cr
- class Home::IndexPage < MainLayout
+ class Home::IndexPage < AuthLayout

The MainLayout is currently setup to be our site layout for users logged in to the app. The AuthLayout is used for pages like the login/signup pages, and now our Home Page. Eventually, you’ll be creating your own layouts to better suit your needs.

Next, we need to tell our root action to render our new page instead of the default Lucky page. Open up your Home::Index action in src/actions/home/index.cr. Update this code:

# src/actions/home/index.cr
- html Lucky::WelcomePage
+ html Home::IndexPage

The html macro here will take the page class we want to render, and mix the content with our layout.

For more information on rendering HTML, read the Rendering HTML guide.

# Updating the Layout

As mentioned previously, we currently have two separate layouts. One for when users are logged-in MainLayout, and one for when users are logged-out AuthLayout. These files live in the root of your src/pages/ directory. We will update our AuthLayout to start so we can get a feel for writing HTML in Lucky.

When it comes to writing HTML in Lucky, we use plain Crystal methods that generate HTML for us! Read the Rendering HTML guide for more details.

# Anatomy of the layout

Open up the AuthLayout in src/pages/auth_layout.cr. This file has a render method which contains the start to our HTML. Within this method are several other Crystal methods like html_doctype, html, and body which should be pretty recognizable. Any HTML tag has an associated method you can call from here. In addition, there’s a few helper methods which are explained more in the HTML guide.

Two methods that may look unfamiliar are mount, and the content method you see inside of the body block. The mount is related to Components which we will cover later. The content method is used to render the page content from pages that inherit from this layout. For example, our Home::IndexPage inherits from AuthLayout, so the Home::IndexPage has a content method where all of the Home page HTML will go.

# Adding a wrapper

Let’s update the html block, and replace it with this code:

# src/pages/auth_layout.cr
html lang: "en" do
  mount Shared::LayoutHead, page_title: page_title

  body do
    mount Shared::FlashMessages, context.flash
    main class: "main-content" do
      content
    end

    footer class: "footer" do
      div class: "container" do
        span "CloverApp", class: "text-muted"
      end
    end
  end
end

As you can see, we can write methods that match up with HTML tags like span, div, main, and footer. We can even add our own custom CSS classes by using the class: "" argument of each tag method.

Boot up your app (lucky dev), and give it a shot! See that you now have “CloverApp” displaying below the content of your Home page.

# Adding a CSS framework

You have the flexibility to use any (or no) css framework you would like. Lucky comes with Bun out of the box allowing you to add in packages as you need. For the purposes of this tutorial, we are going to keep it very simple and use SimpleCSS

# Installing a CSS framework

Before we install SimpleCSS, we should shut down our server. (ctrl-c) Then from the terminal, we can run:

bun add simpledotcss

Next we will import SimpleCSS in our stylesheet. Open up src/css/app.css. You’ll find some default normalize styles in here.

Add this to the top:

// src/css/app.css
@import "simpledotcss/simple.min.css";

Finally, restart the dev server from the terminal lucky dev.

For more information on handling assets, read the Asset Handling guide.

# Updating the Home Page

Now that we have a layout, we can update our Home page to match our new styles.

Open up the Home::IndexPage file in src/pages/home/index_page.cr. In here, we will see the content method defined. This is the method that’s called in the AuthLayout class. In this content method we can see the h1 method. Let’s update that with this code:

# src/pages/home/index_page.cr
def content
  div do
    h1 "CloverApp", class: "title"
    div do
      para "It's your Lucky day! See a fortune, and share the luck.", class: "tagline"
      div class: "button-group" do
        link "Join", to: SignUps::New, class: "btn-primary"
        link "Login", to: SignIns::New, class: "btn-secondary"
      end
    end
  end
  div class: "container" do
    # we will use this later
  end
end

Notice that we’re using the link method. Your first thought might be “Why would we use the <link> tag here?”. This is one of the few exceptions to the “every tag has an associated method” rule. In this case link creates an anchor tag <a></a>. The to: argument takes a Lucky Action class allowing the links to be type-safe and more future proof.

The other new tag here is para. This replaces the <p></p> tag due to Crystal already having a p() method used for printing to STDOUT.

For more information on special tags, read the Special Tags guide in Rendering HTML.

# Your Turn

We’ve created a layout and a new home page. Now it’s your turn to play with some HTML.

Try this:

  • Add a copyright note to your footer that always displays the current year.
  • Create custom CSS styles using normal raw CSS in your src/css/app.css.
  • Apply that custom style to a tag on your Home Page.
  • Update the styles for your Login / Signup pages

If you have existing HTML you want to convert try the HTML to Lucky Converter utility.

See a problem? Have an idea for improvement? Edit this page on GitHub