@ -5,7 +5,7 @@ tmp_dir = ".air-tmp"
|
|||||||
bin = "./tijl.dev"
|
bin = "./tijl.dev"
|
||||||
cmd = "just build"
|
cmd = "just build"
|
||||||
delay = 1000
|
delay = 1000
|
||||||
exclude_dir = ["node_modules","modules/database","static/js","static/css"]
|
exclude_dir = ["node_modules","modules/database","web/assets/static"]
|
||||||
exclude_unchanged = false
|
exclude_unchanged = false
|
||||||
follow_symlink = false
|
follow_symlink = false
|
||||||
include_ext = ["go", "html", "js", "ts"]
|
include_ext = ["go", "html", "js", "ts"]
|
||||||
|
4
.gitignore
vendored
@ -1,6 +1,6 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
tijl.dev
|
tijl.dev
|
||||||
static/js/interactive.js
|
web/assets/static/js/interactive.js
|
||||||
static/css/styles.css
|
web/assets/static/css/styles.css
|
||||||
config.yaml
|
config.yaml
|
||||||
|
|
||||||
|
@ -1,132 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"git.tijl.dev/tijl/tijl.dev/internal/tijl.dev/service"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"git.tijl.dev/tijl/tijl.dev/internal/assets"
|
|
||||||
"git.tijl.dev/tijl/tijl.dev/internal/config"
|
|
||||||
"git.tijl.dev/tijl/tijl.dev/internal/db"
|
|
||||||
"git.tijl.dev/tijl/tijl.dev/internal/i18n"
|
|
||||||
"git.tijl.dev/tijl/tijl.dev/internal/oidc"
|
|
||||||
"git.tijl.dev/tijl/tijl.dev/internal/sessions"
|
|
||||||
"git.tijl.dev/tijl/tijl.dev/modules/logger"
|
|
||||||
"git.tijl.dev/tijl/tijl.dev/static"
|
|
||||||
"git.tijl.dev/tijl/tijl.dev/views"
|
|
||||||
"github.com/gofiber/contrib/fiberzerolog"
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"github.com/gofiber/fiber/v2/middleware/filesystem"
|
|
||||||
"github.com/gofiber/template/html/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Load initial context
|
service.Listen()
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
// Load config
|
|
||||||
config.Load()
|
|
||||||
|
|
||||||
// Load database
|
|
||||||
db.Load()
|
|
||||||
|
|
||||||
// Setup oidc
|
|
||||||
oidc.Load(ctx)
|
|
||||||
|
|
||||||
// Load assets
|
|
||||||
assets.Load()
|
|
||||||
// Load translations
|
|
||||||
i18n.Load()
|
|
||||||
|
|
||||||
// Init templating engine
|
|
||||||
engine := html.NewFileSystem(http.FS(views.Embed), ".html")
|
|
||||||
engine.AddFunc("icon", assets.Svg)
|
|
||||||
|
|
||||||
// Init fiber
|
|
||||||
app := fiber.New(fiber.Config{
|
|
||||||
Views: engine,
|
|
||||||
DisableStartupMessage: true,
|
|
||||||
})
|
|
||||||
app.Use(fiberzerolog.New(fiberzerolog.Config{
|
|
||||||
Logger: &log.Logger,
|
|
||||||
}))
|
|
||||||
|
|
||||||
/*
|
|
||||||
Routes
|
|
||||||
*/
|
|
||||||
app.Get("/", func(c *fiber.Ctx) error {
|
|
||||||
data := getCommon(c)
|
|
||||||
data["Title"] = i18n.Translate(c, "home")
|
|
||||||
return c.Render("index", data, "layouts/base")
|
|
||||||
})
|
|
||||||
app.Get("/blog", func(c *fiber.Ctx) error {
|
|
||||||
data := getCommon(c)
|
|
||||||
data["Title"] = i18n.Translate(c, "blog")
|
|
||||||
return c.Render("blog", data, "layouts/base")
|
|
||||||
})
|
|
||||||
app.Get("/projects", func(c *fiber.Ctx) error {
|
|
||||||
data := getCommon(c)
|
|
||||||
data["Title"] = i18n.Translate(c, "projects")
|
|
||||||
return c.Render("projects", data, "layouts/base")
|
|
||||||
})
|
|
||||||
app.Get("/about", func(c *fiber.Ctx) error {
|
|
||||||
data := getCommon(c)
|
|
||||||
data["Title"] = i18n.Translate(c, "about")
|
|
||||||
return c.Render("about", data, "layouts/base")
|
|
||||||
})
|
|
||||||
app.Get("/settings", func(c *fiber.Ctx) error {
|
|
||||||
lang := c.Query("lang")
|
|
||||||
redirectURL := c.Query("redirect")
|
|
||||||
if lang != "" {
|
|
||||||
c.Cookie(&fiber.Cookie{
|
|
||||||
Name: "language",
|
|
||||||
Value: lang,
|
|
||||||
Secure: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if redirectURL != "" {
|
|
||||||
return c.Redirect(redirectURL)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
app.Get("/login", func(c *fiber.Ctx) error {
|
|
||||||
_, err := sessions.GetSession(c)
|
|
||||||
if err == nil {
|
|
||||||
return c.Redirect("/account")
|
|
||||||
} else {
|
|
||||||
return oidc.HandleRedirect(c)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
app.Get(config.Config.Oidc.CallbackUrl, oidc.HandleCallback)
|
|
||||||
|
|
||||||
// Static routes
|
|
||||||
app.Use("/static", filesystem.New(filesystem.Config{
|
|
||||||
Root: http.FS(static.Embed),
|
|
||||||
}))
|
|
||||||
|
|
||||||
// 404
|
|
||||||
app.Use(func(c *fiber.Ctx) error {
|
|
||||||
data := getCommon(c)
|
|
||||||
return c.Render("404", data, "layouts/base")
|
|
||||||
})
|
|
||||||
|
|
||||||
// Listen web server
|
|
||||||
if err := app.Listen(":3000"); err != nil {
|
|
||||||
log.Fatal().Err(err).Msg("Fiber app error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Common functions for in templating
|
|
||||||
func getCommon(c *fiber.Ctx) fiber.Map {
|
|
||||||
_, err := sessions.GetSession(c)
|
|
||||||
signedIn := false
|
|
||||||
if err == nil {
|
|
||||||
signedIn = true
|
|
||||||
}
|
|
||||||
return fiber.Map{
|
|
||||||
"SignedIn": signedIn,
|
|
||||||
"Path": c.Path(),
|
|
||||||
"Language": i18n.GetLanguage(c),
|
|
||||||
"T": i18n.GetTranslations(i18n.GetLanguage(c)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,9 @@ var SVGData map[string]string
|
|||||||
func loadSVGs() {
|
func loadSVGs() {
|
||||||
SVGData = make(map[string]string)
|
SVGData = make(map[string]string)
|
||||||
|
|
||||||
dir := "static/assets/icons"
|
dir := "web/assets/icons"
|
||||||
|
|
||||||
|
// assets.Embed
|
||||||
|
|
||||||
files, err := filepath.Glob(filepath.Join(dir, "*.svg"))
|
files, err := filepath.Glob(filepath.Join(dir, "*.svg"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
16
internal/handlers/login.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.tijl.dev/tijl/tijl.dev/internal/oidc"
|
||||||
|
"git.tijl.dev/tijl/tijl.dev/internal/sessions"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func loginHandler(c *fiber.Ctx) error {
|
||||||
|
_, err := sessions.GetSession(c)
|
||||||
|
if err == nil {
|
||||||
|
return c.Redirect("/account")
|
||||||
|
} else {
|
||||||
|
return oidc.HandleRedirect(c)
|
||||||
|
}
|
||||||
|
}
|
63
internal/handlers/routes.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.tijl.dev/tijl/tijl.dev/internal/config"
|
||||||
|
"git.tijl.dev/tijl/tijl.dev/internal/i18n"
|
||||||
|
"git.tijl.dev/tijl/tijl.dev/internal/oidc"
|
||||||
|
"git.tijl.dev/tijl/tijl.dev/modules/web"
|
||||||
|
"git.tijl.dev/tijl/tijl.dev/web/assets"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/gofiber/fiber/v2/middleware/filesystem"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Setup() {
|
||||||
|
web.RegisterAppSetupFunc(routes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func routes(app *fiber.App) {
|
||||||
|
|
||||||
|
app.Get("/", func(c *fiber.Ctx) error {
|
||||||
|
data := *web.Common(c)
|
||||||
|
data["Title"] = i18n.Translate(c, "home")
|
||||||
|
return c.Render("index", data, "layouts/base")
|
||||||
|
})
|
||||||
|
app.Get("/blog", func(c *fiber.Ctx) error {
|
||||||
|
data := *web.Common(c)
|
||||||
|
data["Title"] = i18n.Translate(c, "blog")
|
||||||
|
return c.Render("blog", data, "layouts/base")
|
||||||
|
})
|
||||||
|
app.Get("/projects", func(c *fiber.Ctx) error {
|
||||||
|
data := *web.Common(c)
|
||||||
|
data["Title"] = i18n.Translate(c, "projects")
|
||||||
|
return c.Render("projects", data, "layouts/base")
|
||||||
|
})
|
||||||
|
app.Get("/about", func(c *fiber.Ctx) error {
|
||||||
|
data := *web.Common(c)
|
||||||
|
data["Title"] = i18n.Translate(c, "about")
|
||||||
|
return c.Render("about", data, "layouts/base")
|
||||||
|
})
|
||||||
|
|
||||||
|
app.Get("/settings", settingsHandler)
|
||||||
|
app.Get("/login", loginHandler)
|
||||||
|
app.Get(config.Config.Oidc.CallbackUrl, oidc.HandleCallback)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Static
|
||||||
|
*/
|
||||||
|
static, _ := fs.Sub(assets.StaticEmbed, "static")
|
||||||
|
app.Use("/static/", filesystem.New(filesystem.Config{
|
||||||
|
Root: http.FS(static),
|
||||||
|
}))
|
||||||
|
|
||||||
|
/*
|
||||||
|
404
|
||||||
|
*/
|
||||||
|
app.Use(func(c *fiber.Ctx) error {
|
||||||
|
data := *web.Common(c)
|
||||||
|
return c.Render("404", data, "layouts/base")
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
19
internal/handlers/settings.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
|
func settingsHandler(c *fiber.Ctx) error {
|
||||||
|
lang := c.Query("lang")
|
||||||
|
redirectURL := c.Query("redirect")
|
||||||
|
if lang != "" {
|
||||||
|
c.Cookie(&fiber.Cookie{
|
||||||
|
Name: "language",
|
||||||
|
Value: lang,
|
||||||
|
Secure: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if redirectURL != "" {
|
||||||
|
return c.Redirect(redirectURL)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
23
internal/web/common.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.tijl.dev/tijl/tijl.dev/internal/i18n"
|
||||||
|
"git.tijl.dev/tijl/tijl.dev/internal/sessions"
|
||||||
|
"git.tijl.dev/tijl/tijl.dev/modules/web"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Load() {
|
||||||
|
web.RegisterCommon(func(c *fiber.Ctx, m *fiber.Map) {
|
||||||
|
_, err := sessions.GetSession(c)
|
||||||
|
signedIn := false
|
||||||
|
if err == nil {
|
||||||
|
signedIn = true
|
||||||
|
}
|
||||||
|
|
||||||
|
(*m)["SignedIn"] = signedIn
|
||||||
|
(*m)["Path"] = c.Path()
|
||||||
|
(*m)["Language"] = i18n.GetLanguage(c)
|
||||||
|
(*m)["T"] = i18n.GetTranslations(i18n.GetLanguage(c))
|
||||||
|
})
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package static
|
package locales
|
||||||
|
|
||||||
import "embed"
|
import "embed"
|
||||||
|
|
6
migrations/embed.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package migrations
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
//go:embed *
|
||||||
|
var Embed embed.FS
|
@ -10,8 +10,9 @@ var (
|
|||||||
Logger zerolog.Logger
|
Logger zerolog.Logger
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func Load() {
|
||||||
Logger = zerolog.New(os.Stderr).With().Timestamp().Logger().Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
Logger = zerolog.New(os.Stderr).With().Timestamp().Logger().Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||||
|
Logger.Level(zerolog.DebugLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Info() *zerolog.Event {
|
func Info() *zerolog.Event {
|
||||||
|
21
modules/web/app.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import "github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Basic system for being able to add routes from other packages
|
||||||
|
*/
|
||||||
|
|
||||||
|
var setupFuncs []func(*fiber.App)
|
||||||
|
|
||||||
|
func RegisterAppSetupFunc(function func(*fiber.App)) {
|
||||||
|
setupFuncs = append(setupFuncs, function)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Setup(app *fiber.App) {
|
||||||
|
|
||||||
|
for _, function := range setupFuncs {
|
||||||
|
function(app)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
modules/web/common.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "git.tijl.dev/tijl/tijl.dev/modules/logger"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var commons *fiber.Map = &fiber.Map{}
|
||||||
|
var commonFunctions []func(*fiber.Ctx, *fiber.Map)
|
||||||
|
|
||||||
|
func RegisterCommon(function func(*fiber.Ctx, *fiber.Map)) {
|
||||||
|
commonFunctions = append(commonFunctions, function)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Common(c *fiber.Ctx) *fiber.Map {
|
||||||
|
theMap := &fiber.Map{}
|
||||||
|
for _, function := range commonFunctions {
|
||||||
|
function(c, theMap)
|
||||||
|
}
|
||||||
|
log.Debug().Interface("theMap", theMap).Interface("commonFunctions", commonFunctions).Msg("yo")
|
||||||
|
return theMap
|
||||||
|
}
|
1
modules/web/engine.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package web
|
@ -3,7 +3,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"build:css": "tailwindcss -i ./web/styles.css -o ./static/css/styles.css --minify"
|
"build:css": "tailwindcss -i ./web/styles.css -o ./web/assets/static/css/styles.css --minify"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.14",
|
"@tailwindcss/typography": "^0.5.14",
|
||||||
|
@ -3,7 +3,7 @@ import { defineConfig } from "vite";
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [],
|
plugins: [],
|
||||||
build: {
|
build: {
|
||||||
outDir: "static/js", // Output directory for compiled JS
|
outDir: "web/assets/static/js", // Output directory for compiled JS
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
output: {
|
output: {
|
||||||
entryFileNames: "[name].js",
|
entryFileNames: "[name].js",
|
||||||
|
9
web/assets/embed.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package assets
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
//go:embed *
|
||||||
|
var Embed embed.FS
|
||||||
|
|
||||||
|
//go:embed static/*
|
||||||
|
var StaticEmbed embed.FS
|
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 406 B |
Before Width: | Height: | Size: 382 B After Width: | Height: | Size: 382 B |
Before Width: | Height: | Size: 328 B After Width: | Height: | Size: 328 B |
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 301 B |
Before Width: | Height: | Size: 313 B After Width: | Height: | Size: 313 B |
Before Width: | Height: | Size: 271 B After Width: | Height: | Size: 271 B |