   Plugins can alter the processed contents and metadata here.
   """
   @callback processed_list(list :: PostList.t()) :: Result.t(PostList.t())
+
+  @doc "Called after Serum has successfully processed all pages."
+  @callback processed_pages(pages :: [Page.t()]) :: Result.t([Page.t()])
+
+  @doc "Called after Serum has successfully processed all blog posts."
+  @callback processed_posts(posts :: [Post.t()]) :: Result.t([Post.t()])
+
+  @doc """
+  Called while each fragment is being constructed.
+
+  Plugins can alter the HTML tree of its contents (which is generated by
+  Floki). It is recommended to implement this callback if you want to modify
+  the HTML document without worrying about breaking it.
+  """
+  @callback rendering_fragment(html :: Floki.html_tree(), metadata :: map()) ::
+              Result.t(Floki.html_tree())
 
   @doc """
   Called after producing a HTML fragment for each page.

  end

  @doc false
  @spec rendered_fragment(frag :: Fragment.t()) :: Result.t(Fragment.t())
  def rendered_fragment(frag) do
    call_function(:rendered_fragment, [frag])

    processed_post: 1,
    processed_template: 1,
    processed_list: 1,
    processed_pages: 1,
    processed_posts: 1,
    rendering_fragment: 2,
    rendered_fragment: 1,
    rendered_page: 1,
    wrote_file: 1,
