diff --git a/README.md b/README.md
index 677c1b9cb..6a3eec994 100644
--- a/README.md
+++ b/README.md
@@ -3,4 +3,45 @@
Introducing the nostr-java library, a solution written in java for generating, signing, and publishing nostr events to relays.
-For detailed instructions on how to utilise the library, please refer to the [nostr-client](https://github.com/tcheeric/nostr-client/) repository.
\ No newline at end of file
+## Requirements
+- Java 19. (Java 21 is currently not supported, due to a conflict with lombok. See issue [#101](https://github.com/tcheeric/nostr-java/issues/101)
+- A Nostr relay to connect to. This is needed for the [unit tests](https://github.com/tcheeric/nostr-java/tree/main/nostr-java-test). You can either run your own relay, or use a public one. To configure your test relay, update the [relays.properties](https://github.com/tcheeric/nostr-java/blob/main/nostr-java-test/src/test/resources/relays.properties) resource file in the test module.
+
+## Building
+We use Maven to build the project. To build the project, run the following command in the root directory of the project:
+
+```bash
+mvn clean install
+```
+
+## Supported NIPs
+The following NIPs are supported by the API out-of-the-box:
+- [NIP-1](https://github.com/nostr-protocol/nips/blob/master/01.md)
+- [NIP-2](https://github.com/nostr-protocol/nips/blob/master/02.md)
+- [NIP-3](https://github.com/nostr-protocol/nips/blob/master/03.md)
+- [NIP-4](https://github.com/nostr-protocol/nips/blob/master/04.md)
+- [NIP-5](https://github.com/nostr-protocol/nips/blob/master/05.md)
+- [NIP-8](https://github.com/nostr-protocol/nips/blob/master/08.md)
+- [NIP-9](https://github.com/nostr-protocol/nips/blob/master/09.md)
+- [NIP-12](https://github.com/nostr-protocol/nips/blob/master/12.md)
+- [NIP-14](https://github.com/nostr-protocol/nips/blob/master/14.md)
+- [NIP-15](https://github.com/nostr-protocol/nips/blob/master/15.md)
+- [NIP-20](https://github.com/nostr-protocol/nips/blob/master/20.md)
+- [NIP-23](https://github.com/nostr-protocol/nips/blob/master/23.md)
+- [NIP-25](https://github.com/nostr-protocol/nips/blob/master/25.md)
+- [NIP-28](https://github.com/nostr-protocol/nips/blob/master/28.md)
+- [NIP-30](https://github.com/nostr-protocol/nips/blob/master/30.md)
+- [NIP-32](https://github.com/nostr-protocol/nips/blob/master/32.md)
+- [NIP-40](https://github.com/nostr-protocol/nips/blob/master/40.md)
+- [NIP-42](https://github.com/nostr-protocol/nips/blob/master/42.md)
+- [NIP-44](https://github.com/nostr-protocol/nips/blob/master/44.md)
+- [NIP-46](https://github.com/nostr-protocol/nips/blob/master/46.md)
+- [NIP-57](https://github.com/nostr-protocol/nips/blob/master/57.md)
+
+We also provide the classes [GenericEvent](https://github.com/tcheeric/nostr-java/blob/main/nostr-java-event/src/main/java/nostr/event/impl/GenericEvent.java) and [GenericTag](https://github.com/tcheeric/nostr-java/blob/main/nostr-java-event/src/main/java/nostr/event/impl/GenericTag.java) for creating events and tags that are currently not supported out-of-the-box.
+See working example [here](https://github.com/tcheeric/nostr-java/tree/main/nostr-java-examples)
+
+Additional reading:
+- [nostr-java-api](https://github.com/tcheeric/nostr-java/tree/main/nostr-java-api)
+- [nostr-java-id](https://github.com/tcheeric/nostr-java/tree/main/nostr-java-id)
+- [nostr-java-examples](https://github.com/tcheeric/nostr-java/tree/main/nostr-java-examples)
diff --git a/nostr-java-api/README.md b/nostr-java-api/README.md
new file mode 100644
index 000000000..c1fd552c8
--- /dev/null
+++ b/nostr-java-api/README.md
@@ -0,0 +1,7 @@
+# nostr-java-api
+
+This is a Java API for the Nostr protocol. It is a simple wrapper around the Nostr library, which allows you to interact with the Nostr for creating, signing, and publishing events to relays, using Java.
+
+## Usage
+
+For detailed instructions on how to utilise the library, please refer to the [nostr-client](https://github.com/tcheeric/nostr-client/) repository.
\ No newline at end of file
diff --git a/nostr-java-crypto/pom.xml b/nostr-java-crypto/pom.xml
index b145860c2..157eac2a5 100644
--- a/nostr-java-crypto/pom.xml
+++ b/nostr-java-crypto/pom.xml
@@ -36,10 +36,5 @@
nostr-java-util
${project.version}
-
- ${project.groupId}
- nostr-java-secp256k1
- ${project.version}
-
\ No newline at end of file
diff --git a/nostr-java-event/README.md b/nostr-java-event/README.md
deleted file mode 100644
index 9aa10920e..000000000
--- a/nostr-java-event/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# nostr-event
-
-We offer support for selected events and tags out of the box:
-
-The events:
-- Event Deletion
-- Encrypted Direct Messages
-- Ephemeral Events
-- Internet Identifier Metadata Events
-- Mentions
-- Set Metadata events
-- Ots Events
-- Reaction Events
-- Replaceable Events
-- Text Note Events
-
-The Tags:
-- Deletion Tag
-- Event Tag
-- Nonce Tag
-- Pubkey Tag
-- Subject Tag
-
-Additionally, you may use the `GenericTag` and `GenericEvent` classes to create your custom tags and events.
diff --git a/nostr-java-examples/README.md b/nostr-java-examples/README.md
new file mode 100644
index 000000000..20666a64c
--- /dev/null
+++ b/nostr-java-examples/README.md
@@ -0,0 +1,46 @@
+# nostr-java-examples
+This is a collection of examples for the Nostr Java API. It demonstrates how to use the API to create, sign, and publish events to relays.
+
+## Creating an OOTB Nostr Event
+Here is an example illustrating how to create a TextNoteEvent using the Nostr Java API, and submitting it to relays.
+1. Create a sender [identity](https://github.com/tcheeric/nostr-java/tree/main/nostr-java-id). In the example below, we generate a random identity, but you may create an identity from a private key, or use the default identity, if setup.
+2. You create a list of tags. This is an optional step. In the example below, we create a list of tags with a single PubKeyTag, which is the recipient's public key.
+3. You create a NIP01 object, and call the createTextNoteEvent method, passing the list of tags and the message, then sign and send it.
+
+```java
+private static final Identity SENDER = Identity.generateRandomIdentity();
+private final static Map RELAYS = Map.of("lol", "nos.lol", "damus", "relay.damus.io", "ZBD",
+ "nostr.zebedee.cloud", "taxi", "relay.taxi", "mom", "nostr.mom");
+
+private static TextNoteEvent sendTextNoteEvent() {
+logHeader("sendTextNoteEvent");
+
+ List tags = new ArrayList<>(List.of(new PubKeyTag(RECIPIENT.getPublicKey())));
+
+ var nip01 = new NIP01(SENDER);
+ nip01.createTextNoteEvent(tags, "Hello world, I'm here on nostr-java API!")
+ .sign()
+ .send(RELAYS);
+
+ return nip01.getEvent();
+ }
+
+```
+
+## Creating a custom Nostr Event and Tag
+We use the ```nostr.api.EventNostr.GenericEventNostr.createGenericEvent(@NonNull Integer kind, @NonNull String content)``` method to create custom events, i.e. events not supported out-of-the-box by the nostr-java library. The example below re-creates the TextNoteEvent as a custom event, and a custom tag, then sends the event to relays.
+The alt-tag is created using the TagFactory class, which is a helper class for creating custom tags. The TagFactory class has a method for creating each type of tag. In the example below, we create a custom tag with a tag name of ```alt```, a tag kind of ```31```, and a tag content of ```an alt text```. ```["alt", 31, "an alt text"]```.
+
+```java
+private static TextNoteEvent sendTextNoteEvent() {
+logHeader("sendTextNoteEvent");
+
+ var event = new GenericEventNostr(SENDER);
+ nip01.createTextNoteEvent(1, "Hello world, I'm here on nostr-java API!")
+ .addTag(new TagFactory("alt", 31, "an alt text").create())
+ .sign()
+ .send(RELAYS);
+
+ return nip01.getEvent();
+ }
+```
\ No newline at end of file
diff --git a/nostr-java-id/README.md b/nostr-java-id/README.md
new file mode 100644
index 000000000..b1d3ccdb0
--- /dev/null
+++ b/nostr-java-id/README.md
@@ -0,0 +1,10 @@
+# nostr-java-id
+Identities represent nsec, npub pairs. They are used to sign events and to verify the signature of events. The Nostr Java API provides a default identity, which is used if no identity is provided. You may also create an identity from a private key, generate a random identity, or create a custom identity.
+
+## Creating an Identity from a private key (in hex format)
+```java
+Identity.getInstance(String privateKey);
+```
+
+## Creating a random identity
+You use to create a random identity by calling the ```Identity.generateRandomIdentity()``` method.
diff --git a/nostr-java-test/README.md b/nostr-java-test/README.md
new file mode 100644
index 000000000..e69de29bb