Skip to content
/ gromer Public

gromer is a framework and cli to build multipage web apps in golang using htmx and alpinejs.

Notifications You must be signed in to change notification settings

pyrossh/gromer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gromer

Version

gromer is a framework and cli to build multipage web apps in golang using htmx and alpinejs.

It uses a declarative syntax using inline jsx like templates for components and pages.

It also generates http handlers for your routes which follow a particular folder structure. Similar to other frameworks like nextjs, sveltekit.

You can install this extension vscode-go-inline-html to get syntax highlighting for these templates.

Requirements

go >= v1.18

Install

go get -u -v github.com/pyros2097/gromer/cmd/gromer

Using

You need to follow this directory structure similar to nextjs for the api route handlers to be generated and run the gromer command.

Example

These are some components

routes/todo.go

func Todo(c Context, todo *todos.Todo) *Node {
  return c.Render(`
    <li id="todo-{todo.ID}" class="{ completed: todo.Completed }">
      <div class="view">
        <form  hx-target="#todo-{todo.ID}" hx-swap="outerHTML">
          <input type="hidden" name="intent" value="complete" />
          <input type="hidden" name="id" value="{todo.ID}" />
          <input class="checkbox" type="checkbox" checked="{value}" />
        </form>
        <label>{todo.Text}</label>
        <form hx-post="/" hx-target="#todo-{todo.ID}" hx-swap="delete">
          <input type="hidden" name="intent" value="delete" />
          <input type="hidden" name="id" value="{todo.ID}" />
          <button class="destroy"></button>
        </form>
      </div>
    </li>
  `)
}

These are normal page routes

routes/get.go

type GetParams struct {
  Page   int    `json:"page"`
  Filter string `json:"filter"`
}

func GET(c Context, params GetParams) (*Node, int, error) {
  c.Meta("title", "Gromer Todos")
  c.Meta("description", "Gromer Todos")
  c.Meta("author", "gromer")
  c.Meta("keywords", "gromer")
  return c.Render(`
    <div class="todoapp">
      <header class="header">
        <h1>todos</h1>
        <form hx-post="/" hx-target="#todo-list" hx-swap="afterbegin" _="on htmx:afterOnLoad set #text.value to ''">
          <input type="hidden" name="intent" value="create" />
          <input class="new-todo" id="text" name="text" placeholder="What needs to be done?" autofocus="false" autocomplete="off" />
        </form>
      </header>
      <section class="main">
        <input class="toggle-all" id="toggle-all" type="checkbox" />
        <label for="toggle-all">Mark all as complete</label>
        <TodoList id="todo-list" page="{params.Page}" filter="{params.Filter}" />
      </section>
      <footer class="footer">
        <TodoCount filter="{params.Filter}" />
        <ul class="filters">
          <li>
            <a href="?filter=all">All</a>
          </li>
          <li>
            <a href="?filter=active">Active</a>
          </li>
          <li>
            <a href="?filter=completed">Completed</a>
          </li>
        </ul>
        <form hx-target="#todo-list" hx-post="/">
          <input type="hidden" name="intent" value="clear_completed" />
          <button type="submit" class="clear-completed" >Clear completed</button>
        </form>
      </footer>
    </div>
  `), 200, nil
}

And then run the gromer cli command annd it will generate the route handlers in a main.go file,

main.go

// Code generated by gromer. DO NOT EDIT.
package main

import (
	"github.com/gorilla/mux"
	"github.com/pyros2097/gromer"
	"github.com/pyros2097/gromer/assets"
	"github.com/pyros2097/gromer/gsx"
	"github.com/rs/zerolog/log"
	"gocloud.dev/server"

	"github.com/pyros2097/gromer/_example/assets"
	"github.com/pyros2097/gromer/_example/components"
	"github.com/pyros2097/gromer/_example/containers"
	"github.com/pyros2097/gromer/_example/routes/404"
	"github.com/pyros2097/gromer/_example/routes"
	"github.com/pyros2097/gromer/_example/routes/about"
	
)

func init() {
	gsx.RegisterComponent(components.Todo, "todo")
	gsx.RegisterComponent(components.Checkbox, "value")
	gsx.RegisterComponent(containers.TodoCount, "filter")
	gsx.RegisterComponent(containers.TodoList, "page", "filter")
}

func main() {
	baseRouter := mux.NewRouter()
	baseRouter.Use(gromer.LogMiddleware)
	baseRouter.NotFoundHandler = gromer.StatusHandler(not_found_404.GET)
	
	staticRouter := baseRouter.NewRoute().Subrouter()
	staticRouter.Use(gromer.CacheMiddleware)
	gromer.StaticRoute(staticRouter, "/gromer/", gromer_assets.FS)
	gromer.StaticRoute(staticRouter, "/assets/", assets.FS)
	gromer.StylesRoute(staticRouter, "/styles.css")

	pageRouter := baseRouter.NewRoute().Subrouter()
	gromer.Handle(pageRouter, "GET", "/", routes.GET)
	gromer.Handle(pageRouter, "POST", "/", routes.POST)
	gromer.Handle(pageRouter, "GET", "/about", about.GET)
	
	log.Info().Msg("http server listening on http://localhost:3000")
	srv := server.New(baseRouter, nil)
	if err := srv.ListenAndServe(":3000"); err != nil {
		log.Fatal().Stack().Err(err).Msg("failed to listen")
	}
}

TODO:

Add inline css formatting

Add inline html formatting

About

gromer is a framework and cli to build multipage web apps in golang using htmx and alpinejs.

Resources

Stars

Watchers

Forks

Languages