91 Commits

Author SHA1 Message Date
242559acc9 feat: add tailwindcss 2025-03-06 10:02:35 -03:00
c2bddbf32c chore: ignore .tmp folder 2025-03-06 10:02:13 -03:00
c5043a3527 style: format long line in New constructor 2025-03-06 09:45:01 -03:00
1351cd0cde refactor: import renamed excetion package 2025-03-05 13:52:00 -03:00
51bb55816c chore: update submodule 2025-03-05 13:47:05 -03:00
f13dc0fe0f feat: templates prototype 2025-03-05 13:45:19 -03:00
7b6796e2c1 feat: panic recovering on requests 2025-03-05 12:22:38 -03:00
4875f47f94 chore: rename routes log group to requests 2025-03-05 12:22:21 -03:00
fafd7f76bf chore: hotreloading on file change 2025-03-05 11:00:28 -03:00
489a696e82 feat: exceptions hello world 2025-03-05 10:43:42 -03:00
d2308b5a1b feat: hello world 2025-03-05 10:05:21 -03:00
1edc9c6ff0 chore: update submodule url 2025-03-04 17:42:05 -03:00
4063a6fb0d chore: fresh restart 2025-03-01 19:35:33 -03:00
e16e57f387 chore(deps): add loreddev/x submodule 2025-02-20 09:32:18 -03:00
f1e9468f09 refactor(router): rename parsePath to parsePattern 2024-12-18 14:13:26 -03:00
0af4ea3074 fix(router): trailing slash in mux rest pattern 2024-12-18 14:09:17 -03:00
67230ba75d fix(router): missing join for the rest of the path 2024-12-13 16:59:40 -03:00
c2bbd80dce feat(middlewares): use closures instead of structs for middleware constructors 2024-12-13 16:21:47 -03:00
23ac6d6220 fix(router): missing support for mux server in router constructor 2024-12-13 16:13:26 -03:00
5b5de7b206 feat(router): add support for http methods 2024-12-13 16:12:49 -03:00
b14b0be66b chore(eslint,dev): fix eslint errors in htmx files 2024-10-30 10:35:25 -03:00
a7b5ab174b fix(dev,eslint): remove @eslint/markdown since 'no-irregular-whitespace' breaks with it 2024-10-30 10:34:49 -03:00
478dd0216e feat(cookies): MarshalToWriter helper/alias function 2024-10-24 20:28:31 -03:00
c27b0a4e12 feat(cookies): UnmarshalIfRequest helper/alias function 2024-10-24 20:28:02 -03:00
11312ef5fe refactor(cookies): move errors to bottom of file 2024-10-24 20:12:16 -03:00
d74d71dfa3 feat(cookies,errors): error helper for cookie unmarshaling 2024-10-24 19:53:38 -03:00
6ceef9664a feat(forms): Unmarshaler interface 2024-10-24 19:40:25 -03:00
19cf6e13cc feat(forms,errors): error helper for form and query parsing 2024-10-24 19:39:50 -03:00
dd1d67207d feat(forms): forms and queries parsing and unmarshal 2024-10-24 19:39:11 -03:00
6372b20a0b feat(router,errors): BadRequest error 2024-10-24 19:36:35 -03:00
f27784a0b2 refactor(router,errors): move functiosn to alphabetical order 2024-10-24 19:35:43 -03:00
c05086a93e chore(jsdoc): fix jsdoc in htmx.js and htmx.d.ts files 2024-10-24 17:24:46 -03:00
3ae232a779 feat(cookies): add Marshaler and Unmarshaler interface for cookies 2024-10-24 11:06:01 -03:00
535b7aa975 chore(lint,format): make lint and fmt depend on build/templ 2024-10-23 19:08:03 -03:00
218b991caa refactor(lib): move app routing to lib package
These packages and functions under lib will one day be part of it's
dedicated library/framework, so separating them here helps for the
future.
2024-10-23 19:06:03 -03:00
0e96046259 style(imports,handlers): format imports in handlers 2024-10-23 18:58:13 -03:00
013ed1002a chore(dev,makefile): improve clean command 2024-10-23 18:55:28 -03:00
0ed5f27f92 feat(lib,htmx): install htmx 2024-10-23 18:36:02 -03:00
e769a59b57 refactor(javascript,assets): rename javascript directory to lib 2024-10-23 18:35:38 -03:00
7d49a0fd81 feat(errors,router): add error description in 500 errors 2024-10-22 20:34:35 -03:00
012d0b3137 feat(errors,router): add Endpoint field/data to all errors 2024-10-22 20:34:12 -03:00
1e00971f62 feat(cookies,router): new cookies marshaller and unmarshaller 2024-10-22 20:25:26 -03:00
853c86af0a fix(unocss): rename pages to handlers 2024-10-22 16:58:12 -03:00
96dc9ce119 feat(perf,layouts,css): place global css in style tag for instant loading 2024-10-22 16:57:52 -03:00
3ace8799e2 fix(javascript,assets): js to javascript src link 2024-10-22 16:57:17 -03:00
ea22eedd0e refactor(assets,embedded): rewrite embedded assets files handling 2024-10-22 16:56:50 -03:00
409cb86070 refactor(env,config): create DEV global variable 2024-10-22 16:56:10 -03:00
1034cc4906 refactor(javascript,assets): rename js directory to javascript 2024-10-22 16:55:11 -03:00
390774600f fix(logger,middlewares): status code not being read from response 2024-10-22 11:55:00 -03:00
5448517b67 refactor(pages): move pages to handlers package 2024-10-22 10:09:23 -03:00
50e0ee7bcb fix(dashboard): fix color and fonts 2024-10-22 09:04:20 -03:00
6a561f7d6f feat(dev): development page for testing 2024-10-22 09:03:58 -03:00
fbbbb39fc8 feat(fonts): add Karla and Playfair font families 2024-10-22 09:03:44 -03:00
d65abd3e6f feat(cache,middlewares): cache middlewares 2024-10-22 09:02:58 -03:00
27f29990f5 refactor(router): move Router type to interface 2024-10-21 14:57:53 -03:00
c12db37dc2 refactor(errors,middlwares): new error middleware implementation 2024-10-21 14:27:43 -03:00
a72b2d0482 refactor(router): new router implementation with route groups support 2024-10-21 14:26:46 -03:00
f80dd84784 feat(logger,middlewares): add move information for each request 2024-10-21 14:24:28 -03:00
2219de640d refactor(errors,middlewares): move html displaying to dedicated function 2024-10-18 09:12:45 -03:00
d3bb613252 chore: ignore _templ.txt files 2024-10-18 00:24:10 -03:00
fb97c490a8 fix(errors,middlewares): return plain text on 404 error 2024-10-18 00:23:42 -03:00
d74a13bfd6 fix(errors,middlewares): Accept header prefersHtml boolean operator 2024-10-18 00:23:09 -03:00
c55a516a3d feat(errors,middlwares): add error handler middleware 2024-10-17 23:47:35 -03:00
f3f060ddc8 feat(middlewares): middleware struct interface 2024-10-17 23:46:52 -03:00
65e34b4e29 feat(logger,middlewares): add group do logger in logger middleware 2024-10-17 23:46:08 -03:00
5157deda2a chore(dev): move final binary from dist to .dist directory 2024-10-15 15:33:16 -03:00
35dbf51fb0 feat(dev): development pages for testing and prototypes 2024-10-15 01:04:35 -03:00
8a44e0821d feat(ui,theme): dynamic theme css 2024-10-15 01:04:18 -03:00
bfd24e0dc7 feat(layouts): base layout for all pages 2024-10-15 01:03:39 -03:00
a183a5a069 feat(dev): development middleware 2024-10-15 01:02:31 -03:00
8a4a7f06ad feat(dev): logging middleware 2024-10-15 01:01:47 -03:00
0222d191e9 fix: check errors in error ServeHTTP 2024-10-15 00:59:43 -03:00
4ffe2f4e9e refactor: move Middleware interface to sinle function class 2024-10-15 00:57:06 -03:00
8388e2763e fix(dev): ignore json files from linting 2024-10-13 20:29:44 -03:00
36ab51b337 chore(dev): eslint command to make lint 2024-10-13 20:18:56 -03:00
cfac969a12 feat: hello world js test 2024-10-13 20:18:25 -03:00
09e1a0ce1e chore(dev): eslint configuration
I love Javascript :)
2024-10-13 20:18:04 -03:00
d9eb24b9cd feat(dev): debugger configuration 2024-10-11 22:30:13 -03:00
78718c29bf feat(app): static file serving 2024-10-11 22:19:07 -03:00
e70e18aee5 chore(deps): use eslint_d instead of eslint 2024-10-11 14:13:44 -03:00
518c712038 fix(dev): hot reloading 2024-10-11 14:13:34 -03:00
fe427c0394 fix: commands in makefile 2024-10-07 19:16:55 -03:00
a01742828e fix: incorrect fields in Route 2024-10-07 19:16:44 -03:00
34c6b7ccb4 feat: test page 2024-10-07 19:12:27 -03:00
f1d312bfce chore: configure makefile for development 2024-10-07 19:12:06 -03:00
32d393c1da feat(deps): add unocss 2024-10-07 19:11:45 -03:00
4f423794a3 chore(deps): add templ 2024-10-07 15:40:38 -03:00
47c570855f feat(router): error handling of routes 2024-10-07 15:40:26 -03:00
1c7131c216 feat(router): support for middlewares 2024-10-07 15:40:06 -03:00
bb0c4b371a feat: setup project router 2024-10-07 15:39:46 -03:00
9cd1e1b1e9 chore: add golang tools to flake.niix 2024-10-04 19:41:07 -03:00
20 changed files with 1400 additions and 8 deletions

0
.env Normal file
View File

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.dist
wind.css
.tmp

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "x"]
path = x
url = https://forge.capytal.company/loreddev/x

20
.golangci.yml Normal file
View File

@@ -0,0 +1,20 @@
run:
timeout: 5m
modules-download-mode: readonly
linters:
disable-all: true
enable:
- errcheck
- goimports
- gofumpt
- revive # golint
- gosimple
- govet
- ineffassign
- staticcheck
issues:
exclude-use-default: false
max-issues-per-linter: 0
max-same-issues: 0

20
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,20 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch APP",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/main.go"
},
{
"name": "Launch APP (Dev)",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/main.go",
"args": [ "-dev" ]
}
]
}

77
cmd/cmd.go Normal file
View File

@@ -0,0 +1,77 @@
package cmd
import (
"context"
"errors"
"flag"
"fmt"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"forge.capytal.company/capytalcode/project-comicverse/router"
"forge.capytal.company/loreddev/x/tinyssert"
)
var (
host = flag.String("host", "localhost", "Host to listen to")
port = flag.Uint("port", 8080, "Port to be used for the server.")
templatesDir = flag.String("templates", "", "Templates directory to be used instead of built-in ones.")
verbose = flag.Bool("verbose", false, "Print debug information on logs")
dev = flag.Bool("dev", false, "Run the server in debug mode.")
)
func init() {
flag.Parse()
}
func Execute() {
ctx := context.Background()
assertions := tinyssert.NewDisabledAssertions()
if *dev {
assertions = tinyssert.NewAssertions()
}
level := slog.LevelError
if *dev {
level = slog.LevelDebug
} else if *verbose {
level = slog.LevelInfo
}
log := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: level}))
app := router.New(assertions, log, *dev)
srv := &http.Server{
Addr: fmt.Sprintf("%s:%d", *host, *port),
Handler: app,
}
c, stop := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
defer stop()
go func() {
log.Info("Starting application",
slog.String("host", *host),
slog.Uint64("port", uint64(*port)),
slog.Bool("verbose", *verbose),
slog.Bool("development", *dev))
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Error("Failed to start application", slog.String("error", err.Error()))
}
}()
<-c.Done()
log.Info("Stopping application gracefully")
if err := srv.Shutdown(ctx); err != nil {
log.Error("Failed to stop application gracefully", slog.String("error", err.Error()))
}
log.Info("FINAL")
os.Exit(0)
}

View File

@@ -3,10 +3,7 @@
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
};
outputs = {
self,
nixpkgs,
}: let
outputs = {nixpkgs, ...}: let
systems = [
"x86_64-linux"
"aarch64-linux"
@@ -21,11 +18,23 @@
in {
devShells = forAllSystems (system: pkgs: {
default = pkgs.mkShell {
CGO_ENABLED = "0";
hardeningDisable = ["all"];
buildInputs = with pkgs; [
eslint
nodejs_22
nodePackages_latest.prettier
bun
# Go tools
go
golangci-lint
gofumpt
gotools
delve
# TailwindCSS
tailwindcss
# Sqlite tools
sqlite
lazysql
];
};
});

7
go.mod Normal file
View File

@@ -0,0 +1,7 @@
module forge.capytal.company/capytalcode/project-comicverse
go 1.23.3
toolchain go1.23.6
require forge.capytal.company/loreddev/x v0.0.0-20250227192157-90a5169f1bef

2
go.sum Normal file
View File

@@ -0,0 +1,2 @@
forge.capytal.company/loreddev/x v0.0.0-20250227192157-90a5169f1bef h1:IJ9z7otITB5hhjZ+bmU0yOVsa8K1RWYIZ+cQj9XF6NY=
forge.capytal.company/loreddev/x v0.0.0-20250227192157-90a5169f1bef/go.mod h1:MnU08vmXvYIQlQutVcC6o6Xq1KHZuXGXO78bbHseCFo=

6
go.work Normal file
View File

@@ -0,0 +1,6 @@
go 1.23.6
use (
./.
./x
)

7
main.go Normal file
View File

@@ -0,0 +1,7 @@
package main
import "forge.capytal.company/capytalcode/project-comicverse/cmd"
func main() {
cmd.Execute()
}

42
makefile Normal file
View File

@@ -0,0 +1,42 @@
PORT?=8080
lint:
golangci-lint run .
fmt:
go fmt .
golangci-lint run --fix .
dev/server:
go run github.com/joho/godotenv/cmd/godotenv@v1.5.1 \
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,html" \
--build.stop_on_error "false" \
--proxy.enabled true \
--proxy.proxy_port $(PORT) \
--proxy.app_port $$(($(PORT) + 1)) \
--misc.clean_on_exit true \
-- -dev -port $$(($(PORT) + 1))
dev/assets:
tailwindcss -o ./static/css/wind.css -w
dev:
$(MAKE) -j2 dev/server dev/assets
build:
go generate
go build -o ./.dist/app .
run: build
./.dist/app
clean:
# Remove generated directories
if [[ -d ".dist" ]]; then rm -r ./.dist; fi
if [[ -d "tmp" ]]; then rm -r ./tmp; fi
if [[ -d "bin" ]]; then rm -r ./bin; fi

52
router/router.go Normal file
View File

@@ -0,0 +1,52 @@
package router
import (
"errors"
"log/slog"
"net/http"
"forge.capytal.company/capytalcode/project-comicverse/templates"
"forge.capytal.company/loreddev/x/smalltrip"
"forge.capytal.company/loreddev/x/smalltrip/exception"
"forge.capytal.company/loreddev/x/smalltrip/middleware"
"forge.capytal.company/loreddev/x/tinyssert"
)
func New(assertions tinyssert.Assertions, log *slog.Logger, dev bool) http.Handler {
r := smalltrip.NewRouter(
smalltrip.WithAssertions(assertions),
smalltrip.WithLogger(log.WithGroup("smalltrip")),
)
r.Use(middleware.Logger(log.WithGroup("requests")))
if dev {
log.Debug("Development mode activated, using development middleware")
r.Use(middleware.Dev)
} else {
r.Use(middleware.PersistentCache())
}
r.Use(exception.PanicMiddleware())
r.Use(exception.Middleware())
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
err := templates.Templates().ExecuteTemplate(w, "index.html", nil)
if err != nil {
exception.InternalServerError(err).ServeHTTP(w, r)
}
})
r.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
r.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
exception.InternalServerError(errors.New("TEST ERROR"),
exception.WithData("test-data", "test-value"),
).ServeHTTP(w, r)
})
r.HandleFunc("/panic", func(w http.ResponseWriter, r *http.Request) {
panic("TEST PANIC")
})
return r
}
func dashboard(w http.ResponseWriter, r *http.Request) {
}

0
static/css/.gitkeep Normal file
View File

24
static/static.go Normal file
View File

@@ -0,0 +1,24 @@
package static
import (
"embed"
"io/fs"
)
//go:generate tailwindcss -o static/css/wind.css
//go:embed css/*.css
var staticFiles embed.FS
func Files(local ...bool) fs.FS {
var l bool
if len(local) > 0 {
l = local[0]
}
if !l {
return staticFiles
}
return staticFiles
}

1077
tailwind.config.js Normal file

File diff suppressed because it is too large Load Diff

12
templates/index.html Normal file
View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/static/css/wind.css">
</head>
<body class="text-red-600">
<h1>Hello, world</h1>
</body>
</html>

18
templates/templates.go Normal file
View File

@@ -0,0 +1,18 @@
package templates
import (
"embed"
"html/template"
)
//go:embed *.html test/*.html
var embedded embed.FS
var temps = template.Must(template.ParseFS(embedded,
"*.html",
"test/*.html",
))
func Templates() *template.Template {
return temps
}

12
templates/test/test.html Normal file
View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Hello, world 2</h1>
</body>
</html>

1
x Submodule

Submodule x added at 0ccb26ab78