From 4a8413359fd639c10fddd61452b9902702a2197f Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sat, 11 Jul 2026 16:09:28 +0200 Subject: [PATCH] Converted the website service project into a reusable template. --- Makefile | 13 ++ .../Cases/Public/Methods/ServiceTests.swift | 14 +- README.md | 86 ++++++++++ Scripts/bootstrap | 159 ++++++++++++++++++ Services/Website/.env.local | 10 +- Services/Website/Makefile | 6 +- Services/Website/README.md | 12 +- .../Public/Extensions/String+Constants.swift | 6 +- Services/Website/docker-compose.override.yml | 8 +- Services/Website/docker-compose.yml | 8 +- .../project.pbxproj | 12 +- .../contents.xcworkspacedata | 0 12 files changed, 296 insertions(+), 38 deletions(-) create mode 100644 Makefile create mode 100644 README.md create mode 100755 Scripts/bootstrap rename {Loud.xcodeproj => Site.xcodeproj}/project.pbxproj (95%) rename {Loud.xcodeproj => Site.xcodeproj}/project.xcworkspace/contents.xcworkspacedata (100%) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4f0b966 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +# Template root Makefile — bootstrap convenience only. +# This file is removed by `Tools/bootstrap` once the template is generated. + +.DEFAULT_GOAL := help + +.PHONY: bootstrap +bootstrap: ## Generate a concrete website from this template (interactive) + @./Scripts/bootstrap + +.PHONY: help +help: ## Show available commands + @grep -hE '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \ + | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-12s\033[0m %s\n", $$1, $$2}' diff --git a/Packages/Persistence/Tests/Cases/Public/Methods/ServiceTests.swift b/Packages/Persistence/Tests/Cases/Public/Methods/ServiceTests.swift index 0ef5fb1..da8bef7 100644 --- a/Packages/Persistence/Tests/Cases/Public/Methods/ServiceTests.swift +++ b/Packages/Persistence/Tests/Cases/Public/Methods/ServiceTests.swift @@ -36,9 +36,9 @@ struct ServiceTests { .init( host: "127.0.0.1", port: 3306, - name: "loud", - username: "loud", - password: "loud", + name: "site", + username: "site", + password: "site", tls: .off, maxConnectionsPerEventLoop: 1 ) @@ -126,7 +126,7 @@ private extension ServiceTests { try await fluent.migrate() let repository = ExampleRepository(fluent: fluent) - let created = try await repository.create(name: "loud") + let created = try await repository.create(name: "site") #expect(try await repository.all().contains(created)) @@ -158,9 +158,9 @@ private let mysqlDriver: Persistence.Driver? = { .init( host: host, port: environment["MYSQL_TEST_PORT"].flatMap(Int.init) ?? 3306, - name: environment["MYSQL_TEST_NAME"] ?? "loud", - username: environment["MYSQL_TEST_USERNAME"] ?? "loud", - password: environment["MYSQL_TEST_PASSWORD"] ?? "loud", + name: environment["MYSQL_TEST_NAME"] ?? "site", + username: environment["MYSQL_TEST_USERNAME"] ?? "site", + password: environment["MYSQL_TEST_PASSWORD"] ?? "site", tls: .off, maxConnectionsPerEventLoop: 2 ) diff --git a/README.md b/README.md new file mode 100644 index 0000000..63eb852 --- /dev/null +++ b/README.md @@ -0,0 +1,86 @@ +# Website Template + +This repository is a **template** for the platform's websites. It ships as a +complete, buildable reference site whose identity is the neutral placeholder +**`Site`** / **`site`**. You generate a real site from it in two steps: +generate a fresh repository, then run the bootstrap script to stamp in your +site's name and slug. + +## What's in here + +| Path | Role | +| --- | --- | +| `Services/Website` | The Hummingbird website service (the engine + placeholder content). | +| `Packages/Localization`, `Packages/Persistence` | Reusable packages, **vendored** into every site — each generated repo owns its own copy. | +| `Site.xcodeproj` | The umbrella Xcode project (renamed to your site by bootstrap). | +| `Scripts/bootstrap` | The generator. Rewrites placeholders, then deletes itself. | + +The engine is intentionally copied into each site rather than shared as a +remote dependency: a generated site is fully self-contained and can diverge +freely. Engine fixes are propagated to existing sites by hand (or by +re-generating and porting content). + +## Generating a new site + +### 1. Create a repository from this template + +On Gitea, mark this repository as a template once (repository **Settings → +Template → “Template” checkbox**). New sites are then created with the +**“Use this template”** button, which produces a fresh repository with its own +history — no template commits carried over. + +> No Gitea button? Just clone this repo, `rm -rf .git`, and continue — the +> bootstrap script offers to re-initialise git for you. + +### 2. Bootstrap + +Clone the new repository, then from its root run: + +```sh +make bootstrap # or: ./Scripts/bootstrap +``` + +You'll be asked for: + +| Prompt | Example | Rewrites | +| --- | --- | --- | +| **Site display name** (PascalCase) | `Loud` | Server name (`LoudWebsite`), `Loud.xcodeproj`, README title. | +| **Project slug** (lowercase) | `loud-ams` | Container owner, database name/user, Compose project name. | + +The script rewrites the placeholder occurrences in place, renames +`Site.xcodeproj`, optionally starts a fresh git history, and then removes +itself along with this file and the root `Makefile`. + +### 3. Fill in the content + +Bootstrap leaves reminders, but in short: + +1. **Copy & localization** — `Services/Website/Sources/Library/Catalogs/Localizable.xcstrings` + and the landing / 404 pages under `Services/Website/Sources/Library`. +2. **Static assets** — `Services/Website/Resources/Static` (CSS, JS, favicon, icons, manifest). +3. **Secrets** — set a real `DATABASE_PASSWORD` in a git-ignored + `Services/Website/.env` (the committed `.env.local` is an example only). +4. **Domain models** — the `Persistence` package ships a sample + `ExampleRecord` / `ExampleRepository`; replace it when you add real data. + +### 4. Build & run + +```sh +cd Services/Website +make site-run # watch + rebuild +# or +make site-mount # docker compose up --build +``` + +## What bootstrap does NOT change + +- Organisation (`Röck+Cöde VoF`) and Xcode `DEVELOPMENT_TEAM` — shared across all sites. +- The package architecture, middleware, security headers, and persistence layer. +- The generic `website` image name and `Makefile` command names (`site-run`, `site-mount`, …). + +## Maintaining the template itself + +Edit and test the reference site directly — it builds and its tests pass with +the `Site` / `site` placeholders in place. Keep the placeholders intact so the +bootstrap script's targeted replacements keep matching; if you introduce a new +site-specific value, add a matching rewrite line in `Scripts/bootstrap`. diff --git a/Scripts/bootstrap b/Scripts/bootstrap new file mode 100755 index 0000000..10aba68 --- /dev/null +++ b/Scripts/bootstrap @@ -0,0 +1,159 @@ +#!/usr/bin/env sh +# +# bootstrap — turn this template into a concrete website. +# +# The template ships as a fully buildable reference site whose identity is the +# neutral placeholder "Site" / "site". This script rewrites those placeholders, +# in place, to the values you provide — then removes itself. +# +# Run once, from the repository root: +# +# ./Tools/bootstrap +# +# It is idempotent only in the sense that it self-destructs: once run, the +# placeholders are gone and the script (and its scaffolding) are deleted. + +set -eu + +# --- Preconditions ------------------------------------------------------------ + +if [ ! -d "Services/Website" ]; then + echo "error: run this from the repository root (Services/Website not found)." >&2 + exit 1 +fi + +XCODEPROJ="./Site.xcodeproj" + +# --- Prompts ------------------------------------------------------------------ + +printf 'Site display name (PascalCase, e.g. Berlin) [Site]: ' +read -r NAME +NAME="${NAME:-Site}" + +DEFAULT_SLUG="$(printf '%s' "$NAME" | tr '[:upper:]' '[:lower:]')" +printf 'Project slug (lowercase, used for owner/db/compose, e.g. loud-berlin) [%s]: ' "$DEFAULT_SLUG" +read -r SLUG +SLUG="${SLUG:-$DEFAULT_SLUG}" + +echo +echo " display name : $NAME (server name \"${NAME}Website\", ${NAME}.xcodeproj)" +echo " slug : $SLUG (container owner, database name/user, compose project)" +echo +printf 'Apply these values? [y/N]: ' +read -r CONFIRM +case "$CONFIRM" in + y | Y | yes | YES) ;; + *) + echo "Aborted. Nothing was changed." + exit 1 + ;; +esac + +# --- Helpers ------------------------------------------------------------------ + +# Portable in-place sed (works on both BSD/macOS and GNU/Linux). +rewrite() { + file="$1" + shift + [ -f "$file" ] || return 0 + tmp="${file}.bootstrap.tmp" + sed "$@" "$file" >"$tmp" && mv "$tmp" "$file" +} + +W="Services/Website" + +# --- Rewrites ----------------------------------------------------------------- + +# Swift constants: server name + database name/username. +rewrite "$W/Sources/Library/Public/Extensions/String+Constants.swift" \ + -e "s/SiteWebsite/${NAME}Website/g" \ + -e "s/= \"site\"/= \"${SLUG}\"/g" + +# Local env example. +rewrite "$W/.env.local" \ + -e "s/SiteWebsite/${NAME}Website/g" \ + -e "s/^HOST_OWNER=site\$/HOST_OWNER=${SLUG}/" \ + -e "s/^DATABASE_NAME=site\$/DATABASE_NAME=${SLUG}/" \ + -e "s/^DATABASE_USERNAME=site\$/DATABASE_USERNAME=${SLUG}/" \ + -e "s/^DATABASE_PASSWORD=site\$/DATABASE_PASSWORD=${SLUG}/" + +# Production compose. +rewrite "$W/docker-compose.yml" \ + -e "s/SiteWebsite/${NAME}Website/g" \ + -e "s/^name: site-platform\$/name: ${SLUG}-platform/" \ + -e "s/DATABASE_NAME:-site}/DATABASE_NAME:-${SLUG}}/" \ + -e "s/DATABASE_USERNAME:-site}/DATABASE_USERNAME:-${SLUG}}/" + +# Local override compose. +rewrite "$W/docker-compose.override.yml" \ + -e "s/HOST_OWNER:-site}/HOST_OWNER:-${SLUG}}/" \ + -e "s/DATABASE_NAME:-site}/DATABASE_NAME:-${SLUG}}/" \ + -e "s/DATABASE_USERNAME:-site}/DATABASE_USERNAME:-${SLUG}}/" \ + -e "s/DATABASE_PASSWORD:-site}/DATABASE_PASSWORD:-${SLUG}}/" + +# Makefile db-shell fallbacks. +rewrite "$W/Makefile" \ + -e "s/),site)/),${SLUG})/g" + +# Service README. +rewrite "$W/README.md" \ + -e "s/^# Site Website\$/# ${NAME} Website/" \ + -e "s/\*\*Site\*\*/**${NAME}**/" \ + -e "s/SiteWebsite/${NAME}Website/g" \ + -e "s/\`site\`/\`${SLUG}\`/g" + +# Xcode project: PBXProject name + directory. +if [ -d "$XCODEPROJ" ]; then + rewrite "$XCODEPROJ/project.pbxproj" -e "s/\"Site\"/\"${NAME}\"/g" + if command -v git >/dev/null 2>&1 && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then + git mv "$XCODEPROJ" "./${NAME}.xcodeproj" 2>/dev/null || mv "$XCODEPROJ" "./${NAME}.xcodeproj" + else + mv "$XCODEPROJ" "./${NAME}.xcodeproj" + fi +fi + +# --- Optional: fresh git history --------------------------------------------- + +echo +printf 'Start a fresh git history (drops the template history)? [y/N]: ' +read -r FRESH +case "$FRESH" in + y | Y | yes | YES) + if command -v git >/dev/null 2>&1; then + rm -rf .git + git init -q + echo "Reinitialised git. Remember to add your remote and commit." + fi + ;; + *) ;; +esac + +# --- Self-cleanup ------------------------------------------------------------- + +rm -f Scripts/bootstrap +rmdir Scripts 2>/dev/null || true +rm -f Makefile # root convenience Makefile (bootstrap only) +rm -f README.md # template usage docs +rm -rf .gitea # Gitea template metadata + +# --- Done --------------------------------------------------------------------- + +cat < # or 'git remote add origin ...' + 4. Build and run: + cd $W && make site-run + +The Persistence package still ships an ExampleRecord / ExampleRepository sample +model — replace it with your real domain models when you add persistence. +EOF diff --git a/Services/Website/.env.local b/Services/Website/.env.local index 1987239..860ce02 100644 --- a/Services/Website/.env.local +++ b/Services/Website/.env.local @@ -12,7 +12,7 @@ HOST_CONTAINER=containers.rock-n-code.com # Owner of the container running the Website service. -HOST_OWNER=loud +HOST_OWNER=site # Password for authenticating to the container registry. HOST_PASSWORD= @@ -36,7 +36,7 @@ IMAGE_TAG=latest # --- Application config ------------------------------------------------------- # Server name reported by the HTTP service. -HTTP_SERVER_NAME=LoudWebsite +HTTP_SERVER_NAME=SiteWebsite # Log verbosity: trace | debug | info | notice | warning | error | critical LOG_LEVEL=info @@ -55,13 +55,13 @@ DATABASE_HOST=localhost DATABASE_PORT=3306 # Name of the database to connect to. -DATABASE_NAME=loud-ams +DATABASE_NAME=site # Username of the database to connect as. -DATABASE_USERNAME=loud-ams +DATABASE_USERNAME=site # Provide the real password via the environment or a secret — never commit it. -DATABASE_PASSWORD=loud-ams +DATABASE_PASSWORD=site # TLS posture when connecting: off | prefer | require (use `require` in production). DATABASE_TLS=off diff --git a/Services/Website/Makefile b/Services/Website/Makefile index 47d91c8..49351b1 100644 --- a/Services/Website/Makefile +++ b/Services/Website/Makefile @@ -90,9 +90,9 @@ db-shell: ## Open a SQL shell on the local database instance --profile database \ exec mariadb \ mariadb \ - --user=$(or $(DATABASE_USERNAME),loud) \ - --password=$(or $(DATABASE_PASSWORD),loud) \ - $(or $(DATABASE_NAME),loud) + --user=$(or $(DATABASE_USERNAME),site) \ + --password=$(or $(DATABASE_PASSWORD),site) \ + $(or $(DATABASE_NAME),site) .PHONY: db-unmount db-unmount: ## Stop and remove the local database instance (keeps the data volume) diff --git a/Services/Website/README.md b/Services/Website/README.md index c705916..2c67df3 100644 --- a/Services/Website/README.md +++ b/Services/Website/README.md @@ -1,5 +1,5 @@ -# Loud Website -The **Loud** public website service — a [Hummingbird](https://github.com/hummingbird-project/hummingbird) server that renders a static landing page and serves the site's static assets. +# Site Website +The **Site** public website service — a [Hummingbird](https://github.com/hummingbird-project/hummingbird) server that renders a static landing page and serves the site's static assets. ## Overview The service: @@ -73,7 +73,7 @@ A dotted config key maps to an environment variable by upper-casing, splitting c | --- | --- | --- | --- | | `http.host` | `HTTP_HOST` | _none_ | Host the server binds to. Supplied via the `--http-host` CLI flag (the Docker image passes `0.0.0.0`). | | `http.port` | `HTTP_PORT` | _none_ | Port the server listens on. Supplied via the `--http-port` CLI flag (the Docker image passes `8080`). | -| `http.serverName` | `HTTP_SERVER_NAME` | `LoudWebsite` | Server name and logger label. | +| `http.serverName` | `HTTP_SERVER_NAME` | `SiteWebsite` | Server name and logger label. | ### Logging | Config key | Environment variable | Default | Description | @@ -87,8 +87,8 @@ A dotted config key maps to an environment variable by upper-casing, splitting c | `database.migrate` | `DATABASE_MIGRATE` (flag `--database-migrate`) | `false` | When set, run the migrations and exit instead of serving. | | `database.host` | `DATABASE_HOST` | `localhost` | MySQL/MariaDB host. Ignored for `inMemory`. | | `database.port` | `DATABASE_PORT` | `3306` | MySQL/MariaDB port. Ignored for `inMemory`. | -| `database.name` | `DATABASE_NAME` | `loud` | Database name. Ignored for `inMemory`. | -| `database.username` | `DATABASE_USERNAME` | `loud` | Database username. Ignored for `inMemory`. | +| `database.name` | `DATABASE_NAME` | `site` | Database name. Ignored for `inMemory`. | +| `database.username` | `DATABASE_USERNAME` | `site` | Database username. Ignored for `inMemory`. | | `database.password` | `DATABASE_PASSWORD` | _(empty)_ | Database password. Provide via the environment/a secret — never commit it. | | `database.tls` | `DATABASE_TLS` | `prefer` | TLS posture when connecting: `off`, `prefer`, or `require`. Ignored for `inMemory`. | | `database.pool.maxPerEventLoop` | `DATABASE_POOL_MAX_PER_EVENT_LOOP` | `4` | Maximum pooled connections per event loop. Ignored for `inMemory`. | @@ -203,7 +203,7 @@ The Makefile and Compose files read these from a `.env` file (or the environment | `IMAGE_PLATFORM` | Build platform (e.g. `linux/amd64`). | | `HOST_PORT` | Host port mapped to the container's `8080` (default `8080`). | | `LOG_LEVEL` | Runtime log level (default `info`). | -| `HTTP_SERVER_NAME` | Runtime server name (default `LoudWebsite`). | +| `HTTP_SERVER_NAME` | Runtime server name (default `SiteWebsite`). | | `SECURITY_STRICT_TRANSPORT_SECURITY` | HSTS header value (default `max-age=31536000; includeSubDomains`). | | `DATABASE_DRIVER` | `inMemory` (default) or `mysql`. Set to `mysql` in production to use a managed database. | | `DATABASE_HOST`, `DATABASE_PORT`, `DATABASE_NAME`, `DATABASE_USERNAME`, `DATABASE_PASSWORD` | MySQL/MariaDB connection (when `DATABASE_DRIVER=mysql`). Provide the password via a secret. | diff --git a/Services/Website/Sources/Library/Public/Extensions/String+Constants.swift b/Services/Website/Sources/Library/Public/Extensions/String+Constants.swift index 23fa620..eedb8f0 100644 --- a/Services/Website/Sources/Library/Public/Extensions/String+Constants.swift +++ b/Services/Website/Sources/Library/Public/Extensions/String+Constants.swift @@ -8,9 +8,9 @@ extension String { /// The default MySQL/MariaDB host. public static let host = "localhost" /// The default database name. - public static let name = "loud" + public static let name = "site" /// The default database username. - public static let username = "loud" + public static let username = "site" /// The default TLS posture token. public static let tls = "prefer" /// The TLS token disabling TLS. @@ -47,6 +47,6 @@ extension String { /// A namespace for the server string constants. public enum Server { /// The website server's name. - public static let name = "LoudWebsite" + public static let name = "SiteWebsite" } } diff --git a/Services/Website/docker-compose.override.yml b/Services/Website/docker-compose.override.yml index c297e23..e83e081 100644 --- a/Services/Website/docker-compose.override.yml +++ b/Services/Website/docker-compose.override.yml @@ -26,7 +26,7 @@ services: # docker compose --profile database up mariadb mariadb: image: mariadb:11 - container_name: ${HOST_OWNER:-loud}-db + container_name: ${HOST_OWNER:-site}-db restart: unless-stopped profiles: - database @@ -34,9 +34,9 @@ services: - "127.0.0.1:${DATABASE_PORT:-3306}:3306" environment: MARIADB_RANDOM_ROOT_PASSWORD: "yes" - MARIADB_DATABASE: ${DATABASE_NAME:-loud-ams} - MARIADB_USER: ${DATABASE_USERNAME:-loud-ams} - MARIADB_PASSWORD: ${DATABASE_PASSWORD:-loud-ams} + MARIADB_DATABASE: ${DATABASE_NAME:-site} + MARIADB_USER: ${DATABASE_USERNAME:-site} + MARIADB_PASSWORD: ${DATABASE_PASSWORD:-site} MARIADB_AUTO_UPGRADE: "1" command: - "--character-set-server=utf8mb4" diff --git a/Services/Website/docker-compose.yml b/Services/Website/docker-compose.yml index 81c40d5..957c544 100644 --- a/Services/Website/docker-compose.yml +++ b/Services/Website/docker-compose.yml @@ -1,4 +1,4 @@ -name: loud-platform +name: site-platform # Production base configuration. # Deploys a pre-built image pulled from a registry — no build step. @@ -19,7 +19,7 @@ services: - "${HOST_PORT:-8080}:8080" environment: LOG_LEVEL: ${LOG_LEVEL:-info} - HTTP_SERVER_NAME: ${HTTP_SERVER_NAME:-LoudWebsite} + HTTP_SERVER_NAME: ${HTTP_SERVER_NAME:-SiteWebsite} SECURITY_STRICT_TRANSPORT_SECURITY: "${SECURITY_STRICT_TRANSPORT_SECURITY:-max-age=31536000; includeSubDomains}" # Persistence: in-memory by default; set DATABASE_DRIVER=mysql to run against a # managed MySQL/MariaDB database. Provide the password via the environment or a @@ -27,7 +27,7 @@ services: DATABASE_DRIVER: ${DATABASE_DRIVER:-mysql} DATABASE_HOST: ${DATABASE_HOST:-localhost} DATABASE_PORT: ${DATABASE_PORT:-3306} - DATABASE_NAME: ${DATABASE_NAME:-loud-ams} - DATABASE_USERNAME: ${DATABASE_USERNAME:-loud-ams} + DATABASE_NAME: ${DATABASE_NAME:-site} + DATABASE_USERNAME: ${DATABASE_USERNAME:-site} DATABASE_PASSWORD: ${DATABASE_PASSWORD:-} DATABASE_TLS: ${DATABASE_TLS:-require} diff --git a/Loud.xcodeproj/project.pbxproj b/Site.xcodeproj/project.pbxproj similarity index 95% rename from Loud.xcodeproj/project.pbxproj rename to Site.xcodeproj/project.pbxproj index 9b48f17..9e1191a 100644 --- a/Loud.xcodeproj/project.pbxproj +++ b/Site.xcodeproj/project.pbxproj @@ -44,7 +44,7 @@ LastUpgradeCheck = 2700; ORGANIZATIONNAME = "Röck+Cöde VoF"; }; - buildConfigurationList = 02642FD42FEEB9A5007FA466 /* Build configuration list for PBXProject "Loud" */; + buildConfigurationList = 02642FD42FEEB9A5007FA466 /* Build configuration list for PBXProject "Site" */; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -62,14 +62,14 @@ /* End PBXProject section */ /* Begin XCBuildConfiguration section */ - 02642FD52FEEB9A5007FA466 /* Debug configuration for PBXProject "Loud" */ = { + 02642FD52FEEB9A5007FA466 /* Debug configuration for PBXProject "Site" */ = { isa = XCBuildConfiguration; buildSettings = { DEVELOPMENT_TEAM = 7FMNM89WKG; }; name = Debug; }; - 02642FD62FEEB9A5007FA466 /* Release configuration for PBXProject "Loud" */ = { + 02642FD62FEEB9A5007FA466 /* Release configuration for PBXProject "Site" */ = { isa = XCBuildConfiguration; buildSettings = { DEVELOPMENT_TEAM = 7FMNM89WKG; @@ -79,11 +79,11 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 02642FD42FEEB9A5007FA466 /* Build configuration list for PBXProject "Loud" */ = { + 02642FD42FEEB9A5007FA466 /* Build configuration list for PBXProject "Site" */ = { isa = XCConfigurationList; buildConfigurations = ( - 02642FD52FEEB9A5007FA466 /* Debug configuration for PBXProject "Loud" */, - 02642FD62FEEB9A5007FA466 /* Release configuration for PBXProject "Loud" */, + 02642FD52FEEB9A5007FA466 /* Debug configuration for PBXProject "Site" */, + 02642FD62FEEB9A5007FA466 /* Release configuration for PBXProject "Site" */, ); defaultConfigurationName = Release; }; diff --git a/Loud.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Site.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Loud.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Site.xcodeproj/project.xcworkspace/contents.xcworkspacedata