Skip to content

Resetete/kila-hildegarten

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

277 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

README

Here I am building the website for our Kinderladen Kila Hildegarten.

The website is currently reachable through https://kila-hildegarten.herokuapp.com/

The main website is: https://kila-hildegarten.de

Note

Using Cloudflare to securely connect with the domain provider required redirecting from HTTP to HTTPS. This does not work correctly with Devise since the request header is not changed from HTTP to HTTPS. Following this Rails issue #22965, I implemented the recommendation by TonyTonyJan.

Turbolinks are disabled for links in the Materialize sidenav bar. If they are enabled, the links will not work after first-time triggering.


Technical Specifications

  • Security policies are managed via the SecureHeaders gem. Policies are controlled through config/initializers/secure_headers.rb.
  • The app is hosted on Heroku.
  • There is also an API connection to Webling.
  • Redis (Heroku Redis) is used to cache Webling photos for previews.
  • Photos are stored on Dropbox, using a custom Dropbox connection gem updated for current compatibility.

Kila Hildegarten – Website

This repository contains the Ruby on Rails application for the Kinderladen Kila Hildegarten website. It serves both the public website and an internal admin integration with Webling.

🌐 Production: https://kila-hildegarten.de πŸ§ͺ Staging (Heroku): https://kila-hildegarten.herokuapp.com


Overview

The app provides a CMS-like interface. It allows admins to log in and update website content and photos stored on Dropbox.

For our Webling Kila management software, we use a secured page /webling_photos for managing photo previews, content pages, and member information synced from Webling. Only admins with the correct access token can access this page. It uses Cloudinary for asset storage and Redis caching for photo previews. Cloudinary is configured as a Heroku add-on.

The stack is intentionally lightweight and optimized for hosting on Heroku with Cloudflare as CDN and SSL proxy.


Technical Specifications

Framework & Hosting

  • Ruby on Rails (7.x)
  • Ruby version: specify your current version (e.g. 3.2.3)
  • Database: PostgreSQL (Heroku managed)
  • Cache: Redis (Heroku Redis)
  • Website Hosting: Heroku
  • SSL: via Cloudflare
  • Domain: managed via one.com

Asset Management

  • Assets (images, CSS, JS) are served via the Rails Asset Pipeline (Sprockets).
  • On deploy, assets are precompiled with fingerprints (e.g. placeholder-<hash>.png).
  • The placeholder image lives in: app/assets/images/placeholder.png

Example usage:

= image_tag('placeholder.png', onerror: "this.src='#{image_path('placeholder.png')}'")

If assets 404 in production:

heroku run rails assets:clobber
heroku run rails assets:precompile

Storage

  • Dropbox is used to store original photo files for the website (via a custom Dropbox connection gem).
  • Cloudinary is used by ActiveStorage for image transformations (resize_to_limit, etc.). Images are cached and served lazily to improve load times.

Security Headers (CSP)

The app uses the SecureHeaders gem. Configuration is defined in config/initializers/secure_headers.rb.

Key setting:

img_src: %w('self' data: blob: https://*.dropboxusercontent.com https://res.cloudinary.com)

This allows images to be loaded from:

  • Local assets ('self')
  • Inline data URIs (data:)
  • ActiveStorage blob URLs (blob:)
  • Dropbox and Cloudinary

Webling Integration

Integrates with the Webling API to fetch folders, files, and member information. API results are cached in Redis to reduce requests. Webling file objects are wrapped via WeblingFile ActiveRecord models. The /webling_photos page is embedded into the third-party Webling app via iframe.

Caching

Redis is used for caching photo previews and metadata. Cached photos are refreshed periodically when Webling data changes.


Authentication

Uses Devise for user authentication. Because Cloudflare acts as an HTTPS proxy, Devise must recognize the original protocol correctly. Configuration follows Rails issue #22965 (credit: TonyTonyJan).


Frontend

Built with MaterializeCSS. Turbolinks are disabled for sidenav links to prevent reinitialization issues.

Example:

= link_to 'Gallery', photos_path, data: { turbolinks: false }

Architecture Overview

The Kila Hildegarten app integrates several external services to deliver optimized photo content and a secure web experience.

High-Level Architecture

                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                         β”‚  Webling Platform    β”‚
                         β”‚  (member + file API) β”‚
                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚ JSON API calls
                                    β”‚ (authenticated via token)
                                    β–Ό
                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                      β”‚  Rails Application        β”‚
                      β”‚  (Heroku)                 β”‚
                      β”‚                           β”‚
                      β”‚  β€’ Fetches data from Webling
                      β”‚  β€’ Stores metadata in PostgreSQL
                      β”‚  β€’ Caches previews in Redis
                      β”‚  β€’ Uses SecureHeaders for CSP
                      β”‚  β€’ Serves assets via Asset Pipeline
                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                  β”‚
       ActiveStorage              β”‚          Cache Layer
  (with Cloudinary adapter)       β”‚          (Redis on Heroku)
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚  Cloudinary CDN        │◄─────┼──────│  Redis              β”‚
  β”‚  Stores image variants β”‚             β”‚  Cached previews    β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                  β”‚
                                  β”‚
                                  β–Ό
                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                      β”‚  Cloudflare Proxy/CDN    β”‚
                      β”‚  β€’ HTTPS + Caching layer β”‚
                      β”‚  β€’ Enforces SSL redirect β”‚
                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                 β”‚
                                 β”‚ HTTPS / HTTP2
                                 β–Ό
                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                      β”‚        Browser            β”‚
                      β”‚  (Parent or Member view)  β”‚
                      β”‚                          β”‚
                      β”‚ - Loads Materialize CSS   β”‚
                      β”‚ - Lazy-loads images       β”‚
                      β”‚ - Falls back to           β”‚
                      β”‚   `placeholder.png` if    β”‚
                      β”‚   image fails to load     β”‚
                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Data Flow Summary

  • Webling β†’ Rails: Fetch photo metadata and folder info from the Webling API.
  • Rails β†’ Dropbox: Retrieve original photo files via Dropbox gem.
  • Rails β†’ Cloudinary: Store and serve image variants (resized previews).
  • Rails β†’ Redis: Cache photo metadata and Cloudinary URLs.
  • Rails β†’ Cloudflare β†’ Browser: Serve all content securely via Cloudflare.
  • Browser: MaterializeCSS frontend with lazy loading and placeholder fallback.

Key Features

  • SecureHeaders with custom CSP allows Dropbox and Cloudinary image sources.
  • Resilient image loading using lazy data-src and fallback placeholders.
  • HTTPS enforcement via Cloudflare and trusted proxy config.
  • Lightweight integration β€” Webling acts as backend data source.

Development Setup

bundle install
bin/rails db:setup
bin/rails s

Run in production mode locally:

RAILS_ENV=production bin/rails assets:precompile
bin/rails s -e production

Deployment

Deploy to Heroku:

git push heroku main
heroku run rails db:migrate

Rebuild all assets:

heroku run rails assets:clobber
heroku run rails assets:precompile

Maintenance Checklist

Task Command
Clear cache heroku redis:cli --flushall
Rebuild assets heroku run rails assets:clobber && heroku run rails assets:precompile
Restart dynos heroku restart
Run database migrations heroku run rails db:migrate
Open Rails console heroku run rails c
Check logs heroku logs --tail

Known Caveats

Issue Description Solution
Devise login redirects incorrectly (HTTP/HTTPS) Cloudflare proxy affects request scheme Use config.force_ssl = true and trust proxy headers
Placeholder 404 Asset pipeline not refreshed Run rails assets:clobber && rails assets:precompile
Cloudinary images blocked CSP restriction Add https://res.cloudinary.com to img_src in secure_headers.rb

License & Credits

Developed by Theresa Mannschatz for Kinderladen Kila Hildegarten e.V. https://theresamannschatz.design Β© 2025 β€” All rights reserved.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors