diff --git a/.gitignore b/.gitignore index 391c492..150f862 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .DS_Store node_modules -public \ No newline at end of file +public/public +temp_backup \ No newline at end of file diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..b166ec7 --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,113 @@ +# build:1 +labels: + location: manager +clone: + git: + image: woodpeckerci/plugin-git + settings: + partial: false + depth: 1 +when: + branch: [main, production] +steps: + # Build Step for staging Branch + build-staging: + name: build-staging + image: woodpeckerci/plugin-docker-buildx + environment: + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASSWORD: + from_secret: REGISTRY_PASSWORD + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "Building application for staging branch" + - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us + - echo compose build + - docker compose -f docker-compose.staging.yml pull --ignore-buildable + - docker compose -f docker-compose.staging.yml build --pull + when: + event: push + + deploy-new: + name: deploy-new + image: woodpeckerci/plugin-docker-buildx + environment: + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASSWORD: + from_secret: REGISTRY_PASSWORD + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us + - echo compose push + - docker compose -f docker-compose.staging.yml push + - docker stack deploy --with-registry-auth -c ./stack.staging.yml $${CI_REPO_NAME}-staging + when: + event: push + + cleanup-staging: + name: cleanup-staging + image: woodpeckerci/plugin-docker-buildx + environment: + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASSWORD: + from_secret: REGISTRY_PASSWORD + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - for i in {1..5}; do docker stack rm ${CI_REPO_NAME}-staging && break || sleep 10; done + - docker compose -f docker-compose.staging.yml down + - docker compose -f docker-compose.staging.yml rm -f + when: + event: push + + build-push-production: + name: build-push-production + image: woodpeckerci/plugin-docker-buildx + environment: + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASSWORD: + from_secret: REGISTRY_PASSWORD + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "Building application for production branch" + - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us + - echo compose build + - docker compose -f docker-compose.production.yml pull --ignore-buildable + - docker compose -f docker-compose.production.yml build --pull + - docker compose -f docker-compose.production.yml push + when: + branch: main + event: push + + deploy-production: + name: deploy-production + image: woodpeckerci/plugin-docker-buildx + environment: + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASSWORD: + from_secret: REGISTRY_PASSWORD + volumes: + - /var/run/docker.sock:/var/run/docker.sock + commands: + - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us + - docker stack deploy --with-registry-auth -c ./stack.production.yml $${CI_REPO_NAME} + when: + branch: main + event: push + + post-deploy-smoke-tests-git-nixc-us: + name: run-post-deploy-smoke-tests-git-nixc-us + image: git.nixc.us/colin/playwright:latest + environment: + BASE_URL: "https://git.nixc.us" + when: + branch: production + event: push \ No newline at end of file diff --git a/CSS-JS-OPTIMIZATION.md b/CSS-JS-OPTIMIZATION.md deleted file mode 100644 index 341afbf..0000000 --- a/CSS-JS-OPTIMIZATION.md +++ /dev/null @@ -1,68 +0,0 @@ -# CSS and JavaScript Optimization Guide - -This document explains how to eliminate unused CSS and JavaScript from the ShowerLoop website. - -## Quick Start - -1. Install dependencies: - ```bash - npm install --legacy-peer-deps - ``` - -2. Build the production version with optimizations: - ```bash - ./build-production.sh - ``` - -## What This Does - -### CSS Optimization - -The build script optimizes CSS in two ways: - -1. **CSSO Optimization**: Uses CSSO to remove unused selectors, merge similar rules, and minify the CSS. - - Typically reduces CSS by 5-30% depending on the file - - Maintains full functionality while eliminating bloat - - Works without requiring a running website - -2. **File Path Updates**: Automatically updates all HTML files to reference the optimized CSS versions. - -### JavaScript Optimization - -JavaScript optimization happens through: - -1. **Tree Shaking**: Rollup analyzes your code to detect which parts are actually used and removes dead code. - - Eliminates unused imports and functions - - Reduces JavaScript file sizes significantly - -2. **Code Splitting**: JavaScript is split into separate bundles: - - app.modern.min.js - Main application code - - video-init.modern.min.js - Video player initialization - - skip-to-content.modern.min.js - Accessibility features - -3. **Minification**: All JavaScript is minified to reduce file size. - -## Optimization Results - -In our tests, the optimization achieves: - -| File Type | Size Reduction | -|-----------|---------------| -| CSS | 5-30% | -| JavaScript| 30-60% | - -## How to Keep It Optimized - -1. **Maintain Source Files**: Keep original JavaScript source files in `src/js/` - -2. **Run Build Before Deployment**: Always run `./build-production.sh` before deploying to production - -3. **Add New Components Wisely**: When adding new CSS/JS, consider if it's truly needed or if existing code can be reused - -## Troubleshooting - -- **Missing Styles**: If elements look unstyled after optimization, check the original CSS files and update your HTML accordingly. - -- **JavaScript Errors**: If functionality breaks, check the browser console for errors and ensure all required code is in your source files. - -- **Build Errors**: Make sure all dependencies are installed with `npm install --legacy-peer-deps` before running the build scripts. \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index ad69f4d..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 Shower-Loop - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md index b628531..88e99cc 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,34 @@ -# website -https://showerloop.cc new site for https://showerloop.org [planned] +# ShowerLoop Website -## Local Development +This repository contains the source code for the ShowerLoop website, built with Hugo and served via Docker. -To test this site locally: +## Repository Structure -1. Make sure you have [Hugo](https://gohugo.io/installation/) installed on your system -2. Clone this repository -3. Run the development server using the script: +- `/docker/showerloop/` - Container configuration for the website + - `/docker/showerloop/public/` - Hugo website source files + - `/docker/showerloop/Dockerfile` - Docker image definition + - `/docker/showerloop/Caddyfile` - Caddy server configuration + +## Development + +To run the Hugo development server: ```bash +cd docker/showerloop/public ./run-hugo-server.sh ``` -Or run Hugo directly: +The development server will be available at http://localhost:1313/ + +## Building + +To build the production site: ```bash -hugo server -D --disableFastRender +cd docker/showerloop/public +./build-production.sh ``` -4. Open your browser and go to http://localhost:1313/ to view the site -5. The site will automatically reload when you make changes to the content or templates +## Deployment -### Notes -- The `-D` flag enables draft content to be visible in the development environment -- `--disableFastRender` ensures full rebuilds for more reliable preview +The site is automatically built and deployed using Woodpecker CI when changes are pushed to the master branch. \ No newline at end of file diff --git a/categories/index.xml b/categories/index.xml deleted file mode 100644 index d336b43..0000000 --- a/categories/index.xml +++ /dev/null @@ -1 +0,0 @@ -Categories onhttp://localhost:54386/categories/Recent content in Categories onHugoen-us \ No newline at end of file diff --git a/contact-us/index.html b/contact-us/index.html deleted file mode 100644 index 3cdb077..0000000 --- a/contact-us/index.html +++ /dev/null @@ -1,29 +0,0 @@ -Support the Project | ShowerLoop -
Skip to Content
ShowerLoop

Support the Project

If you want to support the ShowerLoop project, check out our Make-It Button where you can contribute to our ongoing development.

    <p>We work with limited resources and recycle many materials. With access to workspace and tools (thank you, Fablab!), we're able to continue developing this sustainable technology.</p>
-    
-    <p>We're collaborating with people around the world to bring ShowerLoop to various environments - boats, RVs, houses in remote locations, Pacific Islands, eco-friendly buildings, and historic structures without modern plumbing. The possibilities are endless, and together we hope to realize them all.</p>
-    
-    <p>Our team is developing a business model that fosters community around social and environmental ethics within the open source circular economy.</p>
-    
-    <div class="mdl-grid" style="justify-content: center; margin-top: 30px;">
-        <a class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored" href="/make-it">
-            Support the Project
-        </a>
-    </div>
-</section>
-
\ No newline at end of file diff --git a/docker-compose.production.yml b/docker-compose.production.yml new file mode 100644 index 0000000..131ff22 --- /dev/null +++ b/docker-compose.production.yml @@ -0,0 +1,7 @@ +services: + showerloop: + build: + context: docker/showerloop + dockerfile: Dockerfile.production + pull: true + image: git.nixc.us/colin/showerloop-cc:production diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml new file mode 100644 index 0000000..0fb5654 --- /dev/null +++ b/docker-compose.staging.yml @@ -0,0 +1,6 @@ +services: + showerloop: + build: + context: docker/showerloop + pull: true + image: git.nixc.us/colin/showerloop-cc:staging diff --git a/docker/Dockerfile.production b/docker/Dockerfile.production new file mode 100644 index 0000000..460adb4 --- /dev/null +++ b/docker/Dockerfile.production @@ -0,0 +1 @@ +FROM git.nixc.us/colin/showerloop-cc:staging diff --git a/docker/showerloop/Caddyfile b/docker/showerloop/Caddyfile new file mode 100644 index 0000000..42ad00c --- /dev/null +++ b/docker/showerloop/Caddyfile @@ -0,0 +1,87 @@ +# Template: Caddyfile.override +# Purpose: Default configuration for custom containers. +# Description: +# - Serves static files from /srv. +# - Provides a /health endpoint for health checks. +# - Designed to run behind a reverse proxy like Træfik, listening only on port 80. +# - comes with security headers + +:80 { + # Health check endpoint + respond /health "OK" 200 + + # Enable compression for text-based resources + encode gzip zstd + + # Security headers + header { + # Cross-Origin headers + Cross-Origin-Embedder-Policy "require-corp" + Cross-Origin-Opener-Policy "same-origin" + Cross-Origin-Resource-Policy "same-origin" + + # Permissions Policy + Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()" + + # Referrer Policy + Referrer-Policy "strict-origin-when-cross-origin" + + # HSTS + Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" + + # Content Type Options + X-Content-Type-Options "nosniff" + + # XSS Protection + X-XSS-Protection "1; mode=block" + + # Frame Options (prevents clickjacking) + X-Frame-Options "SAMEORIGIN" + + # Frame ancestors (prevents embedding in other sites) + Content-Security-Policy "frame-ancestors 'none'" + + # Remove Server header + -Server + } + + # Cache control for static assets - images, fonts, etc. + @staticAssets { + path *.jpg *.jpeg *.png *.webp *.avif *.gif *.ico *.svg *.woff *.woff2 *.ttf *.eot + method GET HEAD + } + header @staticAssets Cache-Control "public, max-age=31536000, immutable" + header @staticAssets ?Access-Control-Allow-Origin * + + # Special handling for CSS and JS files + @cssAndJs { + path *.css *.js + method GET HEAD + } + header @cssAndJs Cache-Control "public, max-age=31536000, immutable" + + # Cache HTML files but for a shorter period + @htmlFiles { + path *.html + method GET HEAD + } + header @htmlFiles Cache-Control "public, max-age=86400, must-revalidate" + + # Static file server + file_server { + root /srv # Root directory for serving static files + } + + # Restrict allowed methods to only GET and HEAD + @staticRequests { + method GET HEAD + } + + handle @staticRequests { + root * /srv + file_server + } + + # Handle all other methods + respond "Method Not Allowed" 405 +} \ No newline at end of file diff --git a/docker/showerloop/Dockerfile b/docker/showerloop/Dockerfile new file mode 100644 index 0000000..72ebc30 --- /dev/null +++ b/docker/showerloop/Dockerfile @@ -0,0 +1,42 @@ +# Stage 1: Build Hugo site +FROM alpine:latest AS hugo-builder + +# Install necessary dependencies (Hugo, Git, Node.js, and npm) +RUN apk add --no-cache hugo git nodejs npm + +# Copy our enhanced Caddyfile +COPY Caddyfile.default.template /etc/caddy/Caddyfile.override + +# Set working directory +WORKDIR /site + +# Copy the Hugo source files +COPY public/ /site + +# Install PostCSS and its dependencies locally and update browserslist +RUN cd /site && npm init -y && \ + npm install --save-dev postcss postcss-cli autoprefixer && \ + npm install --save-dev caniuse-lite && \ + npm update caniuse-lite browserslist + +# Build the Hugo site for production with optimizations +# Disable GitInfo, enable minification, and set production environment +RUN mkdir /public && \ + cd /site && \ + HUGO_ENABLEGITINFO=false \ + HUGO_ENV=production \ + npm run build:prod && \ + cp -r /site/public/* /public/ + +# Stage 2: Production image with prebuilt static files +FROM git.nixc.us/colin/container-base:production-nixiusstatic + +# Copy the built site from the first stage +COPY --from=hugo-builder /public /srv + +# Copy our enhanced Caddyfile for development +COPY Caddyfile.default.template /etc/caddy/Caddyfile.override + +# Add health check endpoint for production monitoring +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD wget -q --spider http://localhost/healthcheck.txt || exit 1 \ No newline at end of file diff --git a/.hugo_build.lock b/docker/showerloop/public/.hugo_build.lock similarity index 100% rename from .hugo_build.lock rename to docker/showerloop/public/.hugo_build.lock diff --git a/CNAME b/docker/showerloop/public/CNAME similarity index 100% rename from CNAME rename to docker/showerloop/public/CNAME diff --git a/_headers b/docker/showerloop/public/_headers similarity index 100% rename from _headers rename to docker/showerloop/public/_headers diff --git a/_redirects b/docker/showerloop/public/_redirects similarity index 100% rename from _redirects rename to docker/showerloop/public/_redirects diff --git a/analyze-css.js b/docker/showerloop/public/analyze-css.js similarity index 100% rename from analyze-css.js rename to docker/showerloop/public/analyze-css.js diff --git a/build-production.sh b/docker/showerloop/public/build-production.sh similarity index 100% rename from build-production.sh rename to docker/showerloop/public/build-production.sh diff --git a/docker/showerloop/public/categories/index.xml b/docker/showerloop/public/categories/index.xml new file mode 100644 index 0000000..e9e2ccc --- /dev/null +++ b/docker/showerloop/public/categories/index.xml @@ -0,0 +1 @@ +Categories onhttp://localhost:1313/categories/Recent content in Categories onHugoen-us \ No newline at end of file diff --git a/components/index.html b/docker/showerloop/public/components/index.html similarity index 98% rename from components/index.html rename to docker/showerloop/public/components/index.html index e1b3acb..df2468a 100644 --- a/components/index.html +++ b/docker/showerloop/public/components/index.html @@ -1,4 +1,4 @@ -Components | ShowerLoop +Components | ShowerLoop How It Works | ShowerLoop +How It Works | ShowerLoop Home | ShowerLoop +Home | ShowerLoop
\ No newline at end of file diff --git a/posts/blog2/index.html b/docker/showerloop/public/posts/blog2/index.html similarity index 85% rename from posts/blog2/index.html rename to docker/showerloop/public/posts/blog2/index.html index 698dea2..08a8af9 100644 --- a/posts/blog2/index.html +++ b/docker/showerloop/public/posts/blog2/index.html @@ -1,4 +1,4 @@ -Showerloop at the Design museum | ShowerLoop +Showerloop at the Design museum | ShowerLoop \ No newline at end of file + + + \ No newline at end of file diff --git a/posts/blog3/index.html b/docker/showerloop/public/posts/blog3/index.html similarity index 91% rename from posts/blog3/index.html rename to docker/showerloop/public/posts/blog3/index.html index bc7a242..dcf997d 100644 --- a/posts/blog3/index.html +++ b/docker/showerloop/public/posts/blog3/index.html @@ -1,4 +1,4 @@ -Don't Put These Things Down The Shower Drain! | ShowerLoop +Don't Put These Things Down The Shower Drain! | ShowerLoop \ No newline at end of file + + + \ No newline at end of file diff --git a/posts/blog4/index.html b/docker/showerloop/public/posts/blog4/index.html similarity index 89% rename from posts/blog4/index.html rename to docker/showerloop/public/posts/blog4/index.html index 7bcb869..f4f58a2 100644 --- a/posts/blog4/index.html +++ b/docker/showerloop/public/posts/blog4/index.html @@ -1,4 +1,4 @@ -2 Ways to Be Economical When Showering With an Injury | ShowerLoop +2 Ways to Be Economical When Showering With an Injury | ShowerLoop \ No newline at end of file + + + \ No newline at end of file diff --git a/posts/index.html b/docker/showerloop/public/posts/index.html similarity index 98% rename from posts/index.html rename to docker/showerloop/public/posts/index.html index 42c15e8..2f7a5ec 100644 --- a/posts/index.html +++ b/docker/showerloop/public/posts/index.html @@ -1,4 +1,4 @@ -Posts | ShowerLoop +Posts | ShowerLoop Research | ShowerLoop +Research | ShowerLoop