diff --git a/rules.build_defs b/rules.build_defs
index 9e64f21d57d5066a5290065ee1de07df3b105090..491a73451dbba09e3c687b98e500ccd48f93a040 100644
--- a/rules.build_defs
+++ b/rules.build_defs
@@ -8,13 +8,22 @@ REVEALJS_DEFAULT_CONFIG = {
     "slideNumber": "true",
 }
 
-def pandoc(name: str = None, src: str = None, out: str = None, toc: bool = True, toc_depth: int = 1, slide_level: int = 2, variables: dict = {}, pandoc_args: list = []):
-    if name is None:
-        name = "pandoc_%s" % src.replace('/', '_')
-    if src is None:
-        src = '%s/index.md' % name
+def pandoc(name: str, src: str, out: str = None, toc: bool = True, toc_depth: int = 1, slide_level: int = 2, variables: dict = {}, pandoc_args: list = [], visibility: list = None):
+    """Use pandoc to generate a reveal.hs index.html from a markdown file.
+
+    Args:
+        name (str): target name.
+        src (str): markdown source.
+        out (str): html output.
+        toc (bool): pandoc --toc option.
+        toc_depth (int): pandoc --toc_depth option.
+        slide_level (int): pandoc --slide_level option.
+        variables (dict): defines variables for pandoc templates.
+        pandoc_args (list): supplementary arguments to pass to pandoc.
+        visibility (list): visilibity of the generated target.
+    """
     if out is None:
-        out = src[:-2] + 'html'
+        out = src.replace('.md', '.html')
 
     args = [
         "$TOOL",
@@ -37,18 +46,55 @@ def pandoc(name: str = None, src: str = None, out: str = None, toc: bool = True,
     args = args + ["--variable=%s:%s" % v for v in vars.items()] + pandoc_args
 
     return genrule(
-        name = "pandoc-%s" % name,
+        name = name,
         cmd = " ".join(args),
         srcs = [src],
         outs = [out],
-        tools = ["///tools/pandoc//:bin"]
+        tools = ["///tools/pandoc//:bin"],
+        visibility = visibility,
     )
 
-def presentation(name: str, src: str = None, out: str = None, toc: bool = True, toc_depth: int = 1, slide_level: int = 2, variables: dict = {}, pandoc_args: list = []):
-    return filegroup(
-        name = "presentation_%s" % name.replace('/', '_'),
-        srcs = [pandoc(name, src, out, toc, toc_depth, slide_level, variables, pandoc_args)] + glob(
-            ["%s/**" % name],
-            exclude = ["*.md"],
+def presentation(directory: str, slides: str = 'index.md', toc: bool = True, toc_depth: int = 1, slide_level: int = 2, variables: dict = {}, pandoc_args: list = [], visibility: list = None):
+    """Generate a presentation from a directory.
+
+    Args:
+        directory (str): path to the directory containing
+        slides (str): name of the files containing the slides in Markdown format.
+        toc (bool): see pandoc option.
+        toc_depth (int): see pandoc option.
+        slide_level (int): see pandoc option.
+        variables (dict): see pandoc option.
+        pandoc_args (list): see pandoc option.
+        visibility (list): visilibity of the generated targets
+    """
+
+    name = directory.replace('/', '_')
+
+    provides = {
+        'index': pandoc(
+            name = '%s#index' % name,
+            src = "%s/%s" % (directory, slides),
+            out = "%s/index.html" % directory,
+            toc = toc,
+            toc_depth = toc_depth,
+            slide_level = slide_level,
+            variables = variables,
+            pandoc_args = pandoc_args,
+            visibility = visibility
         ),
+    }
+
+    static_files = glob(["%s/**" % directory], exclude = [slides])
+    if static_files:
+        provides['static'] = filegroup(
+            name = '%s#static' % name,
+            srcs = static_files,
+            visibility = visibility
+        )
+
+    return filegroup(
+        name = name,
+        deps = provides.values(),
+        provides = provides,
+        visibility = visibility
     )