feat: new admin and web apps

This commit is contained in:
Guz
2024-12-13 17:30:28 -03:00
parent 2f84341ed8
commit 23d20fe93b
13 changed files with 566 additions and 180 deletions

2
.gitignore vendored
View File

@@ -2,4 +2,4 @@ node_modules/
.dist/
*_templ.go
*.env
./assets/css/uno.css
uno.css

123
app/app.go Normal file
View File

@@ -0,0 +1,123 @@
package app
import (
"context"
"errors"
"fmt"
"log/slog"
"net/http"
"forge.capytal.company/capytalcode/project-comicverse/lib/middleware"
"forge.capytal.company/capytalcode/project-comicverse/lib/router"
"forge.capytal.company/capytalcode/project-comicverse/lib/router/rerrors"
"github.com/minio/minio-go/v7"
"keikos.work/configs"
"keikos.work/handlers/pages"
)
type App interface {
Start() error
Stop() error
}
type Options struct {
Port uint
Development bool
Log *slog.Logger
S3 *minio.Client
Assets http.Handler
}
type app struct {
log *slog.Logger
s3 *minio.Client
assets http.Handler
server *http.Server
}
func (a *app) Start() error {
if err := a.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
return err
}
return nil
}
func (a *app) Stop() error {
if err := a.server.Shutdown(context.Background()); err != nil {
return err
}
return nil
}
func NewWeb(opts Options) App {
r := router.NewRouter()
r.Use(middleware.NewLoggerMiddleware(opts.Log))
if opts.Development {
configs.DEVELOPMENT = true
r.Use(middleware.DevMiddleware)
} else {
r.Use(middleware.CacheMiddleware)
}
r.Use(rerrors.NewErrorMiddleware(pages.ErrorPage{}.Component, opts.Log))
r.Handle("/", &pages.Home{})
imgs := &pages.Images{S3: opts.S3}
r.HandleFunc("GET /images", imgs.List)
r.HandleFunc("GET /images/{name}", imgs.Get)
srv := http.Server{
Addr: fmt.Sprintf(":%d", opts.Port),
Handler: r,
}
return &app{
log: opts.Log,
s3: opts.S3,
assets: opts.Assets,
server: &srv,
}
}
func NewAdmin(opts Options) App {
r := router.NewRouter()
r.Use(middleware.NewLoggerMiddleware(opts.Log))
if opts.Development {
configs.DEVELOPMENT = true
r.Use(middleware.DevMiddleware)
} else {
r.Use(middleware.CacheMiddleware)
}
r.Use(rerrors.NewErrorMiddleware(pages.ErrorPage{}.Component, opts.Log))
r.Handle("/", &pages.Dashboard{})
imgs := &pages.Images{S3: opts.S3}
r.HandleFunc("GET /images", imgs.List)
r.HandleFunc("GET /images/{name}", imgs.Get)
r.HandleFunc("POST /images", imgs.Create)
r.HandleFunc("PUT /images/{name}", imgs.Update)
r.HandleFunc("DELETE /images/{name}", imgs.Delete)
srv := http.Server{
Addr: fmt.Sprintf(":%d", opts.Port),
Handler: r,
}
return &app{
log: opts.Log,
s3: opts.S3,
assets: opts.Assets,
server: &srv,
}
}

View File

@@ -1,78 +0,0 @@
package main
import (
"context"
"errors"
"flag"
"fmt"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"forge.capytal.company/capytalcode/project-comicverse/lib/middleware"
"forge.capytal.company/capytalcode/project-comicverse/lib/router"
"keikos.work/assets"
"keikos.work/configs"
"keikos.work/handlers/pages"
)
var (
port int64 = 8080
dev bool = false
)
func init() {
flag.Int64Var(&port, "port", port, "The website port")
flag.BoolVar(&dev, "dev", dev, "Run the website in development mode")
}
func main() {
flag.Parse()
l := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
}))
if dev {
l.Info("RUNNING IN DEVELOPMENT MODE")
configs.DEVELOPMENT = true
}
r := router.NewRouter()
r.Use(middleware.NewLoggerMiddleware(l).Wrap)
if configs.DEVELOPMENT {
r.Use(middleware.DevMiddleware)
r.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("./assets"))))
} else {
r.Use(middleware.CacheMiddleware)
r.Handle("/assets/", http.StripPrefix("/assets/", http.FileServerFS(assets.ASSETS)))
}
r.Handle("/", pages.Routes())
srv := http.Server{
Addr: fmt.Sprintf(":%d", port),
Handler: r,
}
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
go func() {
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
l.Error("Listen and serve returned error", slog.String("error", err.Error()))
}
}()
<-ctx.Done()
l.Info("Shutting down server...")
if err := srv.Shutdown(context.Background()); err != nil {
l.Error("Server shutdown returned error", slog.String("error", err.Error()))
}
l.Info("FINAL")
}

24
go.mod
View File

@@ -2,6 +2,26 @@ module keikos.work
go 1.23.3
require forge.capytal.company/capytalcode/project-comicverse v0.0.0-20241030133525-b14b0be66b7a
require (
forge.capytal.company/capytalcode/project-comicverse v0.0.0-20241213195940-67230ba75d8a
github.com/a-h/templ v0.2.793
github.com/minio/minio-go/v7 v7.0.81
)
require github.com/a-h/templ v0.2.793 // indirect
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/goccy/go-json v0.10.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rs/xid v1.6.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/net v0.32.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

44
go.sum
View File

@@ -1,4 +1,44 @@
forge.capytal.company/capytalcode/project-comicverse v0.0.0-20241030133525-b14b0be66b7a h1:lDGMhHL+B5zmrxiSEVPLNXglPApksQ7HPEAEGOuW7sI=
forge.capytal.company/capytalcode/project-comicverse v0.0.0-20241030133525-b14b0be66b7a/go.mod h1:COqB9i9nyQrQUz/ZqMvN98V7rh0t7vdXmBV36G8Q+7Q=
forge.capytal.company/capytalcode/project-comicverse v0.0.0-20241213192147-c2bbd80dcef8 h1:Jp0qWzdYZesWkcsH19sdsiiODKxsICY26oTwy2e+rmg=
forge.capytal.company/capytalcode/project-comicverse v0.0.0-20241213192147-c2bbd80dcef8/go.mod h1:COqB9i9nyQrQUz/ZqMvN98V7rh0t7vdXmBV36G8Q+7Q=
forge.capytal.company/capytalcode/project-comicverse v0.0.0-20241213195940-67230ba75d8a h1:PDmA2uCzFdn+CdS3C+Pg1YGhJERgMjwgCjUEUaIDZTM=
forge.capytal.company/capytalcode/project-comicverse v0.0.0-20241213195940-67230ba75d8a/go.mod h1:COqB9i9nyQrQUz/ZqMvN98V7rh0t7vdXmBV36G8Q+7Q=
github.com/a-h/templ v0.2.793 h1:Io+/ocnfGWYO4VHdR0zBbf39PQlnzVCVVD+wEEs6/qY=
github.com/a-h/templ v0.2.793/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w=
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/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.81 h1:SzhMN0TQ6T/xSBu6Nvw3M5M8voM+Ht8RH3hE8S7zxaA=
github.com/minio/minio-go/v7 v7.0.81/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -0,0 +1,25 @@
package pages
import (
"net/http"
"forge.capytal.company/capytalcode/project-comicverse/lib/router/rerrors"
"keikos.work/templates/layouts"
)
type Dashboard struct{}
templ (p *Dashboard) Component() {
@layouts.Page() {
<h1>Dashboard</h1>
<h2>Images</h2>
<form action="/images" method="post"></form>
}
}
func (p *Dashboard) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := p.Component().Render(r.Context(), w); err != nil {
rerrors.InternalError(err).ServeHTTP(w, r)
}
}

View File

@@ -0,0 +1,26 @@
package pages
import (
"fmt"
"keikos.work/templates/layouts"
"forge.capytal.company/capytalcode/project-comicverse/lib/router/rerrors"
)
type ErrorPage struct{}
templ (p ErrorPage) Component(err rerrors.RouteError) {
@layouts.Page() {
<main>
<h1>Error</h1>
<p>{ fmt.Sprintf("%#v", err) }</p>
for k, v := range err.Info {
<p>{ k } { fmt.Sprint(v) } </p>
}
if err.Endpoint != "" {
<a href={ templ.SafeURL(err.Endpoint) }>Retry</a>
}
</main>
}
}

View File

@@ -7,20 +7,29 @@ import (
"keikos.work/templates/layouts"
)
type home struct{}
type Home struct{}
func (p *home) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func (p *Home) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := p.page().Render(r.Context(), w); err != nil {
rerrors.InternalError(err).ServeHTTP(w, r)
}
}
templ (p *home) page() {
templ (p *Home) page() {
@layouts.Page() {
<section class="fixed z-1 w-screen h-100lvh top-0 left-0 flex justify-center items-center">
<div class="overflow-x-hidden relative">
<span class="-translate-x-20% block">
<img src="/assets/img/2024-09-03.jpg" class="h-100vh animate-fade-in-right animate-ease-out"/>
<section
class="fixed z-1 w-screen h-100lvh top-0 left-0 flex justify-center items-center"
>
<div
class="overflow-x-hidden relative"
>
<span
class="-translate-x-20% block"
>
<img
src="/assets/img/2024-09-03.jpg"
class="h-100vh animate-fade-in-right animate-ease-out"
/>
</span>
<span
class={ "absolute top-0 left-0 w-100% h-100%",

View File

@@ -0,0 +1,51 @@
package pages
import (
"net/http"
"keikos.work/templates/layouts"
// "forge.capytal.company/capytalcode/project-comicverse/lib/router/rerrors"
"github.com/minio/minio-go/v7"
)
type Images struct {
S3 *minio.Client
}
func (p *Images) List(w http.ResponseWriter, r *http.Request) {
}
func (p *Images) Get(w http.ResponseWriter, r *http.Request) {
}
func (p *Images) Create(w http.ResponseWriter, r *http.Request) {
}
func (p *Images) Update(w http.ResponseWriter, r *http.Request) {
}
func (p *Images) Delete(w http.ResponseWriter, r *http.Request) {
}
templ (p *Images) heading() {
<script type="module" src="/assets/js/Images_form.js"></script>
}
templ (p *Images) Component() {
@layouts.Page(layouts.PageInfo{
Heading: p.heading(),
}) {
<img id="file-preview" src="" class="bg-gray min-h-20rem min-w-20rem max-w-full"/>
<form action="/Images" method="post" enctype="multipart/form-data">
<label for="file">File to upload</label>
<input type="file" id="file" name="file"/>
<button type="submit">Upload</button>
</form>
}
}

View File

@@ -1,11 +0,0 @@
package pages
import "forge.capytal.company/capytalcode/project-comicverse/lib/router"
func Routes() router.Router {
r := router.NewRouter()
r.Handle("/", &home{})
return r
}

161
main.go Normal file
View File

@@ -0,0 +1,161 @@
package main
import (
"context"
"flag"
"log"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"keikos.work/app"
"keikos.work/assets"
)
var (
port uint = 8080
dev bool = false
webFlags *flag.FlagSet = nil
adminFlags *flag.FlagSet = nil
minioAccessKeyID = os.Getenv("AWS_ACCESS_KEY_ID")
minioSecretAccessKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
minioEndpoint = os.Getenv("AWS_ENDPOINT_URL")
minioSSL = false
)
func init() {
webFlags = flag.NewFlagSet("web", flag.ExitOnError)
webFlags.UintVar(&port, "port", 8080, "The port to be used")
webFlags.BoolVar(&dev, "dev", false, "Run the server in development mode")
webFlags.StringVar(&minioAccessKeyID, "aws-access-key-id", os.Getenv("AWS_ACCESS_KEY_ID"), "")
webFlags.StringVar(
&minioSecretAccessKey,
"aws-access-key-secret",
os.Getenv("AWS_SECRET_ACCESS_KEY"),
"",
)
webFlags.StringVar(&minioEndpoint, "aws-enpoint", os.Getenv("AWS_ENDPOINT_URL"), "")
webFlags.BoolVar(&minioSSL, "aws-ssl", false, "")
}
func init() {
adminFlags = flag.NewFlagSet("admin", flag.ExitOnError)
adminFlags.UintVar(&port, "port", 8080, "The port to be used")
adminFlags.BoolVar(&dev, "dev", false, "Run the server in development mode")
adminFlags.StringVar(&minioAccessKeyID, "aws-access-key-id", os.Getenv("AWS_ACCESS_KEY_ID"), "")
adminFlags.StringVar(
&minioSecretAccessKey,
"aws-access-key-secret",
os.Getenv("AWS_SECRET_ACCESS_KEY"),
"",
)
adminFlags.StringVar(&minioEndpoint, "aws-enpoint", os.Getenv("AWS_ENDPOINT_URL"), "")
adminFlags.BoolVar(&minioSSL, "aws-ssl", false, "")
}
func main() {
if len(os.Args) < 2 {
log.Fatalf("Expected 'web' or 'admin' subcommands")
}
s3, err := minio.New(minioEndpoint, &minio.Options{
Creds: credentials.NewStaticV4(minioAccessKeyID, minioSecretAccessKey, ""),
Secure: minioSSL,
})
if err != nil {
panic(err)
}
var a app.App
var l *slog.Logger
switch os.Args[1] {
case "web":
webFlags.Parse(os.Args[2:])
var level slog.Leveler
if dev {
level = slog.LevelDebug
} else {
level = slog.LevelInfo
}
l = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: level}))
var assetsHandler http.Handler
if dev {
assetsHandler = http.StripPrefix("/assets/", http.FileServer(http.Dir("./assets")))
} else {
assetsHandler = http.StripPrefix("/assets/", http.FileServerFS(assets.ASSETS))
}
a = app.NewWeb(app.Options{
Port: port,
Development: dev,
Log: l,
S3: s3,
Assets: assetsHandler,
})
case "admin":
adminFlags.Parse(os.Args[2:])
var level slog.Leveler
if dev {
level = slog.LevelDebug
} else {
level = slog.LevelInfo
}
l = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: level}))
var assetsHandler http.Handler
if dev {
assetsHandler = http.StripPrefix("/assets/", http.FileServer(http.Dir("./assets")))
} else {
assetsHandler = http.StripPrefix("/assets/", http.FileServerFS(assets.ASSETS))
}
a = app.NewAdmin(app.Options{
Port: port,
Development: dev,
Log: l,
S3: s3,
Assets: assetsHandler,
})
default:
log.Fatalf("Command %q is not available", os.Args[1])
}
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
if dev {
l.Info("RUNNING IN DEVELOPMENT MODE")
}
go func() {
if err := a.Start(); err != nil {
l.Error("Failed to start server", slog.String("error", err.Error()))
}
}()
<-ctx.Done()
l.Info("Shutting down")
if err := a.Stop(); err != nil {
l.Error("Failed to shut down", slog.String("error", err.Error()))
}
l.Info("FINAL")
}

View File

@@ -21,15 +21,25 @@ dev/templ:
--proxybind="0.0.0.0" \
--open-browser=false
dev/server:
dev/server/web:
go run github.com/air-verse/air@v1.52.2 \
--build.cmd "go build -o tmp/bin/main ./cmd" \
--build.cmd "go build -o tmp/bin/main ." \
--build.bin "tmp/bin/main" \
--build.exclude_dir "node_modules" \
--build.include_ext "go" \
--build.stop_on_error "false" \
--misc.clean_on_exit true \
-- -dev -port $(PORT)
-- web -dev -port $(PORT)
dev/server/admin:
go run github.com/air-verse/air@v1.52.2 \
--build.cmd "go build -o tmp/bin/main ." \
--build.bin "tmp/bin/main" \
--build.exclude_dir "node_modules" \
--build.include_ext "go" \
--build.stop_on_error "false" \
--misc.clean_on_exit true \
-- admin -dev -port $(PORT)
dev/sync_assets:
go run github.com/air-verse/air@v1.52.2 \
@@ -43,23 +53,33 @@ dev/sync_assets:
dev/assets/css:
bun x unocss --watch
dev:
dev/web:
go run github.com/joho/godotenv/cmd/godotenv@v1.5.1 \
make -j4 dev/templ dev/server dev/sync_assets dev/assets/css
make -j4 dev/templ dev/server/web dev/sync_assets dev/assets/css
dev/admin:
go run github.com/joho/godotenv/cmd/godotenv@v1.5.1 \
make -j4 dev/templ dev/server/admin dev/sync_assets dev/assets/css
build/templ:
go run github.com/a-h/templ/cmd/templ@v0.2.707 generate
build/bin:
go build -o ./.dist/bin ./cmd
go build -o ./.dist/bin .
build/assets:
npx unocss
build: build/templ build/assets build/bin
run: build
./.dist/bin
run/web: build
go run github.com/joho/godotenv/cmd/godotenv@v1.5.1 \
./.dist/bin web -port $(PORT)
run/admin: build
go run github.com/joho/godotenv/cmd/godotenv@v1.5.1 \
./.dist/bin admin -port $(PORT)
clean:
# Remove templ generated files

View File

@@ -1,76 +1,76 @@
import {
defineConfig,
presetIcons,
presetTypography,
presetUno,
presetWebFonts,
transformerDirectives,
transformerVariantGroup,
} from "unocss";
defineConfig,
presetIcons,
presetTypography,
presetUno,
presetWebFonts,
transformerDirectives,
transformerVariantGroup,
} from 'unocss';
export default defineConfig({
cli: {
entry: {
outFile: "./assets/css/uno.css",
patterns: [
"./{templates,handlers}/**/*.templ",
"./assets/**/*.{js,css,html}",
"!./assets/css/uno.css",
],
},
},
presets: [
presetIcons(),
presetTypography(),
presetUno({
dark: "media",
}),
presetWebFonts({
fonts: {
japanese: {
name: "Kaisei Decol",
},
sans: {
name: "Quattrocento Sans",
},
serif: {
name: "Quattrocento",
},
},
provider: "none",
}),
],
rules: [
["w-screen", [["width", "100vw"], ["width", "100dvw"]]],
[/^w-(\d+)dvw$/, ([_, d]) => {
return [
["width", `${d}vw`],
["width", `${d}dvw`],
];
}],
["min-w-screen", [["width", "100vw"], ["width", "100dvw"]]],
[/^w-(\d+)dvw$/, ([_, d]) => {
return [
["min-width", `${d}vw`],
["min-width", `${d}dvw`],
];
}],
["h-screen", [["height", "100vh"], ["height", "100dvh"]]],
[/^h-(\d+)dvh$/, ([_, d]) => {
return [
["height", `${d}vh`],
["height", `${d}dvh`],
];
}],
["min-h-screen", [["height", "100vh"], ["height", "100dvh"]]],
[/^h-(\d+)dvh$/, ([_, d]) => {
return [
["min-height", `${d}vh`],
["min-height", `${d}dvh`],
];
}],
],
/* theme: {
cli: {
entry: {
outFile: './assets/css/uno.css',
patterns: [
'./{templates,handlers}/**/*.templ',
'./assets/**/*.{js,css,html}',
'!./assets/css/uno.css',
],
},
},
presets: [
presetIcons(),
presetTypography(),
presetUno({
dark: 'media',
}),
presetWebFonts({
fonts: {
japanese: {
name: 'Kaisei Decol',
},
sans: {
name: 'Quattrocento Sans',
},
serif: {
name: 'Quattrocento',
},
},
provider: 'none',
}),
],
rules: [
['w-screen', [['width', '100vw'], ['width', '100dvw']]],
[/^w-(\d+)dvw$/, ([, d]) => {
return [
['width', `${d}vw`],
['width', `${d}dvw`],
];
}],
['min-w-screen', [['width', '100vw'], ['width', '100dvw']]],
[/^w-(\d+)dvw$/, ([, d]) => {
return [
['min-width', `${d}vw`],
['min-width', `${d}dvw`],
];
}],
['h-screen', [['height', '100vh'], ['height', '100dvh']]],
[/^h-(\d+)dvh$/, ([, d]) => {
return [
['height', `${d}vh`],
['height', `${d}dvh`],
];
}],
['min-h-screen', [['height', '100vh'], ['height', '100dvh']]],
[/^h-(\d+)dvh$/, ([, d]) => {
return [
['min-height', `${d}vh`],
['min-height', `${d}dvh`],
];
}],
],
/* theme: {
colors: {
white: 'var(--white)',
black: 'var(--black)',
@@ -87,5 +87,5 @@ export default defineConfig({
},
},
}, */
transformers: [transformerDirectives(), transformerVariantGroup()],
transformers: [transformerDirectives(), transformerVariantGroup()],
});