diff --git a/README.md b/README.md
index e2f7a6a..35d48a6 100644
--- a/README.md
+++ b/README.md
@@ -1,38 +1,145 @@
-# GcIndexRelay
+
+

+
+
+# GitCitadel Mercury Index-Relay
+
+A Nostr index relay built with Phoenix 1.8 / Elixir. Stores and serves Nostr events via a REST API, with filter-based querying per NIP-01.
+
+**Supported NIPs:** [NIP-11](https://github.com/nostr-protocol/nips/blob/master/11.md) (relay info), [NIP-70](https://github.com/nostr-protocol/nips/blob/master/70.md) (protected events)
## Getting Started
+### Prerequisites
+
+- Docker (for the database)
+- Elixir ~> 1.15
+
+### Automated setup
+
+Run the setup script — it installs Erlang/Elixir via asdf, starts the Apache AGE database container, and runs `mix setup`:
+
+```bash
+chmod +x setup.sh
+./setup.sh
+```
+
+After setup, database credentials are written to `.env`. Source it before running any `mix` commands:
+
+```bash
+source .env
+```
+
+### Manual setup
+
Start the Apache AGE Docker container:
```bash
-docker build \
- -t age \
- -f ./db/Dockerfile \
- ./db
docker run \
-d \
+ --name gc_age_db \
-p 5455:5432 \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=gc_index_relay_dev \
- age
+ apache/age:release_PG17_1.6.0
```
-To start your Phoenix server:
+Set database environment variables, then install dependencies and run migrations:
-- Run `mix setup` to install and setup dependencies
-- Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server`
+```bash
+export POSTGRES_HOST=localhost
+export POSTGRES_PORT=5455
+export POSTGRES_USER=postgres
+export POSTGRES_PASSWORD=postgres
+export POSTGRES_DB=gc_index_relay_dev
-Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
+mix setup
+```
+
+### Starting the server
+
+```bash
+source .env
+mix phx.server
+```
+
+The relay is available at [http://localhost:4000](http://localhost:4000).
+
+During development, use `dev.sh` instead to get automatic server restarts when config files change:
+
+```bash
+source .env && ./dev.sh
+```
-Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html).
+## API
+
+| Method | Path | Description |
+|--------|------|-------------|
+| `GET` | `/api` | List available endpoints |
+| `GET` | `/api/events` | Query events via URL params (`since`, `until`, `limit` required) |
+| `POST` | `/api/events/filter` | Query events with a NIP-01 filter body (`limit` required) |
+| `GET` | `/api/events/:id` | Fetch a single event by ID |
+| `POST` | `/api/events` | Publish a new event |
+| `DELETE` | `/api/events/:id` | Delete an event by ID |
+| `GET` | `/api/swagger` | Swagger UI |
+| `GET` | `/health` | Health check |
+
+### NIP-11 relay info
+
+```bash
+curl -s -H "Accept: application/nostr+json" http://localhost:4000 | jq
+```
+
+Edit the relay metadata in `config/config.exs` under the `:relay_info` key.
+
+## Testing
+
+Unit tests (no database required):
+
+```bash
+mix test.unit
+```
+
+Integration tests (requires the database to be running):
+
+```bash
+source .env
+mix test.integration
+```
+
+Run the full integration probe against the relay API (covers all endpoints, CORS, NIP-11, NIP-70):
+
+```bash
+source .env
+mix test.integration test/gc_index_relay_web/relay_integration_test.exs
+```
+
+The test scenarios are documented in [test/features/relay_api.feature](test/features/relay_api.feature) and cover:
+
+- Discovery (`GET /api`)
+- Publishing and rejecting events (`POST /api/events`)
+- Deleting events (`DELETE /api/events/:id`)
+- Cacheable queries (`GET /api/events?since=&until=&limit=`)
+- Filter-based queries (`POST /api/events/filter`)
+- Single-event lookup (`GET /api/events/:id`)
+- CORS preflight and headers
+- NIP-11 relay info document including the `icon` field
+
+Pre-commit check (compile with warnings-as-errors, format, credo, integration tests):
+
+```bash
+source .env
+mix precommit
+```
## Project Overview
### Database
- The database stores Nostr events.
-- Nostr events, once signed, are considered to be immutable.
+- Nostr events, once signed, are considered immutable.
+- Uses Apache AGE (PostgreSQL with graph extensions).
#### Migrations
@@ -42,7 +149,7 @@ After modifying an Ecto schema, generate a migration with:
mix ecto.gen.migration
```
-Edit the generated migration file as needed, then perform the migration with:
+Edit the generated migration file as needed, then apply it:
```bash
mix ecto.migrate
@@ -52,8 +159,6 @@ Refer to the Fly.io guide [Safe Ecto Migrations](https://github.com/fly-apps/saf
## Learn more
-- Official website: https://www.phoenixframework.org/
-- Guides: https://hexdocs.pm/phoenix/overview.html
-- Docs: https://hexdocs.pm/phoenix
-- Forum: https://elixirforum.com/c/phoenix-forum
-- Source: https://github.com/phoenixframework/phoenix
+- Phoenix: https://www.phoenixframework.org/
+- Nostr protocol: https://github.com/nostr-protocol/nostr
+- NIP-01 (basic protocol): https://github.com/nostr-protocol/nips/blob/master/01.md
diff --git a/config/config.exs b/config/config.exs
index fe07fa4..c1a703c 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -49,6 +49,27 @@ config :logger, :default_formatter,
# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason
+# NIP-11 relay information document
+# Served at GET / with Accept: application/nostr+json
+# Edit these values to describe your relay instance.
+config :gc_index_relay, :relay_info,
+ name: "Mercury Index-Relay",
+ icon:
+ "https://git.imwald.eu/silberengel/gc_index_relay/src/branch/test/local-setup/priv/static/favicon.ico",
+ banner:
+ "https://git.imwald.eu/silberengel/gc_index_relay/src/branch/test/local-setup/priv/static/mercury_icon.png",
+ description:
+ "A Nostr index relay for the http protocol, from GitCitadel. Featuring a RESTful API and Swagger, it specializes in swift retrieval or publications, repos, and similar graphs of related events",
+ software: "https://git.imwald.eu/silberengel/gc_index_relay.git",
+ version: "0.2",
+ supported_nips: [11, 70],
+ limitation: %{
+ max_limit: 100,
+ auth_required: false,
+ payment_required: false,
+ restricted_writes: false
+ }
+
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs"
diff --git a/dev.sh b/dev.sh
new file mode 100755
index 0000000..1b2ae40
--- /dev/null
+++ b/dev.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+# Development server with auto-restart on config file changes.
+#
+# Normal code changes (controllers, templates, etc.) are still hot-reloaded
+# by Phoenix automatically. This script only handles the cases Phoenix can't:
+# config/config.exs, config/dev.exs, and config/runtime.exs.
+#
+# Usage:
+# chmod +x dev.sh
+# source .env && ./dev.sh
+
+set -euo pipefail
+
+CONFIG_FILES=(
+ config/config.exs
+ config/dev.exs
+ config/runtime.exs
+)
+
+cleanup() {
+ if [ -n "${SERVER_PID:-}" ] && kill -0 "$SERVER_PID" 2>/dev/null; then
+ echo ""
+ echo "[dev] Stopping server (pid $SERVER_PID)..."
+ kill "$SERVER_PID"
+ wait "$SERVER_PID" 2>/dev/null || true
+ fi
+ exit 0
+}
+
+trap cleanup INT TERM
+
+echo "[dev] Watching config files for changes: ${CONFIG_FILES[*]}"
+echo "[dev] Normal code changes are still hot-reloaded automatically."
+echo "[dev] Press Ctrl+C to stop."
+echo ""
+
+while true; do
+ echo "[dev] Starting server..."
+ mix phx.server &
+ SERVER_PID=$!
+
+ # Block until any config file is modified
+ inotifywait -q -e modify "${CONFIG_FILES[@]}" 2>/dev/null
+
+ echo ""
+ echo "[dev] Config changed — restarting server..."
+ kill "$SERVER_PID" 2>/dev/null
+ wait "$SERVER_PID" 2>/dev/null || true
+ echo ""
+done
diff --git a/lib/gc_index_relay_web/components/layouts/root.html.heex b/lib/gc_index_relay_web/components/layouts/root.html.heex
index ff2d7f8..012d6cf 100644
--- a/lib/gc_index_relay_web/components/layouts/root.html.heex
+++ b/lib/gc_index_relay_web/components/layouts/root.html.heex
@@ -7,6 +7,9 @@
<.live_title default="GcIndexRelay" suffix=" · Phoenix Framework">
{assigns[:page_title]}
+
+
+