   def run(mode, state) do
     IO.puts "Generating posts index..."
 
-    postdir = Path.join state.dest, "posts"
-    File.mkdir_p! postdir
-    msg_mkdir postdir
-    all_posts = state.site_ctx[:posts]
-    title = state.project_info.list_title_all
-    save_list Path.join(postdir, "index.html"), title, all_posts, state
-
-    #test {nil, state.site_ctx[:posts]}, state
-
     tags = state.tag_map
-    result = launch_tag mode, tags, state
-    Error.filter_results result, :index_builder
+    case index_task({nil, state.site_ctx[:posts]}, state) do
+      :ok ->
+        result = launch_tag mode, tags, state
+        Error.filter_results result, :index_builder
+      {:error, _} = error -> error
+    end
   end
 
-  defp test({tag, posts}, state) do
+  @spec launch_tag(Build.mode, map, state) :: [Error.result]
+
+  defp launch_tag(:parallel, tagmap, state) do
+    tagmap
+    |> Task.async_stream(__MODULE__, :index_task, [state], @async_opt)
+    |> Enum.map(&elem(&1, 1))
+  end
+
+  defp launch_tag(:sequential, tagmap, state) do
+    tagmap
+    |> Enum.map(&index_task(&1, state))
+  end
+
+  @doc false
+  @spec index_task({nil | Tag.t, [PostInfo.t]}, state) :: Error.result
+
+  def index_task({tag, posts}, state) do
     pagination? = state.project_info.pagination
     posts_per_page = state.project_info.posts_per_page
 
-    list_path = tag && "tags/" <> tag.name || "posts"
+    list_path = tag && Path.join("tags", tag.name) || "posts"
     list_dir = Path.join state.dest, list_path
     list_title =
       if is_nil(tag) do

      {:error, _} = error -> error
    end
  end

  @spec save_lists([binary], binary) :: :ok

  defp save_lists([first|_] = htmls, list_dir) do
    path_index = Path.join list_dir, "index.html"
    fwrite path_index, first
    msg_gen path_index
    htmls
    |> Enum.with_index(1)
    |> Enum.each(fn {html, page_num} ->
      path = Path.join list_dir, "page-#{page_num}.html"
      fwrite path, html
      msg_gen path
    end)
  end

  @spec launch_tag(Build.mode, map, state) :: [Task.t]

  defp launch_tag(:parallel, tagmap, state) do
    %{dest: dir} = state
    tagmap
    |> Task.async_stream(__MODULE__, :tag_task, [dir, state], @async_opt)
    |> Enum.map(&elem(&1, 1))
  end

  defp launch_tag(:sequential, tagmap, state) do
    %{dest: dir} = state
    tagmap
    |> Enum.map(&tag_task(&1, dir, state))
  end

  @doc false
  @spec tag_task({Serum.Tag.t, [PostInfo.t]}, binary, state) :: :ok

  def tag_task({tag, posts}, dest, state) do
    tagdir = Path.join [dest, "tags", tag.name]
    fmt = state.project_info.list_title_tag
    title = fmt |> :io_lib.format([tag.name]) |> IO.iodata_to_binary
    File.mkdir_p! tagdir
    msg_mkdir tagdir
    save_list Path.join(tagdir, "index.html"), title, posts, state
  end

  @spec save_list(binary, binary, [PostInfo.t], state) :: :ok

  defp save_list(path, title, posts, state) do
    list_ctx = [header: title, posts: posts]
    case Renderer.render "list", list_ctx, [page_title: title], state do
      {:ok, html} ->
        fwrite path, html
        msg_gen path
      error -> error
    end
  end

  """
  # for the first page
  path_index = Path.join state.list_dir, "index.html"
  fwrite path_index, html
  msg_gen path_index

  path = Path.join state.list_dir, "page-1.html"
  fwrite path, html
  msg_gen path

  # for other pages
  path = Path.join state.list_dir, "page-# {page_num}.html"
  fwrite path, html
  msg_gen path
  """

  @spec render_lists([[PostInfo.t]], integer, [Error.result(binary)], state)
    :: Error.result([binary])

  alias Serum.Build
  alias Serum.PostInfo
  alias Serum.Renderer
  alias Serum.Tag

  @type state :: Build.state

