summaryrefslogtreecommitdiffci
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build-and-deploy-prod.yml102
-rw-r--r--.github/workflows/build-and-deploy-stage.yml104
-rw-r--r--Dockerfile9
-rw-r--r--Jenkinsfile313
-rw-r--r--config/config.go6
-rw-r--r--config/config.prod.yaml8
-rw-r--r--deploy/playbook.yml9
-rw-r--r--internal/router/handlers/lang-blog-title.go6
-rw-r--r--internal/router/handlers/root.go7
-rw-r--r--internal/router/router.go2
-rw-r--r--static/input.css8
-rw-r--r--views/layouts/general-page.html37
-rw-r--r--views/partials/general-page-header.html2
13 files changed, 255 insertions, 358 deletions
diff --git a/.github/workflows/build-and-deploy-prod.yml b/.github/workflows/build-and-deploy-prod.yml
new file mode 100644
index 0000000..060ae32
--- /dev/null
+++ b/.github/workflows/build-and-deploy-prod.yml
@@ -0,0 +1,102 @@
+name: Docker image building and publishing onto Production
+on:
+ push:
+ tags:
+ - "*"
+jobs:
+ build-and-push:
+ if: github.repository == 'SayaAndy/saya-today-web'
+ runs-on: ubuntu-latest
+ environment: Production
+ permissions:
+ packages: write
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Generate output.css with tailwindcss
+ uses: ZoeyVid/tailwindcss-update@main
+ with:
+ input: static/input.css
+ output: static/output.css
+ params: "--minify"
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v4
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v4
+
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v4
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GHCR_TOKEN }}
+
+ - name: Build and push
+ uses: docker/build-push-action@v7
+ with:
+ 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
+ ghcr.io/sayaandy/saya-today-web:${{ github.ref_name }}
+
+ deploy:
+ if: github.repository == 'SayaAndy/saya-today-web'
+ 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
+ (cat <<EOF
+ ${{ secrets.SVC_GITHUB_PK }}
+ EOF
+ ) > ~/.ssh/id_ed25519
+ chmod 600 ~/.ssh/id_ed25519
+ sed -i 's/\r$//' ~/.ssh/id_ed25519
+ ssh-keyscan -H uz.saya.casa >> ~/.ssh/known_hosts
+
+ - 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'"
+
+ - name: Run Ansible playbook
+ env:
+ 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 }}"
diff --git a/.github/workflows/build-and-deploy-stage.yml b/.github/workflows/build-and-deploy-stage.yml
new file mode 100644
index 0000000..ce4a1fb
--- /dev/null
+++ b/.github/workflows/build-and-deploy-stage.yml
@@ -0,0 +1,104 @@
+name: Docker image building and publishing onto Stage
+on:
+ push:
+ branches: [stage]
+jobs:
+ build-and-push:
+ if: github.repository == 'SayaAndy/saya-today-web'
+ runs-on: ubuntu-latest
+ environment: Stage
+ permissions:
+ packages: write
+ outputs:
+ sha_short: ${{ steps.ghss_vars.outputs.sha_short }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Generate output.css with tailwindcss
+ uses: ZoeyVid/tailwindcss-update@main
+ with:
+ input: static/input.css
+ output: static/output.css
+ params: "--minify"
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v4
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v4
+
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v4
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GHCR_TOKEN }}
+
+ - name: Set github short sha
+ id: ghss_vars
+ run: echo "sha_short=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
+
+ - name: Build and push
+ uses: docker/build-push-action@v7
+ with:
+ 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 }}
+
+ deploy:
+ if: github.repository == 'SayaAndy/saya-today-web'
+ 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
+ (cat <<EOF
+ ${{ secrets.SVC_GITHUB_PK }}
+ EOF
+ ) > ~/.ssh/id_ed25519
+ chmod 600 ~/.ssh/id_ed25519
+ sed -i 's/\r$//' ~/.ssh/id_ed25519
+ ssh-keyscan -H uz.saya.casa >> ~/.ssh/known_hosts
+
+ - 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'"
+
+ - name: Run Ansible playbook
+ env:
+ 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 }}"
diff --git a/Dockerfile b/Dockerfile
index d0b6621..44d1ea2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,9 +1,4 @@
-FROM golang:1.26.4-alpine3.24 AS build-stage
-
-ARG TARGETOS=linux
-ARG TARGETARCH=amd64
-ENV GOOS=${TARGETOS}
-ENV GOARCH=${TARGETARCH}
+FROM golang:1.26-alpine3.23 AS build-stage
RUN apk add --no-cache sqlite-dev musl-dev gcc
@@ -12,7 +7,7 @@ COPY . .
RUN go mod download
RUN CGO_ENABLED=1 go build -o sayana-web .
-FROM alpine:3.24 AS runtime-stage
+FROM alpine:3.23 AS runtime-stage
ENV ENVIRONMENT=""
ENV AUTH_SALT=""
diff --git a/Jenkinsfile b/Jenkinsfile
deleted file mode 100644
index 8633145..0000000
--- a/Jenkinsfile
+++ /dev/null
@@ -1,313 +0,0 @@
-pipeline {
- agent none
-
- stages {
- stage('Compile Tailwind CSS') {
- agent {
- docker {
- image 'node:26.3.1-alpine3.24'
- args '-v /tmp:/tmp -v /.npm:/.npm'
- }
- }
- steps {
- checkout scm
- sh '''
- npm install tailwindcss @tailwindcss/cli @tailwindcss/forms
- npx tailwindcss -i static/input.css -o static/output.css --minify
- '''
- stash name: 'tailwindcss-output', includes: 'static/output.css'
- }
- }
-
- stage('Matrix Build') {
- matrix {
- axes {
- axis {
- name 'GOOS'
- values 'linux'
- }
- axis {
- name 'GOARCH'
- values 'arm64', 'amd64'
- }
- }
- stages {
- stage('Build') {
- agent {
- kubernetes {
- defaultContainer 'kaniko'
- yaml """
-apiVersion: v1
-kind: Pod
-metadata:
- namespace: jenkins
-spec:
- nodeSelector:
- kubernetes.io/arch: ${GOARCH}
- containers:
- - name: kaniko
- image: gcr.io/kaniko-project/executor:v1.24.0-debug
- imagePullPolicy: Always
- command: [ /busybox/cat ]
- tty: true
- resources:
- requests:
- cpu: "1"
- memory: 2Gi
- ephemeral-storage: 4Gi
- limits:
- memory: 4Gi
- ephemeral-storage: 8Gi
-"""
- }
- }
- environment {
- IMAGE_PUSH_DESTINATION="registry.sayag.it/sayauz/web"
- }
- steps {
- checkout scm
- unstash 'tailwindcss-output'
- container(name: 'kaniko', shell: '/busybox/sh') {
- withCredentials([string(credentialsId: 'registry-sayagit-jenkins-password', variable: 'REGISTRY_SAYAGIT_JENKINS_PASSWORD')]) {
- withEnv(['PATH+EXTRA=/busybox']) {
- script {
- env.GIT_COMMIT_SHORT = env.GIT_COMMIT ? env.GIT_COMMIT.take(7) : "unknown"
- try {
- sh '''#!/busybox/sh
- mkdir -p /kaniko/.docker
- printf '{"auths":{"registry.sayag.it":{"username":"jenkins","password":"%s"}}}' "$REGISTRY_SAYAGIT_JENKINS_PASSWORD" > /kaniko/.docker/config.json
- /kaniko/executor --context `pwd` \
- --custom-platform=linux/${GOARCH} \
- --build-arg TARGETOS=linux \
- --build-arg TARGETARCH=${GOARCH} \
- --destination $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT-$GOARCH
- '''
- } catch (Exception e) {
- echo "Caught exception: ${e.getMessage()}"
- currentBuild.result = 'FAILURE'
- throw e
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- stage('Stitch Manifest') {
- agent {
- kubernetes {
- defaultContainer 'manifest-tool'
- yaml """
-apiVersion: v1
-kind: Pod
-metadata:
- namespace: jenkins
-spec:
- containers:
- - name: manifest-tool
- image: mplatform/manifest-tool:alpine-v2.2.2
- imagePullPolicy: Always
- command: [ 'cat' ]
- tty: true
- resources:
- requests:
- cpu: "1"
- memory: 2Gi
- ephemeral-storage: 4Gi
-"""
- }
- }
- environment {
- IMAGE_PUSH_DESTINATION="registry.sayag.it/sayauz/web"
- }
- steps {
- script {
- env.GIT_COMMIT_SHORT = env.GIT_COMMIT ? env.GIT_COMMIT.take(7) : "unknown"
- }
- withCredentials([string(credentialsId: 'registry-sayagit-jenkins-password', variable: 'REGISTRY_SAYAGIT_JENKINS_PASSWORD')]) {
- sh '''mkdir -p /root/.docker
- printf '{"auths":{"registry.sayag.it":{"username":"jenkins","password":"%s"}}}' "$REGISTRY_SAYAGIT_JENKINS_PASSWORD" > /root/.docker/config.json
-
- manifest-tool push from-args \
- --platforms linux/amd64,linux/arm64 \
- --template $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT-ARCH \
- --target $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT
- manifest-tool push from-args \
- --platforms linux/amd64,linux/arm64 \
- --template $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT-ARCH \
- --target $IMAGE_PUSH_DESTINATION:latest
- if [ "$TAG_NAME" != "" ]; then
- manifest-tool push from-args \
- --platforms linux/amd64,linux/arm64 \
- --template $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT-ARCH \
- --target $IMAGE_PUSH_DESTINATION:stable
- manifest-tool push from-args \
- --platforms linux/amd64,linux/arm64 \
- --template $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT-ARCH \
- --target $IMAGE_PUSH_DESTINATION:$TAG_NAME
- fi
- '''
- }
- }
- }
- stage('Deploy (Stage)') {
- when { branch 'stage' }
- agent {
- kubernetes {
- defaultContainer 'ansible'
- yaml """
-apiVersion: v1
-kind: Pod
-metadata:
- namespace: jenkins
-spec:
- containers:
- - name: ansible
- image: ghcr.io/ansible/community-ansible-dev-tools:v26.7.2
- command: [ 'cat' ]
- tty: true
- resources:
- requests:
- cpu: "500m"
- memory: 1Gi
-"""
- }
- }
- steps {
- checkout scm
- container('ansible') {
- script {
- env.GIT_COMMIT_SHORT = env.GIT_COMMIT ? env.GIT_COMMIT.take(7) : "unknown"
-
- def secretVars = [
- 'sayauz-web-stage-auth-salt' : 'AUTH_SALT',
- 'sayauz-web-stage-s3-access-key-id' : 'S3_ACCESS_KEY_ID',
- 'sayauz-web-stage-s3-secret-access-key' : 'S3_SECRET_ACCESS_KEY',
- 'sayauz-web-stage-mail-salt' : 'MAIL_SALT',
- 'sayauz-web-stage-mail-host' : 'MAIL_HOST',
- 'sayauz-web-stage-mail-address' : 'MAIL_ADDRESS',
- 'sayauz-web-stage-mail-username' : 'MAIL_USERNAME',
- 'sayauz-web-stage-mail-password' : 'MAIL_PASSWORD'
- ]
- def bindings = secretVars.collect { id, varName -> string(credentialsId: id, variable: varName) }
- bindings << sshUserPrivateKey(credentialsId: 'sayauz-svc-github', keyFileVariable: 'SSH_KEY_FILE', usernameVariable: 'SSH_USER')
-
- withCredentials(bindings) {
- sh '''
- ansible-galaxy collection install community.docker
-
- mkdir -p ~/.ssh
- cp "$SSH_KEY_FILE" ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- ssh-keyscan -H uz.saya.casa >> ~/.ssh/known_hosts
-
- ssh -o ConnectTimeout=10 -i ~/.ssh/id_ed25519 "$SSH_USER@uz.saya.casa" "echo 'SSH connection successful'"
-
- cd deploy
- ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook \
- playbook.yml \
- -i inventory.yml \
- -l stage \
- --private-key ~/.ssh/id_ed25519 \
- -u "$SSH_USER" \
- -e saya_today_web_auth_salt="$AUTH_SALT" \
- -e saya_today_web_s3_access_key_id="$S3_ACCESS_KEY_ID" \
- -e saya_today_web_s3_secret_access_key="$S3_SECRET_ACCESS_KEY" \
- -e saya_today_web_environment=stage \
- -e saya_today_web_tag=commit-$GIT_COMMIT_SHORT \
- -e saya_today_web_mail_salt="$MAIL_SALT" \
- -e saya_today_web_mail_host="$MAIL_HOST" \
- -e saya_today_web_mail_address="$MAIL_ADDRESS" \
- -e saya_today_web_mail_username="$MAIL_USERNAME" \
- -e saya_today_web_mail_password="$MAIL_PASSWORD"
- '''
- }
- }
- }
- }
- }
- stage('Deploy (Prod)') {
- when { buildingTag() }
- agent {
- kubernetes {
- defaultContainer 'ansible'
- yaml """
-apiVersion: v1
-kind: Pod
-metadata:
- namespace: jenkins
-spec:
- containers:
- - name: ansible
- image: ghcr.io/ansible/community-ansible-dev-tools:v26.7.2
- command: [ 'cat' ]
- tty: true
- resources:
- requests:
- cpu: "500m"
- memory: 1Gi
-"""
- }
- }
- steps {
- checkout scm
- container('ansible') {
- script {
- def secretVars = [
- 'sayauz-web-prod-auth-salt' : 'AUTH_SALT',
- 'sayauz-web-prod-s3-access-key-id' : 'S3_ACCESS_KEY_ID',
- 'sayauz-web-prod-s3-secret-access-key' : 'S3_SECRET_ACCESS_KEY',
- 'sayauz-web-prod-mail-salt' : 'MAIL_SALT',
- 'sayauz-web-prod-mail-host' : 'MAIL_HOST',
- 'sayauz-web-prod-mail-address' : 'MAIL_ADDRESS',
- 'sayauz-web-prod-mail-username' : 'MAIL_USERNAME',
- 'sayauz-web-prod-mail-password' : 'MAIL_PASSWORD',
- 'sayauz-web-prod-verification-google' : 'GOOGLE_VERIFICATION',
- 'sayauz-web-prod-verification-yandex' : 'YANDEX_VERIFICATION',
- 'sayauz-web-prod-verification-bing' : 'BING_VERIFICATION'
- ]
- def bindings = secretVars.collect { id, varName -> string(credentialsId: id, variable: varName) }
- bindings << sshUserPrivateKey(credentialsId: 'sayauz-svc-github', keyFileVariable: 'SSH_KEY_FILE', usernameVariable: 'SSH_USER')
-
- withCredentials(bindings) {
- sh '''
- ansible-galaxy collection install community.docker
-
- mkdir -p ~/.ssh
- cp "$SSH_KEY_FILE" ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- ssh-keyscan -H uz.saya.casa >> ~/.ssh/known_hosts
-
- ssh -o ConnectTimeout=10 -i ~/.ssh/id_ed25519 "$SSH_USER@uz.saya.casa" "echo 'SSH connection successful'"
-
- cd deploy
- ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook \
- playbook.yml \
- -i inventory.yml \
- -l prod \
- --private-key ~/.ssh/id_ed25519 \
- -u "$SSH_USER" \
- -e saya_today_web_auth_salt="$AUTH_SALT" \
- -e saya_today_web_s3_access_key_id="$S3_ACCESS_KEY_ID" \
- -e saya_today_web_s3_secret_access_key="$S3_SECRET_ACCESS_KEY" \
- -e saya_today_web_environment=prod \
- -e saya_today_web_tag=$TAG_NAME \
- -e saya_today_web_mail_salt="$MAIL_SALT" \
- -e saya_today_web_mail_host="$MAIL_HOST" \
- -e saya_today_web_mail_address="$MAIL_ADDRESS" \
- -e saya_today_web_mail_username="$MAIL_USERNAME" \
- -e saya_today_web_mail_password="$MAIL_PASSWORD" \
- -e saya_today_google_verification="$GOOGLE_VERIFICATION" \
- -e saya_today_yandex_verification="$YANDEX_VERIFICATION" \
- -e saya_today_bing_verification="$BING_VERIFICATION"
- '''
- }
- }
- }
- }
- }
- }
-}
diff --git a/config/config.go b/config/config.go
index 9185e6a..8ab1bfc 100644
--- a/config/config.go
+++ b/config/config.go
@@ -20,7 +20,7 @@ type Config struct {
Auth AuthConfig `json:"Auth" yaml:"auth" validate:"required"`
Mail MailConfig `json:"Mail" yaml:"mail" validate:"required"`
CanonicalEndpoint string `json:"CanonicalEndpoint" yaml:"canonicalEndpoint" validate:"required"`
- Meta []MetaConfig `json:"Meta" yaml:"meta"`
+ Meta MetaConfig `json:"Meta" yaml:"meta"`
PhotoStorage PhotoStorageConfig `json:"PhotoStorage" yaml:"photoStorage"`
StaticStorage StaticStorageConfig `json:"StaticStorage" yaml:"staticStorage" validate:"required"`
AllowOrigins []string `json:"AllowOrigins" yaml:"allowOrigins"`
@@ -237,8 +237,8 @@ type TriggerConfig struct {
}
type MetaConfig struct {
- Name string `json:"Name" yaml:"name"`
- Value string `json:"Value" yaml:"value"`
+ GoogleSiteVerification string `json:"GoogleSiteVerification" yaml:"googleSiteVerification"`
+ YandexVerification string `json:"YandexVerification" yaml:"yandexVerification"`
}
type PhotoStorageConfig struct {
diff --git a/config/config.prod.yaml b/config/config.prod.yaml
index 6ec00d8..ce0941d 100644
--- a/config/config.prod.yaml
+++ b/config/config.prod.yaml
@@ -55,12 +55,8 @@ mail:
onNewPost: "0/5 * * * *"
canonicalEndpoint: "https://${FQDN}"
meta:
- - name: google-site-verification
- value: "${GOOGLE_SITE_VERIFICATION}"
- - name: yandex-verification
- value: "${YANDEX_VERIFICATION}"
- - name: msvalidate.01
- value: "${BING_VERIFICATION}"
+ googleSiteVerification: "${GOOGLE_SITE_VERIFICATION}"
+ yandexVerification: "${YANDEX_VERIFICATION}"
photoStorage:
full:
baseUrl: https://cdn.saya.uz/photos/jpeg-full/%s
diff --git a/deploy/playbook.yml b/deploy/playbook.yml
index 057cc19..ae3e936 100644
--- a/deploy/playbook.yml
+++ b/deploy/playbook.yml
@@ -6,7 +6,7 @@
vars:
docker_volumes:
- "{{ saya_today_web_name }}-volume:/data:rw"
-
+
tasks:
- name: Initialize Unix socket volume
when: >-
@@ -26,11 +26,11 @@
community.docker.docker_volume:
name: "{{ saya_today_web_name }}-volume"
- - name: Deploy sayauz/web Docker Container
+ - name: Deploy saya-today-web Docker Container
community.docker.docker_container:
name: "{{ saya_today_web_name }}"
hostname: "{{ saya_today_web_hostname }}"
- image: "registry.sayag.it/sayauz/web:{{ saya_today_web_tag }}"
+ image: "ghcr.io/sayaandy/saya-today-web:{{ saya_today_web_tag }}"
env:
S3_ACCESS_KEY_ID: "{{ saya_today_web_s3_access_key_id }}"
S3_SECRET_ACCESS_KEY: "{{ saya_today_web_s3_secret_access_key }}"
@@ -42,9 +42,8 @@
MAIL_PASSWORD: "{{ saya_today_web_mail_password }}"
MAIL_SALT: "{{ saya_today_web_mail_salt }}"
FQDN: "{{ saya_today_web_listen_address }}"
- GOOGLE_VERIFICATION: "{{ saya_today_google_verification | default('') }}"
+ GOOGLE_SITE_VERIFICATION: "{{ saya_today_google_site_verification | default('') }}"
YANDEX_VERIFICATION: "{{ saya_today_yandex_verification | default('') }}"
- BING_VERIFICATION: "{{ saya_today_bing_verification | default('') }}"
network_mode: caddy
networks:
- name: caddy
diff --git a/internal/router/handlers/lang-blog-title.go b/internal/router/handlers/lang-blog-title.go
index 76dc335..5a1155d 100644
--- a/internal/router/handlers/lang-blog-title.go
+++ b/internal/router/handlers/lang-blog-title.go
@@ -156,13 +156,7 @@ func (r *BlogPageHandler) RenderHeader(c *fiber.Ctx, supplements *router.Supplem
return fiber.StatusNotFound, fmt.Errorf("could not read '%s' for metadata: %w", path, err)
}
- pageTitle := metadata.Title
- if metadata.Medley != "" {
- pageTitle += " // " + l10n.T.GetPath(lang, "Medleys", metadata.Medley).(string)
- }
-
templateMap["Title"] = metadata.Title
- templateMap["PageTitle"] = pageTitle
return fiber.StatusOK, nil
}
diff --git a/internal/router/handlers/root.go b/internal/router/handlers/root.go
index 4fc4e31..6a011e4 100644
--- a/internal/router/handlers/root.go
+++ b/internal/router/handlers/root.go
@@ -47,8 +47,11 @@ func (r *RootHandler) AddMeta(c *fiber.Ctx, supplements *router.Supplements, lan
{Property: "og:url", Content: fmt.Sprint(templateMap["CanonicalEndpoint"]) + "/"},
{Property: "og:type", Content: "website"},
}
- for _, field := range supplements.Meta {
- meta = append(meta, router.MetaField{Name: field.Name, Content: field.Value})
+ if supplements.Meta.GoogleSiteVerification != "" {
+ meta = append(meta, router.MetaField{Name: "google-site-verification", Content: supplements.Meta.GoogleSiteVerification})
+ }
+ if supplements.Meta.YandexVerification != "" {
+ meta = append(meta, router.MetaField{Name: "yandex-verification", Content: supplements.Meta.YandexVerification})
}
return meta, nil
}
diff --git a/internal/router/router.go b/internal/router/router.go
index a11a934..c8b5686 100644
--- a/internal/router/router.go
+++ b/internal/router/router.go
@@ -102,7 +102,7 @@ type Supplements struct {
BlogTrigger *blogtrigger.BlogTriggerScheduler
TemplateManager *templatemanager.TemplateManager
MarkdownRenderer goldmark.Markdown
- Meta []config.MetaConfig
+ Meta config.MetaConfig
PhotoStorage config.PhotoStorageConfig
StaticStorage config.StaticStorageConfig
}
diff --git a/static/input.css b/static/input.css
index e0c5c81..0dfb137 100644
--- a/static/input.css
+++ b/static/input.css
@@ -87,10 +87,6 @@ body {
scrollbar-color: var(--color-background-light) var(--color-main-soft);
}
-body.glightbox-open {
- height: 100dvh;
-}
-
@media screen and (min-width: 900px) and (min-height: 900px) {
html {
font-size: clamp(16px, min(1dvw, 1dvh) + 7px, 20px);
@@ -904,8 +900,8 @@ form.crossable.htmx-request input {
}
.ram-frame {
- width: 8rem;
- height: 8rem;
+ width: 20vmin;
+ height: 20vmin;
user-select: none;
-webkit-user-select: none;
}
diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html
index 06ef625..78c7f0c 100644
--- a/views/layouts/general-page.html
+++ b/views/layouts/general-page.html
@@ -213,8 +213,18 @@
var seed = cyrb128("{{ .Title }}");
var rand = sfc32(seed[0], seed[1], seed[2], seed[3]);
- function calculateRem(remNum) {
- return remNum * parseFloat(getComputedStyle(document.documentElement).fontSize);
+ function calculateVmin(percent) {
+ const viewportWidth = window.innerWidth;
+ const viewportHeight = window.innerHeight;
+
+ const smallerDimension = Math.min(
+ viewportWidth,
+ viewportHeight,
+ );
+
+ const vminValue = (smallerDimension / 100) * percent;
+
+ return vminValue;
}
const _probe = document.createElement('div');
@@ -309,7 +319,7 @@
theme = document.body.getAttribute("data-theme");
}
- rem = calculateRem(1);
+ vmin = calculateVmin(1);
var clWidth = document.documentElement.clientWidth;
var clHeight = document.documentElement.clientHeight;
@@ -328,11 +338,11 @@
"z-0",
"absolute",
);
+ const x = Math.floor(rand() * clWidth);
+ const y = Math.floor(rand() * clHeight * 0.8);
const rot = rand() * 90;
const animDuration = rand() * 10 + 3;
const sz = Math.floor(rand() * 8) + 12;
- const x = Math.floor(rand() * clWidth - 1.42 * sz); // 1.42 ~ sqrt(2)
- const y = Math.floor(rand() * clHeight * 0.8);
star.style.transform = `translateX(${x}px) translateY(${y}px) rotate(${rot}deg)`;
star.style.animationDuration = `${animDuration}s`;
star.style.fontSize = `${sz}px`;
@@ -352,14 +362,14 @@
);
let x, y;
outerLoop: while (true) {
- x = Math.floor(rand() * clWidth - 22.64 * rem) + 11.32 * rem; // 11.32 ~ 8 * sqrt(2)
- y = Math.floor(rand() * clHeight - 22.64 * rem) + 11.32 * rem;
+ x = Math.floor(rand() * clWidth - 20 * vmin);
+ y = Math.floor(rand() * clHeight - 20 * vmin);
for (j = 0; j < i - 1; j++) {
const xd = frameCenters[j].x - x;
const yd = frameCenters[j].y - y;
if (
Math.sqrt(xd * xd + yd * yd) <
- 23 * rem
+ 30 * vmin
) {
continue outerLoop;
}
@@ -704,6 +714,17 @@
}
});
+ function calculateVmax(percent) {
+ const viewportWidth = window.innerWidth;
+ const viewportHeight = window.innerHeight;
+
+ const largerDimension = Math.max(viewportWidth, viewportHeight);
+
+ const vmaxValue = (largerDimension / 100) * percent;
+
+ return vmaxValue;
+ }
+
function positionThemeIcons() {
const sliceAngle = 360 / themeIcons.length;
diff --git a/views/partials/general-page-header.html b/views/partials/general-page-header.html
index a75d32f..ce77b5c 100644
--- a/views/partials/general-page-header.html
+++ b/views/partials/general-page-header.html
@@ -1,4 +1,4 @@
-<title>{{ or .PageTitle .Title }}</title>
+<title>{{ .Title }} // SAYA.UZ</title>
<div class="flex flex-row mb-2">
{{ block "header" . }}{{ end }}
<h1