- Svelte 58.2%
- TypeScript 37.9%
- JavaScript 1.8%
- Dockerfile 0.8%
- HTML 0.4%
- Other 0.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .forgejo/workflows | ||
| .vscode | ||
| deploy | ||
| drizzle | ||
| e2e | ||
| scripts | ||
| src | ||
| static | ||
| .dockerignore | ||
| .editorconfig | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| .npmrc | ||
| .prettierignore | ||
| .prettierrc | ||
| Dockerfile | ||
| drizzle.config.ts | ||
| entrypoint.sh | ||
| eslint.config.js | ||
| LICENSE.md | ||
| mise.toml | ||
| package.json | ||
| playwright.config.ts | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| renovate.json | ||
| svelte.config.js | ||
| tsconfig.json | ||
| vite.config.ts | ||
| vitest-setup.server.ts | ||
HCSS Website
A modern, low-maintenance website for the Helmstedter Chor- und Singschule e.V. (HCSS) designed to replace the old site with a solution that simplifies media and event management.
Overview
This project serves as the official website for HCSS e.V. It was developed to reduce maintenance overhead, particularly when adding new media content or events. The website features a clean, responsive design with an intuitive admin interface for content management.
Features
- Responsive design that works across desktop and mobile devices
- Simple content management system for easily updating website sections
- Event announcement management
- Media gallery for photos
- Admin panel for content management
- Authentication system
Getting Started
Prerequisites
Installation
-
Clone the repository:
git clone https://git.eiflerstrom.de/IC3P3/hcss-website.git cd hcss-website -
Install dependencies:
pnpm install -
To set up environment variables copy
.env.exampleto.envand adjust the values (see Configuration):cp .env.example .env -
Initialize the database and seed development data:
pnpm db:migrate pnpm db:seed
Development
Start the development server:
pnpm run dev
This will start the development server at http://localhost:5173.
Building for Production
Build the project for production:
pnpm run build
Preview the production build:
pnpm run preview
Configuration
All settings are provided through environment variables. Copy .env.example
to .env for local development, or pass them at runtime in Docker.
| Variable | Required | Default (Docker image) | Description |
|---|---|---|---|
ADMIN_PASSWORD |
yes | x | Admin password used by the seed. The container aborts on boot if unset. |
HOST_URL |
yes | x | Public base URL, used for sitemap.xml/robots.txt. |
ADMIN_USERNAME |
no | admin |
Admin username used by the seed. |
DATABASE_URL |
no | /data/website-data.sqlite |
SQLite path. Keep it on the /data volume. |
UPLOAD_PATH |
no | /data/upload |
Upload directory. Keep it on the /data volume. |
BODY_SIZE_LIMIT |
no | Infinity |
Node request body cap; left disabled so the reverse proxy is the limit. |
LOG_LEVEL |
no | info |
winston log level: error, warn, info or debug. |
TZ |
no | container default (UTC) | Server timezone. Set Europe/Berlin so event datetimes entered in the admin panel are stored correctly. |
PUBLIC_UMAMI_SRC |
no | x | URL of the Umami tracking script. Both PUBLIC_UMAMI_* values must be set for the script to be embedded. |
PUBLIC_UMAMI_WEBSITE_ID |
no | x | Website ID from the Umami dashboard. |
ADMIN_PASSWORDmust stay set on every start. The seed validates it before checking whether the admin already exists.
Deployment with Docker
The included Dockerfile produces a self-contained image. On startup the
container applies database migrations and runs an idempotent production seed
(creating the admin user and base page content if missing), then starts the
server on port 3000.
Build
docker build -t hcss-website .
Run
The database and uploaded media are stored under /data, so mount a
persistent volume there. The admin password is injected at runtime:
docker run -d \
--name hcss-website \
-p 3000:3000 \
-v hcss-data:/data \
-e ADMIN_PASSWORD='your-strong-password' \
-e HOST_URL='https://your-domain.example' \
hcss-website
See Configuration for all available variables.
Reverse proxy
Since BODY_SIZE_LIMIT is disabled in the container, the upload size cap lives
at the reverse proxy. For nginx, set a limit that allows your media uploads, e.g.:
client_max_body_size 10M;
Database Management
This project uses Drizzle ORM with SQLite. Database schema changes are managed using Drizzle Kit.
Apply schema changes to the database:
pnpm run db:generate
pnpm run db:migrate
Explore and manage your database with Drizzle Studio:
pnpm db:studio
Content Management
The admin panel can be accessed at /admin (login required). From here, you can:
- Create, edit and delete events (
/admin/create-event,/admin/change-event) - Upload, edit and delete media (
/admin/create-media,/admin/change-media) - Update site content by changing images in different sections
(
/admin/change-design) - Link media items to events
All admin routes are protected by a session guard in hooks.server.ts that
covers page loads and form actions alike. Forms warn before navigating away
with unsaved changes.
Logging
The server logs structured JSON lines to stdout via
winston (src/lib/server/utils/logger.ts).
Logged events include authentication successes/failures, admin content changes,
failed database operations and unhandled server errors. In Docker, read them
with docker logs. The verbosity is controlled by LOG_LEVEL.
Analytics (optional)
The deployment stack ships an optional, self-hosted
Umami instance behind the analytics compose profile.
See deploy/README.md. The tracking script is only embedded on public pages
when both PUBLIC_UMAMI_SRC and PUBLIC_UMAMI_WEBSITE_ID are set. Without
them the site loads no analytics at all.
Testing
The project includes both unit and end-to-end testing:
Run unit tests:
pnpm run test:unit
Run end-to-end tests:
pnpm run test:e2e
Run all tests:
pnpm run test
Code Quality
Maintain code quality with the following commands:
Format code:
pnpm run format
Lint code:
pnpm run lint
# For checking some more rules
pnpm run lint:strict
Svelte diagnostics:
pnpm check
# OR to run it constantly
pnpm check:watch