diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index 21e95b0..0000000 --- a/.drone.yml +++ /dev/null @@ -1,48 +0,0 @@ -kind: pipeline -type: docker -name: default - -platform: - os: linux - arch: arm - -steps: - - name: build - image: node - commands: - - npm install - - npm run build - - name: deploy-develop - image: alpine - environment: - FTP_HOST: - from_secret: FTP_HOST - FTP_USERNAME: - from_secret: FTP_USERNAME - FTP_PASSWORD: - from_secret: FTP_PASSWORD - commands: - - which lftp || ( apk --update add lftp ) - - lftp -e "set ftp:ssl-force true; set ssl:verify-certificate no; mirror -R ./dist/ dev.sp-codes.de/; bye" -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST - when: - branch: - - develop - event: - - push - - name: deploy-master - image: alpine - environment: - FTP_HOST: - from_secret: FTP_HOST - FTP_USERNAME: - from_secret: FTP_USERNAME - FTP_PASSWORD: - from_secret: FTP_PASSWORD - commands: - - which lftp || ( apk --update add lftp ) - - lftp -e "set ftp:ssl-force true; set ssl:verify-certificate no; mirror -R ./dist/ sp-codes.de/; bye" -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST - when: - branch: - - master - event: - - push diff --git a/.eleventy.js b/.eleventy.js index 9a02e4b..d8e63bb 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -1,22 +1,91 @@ -const eleventyNavigationPlugin = require("@11ty/eleventy-navigation"); +const pluginRev = require("eleventy-plugin-rev"); +const pluginSass = require("eleventy-sass"); +const pluginTinyHtml = require("@sardine/eleventy-plugin-tinyhtml"); +const pluginNavigation = require("@11ty/eleventy-navigation"); -module.exports = function(eleventyConfig) { - eleventyConfig.addWatchTarget("./src/scss/"); +module.exports = function (eleventyConfig) { + eleventyConfig.addPlugin(pluginRev); + eleventyConfig.addPlugin(pluginTinyHtml); + eleventyConfig.addPlugin(pluginSass, { + sass: { + loadPaths: ["node_modules"], + style: "compressed", + sourceMap: false, + }, + compileOptions: { + permalink: function (contents, inputPath) { + return (data) => { + return data.page.filePathStem.replace(/^\/scss\//, "/css/") + ".css"; + }; + } + }, + rev: true + }); + eleventyConfig.addPlugin(pluginNavigation); - eleventyConfig.addPlugin(eleventyNavigationPlugin); eleventyConfig.setUseGitIgnore(false); eleventyConfig.addPassthroughCopy({ "src/img": "img", "src/font": "font", - "node_modules/@fortawesome/fontawesome-free/webfonts/": "font", - "node_modules/flag-icon-css/flags/4x3/(de|us)*": "flags" + "src/favicon.*": "", + }); + eleventyConfig.addShortcode("translatedUrl", function (currentLocale, newLocale) { + return this.page.url.replace(new RegExp(`\/${currentLocale}\/`), `/${newLocale}/`); + }); + + eleventyConfig.addFilter('year', function (value) { + return value * 12; + }); + + eleventyConfig.addFilter("sum", function (value) { + return value.map(d => d.amount).reduce((a, b) => a + b, 0); + }); + + eleventyConfig.addFilter("amount", function (value) { + // TODO update language dynamically + return value.toLocaleString('de', {minimumFractionDigits: 2}); + }); + + eleventyConfig.addFilter("banktransfers", function (donations) { + return donations + .flatMap(y => y.donations) + .filter(d => d.via === 'banktransfer') + .filter(d => d.first) + .length; + }); + + eleventyConfig.addFilter("cash", function (donations) { + return donations + .flatMap(y => y.donations) + .filter(d => d.via === 'cash') + .filter(d => d.first) + .length; + }); + + eleventyConfig.addCollection("series", function (collectionApi) { + return collectionApi.getAll() + .filter(p => p.data?.series) + .sort((p0, p1) => p0.data.order - p1.data.order) + .reduce((series, post) => { + series[post.data.series] = series[post.data.series] ?? []; + series[post.data.series].push(post); + return series; + }, {}); }); return { + // Pre-process *.md files with: (default: `liquid`) + markdownTemplateEngine: "njk", + // Pre-process *.html files with: (default: `liquid`) + htmlTemplateEngine: "njk", + // Opt-out of pre-processing global data JSON files: (default: `liquid`) + dataTemplateEngine: false, + dir: { input: "src", includes: "_includes", layouts: "_includes/layouts", + data: "_data", output: "dist" } }; diff --git a/.forgejo/workflows/build-deploy.yml b/.forgejo/workflows/build-deploy.yml new file mode 100644 index 0000000..4a7e086 --- /dev/null +++ b/.forgejo/workflows/build-deploy.yml @@ -0,0 +1,71 @@ +name: Build and Deploy Website + +on: [push] + +jobs: + build-dev: + name: Build Dev Website + runs-on: docker + container: + image: node:lts + if: github.ref != 'refs/heads/main' + steps: + - uses: actions/checkout@v4 + - name: Install Dependencies + run: npm install + - name: Build Website + run: npm run build:dev + - uses: actions/upload-artifact@v3 + with: + name: build + path: dist/ + build: + name: Build Website + runs-on: docker + container: + image: node:lts + if: github.ref == 'refs/heads/main' + steps: + - uses: actions/checkout@v4 + - name: Install Dependencies + run: npm install + - name: Build Website + run: npm run build + - uses: actions/upload-artifact@v3 + with: + name: build + path: dist/ + deploy-dev: + name: Deploy Dev Website + runs-on: docker + container: + image: node:lts-alpine + needs: [build-dev] + if: github.ref == 'refs/heads/develop' + steps: + - uses: actions/download-artifact@v3 + - name: Install Dependencies + run: which lftp || ( apk --update add lftp ) + - name: Deploy Website + run: lftp -e "set ftp:ssl-force true; set ssl:verify-certificate no; mirror -R -e ./build/ dev.sp-codes.de/; bye" -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST + env: + FTP_HOST: ${{ secrets.FTP_HOST }} + FTP_USERNAME: ${{ secrets.FTP_USERNAME }} + FTP_PASSWORD: ${{ secrets.FTP_PASSWORD }} + deploy: + name: Deploy Website + runs-on: docker + container: + image: node:lts-alpine + needs: [build] + if: github.ref == 'refs/heads/main' + steps: + - uses: actions/download-artifact@v3 + - name: Install Dependencies + run: which lftp || ( apk --update add lftp ) + - name: Deploy Website + run: lftp -e "set ftp:ssl-force true; set ssl:verify-certificate no; mirror -R -e ./build/ sp-codes.de/; bye" -u $FTP_USERNAME,$FTP_PASSWORD $FTP_HOST + env: + FTP_HOST: ${{ secrets.FTP_HOST }} + FTP_USERNAME: ${{ secrets.FTP_USERNAME }} + FTP_PASSWORD: ${{ secrets.FTP_PASSWORD }} diff --git a/README.md b/README.md index e2babdb..f6704d0 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,13 @@ # sp-codes.de -[](https://ci.sp-codes.de/samuel-p/sp-codes.de) - -Website for sp-codes.de - -[GitHub](https://github.com/samuel-p/sp-codes.de) -[GitLab](https://gitlab.com/samuel-p/sp-codes.de) +Website for [sp-codes.de](https://sp-codes.de) ## Additional Header Parameters The following Parameters are set directly on the Web-Server. ``` -Content-Security-Policy: default-src 'none'; script-src 'self' https://plausible.sp-codes.de; object-src 'none'; style-src 'self'; img-src 'self'; media-src 'none'; frame-src 'none'; font-src 'self'; connect-src 'self' https://plausible.sp-codes.de +Content-Security-Policy: default-src 'none'; script-src 'self' https://umami.sp-codes.de; object-src 'none'; style-src 'self'; img-src 'self' https://status.sp-codes.de https://shields.sp-codes.de; media-src 'none'; frame-src 'none'; font-src 'self'; connect-src 'self' https://umami.sp-codes.de Referrer-Policy: strict-origin-when-cross-origin Feature-Policy: sync-xhr 'self' Strict-Transport-Security: max-age=31536000; includeSubDomains; preload diff --git a/package.json b/package.json index a48cdc1..e974955 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,11 @@ "version": "1.0.0", "description": "website for sp-codes.de", "scripts": { - "compile-sass": "node-sass --output-style compressed --importer=node_modules/node-sass-tilde-importer src/scss/main.scss dist/css/main.css", - "watch:eleventy": "eleventy --serve", - "watch:sass": "npm run compile-sass -- --watch", - "start": "npm-run-all compile-sass --parallel watch:*", - "build": "npm run compile-sass && eleventy && npm run move-index", - "move-index": "cpx dist/de/index.html dist/" + "minify-css": "uncss -n -H dist/ -o dist/css/main-*.css dist/**/*.html dist/**/**/*.html dist/**/**/**/*.html dist/**/**/**/**/*.html dist/**/**/**/**/**/*.html", + "add-index": "cpx dist/de/index.html dist/ && replace-in-file sp-codes.de/de/ sp-codes.de/ dist/index.html", + "start": "eleventy --serve --watch", + "build": "eleventy && npm run minify-css && npm run add-index", + "build:dev": "BUILD=dev eleventy && npm run minify-css && npm run add-index" }, "author": "samuel-p", "repository": { @@ -16,19 +15,26 @@ "url": "https://git.sp-codes.de/samuel-p/sp-codes.de" }, "optionalDependencies": { - "browser-sync": "^2.26.12" + "browser-sync": "^3.0.4" }, "devDependencies": { - "@11ty/eleventy": "^0.11.0", - "@11ty/eleventy-navigation": "^0.1.6", + "@11ty/eleventy": "^2.0.1", + "@11ty/eleventy-navigation": "^0.3.5", + "@node-minify/core": "^9.0.2", + "@node-minify/crass": "^9.0.1", + "@node-minify/html-minifier": "^9.0.1", + "@sardine/eleventy-plugin-tinyhtml": "^0.2.0", "cpx": "^1.5.0", - "node-sass": "^4.14.1", - "node-sass-tilde-importer": "^1.0.2", - "npm-run-all": "^4.1.5" + "eleventy-plugin-rev": "^2.0.0", + "eleventy-sass": "^2.2.6", + "glob": "^11.0.2", + "minify": "^14.0.0", + "postcss": "^8.5.4", + "replace-in-file": "^8.3.0", + "sass": "^1.89.1", + "uncss": "^0.17.3" }, "dependencies": { - "@fortawesome/fontawesome-free": "^5.14.0", - "bootstrap": "^4.5.2", - "flag-icon-css": "^3.5.0" + "bootstrap": "^5.3.6" } } diff --git a/renovate.json b/renovate.json index 3b73487..8fba284 100644 --- a/renovate.json +++ b/renovate.json @@ -5,5 +5,6 @@ "baseBranches": [ "develop" ], - "rangeStrategy": "bump" + "rangeStrategy": "bump", + "rebaseWhen": "behind-base-branch" } diff --git a/src/_data/donations.json b/src/_data/donations.json new file mode 100644 index 0000000..4bbc82b --- /dev/null +++ b/src/_data/donations.json @@ -0,0 +1,389 @@ +[ + { + "year": 2025, + "donations": [ + { + "date": "04.06.2025", + "amount": 20, + "via": "banktransfer", + "from": "ub1x", + "first": false + }, + { + "date": "30.04.2025", + "amount": 10, + "via": "banktransfer", + "from": "Andresimous", + "first": false + }, + { + "date": "08.04.2025", + "amount": 20, + "via": "banktransfer", + "from": "frantab", + "first": true + }, + { + "date": "04.04.2025", + "amount": 20, + "via": "banktransfer", + "from": "ub1x", + "first": false + }, + { + "date": "25.03.2025", + "amount": 100, + "via": "banktransfer", + "from": "BrauchC", + "first": true + }, + { + "date": "14.02.2025", + "amount": 20, + "via": "banktransfer", + "from": "ub1x", + "first": false + }, + { + "date": "31.01.2025", + "amount": 10, + "via": "banktransfer", + "from": "Andresimous", + "first": true + } + ] + }, + { + "year": 2024, + "donations": [ + { + "date": "18.11.2024", + "amount": 25, + "via": "banktransfer", + "from": null, + "first": false + }, + { + "date": "05.11.2024", + "amount": 50, + "via": "banktransfer", + "from": "bings81", + "first": true + }, + { + "date": "31.10.2024", + "amount": 20, + "via": "banktransfer", + "from": "ub1x", + "first": false + }, + { + "date": "02.08.2024", + "amount": 20, + "via": "banktransfer", + "from": "ub1x", + "first": false + }, + { + "date": "03.07.2024", + "amount": 25, + "via": "banktransfer", + "from": "Astrid", + "first": true + }, + { + "date": "26.02.2024", + "amount": 20, + "via": "banktransfer", + "from": "ub1x", + "first": false + }, + { + "date": "23.01.2024", + "amount": 25, + "via": "banktransfer", + "from": null, + "first": true + } + ] + }, + { + "year": 2023, + "donations": [ + { + "date": "27.12.2023", + "amount": 50, + "via": "banktransfer", + "from": null, + "first": false + }, + { + "date": "16.11.2023", + "amount": 25, + "via": "banktransfer", + "from": null, + "first": false + }, + { + "date": "26.10.2023", + "amount": 20, + "via": "banktransfer", + "from": "ub1x", + "first": false + }, + { + "date": "17.07.2023", + "amount": 20, + "via": "banktransfer", + "from": "ub1x", + "first": false + }, + { + "date": "27.02.2023", + "amount": 40, + "via": "banktransfer", + "from": "xhoff637", + "first": true + }, + { + "date": "20.02.2023", + "amount": 50, + "via": "banktransfer", + "from": null, + "first": false + }, + { + "date": "16.01.2023", + "amount": 12, + "via": "banktransfer", + "from": null, + "first": true + } + ] + }, + { + "year": 2022, + "donations": [ + { + "date": "15.12.2022", + "amount": 20, + "via": "banktransfer", + "from": "ub1x", + "first": false + }, + { + "date": "16.11.2022", + "amount": 25, + "via": "banktransfer", + "from": null, + "first": false + }, + { + "date": "02.11.2022", + "amount": 30, + "via": "banktransfer", + "from": null, + "first": false + }, + { + "date": "11.08.2022", + "amount": 10, + "via": "banktransfer", + "from": "TeomaHK", + "first": false + }, + { + "date": "11.07.2022", + "amount": 10, + "via": "banktransfer", + "from": "TeomaHK", + "first": false + }, + { + "date": "03.06.2022", + "amount": 10, + "via": "banktransfer", + "from": "TeomaHK", + "first": false + }, + { + "date": "11.05.2022", + "amount": 20, + "via": "banktransfer", + "from": "ub1x", + "first": true + }, + { + "date": "03.05.2022", + "amount": 10, + "via": "banktransfer", + "from": "TeomaHK", + "first": false + }, + { + "date": "04.04.2022", + "amount": 10, + "via": "banktransfer", + "from": "TeomaHK", + "first": false + }, + { + "date": "15.03.2022", + "amount": 1, + "via": "banktransfer", + "from": "Jonathan Klatt", + "first": false + }, + { + "date": "10.03.2022", + "amount": 1.42, + "via": "banktransfer", + "from": "Jonathan Klatt", + "first": false + }, + { + "date": "03.03.2022", + "amount": 10, + "via": "banktransfer", + "from": "TeomaHK", + "first": false + }, + { + "date": "14.02.2022", + "amount": 10, + "via": "banktransfer", + "from": "TeomaHK", + "first": false + }, + { + "date": "17.01.2022", + "amount": 1, + "via": "banktransfer", + "from": "Jonathan Klatt", + "first": true + }, + { + "date": "03.01.2022", + "amount": 10, + "via": "banktransfer", + "from": "TeomaHK", + "first": true + } + ] + }, + { + "year": 2021, + "donations": [ + { + "date": "30.11.2021", + "amount": 5, + "via": "banktransfer", + "from": "Rumo", + "first": false + }, + { + "date": "16.11.2021", + "amount": 120, + "via": "banktransfer", + "from": "poetaster", + "first": true + }, + { + "date": "16.11.2021", + "amount": 25, + "via": "banktransfer", + "from": null, + "first": true + }, + { + "date": "20.09.2021", + "amount": 20, + "via": "banktransfer", + "from": "Clemi", + "first": true + }, + { + "date": "26.08.2021", + "amount": 18.27, + "via": "opencollective", + "from": "Skoop", + "first": true + }, + { + "date": "18.08.2021", + "amount": 30, + "via": "banktransfer", + "from": null, + "first": true + }, + { + "date": "02.08.2021", + "amount": 10, + "via": "banktransfer", + "from": null, + "first": false + }, + { + "date": "01.06.2021", + "amount": 20, + "via": "banktransfer", + "from": "Rumo", + "first": true + }, + { + "date": "26.04.2021", + "amount": 8.96, + "via": "banktransfer", + "from": null, + "first": false + }, + { + "date": "23.03.2021", + "amount": 30, + "via": "banktransfer", + "from": null, + "first": true + }, + { + "date": "19.02.2021", + "amount": 20, + "via": "banktransfer", + "from": null, + "first": true + }, + { + "date": "02.02.2021", + "amount": 9.01, + "via": "opencollective", + "from": "Dennis H.", + "first": true + }, + { + "date": "20.01.2021", + "amount": 10, + "via": "banktransfer", + "from": null, + "first": true + }, + { + "date": "17.01.2021", + "amount": 4.41, + "via": "opencollective", + "from": "Michael Haak", + "first": true + } + ] + }, + { + "year": 2020, + "donations": [ + { + "date": "04.12.2020", + "amount": 10, + "via": "banktransfer", + "from": null, + "first": true + } + ] + } +] diff --git a/src/_data/eleventyComputed.js b/src/_data/eleventyComputed.js new file mode 100644 index 0000000..00295a2 --- /dev/null +++ b/src/_data/eleventyComputed.js @@ -0,0 +1,5 @@ +module.exports = { + service: (data) => data.services.find(s => s.id === data.service), + title: (data) => data.title || data.service?.name || "", + summary: (data) => data.summary || data.service?.summary?.[data.locale] || "" +} diff --git a/src/_data/expenses.json b/src/_data/expenses.json new file mode 100644 index 0000000..8898c5f --- /dev/null +++ b/src/_data/expenses.json @@ -0,0 +1,50 @@ +[ + { + "name": "Services", + "type": "Cloud Server", + "provider": "Hetzner", + "location": "Nürnberg", + "amount": 38.56 + }, + { + "name": "Docker", + "type": "Cloud Storage", + "provider": "Hetzner", + "location": "Nürnberg", + "amount": 4.16 + }, + { + "name": { + "en": "Media", + "de": "Medien" + }, + "type": "Object Storage", + "provider": "Hetzner", + "location": "Nürnberg", + "amount": 5.94 + }, + { + "name": "Monitoring", + "type": "Cloud Server", + "provider": "Hetzner", + "location": "Falkenstein", + "amount": 4.51 + }, + { + "name": "Backup", + "type": "Storage Box", + "provider": "Hetzner", + "location": "Helsinki", + "amount": 12.97 + }, + { + "name": { + "en": "Websites", + "de": "Webseiten" + }, + "type": "Webhosting", + "provider": "netcup", + "location": "Nürnberg", + "amount": 2.17 + } +] diff --git a/src/_data/global.dev.json b/src/_data/global.dev.json new file mode 100644 index 0000000..fd531ee --- /dev/null +++ b/src/_data/global.dev.json @@ -0,0 +1,4 @@ +{ + "title": "DEV sp-codes", + "url": "https://dev.sp-codes.de" +} diff --git a/src/_data/global.json b/src/_data/global.json new file mode 100644 index 0000000..878c0d0 --- /dev/null +++ b/src/_data/global.json @@ -0,0 +1,18 @@ +{ + "title": "sp-codes", + "url": "https://sp-codes.de", + "baseUrl": "/", + "author": "Samuel Philipp", + "languages": [ + { + "label": "English", + "code": "en", + "icon": "us" + }, + { + "label": "Deutsch", + "code": "de", + "icon": "de" + } + ] +} diff --git a/src/_data/services.json b/src/_data/services.json index 8227519..4f58d6e 100644 --- a/src/_data/services.json +++ b/src/_data/services.json @@ -1,81 +1,285 @@ [ - { - "id": "searx", - "name": "Searx", - "icon": "fas fa-search", - "url": "https://searx.sp-codes.de", - "summary": { - "de": "Eine privatsphären-respektierende, hackbare Metasuchmaschine.", - "en": "A privacy-respecting, hackable metasearch engine." - } - }, - { - "id": "invidious", - "name": "Invidious", - "icon": "fab fa-youtube", - "url": "https://invidious.sp-codes.de", - "summary": { - "de": "Ein alternatives YouTube-Frontend.", - "en": "An alternative YouTube-Frontend." - } - }, - { - "id": "connectivitycheck", - "name": "Captive Portal Check", - "icon": "fas fa-wifi", - "summary": { - "de": "Eine datenschutzfreundliches Tool, um Anmeldeseiten in WLAN-Netzwerken zu erkennen.", - "en": "A privacy friendly Service to detect captive portals in WIFI networks." - } - }, { "id": "matrix", "name": "Matrix", - "icon": "fas fa-comments", + "icon": "i-comments", "url": "https://chat.sp-codes.de", + "status": "1", "summary": { - "de": "Ein offenes Netzwerk für sichere, dezentralisierte Kommunikation.", - "en": "An open network for secure, decentralized communication." - } - }, - { - "id": "gitea", - "name": "Gitea", - "icon": "fas fa-code", - "url": "https://git.sp-codes.de", - "summary": { - "de": "Eine leichtgewichtige Code-Hosting-Plattform für git.", - "en": "A lightweight code hosting platform for git." - } - }, - { - "id": "firefox-sync", - "name": "Firefox Sync", - "icon": "fab fa-firefox-browser", - "summary": { - "de": "Ein Service um Firefox Einstellungen, Lesezeichen, offene Tabs und vieles mehr über verschiedene Geräte zu synchronisieren.", - "en": "A service to sync Firefox settings, bookmarks, open tabs and much more between multiple devices." - } + "de": "Die offene Plattform für sichere und dezentrale Kommunikation.", + "en": "The open platform for secure and decentralized communication." + }, + "cards": [ + { + "title": { + "de": "Mein Angebot", + "en": "My Offer" + }, + "content": { + "de": "
Seit Anfang 2020 betreibe ich einen öffentlichen Matrix-Server: matrix.sp-codes.de und eine öffentliche Element-Web Instanz: chat.sp-codes.de
", + "en": "Since the beginning of 2020 I run a public Matrix server: matrix.sp-codes.de and a public Element-Web instance: chat.sp-codes.de
" + } + }, + { + "title": { + "de": "Einstieg", + "en": "Getting started" + }, + "content": { + "de": "Hier findest du eine Artikelserie für einen einfachen Einstieg in Matrix:
", + "en": "Here you will find an article series (German) for an easy start to Matrix:
" + } + }, + { + "ossrox": { + "url": "https://ossrox.org/store/matrix" + }, + "content": { + "de": "Wenn du einen eigenen Matrix-Server für dich, deine Familie oder deine Firma betreiben willst, unterstütze ich dich gerne mit meiner Firma Ossrox damit. Schau dir gerne unser Angebot dazu auf unserer Webseite an oder schreib mir eine Nachricht dazu.", + "en": "If you want to have your own Matrix server for you, your family or your company, I would be happy to support you with my company Ossrox. Please have a look at our services on our website or send me a message." + } + } + ] }, { "id": "jitsi", "name": "Jitsi Meet", - "icon": "fas fa-users", + "icon": "i-users", "url": "https://jitsi.sp-codes.de", + "status": "2", "summary": { - "de": "Eine sichere, einfache und skalierbare Plattform für Videokonferenzen.", - "en": "A secure, simple and scalable platform for video conferencing." + "de": "Einfache und sichere Videokonferenzen.", + "en": "Easy and secure video conferencing." + }, + "cards": [ + { + "title": { + "de": "Mein Angebot", + "en": "My Offer" + }, + "content": { + "de": "Seit Juli 2020 betreibe ich eine eigene Jitsi-Meet Instanz. Du findest sie unter jitsi.sp-codes.de.
", + "en": "Since July 2020 I run my own Jitsi-Meet instance. You can find it at jitsi.sp-codes.de.
" + } + }, + { + "ossrox": { + "url": "https://ossrox.org/store/jitsi" + }, + "content": { + "de": "Wenn du einen eigenen Jitsi-Server für dich, deine Familie oder deine Firma betreiben willst, unterstütze ich dich gerne mit meiner Firma Ossrox damit. Schau dir gerne unser Angebot dazu auf unserer Webseite an oder schreib mir eine Nachricht dazu.", + "en": "If you want to have your own Jitsi server for you, your family or your company, I would be happy to support you with my company Ossrox. Please have a look at our services on our website or send me a message." + } + } + ] + }, + { + "id": "mastodon", + "name": "Mastodon", + "icon": "i-mastodon", + "url": "https://social.sp-codes.de", + "status": "7", + "summary": { + "de": "Das soziale Netzwerk für dezentrale und sichere Interaktion.", + "en": "The social network for decentralized and secure interaction." + }, + "cards": [ + { + "title": { + "de": "Mein Angebot", + "en": "My Offer" + }, + "content": { + "de": "Seit Mai 2021 betreibe ich eine öffentliche Mastodon-Instanz: social.sp-codes.de
", + "en": "Since May 2021 I run a public Mastodon instance: social.sp-codes.de
" + } + }, + { + "ossrox": { + "url": "https://ossrox.org/store/mastodon" + }, + "content": { + "de": "Wenn du einen eigenen Mastodon-Server für dich, deine Familie oder deine Firma betreiben willst, unterstütze ich dich gerne mit meiner Firma Ossrox damit. Schau dir gerne unser Angebot dazu auf unserer Webseite an oder schreib mir eine Nachricht dazu.", + "en": "If you want to have your own mastodon server for you, your family or your company, I would be happy to support you with my company Ossrox. Please have a look at our services on our website or send me a message." + } + } + ] + }, + { + "id": "peertube", + "name": "PeerTube", + "icon": "i-peertube", + "url": "https://tube.sp-codes.de", + "status": "9", + "summary": { + "de": "Die freie und dezentrale Plattform für gemeinsames Video-Streaming.", + "en": "The free and decentralized platform for collaborative video streaming." + }, + "cards": [ + { + "title": { + "de": "Mein Angebot", + "en": "My Offer" + }, + "content": { + "de": "Seit August 2021 betreibe ich eine öffentliche PeerTube-Instanz: tube.sp-codes.de
", + "en": "Since August 2021 I run a public PeerTube instance: tube.sp-codes.de
" + } + }, + { + "ossrox": { + "url": "https://ossrox.org/store" + }, + "content": { + "de": "Wenn du einen eigenen PeerTube-Server betreiben willst, um deine Plattform für Videos und Live-Streams zu starten, unterstütze ich dich gerne mit meiner Firma Ossrox damit. Schau dir gerne unser Angebot dazu auf unserer Webseite an oder schreib mir eine Nachricht dazu.", + "en": "If you want to run your own PeerTube server to start your platform for videos and live streams, I would be happy to support you with my company Ossrox. Take a look at our offer on our website or write me a message." + } + } + ] + }, + { + "id": "pixelfed", + "name": "Pixelfed", + "icon": "i-pixelfed", + "url": "https://pixel.sp-codes.de", + "status": "11", + "beta": true, + "summary": { + "de": "Das soziale Netzwerk für den Austausch von Bildern und Fotografie.", + "en": "The social network for sharing images and photography." } }, + { + "id": "forgejo", + "name": "Forgejo", + "icon": "i-git", + "url": "https://git.sp-codes.de", + "status": "13", + "summary": { + "de": "Die Plattform für einfaches und sicheres Code-Hosting.", + "en": "The platform for easy and secure code hosting." + }, + "cards": [ + { + "title": { + "de": "Mein Angebot", + "en": "My Offer" + }, + "content": { + "de": "Seit Ende 2019 betreibe ich eine eigene Forgejo Instanz, in der ich meine Projekte verwalte. Hier geht's lang: git.sp-codes.de
", + "en": "Since the end of 2019, I have been running my own Forgejo instance where I manage my projects. This way: git.sp-codes.de
" + } + }, + { + "ossrox": { + "url": "https://ossrox.org/store" + }, + "content": { + "de": "Wenn du deine Projekte in einer eigenen Forgejo-, Gitea- oder GitLab-Instanz verwalten willst, unterstütze ich dich gerne mit meiner Firma Ossrox damit. Schau dir gerne unser Angebot dazu auf unserer Webseite an oder schreib mir eine Nachricht dazu.", + "en": "If you want to manage your projects in your own Forgejo, Gitea or GitLab instance, I will be happy to support you with my company Ossrox. Take a look at our offer on our website or write me a message." + } + } + ] + }, + { + "id": "connectivitycheck", + "name": "Captive Portal Check", + "icon": "i-wifi", + "status": "19", + "summary": { + "de": "Überprüfung der Verfügbarkeit von Internetzugang.", + "en": "Verification of Internet access availability." + }, + "cards": [ + { + "title": { + "de": "Mein Angebot", + "en": "My Offer" + }, + "content": { + "de": "Seit Mitte 2019 stelle ich einen freien Captive Portal Check zur Verfügung: https://connectivitycheck.sp-codes.de/generate204
", + "en": "Since mid 2019 I provide a free Captive Portal Check: https://connectivitycheck.sp-codes.de/generate204
" + } + }, + { + "title": { + "de": "Einrichtung", + "en": "Setup" + }, + "content": { + "de": "Hier findest du einen Artikel, der dir die Einrichtung auf verschiedenen Geräten erklärt:
", + "en": "Here you will find an article that explains how to set it up on various devices:
" + } + } + ] + }, + { + "id": "ntfy", + "name": "ntfy", + "icon": "i-cloud-download", + "url": "https://ntfy.sp-codes.de", + "status": "18", + "summary": { + "de": "Echtzeitbenachrichtigungen mit UnifiedPush-Unterstützung.", + "en": "Real-time notifications with UnifiedPush support." + }, + "cards": [ + { + "title": { + "de": "Mein Angebot", + "en": "My Offer" + }, + "content": { + "de": "Seit Mai 2023 stelle ich ntfy zur freien Verfügung: ntfy.sp-codes.de
Since May 2023 I provide ntfy for free: https://ntfy.sp-codes.de You are welcome to use ntfy as push provider for your apps if you like.
" + } + } + ] + }, + { + "id": "etherpad", + "name": "Etherpad", + "icon": "i-pencil-square", + "url": "https://pad.sp-codes.de", + "status": "17", + "summary": { + "de": "Gemeinsame Echtzeit-Textbearbeitung für effektive Zusammenarbeit.", + "en": "Collaborative real-time text editing for effective collaboration." + }, + "cards": [ + { + "title": { + "de": "Mein Angebot", + "en": "My Offer" + }, + "content": { + "de": "Seit Ende 2020 betreibe ich Etherpad: pad.sp-codes.de
", + "en": "I've been running Etherpad since the end of 2020: pad.sp-codes.de
" + } + } + ] + }, { "id": "shields", "name": "Shields", - "icon": "fas fa-tags", + "icon": "i-tags", "url": "https://shields.sp-codes.de", - "beta": true, + "status": "20", "summary": { - "de": "Prägnante, konsistente und lesbare Badges im SVG- und Rasterformat.", - "en": "Concise, consistent, and legible badges in SVG and raster format." - } + "de": "Visuelle Badges zur Anzeige von Projektinformationen und Status.", + "en": "Visual badges for displaying project information and status." + }, + "cards": [ + { + "title": { + "de": "Mein Angebot", + "en": "My Offer" + }, + "content": { + "de": "Seit August 2020 betreibe ich eine öffentliche Shields Instanz. Schau gerne mal rein: shields.sp-codes.de
", + "en": "Since August 2020 I have been running a public Shields instance. Feel free to take a look: shields.sp-codes.de
" + } + } + ] } ] diff --git a/src/_data/site.js b/src/_data/site.js index dff3c06..9f67ce6 100644 --- a/src/_data/site.js +++ b/src/_data/site.js @@ -1,21 +1,10 @@ -module.exports = { - title: "sp-codes", - description: "Samuel Philipp - Software Engineer from Magdeburg", - url: "https://sp-codes.de", - baseUrl: "/", - author: "Samuel Philipp", - buildTime: new Date(), - languages: [ - { - label: "English", - code: "en", - icon: "us" - }, - { - label: "Deutsch", - code: "de", - icon: "de" - } - ] -}; +const fs = require("fs"); +const site = require("./global.json"); +site.buildName = process.env.BUILD || 'prod'; +if (fs.existsSync(`${__dirname}/global.${site.buildName}.json`)) { + Object.assign(site, require(`./global.${site.buildName}.json`)); +} +site.buildTime = new Date().toISOString(); + +module.exports = site; diff --git a/src/_data/strings.json b/src/_data/strings.json deleted file mode 100644 index fd2d568..0000000 --- a/src/_data/strings.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "imprint": { - "de": "Impressum", - "en": "Imprint" - }, - "privacy": { - "de": "Datenschutz", - "en": "Privacy" - }, - "code": { - "de": "Code", - "en": "Code" - }, - "stats": { - "de": "Statistiken", - "en": "Stats" - } -} diff --git a/src/_includes/donations-current.html b/src/_includes/donations-current.html new file mode 100644 index 0000000..5ecb715 --- /dev/null +++ b/src/_includes/donations-current.html @@ -0,0 +1,32 @@ +{{strings.donations.date}} | +{{strings.donations.via}} | +{{strings.donations.from}} | +{{strings.donations.amount}} | +|
---|---|---|---|---|
{{donation.date}} | +{{strings.donations[donation.via]}} | + {% if donation.from %} +{{donation.from}} | + {% else %} +*** | + {% endif %} +{{donation.amount | amount}} € | +
{{strings.donations.total}} | +{{donations[0].donations | sum | amount}} € | +
{{strings.donations.date}} | +{{strings.donations.via}} | +{{strings.donations.from}} | +{{strings.donations.amount}} | +|
---|---|---|---|---|
{{donation.date}} | +{{strings.donations[donation.via]}} | + {% if donation.from %} +{{donation.from}} | + {% else %} +*** | + {% endif %} +{{donation.amount | amount}} € | +
{{strings.donations.total}} | +{{year.donations | sum | amount}} € | +
{{strings.donations.name}} | +{{strings.donations.type}} | +{{strings.donations.provider}} | +{{strings.donations.location}} | +{{strings.donations.amount}} / {{strings.donations.month}} | +{{strings.donations.amount}} / {{strings.donations.year}} | +|
---|---|---|---|---|---|---|
{{expense.name[locale]}} | + {% else %} +{{expense.name}} | + {% endif %} +{{expense.type}} | +{{expense.provider}} | +{{expense.location}} | +{{expense.amount | amount}} € | +{{expense.amount | year | amount}} € | +
{{strings.donations.total}} | +{{expenses | sum | amount}} € | +{{expenses | sum | year | amount}} € | +