summaryrefslogtreecommitdiff
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build-and-deploy-prod.yml37
-rw-r--r--.github/workflows/build-and-deploy-stage.yml43
-rw-r--r--.gitignore2
-rw-r--r--Dockerfile1
-rw-r--r--internal/router/router.go57
-rw-r--r--static/favicon.icobin7633 -> 0 bytes
-rw-r--r--views/layouts/general-page.html127
-rw-r--r--views/pages/blog-page.html9
-rw-r--r--views/pages/global-map.html9
-rw-r--r--views/pages/unsubscribe-page.html5
-rw-r--r--views/partials/general-page-header.html4
11 files changed, 109 insertions, 185 deletions
diff --git a/.github/workflows/build-and-deploy-prod.yml b/.github/workflows/build-and-deploy-prod.yml
index 060ae32..97afdf7 100644
--- a/.github/workflows/build-and-deploy-prod.yml
+++ b/.github/workflows/build-and-deploy-prod.yml
@@ -40,8 +40,6 @@ jobs:
context: .
file: ./Dockerfile
push: true
- cache-from: type=gha
- cache-to: type=gha,mode=max
tags: |
ghcr.io/sayaandy/saya-today-web:latest
ghcr.io/sayaandy/saya-today-web:stable
@@ -52,16 +50,10 @@ jobs:
runs-on: ubuntu-latest
environment: Production
needs: [build-and-push]
- container:
- image: ghcr.io/ansible/community-ansible-dev-tools:v26.4.6
- options: --user root
steps:
- name: Checkout
uses: actions/checkout@v6
- - name: Install community.docker collection
- run: ansible-galaxy collection install community.docker
-
- name: Set up SSH connection for uz.saya.casa
run: |
mkdir -p ~/.ssh
@@ -75,28 +67,17 @@ jobs:
- name: Test SSH connection
run: |
- ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 svc_github@uz.saya.casa "echo 'SSH connection successful'"
+ ssh -o ConnectTimeout=10 -i ~/.ssh/id_ed25519 svc_github@uz.saya.casa "echo 'SSH connection successful'"
+
+ - name: Install Ansible
+ shell: bash
+ run: |
+ sudo apt update
+ sudo apt install -y ansible
- name: Run Ansible playbook
env:
- ANSIBLE_HOST_KEY_CHECKING: "False"
+ ANSIBLE_HOST_KEY_CHECKING: False
working-directory: ./deploy
run: |
- ansible-playbook \
- playbook.yml \
- -i inventory.yml \
- -l prod \
- --private-key ~/.ssh/id_ed25519 \
- -u svc_github \
- -e saya_today_web_auth_salt="${{ secrets.AUTH_SALT }}" \
- -e saya_today_web_s3_access_key_id="${{ secrets.S3_ACCESS_KEY_ID }}" \
- -e saya_today_web_s3_secret_access_key="${{ secrets.S3_SECRET_ACCESS_KEY }}" \
- -e saya_today_web_environment=prod \
- -e saya_today_web_tag=${{ github.ref_name }} \
- -e saya_today_web_mail_salt="${{ secrets.MAIL_SALT }}" \
- -e saya_today_web_mail_host="${{ secrets.MAIL_HOST }}" \
- -e saya_today_web_mail_address="${{ secrets.MAIL_ADDRESS }}" \
- -e saya_today_web_mail_username="${{ secrets.MAIL_USERNAME }}" \
- -e saya_today_web_mail_password="${{ secrets.MAIL_PASSWORD }}" \
- -e saya_today_google_site_verification="${{ secrets.GOOGLE_SITE_VERIFICATION }}" \
- -e saya_today_yandex_verification="${{ secrets.YANDEX_VERIFICATION }}"
+ ansible-playbook -i inventory.yml -l prod playbook.yml --private-key ~/.ssh/id_ed25519 -u svc_github -e saya_today_web_auth_salt="${{ secrets.AUTH_SALT }}" -e saya_today_web_s3_access_key_id="${{ secrets.S3_ACCESS_KEY_ID }}" -e saya_today_web_s3_secret_access_key="${{ secrets.S3_SECRET_ACCESS_KEY }}" -e saya_today_web_environment=prod -e saya_today_web_tag=${{ github.ref_name }} -e saya_today_web_mail_salt="${{ secrets.MAIL_SALT }}" -e saya_today_web_mail_host="${{ secrets.MAIL_HOST }}" -e saya_today_web_mail_address="${{ secrets.MAIL_ADDRESS }}" -e saya_today_web_mail_username="${{ secrets.MAIL_USERNAME }}" -e saya_today_web_mail_password="${{ secrets.MAIL_PASSWORD }}" -e saya_today_google_site_verification="${{ secrets.GOOGLE_SITE_VERIFICATION }}" -e saya_today_yandex_verification="${{ secrets.YANDEX_VERIFICATION }}"
diff --git a/.github/workflows/build-and-deploy-stage.yml b/.github/workflows/build-and-deploy-stage.yml
index ce4a1fb..ffee091 100644
--- a/.github/workflows/build-and-deploy-stage.yml
+++ b/.github/workflows/build-and-deploy-stage.yml
@@ -9,8 +9,6 @@ jobs:
environment: Stage
permissions:
packages: write
- outputs:
- sha_short: ${{ steps.ghss_vars.outputs.sha_short }}
steps:
- name: Checkout
uses: actions/checkout@v6
@@ -37,7 +35,7 @@ jobs:
- name: Set github short sha
id: ghss_vars
- run: echo "sha_short=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
+ run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Build and push
uses: docker/build-push-action@v7
@@ -45,8 +43,6 @@ jobs:
context: .
file: ./Dockerfile
push: true
- cache-from: type=gha
- cache-to: type=gha,mode=max
tags: |
ghcr.io/sayaandy/saya-today-web:latest
ghcr.io/sayaandy/saya-today-web:commit-${{ steps.ghss_vars.outputs.sha_short }}
@@ -56,16 +52,10 @@ jobs:
runs-on: ubuntu-latest
environment: Stage
needs: [build-and-push]
- container:
- image: ghcr.io/ansible/community-ansible-dev-tools:v26.4.6
- options: --user root
steps:
- name: Checkout
uses: actions/checkout@v6
- - name: Install community.docker collection
- run: ansible-galaxy collection install community.docker
-
- name: Set up SSH connection for uz.saya.casa
run: |
mkdir -p ~/.ssh
@@ -79,26 +69,21 @@ jobs:
- name: Test SSH connection
run: |
- ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 svc_github@uz.saya.casa "echo 'SSH connection successful'"
+ ssh -o ConnectTimeout=10 -i ~/.ssh/id_ed25519 svc_github@uz.saya.casa "echo 'SSH connection successful'"
+
+ - name: Install Ansible
+ shell: bash
+ run: |
+ sudo apt update
+ sudo apt install -y ansible
+
+ - name: Set github short sha
+ id: ghss_vars
+ run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Run Ansible playbook
env:
- ANSIBLE_HOST_KEY_CHECKING: "False"
+ ANSIBLE_HOST_KEY_CHECKING: False
working-directory: ./deploy
run: |
- ansible-playbook \
- playbook.yml \
- -i inventory.yml \
- -l stage \
- --private-key ~/.ssh/id_ed25519 \
- -u svc_github \
- -e saya_today_web_auth_salt="${{ secrets.AUTH_SALT }}" \
- -e saya_today_web_s3_access_key_id="${{ secrets.S3_ACCESS_KEY_ID }}" \
- -e saya_today_web_s3_secret_access_key="${{ secrets.S3_SECRET_ACCESS_KEY }}" \
- -e saya_today_web_environment=stage \
- -e saya_today_web_tag=commit-${{ needs.build-and-push.outputs.sha_short }} \
- -e saya_today_web_mail_salt="${{ secrets.MAIL_SALT }}" \
- -e saya_today_web_mail_host="${{ secrets.MAIL_HOST }}" \
- -e saya_today_web_mail_address="${{ secrets.MAIL_ADDRESS }}" \
- -e saya_today_web_mail_username="${{ secrets.MAIL_USERNAME }}" \
- -e saya_today_web_mail_password="${{ secrets.MAIL_PASSWORD }}"
+ ansible-playbook -i inventory.yml -l stage playbook.yml --private-key ~/.ssh/id_ed25519 -u svc_github -e saya_today_web_auth_salt="${{ secrets.AUTH_SALT }}" -e saya_today_web_s3_access_key_id="${{ secrets.S3_ACCESS_KEY_ID }}" -e saya_today_web_s3_secret_access_key="${{ secrets.S3_SECRET_ACCESS_KEY }}" -e saya_today_web_environment=stage -e saya_today_web_tag=commit-${{ steps.ghss_vars.outputs.sha_short }} -e saya_today_web_mail_salt="${{ secrets.MAIL_SALT }}" -e saya_today_web_mail_host="${{ secrets.MAIL_HOST }}" -e saya_today_web_mail_address="${{ secrets.MAIL_ADDRESS }}" -e saya_today_web_mail_username="${{ secrets.MAIL_USERNAME }}" -e saya_today_web_mail_password="${{ secrets.MAIL_PASSWORD }}"
diff --git a/.gitignore b/.gitignore
index a620479..b5ae410 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,5 +42,3 @@ config*.json
.envrc
/.ansible
-
-.DS_Store
diff --git a/Dockerfile b/Dockerfile
index 318ca51..5c38111 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,7 +4,6 @@ RUN apk add --no-cache sqlite-dev musl-dev gcc
WORKDIR /builddir
COPY . .
-RUN go mod download
RUN CGO_ENABLED=1 go build -o sayana-web .
FROM alpine:3.23 AS runtime-stage
diff --git a/internal/router/router.go b/internal/router/router.go
index 7f3511a..65e35a4 100644
--- a/internal/router/router.go
+++ b/internal/router/router.go
@@ -394,11 +394,6 @@ func (r *Router) Listen() error {
case "unix":
unixConfig := r.endpoint.Config.(*config.UnixConfig)
endpoint, _ := strings.CutPrefix(unixConfig.Path, "unix://")
-
- if err := os.Remove(endpoint); err != nil && !errors.Is(err, os.ErrNotExist) {
- return fmt.Errorf("error while cleaning up existing unix socket: %w", err)
- }
-
ln, err := net.Listen("unix", endpoint)
if err != nil {
return fmt.Errorf("error while initializing unix listener: %w", err)
@@ -451,8 +446,8 @@ func (r *Router) generalPage(c *fiber.Ctx, route Route, lang string) error {
path := c.Path()
method := c.Method()
trimmedPath := strings.Trim(path, "/")
- queryString := c.Request().URI().QueryString()
cacheKey := ""
+ queryString := c.Request().URI().QueryString()
switch route.ToCache() {
case ByUrlOnly:
@@ -469,7 +464,6 @@ func (r *Router) generalPage(c *fiber.Ctx, route Route, lang string) error {
valueMap := fiber.Map{
"L": r.supplements.Localization[lang],
"Lang": lang,
- "Path": trimmedPath,
"QueryString": queryString,
"CanonicalEndpoint": r.canonicalEndpoint,
"StaticStorageBaseUrl": r.supplements.StaticStorage.BaseUrl,
@@ -490,52 +484,10 @@ func (r *Router) generalPage(c *fiber.Ctx, route Route, lang string) error {
valueMap["LinkedData"] = template.JS(ldBytes)
}
- syntheticReferer := path
- if len(queryString) > 0 {
- syntheticReferer += "?" + string(queryString)
- }
- c.Request().Header.Set("Referer", syntheticReferer)
-
- parts := []struct {
- name string
- key string
- render func(c *fiber.Ctx, supplements *Supplements, lang string, templateMap fiber.Map) (int, error)
- }{
- {"top-embeds", "RenderedTopEmbeds", route.RenderTopEmbeds},
- {"header", "RenderedHeader", route.RenderHeader},
- {"body", "RenderedBody", route.RenderBody},
- {"footer", "RenderedFooter", route.RenderFooter},
- {"bottom-embeds", "RenderedBottomEmbeds", route.RenderBottomEmbeds},
- }
-
- for _, p := range parts {
- statusCode, err := p.render(c, r.supplements, lang, valueMap)
- if err != nil {
- slog.Error("failed to render segment for full page",
- slog.String("path", path),
- slog.String("segment", p.name),
- slog.String("error", err.Error()),
- )
- c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
- return c.Status(statusCode).SendString(err.Error())
- }
- segContent, err := r.supplements.TemplateManager.Render("general-page-"+p.name, valueMap, route.TemplatesToInject()...)
- if err != nil {
- slog.Error("failed to render segment template for full page",
- slog.String("path", path),
- slog.String("segment", p.name),
- slog.String("error", err.Error()),
- )
- c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
- return c.Status(fiber.ErrInternalServerError.Code).SendString("failed to generate segment")
- }
- valueMap[p.key] = template.HTML(segContent)
- }
-
content, err := r.supplements.TemplateManager.Render("general-page", valueMap)
if err != nil {
- slog.Warn("failed to generate full page", slog.String("path", path), slog.String("error", err.Error()))
- return c.Status(fiber.ErrInternalServerError.Code).SendString("failed to generate full page")
+ slog.Warn("failed to generate div", slog.String("path", path), slog.String("error", err.Error()))
+ return c.Status(fiber.ErrInternalServerError.Code).SendString("failed to generate div")
}
go r.supplements.PageCache.SetWithTTL(cacheKey, content, int64(len(content)), route.CacheDuration())
@@ -690,7 +642,8 @@ func (r *Router) getAndValidateLang(c *fiber.Ctx, langSetting LangSetting, defau
return lang, nil
}
}
- return "", fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("lang value is invalid: '%s' is not considered an available language", lang))
+ c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
+ return "", c.Status(fiber.ErrBadRequest.Code).SendString(fmt.Sprintf("lang value is invalid: '%s' is not considered an available language", lang))
}
func GetPathFromReferer(c *fiber.Ctx) (path string, pathParts []string, queryString string, err error) {
diff --git a/static/favicon.ico b/static/favicon.ico
deleted file mode 100644
index 99d5fbf..0000000
--- a/static/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html
index d787c16..98cbfcf 100644
--- a/views/layouts/general-page.html
+++ b/views/layouts/general-page.html
@@ -43,11 +43,6 @@
type="image/svg+xml"
media="(prefers-color-scheme: dark)"
/>
- <link
- rel="icon"
- href="/favicon.ico"
- type="image/x-icon"
- />
{{- with .LinkedData }}
<script type="application/ld+json">
{{ . }}
@@ -311,50 +306,14 @@
switchTheme(savedTheme);
</script>
- <script src="{{ .StaticStorageBaseUrl }}/libs/htmx/2.0.6/htmx.min.js"></script>
- <script src="{{ .StaticStorageBaseUrl }}/libs/leaflet/1.9.4/leaflet.js"></script>
- <script src="{{ .StaticStorageBaseUrl }}/libs/imagesloaded/5.0.0/imagesloaded.pkgd.min.js"></script>
- <script src="{{ .StaticStorageBaseUrl }}/libs/packery/3.0.0/dist/packery.pkgd.min.js"></script>
-
- <script>
- // Enable fitWidth-like attribute for Packery. Source: https://codepen.io/desandro/pen/kVmLYz
- var __resetLayout = Packery.prototype._resetLayout;
- Packery.prototype._resetLayout = function () {
- __resetLayout.call(this);
- var parentSize = getSize(this.element.parentNode);
- var colW = this.columnWidth + this.gutter;
- this.fitWidth =
- Math.floor((parentSize.innerWidth + this.gutter) / colW) *
- colW;
- this.packer.width = this.fitWidth;
- this.packer.height = Number.POSITIVE_INFINITY;
- this.packer.reset();
- };
-
- Packery.prototype._getContainerSize = function () {
- var emptyWidth = 0;
- for (var i = 0, len = this.packer.spaces.length; i < len; i++) {
- var space = this.packer.spaces[i];
- if (
- space.y === 0 &&
- space.height === Number.POSITIVE_INFINITY
- ) {
- emptyWidth += space.width;
- }
- }
-
- return {
- width: this.fitWidth - this.gutter - emptyWidth,
- height: this.maxY - this.gutter,
- };
- };
-
- Packery.prototype.needsResizeLayout = function () {
- return true;
- };
- </script>
-
- <div id="general-page-top-embeds" class="flex">{{ .RenderedTopEmbeds }}</div>
+ <div
+ id="general-page-top-embeds"
+ class="flex"
+ hx-get="/api/v1/general-page/top-embeds{{ if .QueryString }}?{{ .QueryString }}{{ end }}"
+ hx-trigger="load"
+ hx-target="this"
+ hx-swap="innerHTML"
+ ></div>
<div
id="general-page-top-embeds-trigger"
hx-get="/api/v1/general-page/top-embeds{{ if .QueryString }}?{{ .QueryString }}{{ end }}"
@@ -528,7 +487,11 @@
<header
id="general-page-header"
class="max-xs:hidden [@media(max-height:32rem)]:hidden flex flex-col ml-8 basis-8"
- >{{ .RenderedHeader }}</header>
+ hx-get="/api/v1/general-page/header{{ if .QueryString }}?{{ .QueryString }}{{ end }}"
+ hx-trigger="load"
+ hx-target="this"
+ hx-swap="innerHTML"
+ ></header>
<div
id="general-page-header-trigger"
hx-get="/api/v1/general-page/header{{ if .QueryString }}?{{ .QueryString }}{{ end }}"
@@ -544,7 +507,11 @@
<main
id="general-page-body"
class="relative flex-1 overflow-y-auto"
- >{{ .RenderedBody }}</main>
+ hx-get="/api/v1/general-page/body{{ if .QueryString }}?{{ .QueryString }}{{ end }}"
+ hx-trigger="load"
+ hx-target="this"
+ hx-swap="innerHTML"
+ ></main>
<div
id="general-page-body-trigger"
hx-get="/api/v1/general-page/body{{ if .QueryString }}?{{ .QueryString }}{{ end }}"
@@ -556,7 +523,11 @@
<footer
id="general-page-footer"
class="flex flex-row basis-4 my-1"
- >{{ .RenderedFooter }}</footer>
+ hx-get="/api/v1/general-page/footer{{ if .QueryString }}?{{ .QueryString }}{{ end }}"
+ hx-trigger="load"
+ hx-target="this"
+ hx-swap="innerHTML"
+ ></footer>
<div
id="general-page-footer-trigger"
hx-get="/api/v1/general-page/footer{{ if .QueryString }}?{{ .QueryString }}{{ end }}"
@@ -578,7 +549,57 @@
<div class="grow bg-split-right"></div>
- <div id="general-page-bottom-embeds" class="flex">{{ .RenderedBottomEmbeds }}</div>
+ <script src="{{ .StaticStorageBaseUrl }}/libs/htmx/2.0.6/htmx.min.js"></script>
+ <script src="{{ .StaticStorageBaseUrl }}/libs/leaflet/1.9.4/leaflet.js"></script>
+ <script src="{{ .StaticStorageBaseUrl }}/libs/imagesloaded/5.0.0/imagesloaded.pkgd.min.js"></script>
+ <script src="{{ .StaticStorageBaseUrl }}/libs/packery/3.0.0/dist/packery.pkgd.min.js"></script>
+
+ <script>
+ // Enable fitWidth-like attribute for Packery. Source: https://codepen.io/desandro/pen/kVmLYz
+ var __resetLayout = Packery.prototype._resetLayout;
+ Packery.prototype._resetLayout = function () {
+ __resetLayout.call(this);
+ var parentSize = getSize(this.element.parentNode);
+ var colW = this.columnWidth + this.gutter;
+ this.fitWidth =
+ Math.floor((parentSize.innerWidth + this.gutter) / colW) *
+ colW;
+ this.packer.width = this.fitWidth;
+ this.packer.height = Number.POSITIVE_INFINITY;
+ this.packer.reset();
+ };
+
+ Packery.prototype._getContainerSize = function () {
+ var emptyWidth = 0;
+ for (var i = 0, len = this.packer.spaces.length; i < len; i++) {
+ var space = this.packer.spaces[i];
+ if (
+ space.y === 0 &&
+ space.height === Number.POSITIVE_INFINITY
+ ) {
+ emptyWidth += space.width;
+ }
+ }
+
+ return {
+ width: this.fitWidth - this.gutter - emptyWidth,
+ height: this.maxY - this.gutter,
+ };
+ };
+
+ Packery.prototype.needsResizeLayout = function () {
+ return true;
+ };
+ </script>
+
+ <div
+ id="general-page-bottom-embeds"
+ class="flex"
+ hx-get="/api/v1/general-page/bottom-embeds{{ if .QueryString }}?{{ .QueryString }}{{ end }}"
+ hx-trigger="load"
+ hx-target="this"
+ hx-swap="innerHTML"
+ ></div>
<div
id="general-page-bottom-embeds-trigger"
hx-get="/api/v1/general-page/bottom-embeds{{ if .QueryString }}?{{ .QueryString }}{{ end }}"
diff --git a/views/pages/blog-page.html b/views/pages/blog-page.html
index d8cfbff..a5e80d8 100644
--- a/views/pages/blog-page.html
+++ b/views/pages/blog-page.html
@@ -1,10 +1,7 @@
{{ define "body" }}
<div class="absolute w-full h-full inset-0 inset-shadow-[0_0_0.4rem_black] pointer-events-none z-20"></div>
<article class="relative bg-paper bg-background-light flex flex-col px-8 py-4 overflow-y-auto">
- <h1 class="max-xs:flex flex-row content-center [@media(max-height:32rem)]:block hidden font-gentium text-2xl font-bold italic text-main-hard tracking-[.0125rem] mb-1">
- <div hx-get="/api/v1/like" hx-target="this" hx-swap="outerHTML" hx-trigger="load"></div>
- {{ .Title }}
- </h1>
+ <h1 class="max-xs:block [@media(max-height:32rem)]:block hidden font-gentium text-2xl font-bold italic text-main-hard tracking-[.0125rem] mb-1">{{ .Title }}</h1>
<p class="block grow text-lg font-gentium text-secondary">
<b>{{ .L.Metadata.Published }}</b>:
<time datetime="{{ .PublishedDate }}" hx-get="/api/v1/tz" hx-vals='js:{timestamp: "{{ .PublishedDate }}", tz: clientTimeZone}' hx-target="this" hx-swap="innerHTML" hx-trigger="load">
@@ -24,9 +21,9 @@
function initLocationMap(id, x, y, relativeErrorMeters = 0) {
map = L.map(id).setView([x, y], 8);
- L.tileLayer('https://tiles.stadiamaps.com/tiles/outdoors/{z}/{x}/{y}{r}.png', {
+ L.tileLayer('https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png', {
maxZoom: 20,
- attribution: '&copy; <a href="https://stadiamaps.com/" target="_blank">Stadia Maps</a>, &copy; <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> &copy; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>',
+ attribution: '<a href="https://github.com/cyclosm/cyclosm-cartocss-style/releases" title="CyclOSM - Open Bicycle render">CyclOSM</a> | Map data: &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
if (relativeErrorMeters != 0) {
diff --git a/views/pages/global-map.html b/views/pages/global-map.html
index 1501111..248d0b9 100644
--- a/views/pages/global-map.html
+++ b/views/pages/global-map.html
@@ -35,11 +35,6 @@
media="(prefers-color-scheme: dark)"
/>
<link
- rel="icon"
- href="/favicon.ico"
- type="image/x-icon"
- />
- <link
rel="stylesheet"
href="{{ .StaticStorageBaseUrl }}/libs/leaflet/1.9.4/leaflet.css"
/>
@@ -394,9 +389,9 @@
function initLocationMap() {
map = L.map('map-container').setView([{{ .MapLocationLat }}, {{ .MapLocationLong }}], 4);
- L.tileLayer('https://tiles.stadiamaps.com/tiles/outdoors/{z}/{x}/{y}{r}.png', {
+ L.tileLayer('https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png', {
maxZoom: 20,
- attribution: '&copy; <a href="https://stadiamaps.com/" target="_blank">Stadia Maps</a>, &copy; <a href="https://openmaptiles.org/" target="_blank">OpenMapTiles</a> &copy; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a>',
+ attribution: '<a href="https://github.com/cyclosm/cyclosm-cartocss-style/releases" title="CyclOSM - Open Bicycle render">CyclOSM</a> | Map data: &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
zoomControl: false
}).addTo(map);
diff --git a/views/pages/unsubscribe-page.html b/views/pages/unsubscribe-page.html
index 9a78488..a917746 100644
--- a/views/pages/unsubscribe-page.html
+++ b/views/pages/unsubscribe-page.html
@@ -16,11 +16,6 @@
type="image/svg+xml"
media="(prefers-color-scheme: dark)"
/>
- <link
- rel="icon"
- href="/favicon.ico"
- type="image/x-icon"
- />
<title>{{ .L.UnsubscribePage.Header }} // SAYA.UZ</title>
<style>
.bg-paper {
diff --git a/views/partials/general-page-header.html b/views/partials/general-page-header.html
index 3b8a6c8..995ebf3 100644
--- a/views/partials/general-page-header.html
+++ b/views/partials/general-page-header.html
@@ -1,9 +1,9 @@
<title>{{ .Title }} // SAYA.UZ</title>
<div class="flex flex-row mb-2">
{{ block "header" . }}{{ end }}
- <h1
+ <p
class="text-4xl font-m-plus font-bold italic text-shadow-[0_2px_2px_var(--color-main-soft)] text-left my-auto"
>
{{ .Title }}
- </h1>
+ </p>
</div>