Let it be hermes
* rename to hermes * use echo+htmx+templ stack * use code from delphi.market as scaffolding
This commit is contained in:
parent
97c25541e1
commit
abad39a2bc
|
@ -0,0 +1,15 @@
|
||||||
|
# go executable
|
||||||
|
hermes
|
||||||
|
|
||||||
|
# environment
|
||||||
|
.env
|
||||||
|
|
||||||
|
# templ
|
||||||
|
*_templ.go
|
||||||
|
|
||||||
|
# tailwindcss
|
||||||
|
public/css/tailwind.css
|
||||||
|
|
||||||
|
# js
|
||||||
|
node_modules
|
||||||
|
public/js/*.min.js
|
16
Makefile
16
Makefile
|
@ -1,2 +1,16 @@
|
||||||
dev:
|
.PHONY: build run
|
||||||
|
|
||||||
|
SOURCE := $(shell find fonts lib pages server -type f) main.go
|
||||||
|
|
||||||
|
# build binary for deployment
|
||||||
|
build: hermes
|
||||||
|
hermes: $(SOURCE)
|
||||||
|
tailwindcss -i public/css/base.css -o public/css/tailwind.css
|
||||||
|
templ generate -path pages
|
||||||
|
go build -o hermes .
|
||||||
|
|
||||||
|
# run code for development (no watch mode yet)
|
||||||
|
run:
|
||||||
|
tailwindcss -i public/css/base.css -o public/css/tailwind.css
|
||||||
|
templ generate -path pages
|
||||||
go run .
|
go run .
|
17
README.md
17
README.md
|
@ -1,3 +1,16 @@
|
||||||
# baas
|
# hermes
|
||||||
|
|
||||||
> [bankify](https://github.com/supertestnet/bankify) as a service
|
```
|
||||||
|
.__
|
||||||
|
| |__ ___________ _____ ____ ______
|
||||||
|
| | \_/ __ \_ __ \/ \_/ __ \ / ___/
|
||||||
|
| Y \ ___/| | \/ Y Y \ ___/ \___ \
|
||||||
|
|___| /\___ >__| |__|_| /\___ >____ >
|
||||||
|
\/ \/....wallet....\/ \/ \/
|
||||||
|
```
|
||||||
|
|
||||||
|
> _Not the wallet you need, but the wallet you deserve._
|
||||||
|
|
||||||
|
**Development**
|
||||||
|
|
||||||
|
See [Makefile](./Makefile).
|
||||||
|
|
11
go.mod
11
go.mod
|
@ -1,4 +1,4 @@
|
||||||
module github.com/ekzyis/baas
|
module github.com/ekzyis/hermes
|
||||||
|
|
||||||
go 1.22.0
|
go 1.22.0
|
||||||
|
|
||||||
|
@ -11,15 +11,16 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/a-h/templ v0.2.778 // indirect
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||||
github.com/labstack/gommon v0.4.2 // indirect
|
github.com/labstack/gommon v0.4.2 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||||
golang.org/x/crypto v0.22.0 // indirect
|
golang.org/x/crypto v0.26.0 // indirect
|
||||||
golang.org/x/net v0.24.0 // indirect
|
golang.org/x/net v0.28.0 // indirect
|
||||||
golang.org/x/sys v0.19.0 // indirect
|
golang.org/x/sys v0.23.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.17.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
18
go.sum
18
go.sum
|
@ -1,3 +1,5 @@
|
||||||
|
github.com/a-h/templ v0.2.778 h1:VzhOuvWECrwOec4790lcLlZpP4Iptt5Q4K9aFxQmtaM=
|
||||||
|
github.com/a-h/templ v0.2.778/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||||
|
@ -21,18 +23,18 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
||||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
||||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|
22
main.go
22
main.go
|
@ -5,16 +5,24 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/ekzyis/baas/baas"
|
"github.com/ekzyis/hermes/server"
|
||||||
"github.com/ekzyis/baas/lib"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func banner() {
|
||||||
fmt.Printf("%s%s\n\n",
|
fmt.Printf("" +
|
||||||
lib.Figlet("graffiti", "baas"),
|
".__\n" +
|
||||||
" --- bankify as a service --- ")
|
"| |__ ___________ _____ ____ ______\n" +
|
||||||
|
"| | \\_/ __ \\_ __ \\/ \\_/ __ \\ / ___/\n" +
|
||||||
|
"| Y \\ ___/| | \\/ Y Y \\ ___/ \\___ \\\n" +
|
||||||
|
"|___| /\\___ >__| |__|_| /\\___ >____ >\n" +
|
||||||
|
" \\/ \\/...wallet...\\/ \\/ \\/\n",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
s := baas.NewServer()
|
func main() {
|
||||||
|
banner()
|
||||||
|
|
||||||
|
s := server.New()
|
||||||
|
|
||||||
// TODO: read port from env
|
// TODO: read port from env
|
||||||
if err := s.Start("127.0.0.1:8888"); err != http.ErrServerClosed {
|
if err := s.Start("127.0.0.1:8888"); err != http.ErrServerClosed {
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package components
|
||||||
|
|
||||||
|
templ Head() {
|
||||||
|
<head>
|
||||||
|
<title>hermes</title>
|
||||||
|
<!-- TODO: add favicon, manifest etc. -->
|
||||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico"/>
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/>
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/>
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/>
|
||||||
|
<link rel="manifest" href="/site.webmanifest"/>
|
||||||
|
<link rel="stylesheet" href="/css/tailwind.css"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||||
|
<meta name="theme-color" content="#191d21"/>
|
||||||
|
<meta
|
||||||
|
name="htmx-config"
|
||||||
|
content='{
|
||||||
|
"responseHandling": [
|
||||||
|
{ "code": "204", "swap": false },
|
||||||
|
{ "code": "[23]..", "swap": true },
|
||||||
|
{ "code": "[45]..", "swap": true, "error": true }
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
/>
|
||||||
|
<script src="/js/htmx.js" integrity="sha384-Xh+GLLi0SMFPwtHQjT72aPG19QvKB8grnyRbYBNIdHWc2NkCrz65jlU7YrzO6qRp" crossorigin="anonymous"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// helper functions
|
||||||
|
var $ = selector => document.querySelector(selector)
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package pages
|
||||||
|
|
||||||
|
import "github.com/ekzyis/hermes/pages/components"
|
||||||
|
|
||||||
|
templ Index() {
|
||||||
|
<html>
|
||||||
|
@components.Head()
|
||||||
|
<body class="container">
|
||||||
|
<div id="content" class="grid mt-3">
|
||||||
|
<div class="grid gap-10 self-center justify-self-center">
|
||||||
|
<h1 class="text-center text-5xl font-bold">0 sats</h1>
|
||||||
|
<div class="flex justify-self-center">
|
||||||
|
<button class="flex items-center justify-center text-xl mx-3 w-[120px]">
|
||||||
|
<img src="/svg/arrow-left-down-line.svg" width="24px" height="24px"/>
|
||||||
|
receive
|
||||||
|
</button>
|
||||||
|
<button class="flex items-center justify-center text-xl mx-3 w-[120px]">
|
||||||
|
<img src="/svg/arrow-right-up-line.svg" width="24px" height="24px"/>
|
||||||
|
send
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--background: #191d21;
|
||||||
|
--color: #d3d3d3;
|
||||||
|
--muted: #6c757d;
|
||||||
|
--lightning: #fada5e;
|
||||||
|
--nostr: #8d45dd;
|
||||||
|
--black: #000;
|
||||||
|
--white: #fff;
|
||||||
|
--bg-success: #149e613d;
|
||||||
|
--fg-success: #35df8d;
|
||||||
|
--bg-error: #f5395e3d;
|
||||||
|
--fg-error: #ff7386;
|
||||||
|
--bg-btn: #ebebeb;
|
||||||
|
--fg-btn: #0a0a0a;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
body {
|
||||||
|
background-color: var(--background);
|
||||||
|
color: var(--color);
|
||||||
|
font-family: Roboto, -apple-system, Helvetica Neue, Helvetica, Arial, sans-serif;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
min-height: 85svh;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
#content {
|
||||||
|
min-height: 90svh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: var(--bg-btn);
|
||||||
|
color: var(--fg-btn);
|
||||||
|
border-radius: 28px;
|
||||||
|
outline: 0;
|
||||||
|
min-height: 2rem;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
filter: brightness(130%) drop-shadow(0 0 0.3em var(--bg-btn));
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M9 13.589L17.6066 4.98242L19.0208 6.39664L10.4142 15.0032H18V17.0032H7V6.00324H9V13.589Z"></path></svg>
|
After Width: | Height: | Size: 192 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M16.0037 9.41421L7.39712 18.0208L5.98291 16.6066L14.5895 8H7.00373V6H18.0037V17H16.0037V9.41421Z"></path></svg>
|
After Width: | Height: | Size: 200 B |
|
@ -1,6 +1,7 @@
|
||||||
package baas
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/ekzyis/hermes/pages"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
)
|
)
|
||||||
|
@ -9,13 +10,13 @@ type Server struct {
|
||||||
*echo.Echo
|
*echo.Echo
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer() *Server {
|
func New() *Server {
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
|
|
||||||
e.Static("/", "public")
|
e.Static("/", "public")
|
||||||
|
|
||||||
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
|
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
|
||||||
Format: "${time_custom} ${method} ${uri} ${status}\n",
|
Format: "${time_custom} ${remote_ip} ${method} ${uri} ${status}\n",
|
||||||
CustomTimeFormat: "2006-01-02 15:04:05.00000-0700",
|
CustomTimeFormat: "2006-01-02 15:04:05.00000-0700",
|
||||||
}))
|
}))
|
||||||
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
|
||||||
|
@ -28,6 +29,10 @@ func NewServer() *Server {
|
||||||
// TODO: attach error handler
|
// TODO: attach error handler
|
||||||
// e.HTTPErrorHandler = ...
|
// e.HTTPErrorHandler = ...
|
||||||
|
|
||||||
|
e.GET("/", func(c echo.Context) error {
|
||||||
|
return pages.Index().Render(c.Request().Context(), c.Response().Writer)
|
||||||
|
})
|
||||||
|
|
||||||
s := &Server{e}
|
s := &Server{e}
|
||||||
|
|
||||||
return s
|
return s
|
|
@ -0,0 +1,19 @@
|
||||||
|
let
|
||||||
|
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-23.11";
|
||||||
|
pkgs = import nixpkgs { config = {}; overlays = []; };
|
||||||
|
in
|
||||||
|
|
||||||
|
pkgs.mkShell {
|
||||||
|
packages = with pkgs; [
|
||||||
|
go
|
||||||
|
tailwindcss
|
||||||
|
gnumake
|
||||||
|
inotify-tools
|
||||||
|
figlet
|
||||||
|
postgresql
|
||||||
|
];
|
||||||
|
shellHook = ''
|
||||||
|
# install templ if not already installed
|
||||||
|
command -v templ > /dev/null || go install github.com/a-h/templ/cmd/templ@latest
|
||||||
|
'';
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ["./pages/**/*.templ"],
|
||||||
|
theme: {
|
||||||
|
container: {
|
||||||
|
center: true,
|
||||||
|
padding: '1rem'
|
||||||
|
},
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
'background': '191d21',
|
||||||
|
'muted': '#6c757d',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
function ({ addComponents }) {
|
||||||
|
addComponents({
|
||||||
|
'.container': {
|
||||||
|
'@screen lg': {
|
||||||
|
maxWidth: '768px',
|
||||||
|
},
|
||||||
|
'@screen xl': {
|
||||||
|
maxWidth: '768px',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
Loading…
Reference in New Issue