diff --git a/briar-api/src/org/briarproject/api/blogs/Blog.java b/briar-api/src/org/briarproject/api/blogs/Blog.java
index c97e42be2aae72185845fa2b5ea05ee257ebd17c..4e6827891a67ebde4d63d842fa7e0e5bce2c1269 100644
--- a/briar-api/src/org/briarproject/api/blogs/Blog.java
+++ b/briar-api/src/org/briarproject/api/blogs/Blog.java
@@ -11,13 +11,16 @@ public class Blog extends Forum {
 	private final String description;
 	@NotNull
 	private final Author author;
+	private final boolean permanent;
 
 	public Blog(@NotNull Group group, @NotNull String name,
-			@NotNull String description, @NotNull Author author) {
+			@NotNull String description, @NotNull Author author,
+			boolean permanent) {
 		super(group, name, null);
 
 		this.description = description;
 		this.author = author;
+		this.permanent = permanent;
 	}
 
 	@NotNull
@@ -29,4 +32,8 @@ public class Blog extends Forum {
 	public Author getAuthor() {
 		return author;
 	}
+
+	public boolean isPermanent() {
+		return permanent;
+	}
 }
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogConstants.java b/briar-api/src/org/briarproject/api/blogs/BlogConstants.java
index 738e012a3ef2872f1c341aacc7e5a6a68d5a7da5..7bbaacdb8b2c33bd74c86ee1e5ce0a103479514c 100644
--- a/briar-api/src/org/briarproject/api/blogs/BlogConstants.java
+++ b/briar-api/src/org/briarproject/api/blogs/BlogConstants.java
@@ -16,12 +16,12 @@ public interface BlogConstants {
 	/** The length of a blog post's title in UTF-8 bytes. */
 	int MAX_BLOG_POST_TITLE_LENGTH = 100;
 
-	/** The length of a blog post's teaser in UTF-8 bytes. */
-	int MAX_BLOG_POST_TEASER_LENGTH = 240;
-
 	/** The maximum length of a blog post's body in bytes. */
 	int MAX_BLOG_POST_BODY_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024;
 
+	/** The internal name of personal blogs that are created automatically */
+	String PERSONAL_BLOG_NAME = "briar.PERSONAL_BLOG_NAME";
+
 	/* Blog Sharing Constants */
 	String BLOG_TITLE = "blogTitle";
 	String BLOG_DESC = "blogDescription";
@@ -31,9 +31,8 @@ public interface BlogConstants {
 	// Metadata keys
 	String KEY_DESCRIPTION = "description";
 	String KEY_TITLE = "title";
-	String KEY_TEASER = "teaser";
-	String KEY_HAS_BODY = "hasBody";
 	String KEY_TIMESTAMP = "timestamp";
+	String KEY_TIME_RECEIVED = "timeReceived";
 	String KEY_PARENT = "parent";
 	String KEY_AUTHOR_ID = "id";
 	String KEY_AUTHOR_NAME = "name";
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogFactory.java b/briar-api/src/org/briarproject/api/blogs/BlogFactory.java
index 8da9db1926f11d4dc31ed633fb61d794aa1444fb..190236bae1f5ae92efc79f535fa1c36e4a02c0e3 100644
--- a/briar-api/src/org/briarproject/api/blogs/BlogFactory.java
+++ b/briar-api/src/org/briarproject/api/blogs/BlogFactory.java
@@ -1,6 +1,7 @@
 package org.briarproject.api.blogs;
 
 import org.briarproject.api.FormatException;
+import org.briarproject.api.contact.Contact;
 import org.briarproject.api.identity.Author;
 import org.briarproject.api.sync.Group;
 import org.jetbrains.annotations.NotNull;
@@ -11,6 +12,9 @@ public interface BlogFactory {
 	Blog createBlog(@NotNull String name, @NotNull String description,
 			@NotNull Author author);
 
+	/** Creates a personal blog for a given author. */
+	Blog createPersonalBlog(@NotNull Author author);
+
 	/** Parses a blog with the given Group and description */
 	Blog parseBlog(@NotNull Group g, @NotNull String description)
 			throws FormatException;
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogManager.java b/briar-api/src/org/briarproject/api/blogs/BlogManager.java
index e01fa5efb9a8bc30cf6dbd4dd3f97d063dae713c..7d6188feda24f7c3fdaf06b28460c0878c467676 100644
--- a/briar-api/src/org/briarproject/api/blogs/BlogManager.java
+++ b/briar-api/src/org/briarproject/api/blogs/BlogManager.java
@@ -1,8 +1,8 @@
 package org.briarproject.api.blogs;
 
-import org.briarproject.api.FormatException;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.Transaction;
+import org.briarproject.api.identity.Author;
 import org.briarproject.api.identity.LocalAuthor;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.GroupId;
@@ -20,6 +20,9 @@ public interface BlogManager {
 	Blog addBlog(LocalAuthor localAuthor, String name, String description)
 			throws DbException;
 
+	/** Removes and deletes a blog. */
+	void removeBlog(Blog b) throws DbException;
+
 	/** Stores a local blog post. */
 	void addLocalPost(BlogPost p) throws DbException;
 
@@ -29,9 +32,12 @@ public interface BlogManager {
 	/** Returns the blog with the given ID. */
 	Blog getBlog(Transaction txn, GroupId g) throws DbException;
 
-	/** Returns all blogs to which the localAuthor created. */
+	/** Returns all blogs owned by the given localAuthor. */
 	Collection<Blog> getBlogs(LocalAuthor localAuthor) throws DbException;
 
+	/** Returns only the personal blog of the given author. */
+	Blog getPersonalBlog(Author author) throws DbException;
+
 	/** Returns all blogs to which the user subscribes. */
 	Collection<Blog> getBlogs() throws DbException;
 
@@ -45,4 +51,11 @@ public interface BlogManager {
 	/** Marks a blog post as read or unread. */
 	void setReadFlag(MessageId m, boolean read) throws DbException;
 
+	/** Registers a hook to be called whenever a blog is removed. */
+	void registerRemoveBlogHook(RemoveBlogHook hook);
+
+	interface RemoveBlogHook {
+		void removingBlog(Transaction txn, Blog b) throws DbException;
+	}
+
 }
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogPost.java b/briar-api/src/org/briarproject/api/blogs/BlogPost.java
index a6aa1167aebc9c24ac00bfc81fa1f5ffc157a064..3854c047279b90f2718a39644cee381893ad9a5b 100644
--- a/briar-api/src/org/briarproject/api/blogs/BlogPost.java
+++ b/briar-api/src/org/briarproject/api/blogs/BlogPost.java
@@ -1,43 +1,27 @@
 package org.briarproject.api.blogs;
 
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
 import org.briarproject.api.forum.ForumPost;
 import org.briarproject.api.identity.Author;
 import org.briarproject.api.sync.Message;
 import org.briarproject.api.sync.MessageId;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public class BlogPost extends ForumPost {
 
 	@Nullable
 	private final String title;
-	@NotNull
-	private final String teaser;
-	private final boolean hasBody;
 
-	public BlogPost(@Nullable String title, @NotNull String teaser,
-			boolean hasBody, @NotNull Message message,
-			@Nullable MessageId parent, @NotNull Author author,
+	public BlogPost(@Nullable String title,	@NotNull Message message,
+			@Nullable MessageId parent,	@NotNull Author author,
 			@NotNull String contentType) {
 		super(message, parent, author, contentType);
 
 		this.title = title;
-		this.teaser = teaser;
-		this.hasBody = hasBody;
 	}
 
 	@Nullable
 	public String getTitle() {
 		return title;
 	}
-
-	@NotNull
-	public String getTeaser() {
-		return teaser;
-	}
-
-	public boolean hasBody() {
-		return hasBody;
-	}
 }
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java b/briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java
index 2565bfb0e731dc532e8cdc0a691538f8c8166d3a..6ced9ba20fe646822eced9d1269648f0740e51f2 100644
--- a/briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java
+++ b/briar-api/src/org/briarproject/api/blogs/BlogPostFactory.java
@@ -12,8 +12,8 @@ import java.security.GeneralSecurityException;
 public interface BlogPostFactory {
 
 	BlogPost createBlogPost(@NotNull GroupId groupId, @Nullable String title,
-			@NotNull String teaser, long timestamp, @Nullable MessageId parent,
+			long timestamp, @Nullable MessageId parent,
 			@NotNull LocalAuthor author, @NotNull String contentType,
-			@Nullable byte[] body)
+			@NotNull byte[] body)
 			throws FormatException, GeneralSecurityException;
 }
diff --git a/briar-api/src/org/briarproject/api/blogs/BlogPostHeader.java b/briar-api/src/org/briarproject/api/blogs/BlogPostHeader.java
index 24d421c13959ddb173c91130f70f42bad408bc07..980ea27eb4005139004322a3a290dd0f888171dd 100644
--- a/briar-api/src/org/briarproject/api/blogs/BlogPostHeader.java
+++ b/briar-api/src/org/briarproject/api/blogs/BlogPostHeader.java
@@ -11,20 +11,16 @@ public class BlogPostHeader extends PostHeader {
 
 	@Nullable
 	private final String title;
-	@NotNull
-	private final String teaser;
-	private final boolean hasBody;
+	private final long timeReceived;
 
-	public BlogPostHeader(@Nullable String title, @NotNull String teaser,
-			boolean hasBody, @NotNull MessageId id,
-			@Nullable MessageId parentId, long timestamp,
+	public BlogPostHeader(@Nullable String title, @NotNull MessageId id,
+			@Nullable MessageId parentId, long timestamp, long timeReceived,
 			@NotNull Author author,	@NotNull Status authorStatus,
 			@NotNull String contentType, boolean read) {
 		super(id, parentId, timestamp, author, authorStatus, contentType, read);
 
 		this.title = title;
-		this.teaser = teaser;
-		this.hasBody = hasBody;
+		this.timeReceived = timeReceived;
 	}
 
 	@Nullable
@@ -32,12 +28,8 @@ public class BlogPostHeader extends PostHeader {
 		return title;
 	}
 
-	@NotNull
-	public String getTeaser() {
-		return teaser;
+	public long getTimeReceived() {
+		return timeReceived;
 	}
 
-	public boolean hasBody() {
-		return hasBody;
-	}
 }
diff --git a/briar-api/src/org/briarproject/api/event/BlogPostAddedEvent.java b/briar-api/src/org/briarproject/api/event/BlogPostAddedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..c00e4efbff7e80d117cbcb2787a366a0a5988f50
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/event/BlogPostAddedEvent.java
@@ -0,0 +1,32 @@
+package org.briarproject.api.event;
+
+import org.briarproject.api.blogs.BlogPostHeader;
+import org.briarproject.api.sync.GroupId;
+
+/** An event that is broadcast when a blog post was added to the database. */
+public class BlogPostAddedEvent extends Event {
+
+	private final GroupId groupId;
+	private final BlogPostHeader header;
+	private final boolean local;
+
+	public BlogPostAddedEvent(GroupId groupId, BlogPostHeader header,
+			boolean local) {
+
+		this.groupId = groupId;
+		this.header = header;
+		this.local = local;
+	}
+
+	public GroupId getGroupId() {
+		return groupId;
+	}
+
+	public BlogPostHeader getHeader() {
+		return header;
+	}
+
+	public boolean isLocal() {
+		return local;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/identity/IdentityManager.java b/briar-api/src/org/briarproject/api/identity/IdentityManager.java
index e5420a043f267c9a643fd24987369552839e560e..e89f49d8ac0ea279093234cdcfeba0e4a3113fc4 100644
--- a/briar-api/src/org/briarproject/api/identity/IdentityManager.java
+++ b/briar-api/src/org/briarproject/api/identity/IdentityManager.java
@@ -29,6 +29,9 @@ public interface IdentityManager {
 	/** Returns the trust-level status of the author */
 	Status getAuthorStatus(AuthorId a) throws DbException;
 
+	/** Returns the trust-level status of the author */
+	Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;
+
 	interface AddIdentityHook {
 		void addingIdentity(Transaction txn, LocalAuthor a) throws DbException;
 	}
diff --git a/briar-core/src/org/briarproject/blogs/BlogFactoryImpl.java b/briar-core/src/org/briarproject/blogs/BlogFactoryImpl.java
index b04401f5d1297854af0e45c6694afa5f26edc796..9a3e0583aa1f04952920139ea626f43d44e72de3 100644
--- a/briar-core/src/org/briarproject/blogs/BlogFactoryImpl.java
+++ b/briar-core/src/org/briarproject/blogs/BlogFactoryImpl.java
@@ -4,6 +4,7 @@ import org.briarproject.api.FormatException;
 import org.briarproject.api.blogs.Blog;
 import org.briarproject.api.blogs.BlogFactory;
 import org.briarproject.api.clients.ClientHelper;
+import org.briarproject.api.contact.Contact;
 import org.briarproject.api.data.BdfList;
 import org.briarproject.api.identity.Author;
 import org.briarproject.api.identity.AuthorFactory;
@@ -13,6 +14,8 @@ import org.jetbrains.annotations.NotNull;
 
 import javax.inject.Inject;
 
+import static org.briarproject.api.blogs.BlogConstants.PERSONAL_BLOG_NAME;
+
 class BlogFactoryImpl implements BlogFactory {
 
 	private final GroupFactory groupFactory;
@@ -31,6 +34,16 @@ class BlogFactoryImpl implements BlogFactory {
 	@Override
 	public Blog createBlog(@NotNull String name, @NotNull String description,
 			@NotNull Author author) {
+		return createBlog(name, description, author, false);
+	}
+
+	@Override
+	public Blog createPersonalBlog(@NotNull Author a) {
+		return createBlog(PERSONAL_BLOG_NAME, "", a, true);
+	}
+
+	private Blog createBlog(@NotNull String name, @NotNull String description,
+			@NotNull Author author, boolean permanent) {
 		try {
 			BdfList blog = BdfList.of(
 					name,
@@ -40,7 +53,7 @@ class BlogFactoryImpl implements BlogFactory {
 			byte[] descriptor = clientHelper.toByteArray(blog);
 			Group g = groupFactory
 					.createGroup(BlogManagerImpl.CLIENT_ID, descriptor);
-			return new Blog(g, name, description, author);
+			return new Blog(g, name, description, author, permanent);
 		} catch (FormatException e) {
 			throw new RuntimeException(e);
 		}
@@ -55,7 +68,9 @@ class BlogFactoryImpl implements BlogFactory {
 		BdfList blog = clientHelper.toList(descriptor, 0, descriptor.length);
 		Author a =
 				authorFactory.createAuthor(blog.getString(1), blog.getRaw(2));
-		return new Blog(g, blog.getString(0), description, a);
+		// TODO change permanent depending on how this will be used
+		boolean permanent = false;
+		return new Blog(g, blog.getString(0), description, a, permanent);
 	}
 
 }
diff --git a/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java b/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java
index eabfc251e3c7284557952ca8766196646cb063a9..182ea11869bb779e697910b5c9c73f5230ad75e9 100644
--- a/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java
+++ b/briar-core/src/org/briarproject/blogs/BlogManagerImpl.java
@@ -6,22 +6,31 @@ import org.briarproject.api.blogs.BlogFactory;
 import org.briarproject.api.blogs.BlogManager;
 import org.briarproject.api.blogs.BlogPost;
 import org.briarproject.api.blogs.BlogPostHeader;
+import org.briarproject.api.clients.Client;
 import org.briarproject.api.clients.ClientHelper;
+import org.briarproject.api.contact.Contact;
+import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.data.BdfDictionary;
 import org.briarproject.api.data.BdfEntry;
 import org.briarproject.api.data.BdfList;
+import org.briarproject.api.data.MetadataParser;
 import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.Transaction;
+import org.briarproject.api.event.BlogPostAddedEvent;
 import org.briarproject.api.identity.Author;
 import org.briarproject.api.identity.Author.Status;
 import org.briarproject.api.identity.AuthorId;
 import org.briarproject.api.identity.IdentityManager;
+import org.briarproject.api.identity.IdentityManager.AddIdentityHook;
+import org.briarproject.api.identity.IdentityManager.RemoveIdentityHook;
 import org.briarproject.api.identity.LocalAuthor;
 import org.briarproject.api.sync.ClientId;
 import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupId;
+import org.briarproject.api.sync.Message;
 import org.briarproject.api.sync.MessageId;
+import org.briarproject.clients.BdfIncomingMessageHook;
 import org.briarproject.util.StringUtils;
 import org.jetbrains.annotations.Nullable;
 
@@ -31,24 +40,29 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
 
+import static java.util.logging.Level.WARNING;
 import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR;
 import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_ID;
 import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_NAME;
 import static org.briarproject.api.blogs.BlogConstants.KEY_CONTENT_TYPE;
 import static org.briarproject.api.blogs.BlogConstants.KEY_DESCRIPTION;
-import static org.briarproject.api.blogs.BlogConstants.KEY_HAS_BODY;
 import static org.briarproject.api.blogs.BlogConstants.KEY_PARENT;
 import static org.briarproject.api.blogs.BlogConstants.KEY_PUBLIC_KEY;
 import static org.briarproject.api.blogs.BlogConstants.KEY_READ;
-import static org.briarproject.api.blogs.BlogConstants.KEY_TEASER;
 import static org.briarproject.api.blogs.BlogConstants.KEY_TIMESTAMP;
+import static org.briarproject.api.blogs.BlogConstants.KEY_TIME_RECEIVED;
 import static org.briarproject.api.blogs.BlogConstants.KEY_TITLE;
+import static org.briarproject.api.contact.ContactManager.AddContactHook;
+import static org.briarproject.api.contact.ContactManager.RemoveContactHook;
 
-class BlogManagerImpl implements BlogManager {
+class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
+		AddContactHook, RemoveContactHook, Client,
+		AddIdentityHook, RemoveIdentityHook {
 
 	private static final Logger LOG =
 			Logger.getLogger(BlogManagerImpl.class.getName());
@@ -59,17 +73,19 @@ class BlogManagerImpl implements BlogManager {
 
 	private final DatabaseComponent db;
 	private final IdentityManager identityManager;
-	private final ClientHelper clientHelper;
 	private final BlogFactory blogFactory;
+	private final List<RemoveBlogHook> removeHooks;
 
 	@Inject
 	BlogManagerImpl(DatabaseComponent db, IdentityManager identityManager,
-			ClientHelper clientHelper, BlogFactory blogFactory) {
+			ClientHelper clientHelper, MetadataParser metadataParser,
+			BlogFactory blogFactory) {
+		super(clientHelper, metadataParser);
 
 		this.db = db;
 		this.identityManager = identityManager;
-		this.clientHelper = clientHelper;
 		this.blogFactory = blogFactory;
+		removeHooks = new CopyOnWriteArrayList<RemoveBlogHook>();
 	}
 
 	@Override
@@ -77,6 +93,79 @@ class BlogManagerImpl implements BlogManager {
 		return CLIENT_ID;
 	}
 
+	@Override
+	public void createLocalState(Transaction txn) throws DbException {
+		// Ensure every identity does have its own personal blog
+		// TODO this can probably be removed once #446 is resolved and all users migrated to a new version
+		for (LocalAuthor a : db.getLocalAuthors(txn)) {
+			Blog b = blogFactory.createPersonalBlog(a);
+			Group g = b.getGroup();
+			if (!db.containsGroup(txn, g.getId())) {
+				db.addGroup(txn, g);
+				for (ContactId c : db.getContacts(txn, a.getId())) {
+					db.setVisibleToContact(txn, c, g.getId(), true);
+				}
+			}
+		}
+		// Ensure that we have the personal blogs of all pre-existing contacts
+		for (Contact c : db.getContacts(txn)) addingContact(txn, c);
+	}
+
+	@Override
+	public void addingContact(Transaction txn, Contact c) throws DbException {
+		// get personal blog of the contact
+		Blog b = blogFactory.createPersonalBlog(c.getAuthor());
+		Group g = b.getGroup();
+		if (!db.containsGroup(txn, g.getId())) {
+			// add the personal blog of the contact
+			db.addGroup(txn, g);
+			db.setVisibleToContact(txn, c.getId(), g.getId(), true);
+
+			// share our personal blog with the new contact
+			LocalAuthor a = db.getLocalAuthor(txn, c.getLocalAuthorId());
+			Blog b2 = blogFactory.createPersonalBlog(a);
+			db.setVisibleToContact(txn, c.getId(), b2.getId(), true);
+		}
+	}
+
+	@Override
+	public void removingContact(Transaction txn, Contact c) throws DbException {
+		if (c != null) {
+			Blog b = blogFactory.createPersonalBlog(c.getAuthor());
+			db.removeGroup(txn, b.getGroup());
+		}
+	}
+
+	@Override
+	public void addingIdentity(Transaction txn, LocalAuthor a)
+			throws DbException {
+
+		// add a personal blog for the new identity
+		LOG.info("New Personal Blog Added.");
+		Blog b = blogFactory.createPersonalBlog(a);
+		db.addGroup(txn, b.getGroup());
+	}
+
+	@Override
+	public void removingIdentity(Transaction txn, LocalAuthor a)
+			throws DbException {
+
+		// remove the personal blog of that identity
+		Blog b = blogFactory.createPersonalBlog(a);
+		db.removeGroup(txn, b.getGroup());
+	}
+
+	@Override
+	protected void incomingMessage(Transaction txn, Message m, BdfList list,
+			BdfDictionary meta) throws DbException, FormatException {
+
+		GroupId groupId = m.getGroupId();
+		BlogPostHeader h = getPostHeaderFromMetadata(txn, m.getId(), meta);
+		BlogPostAddedEvent event =
+				new BlogPostAddedEvent(groupId, h, false);
+		txn.attach(event);
+	}
+
 	@Override
 	public Blog addBlog(LocalAuthor localAuthor, String name,
 			String description) throws DbException {
@@ -100,14 +189,26 @@ class BlogManagerImpl implements BlogManager {
 		return b;
 	}
 
+	@Override
+	public void removeBlog(Blog b) throws DbException {
+		Transaction txn = db.startTransaction(false);
+		try {
+			for (RemoveBlogHook hook : removeHooks)
+				hook.removingBlog(txn, b);
+			db.removeGroup(txn, b.getGroup());
+			txn.setComplete();
+		} finally {
+			db.endTransaction(txn);
+		}
+	}
+
 	@Override
 	public void addLocalPost(BlogPost p) throws DbException {
+		BdfDictionary meta;
 		try {
-			BdfDictionary meta = new BdfDictionary();
+			meta = new BdfDictionary();
 			if (p.getTitle() != null) meta.put(KEY_TITLE, p.getTitle());
-			meta.put(KEY_TEASER, p.getTeaser());
 			meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp());
-			meta.put(KEY_HAS_BODY, p.hasBody());
 			if (p.getParent() != null) meta.put(KEY_PARENT, p.getParent());
 
 			Author a = p.getAuthor();
@@ -123,6 +224,22 @@ class BlogManagerImpl implements BlogManager {
 		} catch (FormatException e) {
 			throw new RuntimeException(e);
 		}
+
+		// broadcast event about new post
+		Transaction txn = db.startTransaction(true);
+		try {
+			GroupId groupId = p.getMessage().getGroupId();
+			MessageId postId = p.getMessage().getId();
+			BlogPostHeader h = getPostHeaderFromMetadata(txn, postId, meta);
+			BlogPostAddedEvent event =
+					new BlogPostAddedEvent(groupId, h, true);
+			txn.attach(event);
+			txn.setComplete();
+		} catch (FormatException e) {
+			if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
+		} finally {
+			db.endTransaction(txn);
+		}
 	}
 
 	@Override
@@ -163,6 +280,11 @@ class BlogManagerImpl implements BlogManager {
 		return Collections.unmodifiableList(blogs);
 	}
 
+	@Override
+	public Blog getPersonalBlog(Author author) throws DbException {
+		return blogFactory.createPersonalBlog(author);
+	}
+
 	@Override
 	public Collection<Blog> getBlogs() throws DbException {
 		try {
@@ -189,16 +311,20 @@ class BlogManagerImpl implements BlogManager {
 	@Nullable
 	public byte[] getPostBody(MessageId m) throws DbException {
 		try {
-			// content, signature
-			// content: parent, contentType, title, teaser, body, attachments
 			BdfList message = clientHelper.getMessageAsList(m);
-			BdfList content = message.getList(0);
-			return content.getRaw(4);
+			return getPostBody(message);
 		} catch (FormatException e) {
 			throw new DbException(e);
 		}
 	}
 
+	private byte[] getPostBody(BdfList message) throws FormatException {
+		// content, signature
+		// content: parent, contentType, title, body, attachments
+		BdfList content = message.getList(0);
+		return content.getRaw(3);
+	}
+
 	@Override
 	public Collection<BlogPostHeader> getPostHeaders(GroupId g)
 			throws DbException {
@@ -213,26 +339,9 @@ class BlogManagerImpl implements BlogManager {
 		for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
 			try {
 				BdfDictionary meta = entry.getValue();
-				String title = meta.getOptionalString(KEY_TITLE);
-				String teaser = meta.getString(KEY_TEASER);
-				boolean hasBody = meta.getBoolean(KEY_HAS_BODY);
-				long timestamp = meta.getLong(KEY_TIMESTAMP);
-				MessageId parentId = null;
-				if (meta.containsKey(KEY_PARENT))
-					parentId = new MessageId(meta.getRaw(KEY_PARENT));
-
-				BdfDictionary d = meta.getDictionary(KEY_AUTHOR);
-				AuthorId authorId = new AuthorId(d.getRaw(KEY_AUTHOR_ID));
-				String name = d.getString(KEY_AUTHOR_NAME);
-				byte[] publicKey = d.getRaw(KEY_PUBLIC_KEY);
-				Author author = new Author(authorId, name, publicKey);
-				Status authorStatus = identityManager.getAuthorStatus(authorId);
-
-				String contentType = meta.getString(KEY_CONTENT_TYPE);
-				boolean read = meta.getBoolean(KEY_READ);
-				headers.add(new BlogPostHeader(title, teaser, hasBody,
-						entry.getKey(), parentId, timestamp, author,
-						authorStatus, contentType, read));
+				BlogPostHeader h =
+						getPostHeaderFromMetadata(null, entry.getKey(), meta);
+				headers.add(h);
 			} catch (FormatException e) {
 				throw new DbException(e);
 			}
@@ -251,10 +360,43 @@ class BlogManagerImpl implements BlogManager {
 		}
 	}
 
+	@Override
+	public void registerRemoveBlogHook(RemoveBlogHook hook) {
+		removeHooks.add(hook);
+	}
+
 	private String getBlogDescription(Transaction txn, GroupId g)
 			throws DbException, FormatException {
 		BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g);
-		return d.getString(KEY_DESCRIPTION);
+		return d.getString(KEY_DESCRIPTION, "");
 	}
 
+	private BlogPostHeader getPostHeaderFromMetadata(@Nullable Transaction txn,
+			MessageId id, BdfDictionary meta)
+			throws DbException, FormatException {
+
+		String title = meta.getOptionalString(KEY_TITLE);
+		long timestamp = meta.getLong(KEY_TIMESTAMP);
+		long timeReceived = meta.getLong(KEY_TIME_RECEIVED, timestamp);
+		MessageId parentId = null;
+		if (meta.containsKey(KEY_PARENT))
+			parentId = new MessageId(meta.getRaw(KEY_PARENT));
+
+		BdfDictionary d = meta.getDictionary(KEY_AUTHOR);
+		AuthorId authorId = new AuthorId(d.getRaw(KEY_AUTHOR_ID));
+		String name = d.getString(KEY_AUTHOR_NAME);
+		byte[] publicKey = d.getRaw(KEY_PUBLIC_KEY);
+		Author author = new Author(authorId, name, publicKey);
+		Status authorStatus;
+		if (txn == null)
+			authorStatus = identityManager.getAuthorStatus(authorId);
+		else {
+			authorStatus = identityManager.getAuthorStatus(txn, authorId);
+		}
+
+		String contentType = meta.getString(KEY_CONTENT_TYPE);
+		boolean read = meta.getBoolean(KEY_READ);
+		return new BlogPostHeader(title, id, parentId, timestamp, timeReceived,
+				author, authorStatus, contentType, read);
+	}
 }
diff --git a/briar-core/src/org/briarproject/blogs/BlogPostFactoryImpl.java b/briar-core/src/org/briarproject/blogs/BlogPostFactoryImpl.java
index e9ced2d3fe86ec555eb19e580e4c8ec5a83cdbcc..ce134d33c6214368f592037a545a605266f1ec88 100644
--- a/briar-core/src/org/briarproject/blogs/BlogPostFactoryImpl.java
+++ b/briar-core/src/org/briarproject/blogs/BlogPostFactoryImpl.java
@@ -22,7 +22,6 @@ import java.security.GeneralSecurityException;
 import javax.inject.Inject;
 
 import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
-import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_TEASER_LENGTH;
 import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_TITLE_LENGTH;
 import static org.briarproject.api.blogs.BlogConstants.MAX_CONTENT_TYPE_LENGTH;
 
@@ -39,25 +38,22 @@ class BlogPostFactoryImpl implements BlogPostFactory {
 
 	@Override
 	public BlogPost createBlogPost(@NotNull GroupId groupId,
-			@Nullable String title, @NotNull String teaser,	long timestamp,
+			@Nullable String title, long timestamp,
 			@Nullable MessageId parent,	@NotNull LocalAuthor author,
-			@NotNull String contentType, @Nullable byte[] body)
+			@NotNull String contentType, @NotNull byte[] body)
 			throws FormatException, GeneralSecurityException {
 
 		// Validate the arguments
 		if (title != null &&
 				StringUtils.toUtf8(title).length > MAX_BLOG_POST_TITLE_LENGTH)
 			throw new IllegalArgumentException();
-		if (StringUtils.toUtf8(teaser).length > MAX_BLOG_POST_TEASER_LENGTH)
-			throw new IllegalArgumentException();
 		if (StringUtils.toUtf8(contentType).length > MAX_CONTENT_TYPE_LENGTH)
 			throw new IllegalArgumentException();
-		if (body != null && body.length > MAX_BLOG_POST_BODY_LENGTH)
+		if (body.length > MAX_BLOG_POST_BODY_LENGTH)
 			throw new IllegalArgumentException();
 
 		// Serialise the data to be signed
-		BdfList content =
-				BdfList.of(parent, contentType, title, teaser, body, null);
+		BdfList content = BdfList.of(parent, contentType, title, body, null);
 		BdfList signed = BdfList.of(groupId, timestamp, content);
 
 		// Generate the signature
@@ -72,7 +68,6 @@ class BlogPostFactoryImpl implements BlogPostFactory {
 		// Serialise the signed message
 		BdfList message = BdfList.of(content, sig);
 		Message m = clientHelper.createMessage(groupId, timestamp, message);
-		return new BlogPost(title, teaser, body != null, m, parent, author,
-				contentType);
+		return new BlogPost(title, m, parent, author, contentType);
 	}
 }
diff --git a/briar-core/src/org/briarproject/blogs/BlogPostValidator.java b/briar-core/src/org/briarproject/blogs/BlogPostValidator.java
index bacf02dff64d45e59ca80113158cba6e2778c206..d412f10aea4ebd7f5bf4948f213b59abce090cea 100644
--- a/briar-core/src/org/briarproject/blogs/BlogPostValidator.java
+++ b/briar-core/src/org/briarproject/blogs/BlogPostValidator.java
@@ -11,6 +11,7 @@ import org.briarproject.api.crypto.KeyParser;
 import org.briarproject.api.crypto.PublicKey;
 import org.briarproject.api.crypto.Signature;
 import org.briarproject.api.data.BdfDictionary;
+import org.briarproject.api.data.BdfEntry;
 import org.briarproject.api.data.BdfList;
 import org.briarproject.api.data.MetadataEncoder;
 import org.briarproject.api.identity.Author;
@@ -25,15 +26,17 @@ import java.security.GeneralSecurityException;
 import java.util.Collection;
 import java.util.Collections;
 
+import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR;
+import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_ID;
+import static org.briarproject.api.blogs.BlogConstants.KEY_AUTHOR_NAME;
 import static org.briarproject.api.blogs.BlogConstants.KEY_CONTENT_TYPE;
-import static org.briarproject.api.blogs.BlogConstants.KEY_HAS_BODY;
 import static org.briarproject.api.blogs.BlogConstants.KEY_PARENT;
+import static org.briarproject.api.blogs.BlogConstants.KEY_PUBLIC_KEY;
 import static org.briarproject.api.blogs.BlogConstants.KEY_READ;
-import static org.briarproject.api.blogs.BlogConstants.KEY_TEASER;
 import static org.briarproject.api.blogs.BlogConstants.KEY_TIMESTAMP;
+import static org.briarproject.api.blogs.BlogConstants.KEY_TIME_RECEIVED;
 import static org.briarproject.api.blogs.BlogConstants.KEY_TITLE;
 import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
-import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_TEASER_LENGTH;
 import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_TITLE_LENGTH;
 import static org.briarproject.api.blogs.BlogConstants.MAX_CONTENT_TYPE_LENGTH;
 import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
@@ -60,37 +63,36 @@ class BlogPostValidator extends BdfMessageValidator {
 		checkSize(body, 2);
 		BdfList content = body.getList(0);
 
-		// Content: Parent ID, content type, title (optional), teaser,
-		//          post body (optional), attachments (optional)
-		checkSize(body, 6);
+		// Content: Parent ID, content type, title (optional), post body,
+		//          attachments (optional)
+		checkSize(content, 5);
 		// Parent ID is optional
 		byte[] parent = content.getOptionalRaw(0);
 		checkLength(parent, UniqueId.LENGTH);
 		// Content type
 		String contentType = content.getString(1);
 		checkLength(contentType, 0, MAX_CONTENT_TYPE_LENGTH);
+		if (!contentType.equals("text/plain"))
+			throw new InvalidMessageException("Invalid content type");
 		// Blog post title is optional
 		String title = content.getOptionalString(2);
 		checkLength(contentType, 0, MAX_BLOG_POST_TITLE_LENGTH);
-		// Blog teaser
-		String teaser = content.getString(3);
-		// TODO make sure that there is only text in the teaser
-		checkLength(contentType, 0, MAX_BLOG_POST_TEASER_LENGTH);
-		// Blog post body is optional
-		byte[] postBody = content.getOptionalRaw(4);
+		// Blog post body
+		byte[] postBody = content.getRaw(3);
 		checkLength(postBody, 0, MAX_BLOG_POST_BODY_LENGTH);
 		// Attachments
-		BdfDictionary attachments = content.getOptionalDictionary(5);
+		BdfDictionary attachments = content.getOptionalDictionary(4);
 		// TODO handle attachments somehow
 
 		// Signature
 		byte[] sig = body.getRaw(1);
 		checkLength(sig, 0, MAX_SIGNATURE_LENGTH);
 		// Verify the signature
+		Author a;
 		try {
 			// Get the blog author
 			Blog b = blogFactory.parseBlog(g, ""); // description doesn't matter
-			Author a = b.getAuthor();
+			a = b.getAuthor();
 			// Parse the public key
 			KeyParser keyParser = crypto.getSignatureKeyParser();
 			PublicKey key = keyParser.parsePublicKey(a.getPublicKey());
@@ -111,9 +113,14 @@ class BlogPostValidator extends BdfMessageValidator {
 		BdfDictionary meta = new BdfDictionary();
 		Collection<MessageId> dependencies = null;
 		if (title != null) meta.put(KEY_TITLE, title);
-		meta.put(KEY_TEASER, teaser);
-		meta.put(KEY_HAS_BODY, postBody != null);
+		BdfDictionary author = BdfDictionary.of(
+				new BdfEntry(KEY_AUTHOR_ID, a.getId()),
+				new BdfEntry(KEY_AUTHOR_NAME, a.getName()),
+				new BdfEntry(KEY_PUBLIC_KEY, a.getPublicKey())
+		);
+		meta.put(KEY_AUTHOR, author);
 		meta.put(KEY_TIMESTAMP, m.getTimestamp());
+		meta.put(KEY_TIME_RECEIVED, clock.currentTimeMillis());
 		if (parent != null) {
 			meta.put(KEY_PARENT, parent);
 			dependencies = Collections.singletonList(new MessageId(parent));
diff --git a/briar-core/src/org/briarproject/blogs/BlogsModule.java b/briar-core/src/org/briarproject/blogs/BlogsModule.java
index 4cf7894d1b608b2557a8098f5509a1ebb6ec7b18..055328ad9cbb664f7e027bb6bb46ce70a5309f8b 100644
--- a/briar-core/src/org/briarproject/blogs/BlogsModule.java
+++ b/briar-core/src/org/briarproject/blogs/BlogsModule.java
@@ -4,11 +4,12 @@ import org.briarproject.api.blogs.BlogFactory;
 import org.briarproject.api.blogs.BlogManager;
 import org.briarproject.api.blogs.BlogPostFactory;
 import org.briarproject.api.clients.ClientHelper;
+import org.briarproject.api.contact.ContactManager;
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.data.MetadataEncoder;
-import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.identity.IdentityManager;
+import org.briarproject.api.lifecycle.LifecycleManager;
 import org.briarproject.api.sync.GroupFactory;
 import org.briarproject.api.sync.ValidationManager;
 import org.briarproject.api.system.Clock;
@@ -19,17 +20,31 @@ import javax.inject.Singleton;
 import dagger.Module;
 import dagger.Provides;
 
+import static org.briarproject.blogs.BlogManagerImpl.CLIENT_ID;
+
 @Module
 public class BlogsModule {
 
 	public static class EagerSingletons {
 		@Inject
 		BlogPostValidator blogPostValidator;
+		@Inject
+		BlogManager blogManager;
 	}
 
 	@Provides
 	@Singleton
-	BlogManager provideBlogManager(BlogManagerImpl blogManager) {
+	BlogManager provideBlogManager(BlogManagerImpl blogManager,
+			LifecycleManager lifecycleManager, ContactManager contactManager,
+			IdentityManager identityManager,
+			ValidationManager validationManager) {
+
+		lifecycleManager.registerClient(blogManager);
+		contactManager.registerAddContactHook(blogManager);
+		contactManager.registerRemoveContactHook(blogManager);
+		identityManager.registerAddIdentityHook(blogManager);
+		identityManager.registerRemoveIdentityHook(blogManager);
+		validationManager.registerIncomingMessageHook(CLIENT_ID, blogManager);
 		return blogManager;
 	}
 
@@ -54,8 +69,7 @@ public class BlogsModule {
 
 		BlogPostValidator validator = new BlogPostValidator(crypto,
 				blogFactory, clientHelper, metadataEncoder, clock);
-		validationManager.registerMessageValidator(
-				BlogManagerImpl.CLIENT_ID, validator);
+		validationManager.registerMessageValidator(CLIENT_ID, validator);
 
 		return validator;
 	}
diff --git a/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java b/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java
index e04e206020edd797cf1da082d7b075df9a7156c3..5b1434ad1e3644b6964bea20916d5508d4ee53dc 100644
--- a/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java
+++ b/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java
@@ -99,17 +99,24 @@ class IdentityManagerImpl implements IdentityManager {
 	public Status getAuthorStatus(AuthorId authorId) throws DbException {
 		Transaction txn = db.startTransaction(false);
 		try {
-			// Compare to the IDs of the user's identities
-			for (LocalAuthor a : db.getLocalAuthors(txn))
-				if (a.getId().equals(authorId)) return VERIFIED;
-			// Compare to the IDs of contacts' identities
-			for (Contact c : db.getContacts(txn))
-				if (c.getAuthor().getId().equals(authorId)) return VERIFIED;
-
-			// TODO also handle UNVERIFIED when #261 is implemented
-			return UNKNOWN;
+			return getAuthorStatus(txn, authorId);
 		} finally {
 			db.endTransaction(txn);
 		}
 	}
+
+	@Override
+	public Status getAuthorStatus(Transaction txn, AuthorId authorId)
+			throws DbException {
+		// Compare to the IDs of the user's identities
+		for (LocalAuthor a : db.getLocalAuthors(txn))
+			if (a.getId().equals(authorId)) return VERIFIED;
+		// Compare to the IDs of contacts' identities
+		for (Contact c : db.getContacts(txn))
+			if (c.getAuthor().getId().equals(authorId)) return VERIFIED;
+
+		// TODO also handle UNVERIFIED when #261 is implemented
+		return UNKNOWN;
+	}
+
 }
diff --git a/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java
index ba67ff635ee898c342994773cf8f5b4dd9787160..a25520fac0f49ffdcea490d227340bff041181cb 100644
--- a/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java
+++ b/briar-core/src/org/briarproject/sharing/BlogSharingManagerImpl.java
@@ -5,6 +5,7 @@ import org.briarproject.api.blogs.Blog;
 import org.briarproject.api.blogs.BlogFactory;
 import org.briarproject.api.blogs.BlogInvitationMessage;
 import org.briarproject.api.blogs.BlogManager;
+import org.briarproject.api.blogs.BlogManager.RemoveBlogHook;
 import org.briarproject.api.blogs.BlogSharingManager;
 import org.briarproject.api.blogs.BlogSharingMessage.BlogInvitation;
 import org.briarproject.api.clients.ClientHelper;
@@ -40,7 +41,7 @@ import static org.briarproject.api.blogs.BlogConstants.BLOG_TITLE;
 
 class BlogSharingManagerImpl extends
 		SharingManagerImpl<Blog, BlogInvitation, BlogInvitationMessage, BlogInviteeSessionState, BlogSharerSessionState, BlogInvitationReceivedEvent, BlogInvitationResponseReceivedEvent>
-		implements BlogSharingManager {
+		implements BlogSharingManager, RemoveBlogHook {
 
 	static final ClientId CLIENT_ID = new ClientId(StringUtils.fromHexString(
 			"bee438b5de0b3a685badc4e49d76e72d"
@@ -124,6 +125,11 @@ class BlogSharingManagerImpl extends
 		return irrFactory;
 	}
 
+	@Override
+	public void removingBlog(Transaction txn, Blog b) throws DbException {
+		removingShareable(txn, b);
+	}
+
 	static class SFactory implements
 			ShareableFactory<Blog, BlogInvitation, BlogInviteeSessionState, BlogSharerSessionState> {
 
diff --git a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java b/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java
index 0d55b4a3cef39ef2fdb61609485968f343975c03..e4929fb7948d7a9d492782b15bd35223875c6896 100644
--- a/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java
+++ b/briar-core/src/org/briarproject/sharing/SharingManagerImpl.java
@@ -792,6 +792,8 @@ abstract class SharingManagerImpl<S extends Shareable, I extends Invitation, IM
 		} else if (task == TASK_REMOVE_SHAREABLE_FROM_LIST_SHARED_WITH_US) {
 			removeFromList(txn, groupId, SHARED_WITH_US, f);
 		} else if (task == TASK_ADD_SHARED_SHAREABLE) {
+			// TODO we might want to call the add() method of the respective
+			//      manager here, because blogs add a description for example
 			db.addGroup(txn, f.getGroup());
 			db.setVisibleToContact(txn, contactId, f.getId(), true);
 		} else if (task == TASK_ADD_SHAREABLE_TO_LIST_TO_BE_SHARED_BY_US) {
diff --git a/briar-core/src/org/briarproject/sharing/SharingModule.java b/briar-core/src/org/briarproject/sharing/SharingModule.java
index d62c7dccf7945810b7d271e85c4ac43e78131268..3af07e12925533cfe19898dd00c22178bf23b2ab 100644
--- a/briar-core/src/org/briarproject/sharing/SharingModule.java
+++ b/briar-core/src/org/briarproject/sharing/SharingModule.java
@@ -1,5 +1,6 @@
 package org.briarproject.sharing;
 
+import org.briarproject.api.blogs.BlogManager;
 import org.briarproject.api.blogs.BlogSharingManager;
 import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.clients.MessageQueueManager;
@@ -49,6 +50,7 @@ public class SharingModule {
 			LifecycleManager lifecycleManager,
 			ContactManager contactManager,
 			MessageQueueManager messageQueueManager,
+			BlogManager blogManager,
 			BlogSharingManagerImpl blogSharingManager) {
 
 		lifecycleManager.registerClient(blogSharingManager);
@@ -56,6 +58,7 @@ public class SharingModule {
 		contactManager.registerRemoveContactHook(blogSharingManager);
 		messageQueueManager.registerIncomingMessageHook(
 				BlogSharingManagerImpl.CLIENT_ID, blogSharingManager);
+		blogManager.registerRemoveBlogHook(blogSharingManager);
 
 		return blogSharingManager;
 	}