Quick Start Guide

Before starting, make sure you have installed Hologram correctly by following the Installation Guide.

Let's build a simple blog application to demonstrate Hologram's key features. Our blog will have:

Creating the Layout

First, let's create a layout that will be shared across all pages:

defmodule Blog.MainLayout do
  use Hologram.Component
  
  alias Hologram.UI.Link
  alias Hologram.UI.Runtime
  
  def template do
    ~H"""
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <title>My Blog</title>
        <Runtime />
      </head>
      <body>
        <nav>
          <Link to={Blog.HomePage}>Home</Link>
        </nav>
        <main>
          <slot />
        </main>
      </body>
    </html>
    """
  end
end

Creating the Home Page

Now let's create the home page that lists blog posts:

defmodule Blog.HomePage do
  use Hologram.Page
  alias Blog.Components.PostPreview
  
  route "/"
  
  layout Blog.MainLayout
  
  def init(_params, component, _server) do
    posts = [
      %{id: 1, title: "First Post", excerpt: "This is my first post"},
      %{id: 2, title: "Second Post", excerpt: "Another great post"}
    ]
    
    put_state(component, :posts, posts)
  end

  def template do
    ~H"""
    <h1>Welcome to my Blog</h1>
    
    <div class="posts">
      {%for post <- @posts}
        <PostPreview post={post} />
      {/for}
    </div>
    """
  end
end

Creating a Post Preview Component

Let's create a reusable component for displaying post previews:

defmodule Blog.Components.PostPreview do
  use Hologram.Component
  alias Hologram.UI.Link
  
  prop :post, :map
  
  def template do
    ~H"""
    <article class="post-preview">
      <h2>{@post.title}</h2>
      <p>{@post.excerpt}</p>
      <Link to={Blog.PostPage, id: @post.id}>Read more</Link>
    </article>
    """
  end
end

Creating the Post Page

Now let's create a page for individual posts with a like button:

defmodule Blog.PostPage do
  use Hologram.Page
  
  route "/posts/:id"

  param :id, :integer
  
  layout Blog.MainLayout

  def init(params, component, _server) do
    # In real app, fetch from database
    post = %{
      id: params.id,
      title: "Example Post",
      content: "This is the full content...",
      likes: 0
    }
    
    put_state(component, :post, post)
  end

  def template do
    ~H"""
    <article>
      <h1>{@post.title}</h1>
      <p>{@post.content}</p>
      
      <div class="likes">
        Likes: {@post.likes}
        <button $click="like_post">Like</button>
      </div>
    </article>
    """
  end

  def action(:like_post, _params, component) do
    # Update likes locally first for instant feedback
    put_state(component, :post, %{
      component.state.post | 
      likes: component.state.post.likes + 1
    })
    |> put_command(:save_like, post_id: component.state.post.id)
  end

  def command(:save_like, params, server) do
    # In real app, save to database
    IO.puts("Liked post #{params.post_id}")
    server
  end
end

Key Concepts Demonstrated

This example demonstrates the basic building blocks of a Hologram application. The framework handles the client-server communication and state management automatically, letting you focus on building features.

Remember that Hologram keeps state on the client side for better performance while using commands for server-side operations when needed.