diff --git a/Project.toml b/Project.toml
index 0b57de8a3..88509d5dd 100644
--- a/Project.toml
+++ b/Project.toml
@@ -8,6 +8,7 @@ Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
 DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
 DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
 JuDocTemplates = "6793090a-55ae-11e9-0511-73b91164f4ea"
+Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
 LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589"
 Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
 Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
diff --git a/src/JuDoc.jl b/src/JuDoc.jl
index 6b9e1f179..c3fb70349 100644
--- a/src/JuDoc.jl
+++ b/src/JuDoc.jl
@@ -9,6 +9,7 @@ using DelimitedFiles: readdlm
 using OrderedCollections
 using Pkg
 using DocStringExtensions: SIGNATURES, TYPEDEF
+using Literate: markdown
 
 import Logging
 import LiveServer
@@ -126,4 +127,7 @@ include("misc_html.jl")
 # ERROR TYPES
 include("error_types.jl")
 
+# INTEGRATION
+include("integration/literate.jl")
+
 end # module
diff --git a/src/converter/lx.jl b/src/converter/lx.jl
index 4d43fdb73..c2f76daae 100644
--- a/src/converter/lx.jl
+++ b/src/converter/lx.jl
@@ -228,10 +228,19 @@ function resolve_lx_input_hlcode(rpath::AS, lang::AS)::String
 
         end
     end
-    hideall && take!(io_in) # discard the content
+    hideall && take!(io_in)     # discard the content
     code = String(take!(io_in))
+    isempty(code) && return ""
     endswith(code, "\n") && (code = chop(code, tail=1))
-    return html_code(code, lang)
+    html = html_code(code, lang)
+    if LOCAL_PAGE_VARS["showall"].first
+        fd, fn = splitdir(fpath)
+        res = read(joinpath(fd, "output", splitext(fn)[1] * ".res"), String)
+        if !isempty(res)
+            html *= html_div("code_output", html_code(res))
+        end
+    end
+    return html
 end
 
 
@@ -259,9 +268,11 @@ function resolve_lx_input_plainoutput(rpath::AS, reproc::Bool=false; code::Bool=
     out_file = joinpath(dir, "output", fname * ".out")
     # check if the output file exists
     isfile(out_file) || throw(ErrorException("I found an \\input but no relevant output file."))
-    # return the content in a pre block
-    reproc || return html_code(read(out_file, String))
-    return read(out_file, String) * EOS
+    # return the content in a pre block (if non empty)
+    content = read(out_file, String)
+    isempty(content) && return ""
+    reproc || return html_code(content)
+    return content * EOS
 end
 
 
@@ -277,7 +288,9 @@ function resolve_lx_input_textfile(rpath::AS)::String
     fpath = resolve_assets_rpath(rpath; canonical=true)
     isempty(splitext(fpath)[2]) && (fpath *= ".md")
     isfile(fpath) || throw(ErrorException("I found a \\textinput but no relevant file."))
-    return read(fpath, String) * EOS
+    content = read(fpath, String)
+    isempty(content) && return ""
+    return content * EOS
 end
 
 
diff --git a/src/converter/lx_simple.jl b/src/converter/lx_simple.jl
index efb2dabba..0a374429c 100644
--- a/src/converter/lx_simple.jl
+++ b/src/converter/lx_simple.jl
@@ -33,6 +33,24 @@ function resolve_lx_textinput(lxc::LxCom)::String
 end
 
 
+"""
+$SIGNATURES
+
+Internal function to resolve a `\\literate{rpath}` see [`literate_to_judoc`](@ref).
+"""
+function resolve_lx_literate(lxc::LxCom)::String
+    rpath = strip(content(lxc.braces[1]))
+    path  = resolve_assets_rpath(rpath; canonical=true)
+    endswith(path, ".jl") || (path *= ".jl")
+    if !isfile(path)
+        @warn "File not found when trying to resolve a \\literate command ($path)."
+        return ""
+    end
+    opath = literate_to_judoc(path)
+    return read(opath, String) * EOS
+end
+
+
 """
 $SIGNATURES
 
@@ -172,4 +190,5 @@ Same as [`LXCOM_SIMPLE`](@ref) except the output is re-processed before being in
 const LXCOM_SIMPLE_REPROCESS = LittleDict{String, Function}(
     "\\textoutput" => resolve_lx_textoutput, # include output generated by code and reproc
     "\\textinput"  => resolve_lx_textinput,
-    )
+    "\\literate"   => resolve_lx_literate,
+     )
diff --git a/src/converter/md_blocks.jl b/src/converter/md_blocks.jl
index 01c9ce742..c4f8f8fa3 100644
--- a/src/converter/md_blocks.jl
+++ b/src/converter/md_blocks.jl
@@ -161,11 +161,13 @@ function eval_and_resolve_code(code::AS, rpath::AS;
     out_path, fname = splitdir(path)
     out_path = mkpath(joinpath(out_path, "output"))
     out_name = splitext(fname)[1] * ".out"
+    res_name = splitext(fname)[1] * ".res"
+    res_path = joinpath(out_path, res_name)
     out_path = joinpath(out_path, out_name)
 
     # if we're in the no-eval case, check that the relevant files are
     # there otherwise do re-eval with re-write
-    if !eval && isfile(path) && isfile(out_path)
+    if !eval && isfile(path) && isfile(out_path) && isfile(res_path)
         # just return the resolved code block
         return resolve_lx_input_hlcode(rpath, "julia")
     end
@@ -174,15 +176,21 @@ function eval_and_resolve_code(code::AS, rpath::AS;
     print(rpad("\r→ evaluating code [...] ($(CUR_PATH[]), $rpath)", 79))
     # - execute the code while redirecting stdout to file
     Logging.disable_logging(Logging.LogLevel(3_000))
+    res = nothing
     open(out_path, "w") do outf        # for stdout
         redirect_stdout(outf) do
-            try
+            res = try
                 Main.include(path)
             catch e
                 print("There was an error running the code:\n$(e.error)")
             end
         end
     end
+    open(res_path, "w") do outf
+        redirect_stdout(outf) do
+            show(res)
+        end
+    end
     Logging.disable_logging(Logging.Debug)
     print(rpad("\r→ evaluating code [✓]", 79)*"\r")
 
diff --git a/src/integration/literate.jl b/src/integration/literate.jl
new file mode 100644
index 000000000..a660d9b93
--- /dev/null
+++ b/src/integration/literate.jl
@@ -0,0 +1,45 @@
+const LITERATE_JULIA_FENCE   = "```julia"
+const LITERATE_JULIA_FENCE_L = length(LITERATE_JULIA_FENCE)
+const LITERATE_JULIA_FENCE_R = Regex(LITERATE_JULIA_FENCE)
+
+"""
+$SIGNATURES
+
+Take a markdown string generated by literate and post-process it to number each code block
+and mark them as eval-ed ones.
+"""
+function literate_post_process(s::String)::String
+    isempty(s) && return s
+    em   = eachmatch(LITERATE_JULIA_FENCE_R, s)
+    buf  = IOBuffer()
+    head = 1
+    c    = 1
+    for m in em
+        write(buf, SubString(s, head, prevind(s, m.offset)))
+        write(buf, "```julia:ex$c\n")
+        head = nextind(s, m.offset + LITERATE_JULIA_FENCE_L)
+        c   += 1
+    end
+    lis = lastindex(s)
+    head < lis && write(buf, SubString(s, head, lis))
+    return String(take!(buf))
+end
+
+
+"""
+$SIGNATURES
+
+Take a Literate.jl script and transform it into a JuDoc-markdown file.
+"""
+function literate_to_judoc(fpath::String)::String
+    outpath = joinpath(PATHS[:assets], "literate")
+    isdir(outpath) || mkdir(outpath)
+    # don't show infos
+    Logging.disable_logging(Logging.LogLevel(Logging.Info))
+    markdown(fpath, outpath, documenter=false,
+             postprocess=literate_post_process, credit=false)
+    # bring back logging
+    Logging.disable_logging(Logging.LogLevel(Logging.Debug))
+    fname = splitdir(fpath)[2]
+    return joinpath(outpath, splitext(fname)[1] * ".md")
+end
diff --git a/src/jd_vars.jl b/src/jd_vars.jl
index c75be6409..53234ae12 100644
--- a/src/jd_vars.jl
+++ b/src/jd_vars.jl
@@ -93,7 +93,17 @@ is processed.
     LOCAL_PAGE_VARS["date"]       = Pair(Date(1), (String, Date, Nothing))
     LOCAL_PAGE_VARS["lang"]       = Pair("julia", (String,)) # default lang for indented code
     LOCAL_PAGE_VARS["reflinks"]   = Pair(true,    (Bool,))   # whether there are reflinks or not
-    LOCAL_PAGE_VARS["freezecode"] = Pair(false,   (Bool,))   # no-reevaluation of the code
+
+    # CODE EVALUATION
+    #
+    LOCAL_PAGE_VARS["reeval"]        = Pair(false,  (Bool,)) # whether to always re-evals all on pg
+    LOCAL_PAGE_VARS["freezecode"]    = Pair(false,  (Bool,)) # no-reevaluation of the code
+    LOCAL_PAGE_VARS["showall"]       = Pair(false,  (Bool,)) # like a notebook on each cell
+    # the jd_* should not be assigned externally
+    LOCAL_PAGE_VARS["jd_code_scope"] = code_scope
+    LOCAL_PAGE_VARS["jd_code_head"]  = Pair(Ref(0),     (Ref{Int},))
+    LOCAL_PAGE_VARS["jd_code_eval"]  = Pair(Ref(false), (Ref{Bool},)) # toggle reeval
+    LOCAL_PAGE_VARS["jd_code"]       = Pair("",         (String,))    # just the script
 
     # RSS 2.0 item specs:
     # only title, link and description must be defined
@@ -123,13 +133,6 @@ is processed.
     LOCAL_PAGE_VARS["jd_mtime"]  = Pair(Date(1), (Date,))   # time of last modification
     LOCAL_PAGE_VARS["jd_rpath"]  = Pair("",      (String,)) # local path to file src/[...]/blah.md
 
-    # Internal vars for code blocks
-    LOCAL_PAGE_VARS["jd_code_scope"] = code_scope
-    LOCAL_PAGE_VARS["jd_code_head"]  = Pair(Ref(0),     (Ref{Int},))
-    LOCAL_PAGE_VARS["jd_code_eval"]  = Pair(Ref(false), (Ref{Bool},)) # toggle reeval
-    LOCAL_PAGE_VARS["reeval"]        = Pair(false,      (Bool,))      # always reeval on pg
-    LOCAL_PAGE_VARS["jd_code"]       = Pair("",         (String,))    # just the script
-
     # If there are GLOBAL vars that are defined, they take precedence
     local_keys = keys(LOCAL_PAGE_VARS)
     for k in keys(GLOBAL_PAGE_VARS)
@@ -230,12 +233,14 @@ the site. See [`resolve_lxcom`](@ref).
     # inclusion
     GLOBAL_LXDEFS["\\input"]      = LxDef("\\input",      2, EMPTY_SS)
     GLOBAL_LXDEFS["\\output"]     = LxDef("\\output",     1, EMPTY_SS)
+    GLOBAL_LXDEFS["\\codeoutput"] = LxDef("\\codeoutput", 1, subs("@@code_output \\output{#1}@@"))
     GLOBAL_LXDEFS["\\textoutput"] = LxDef("\\textoutput", 1, EMPTY_SS)
-    GLOBAL_LXDEFS["\\textinput"]  = LxDef("\\textinput", 1, EMPTY_SS)
+    GLOBAL_LXDEFS["\\textinput"]  = LxDef("\\textinput",  1, EMPTY_SS)
     GLOBAL_LXDEFS["\\figalt"]     = LxDef("\\figalt",     2, EMPTY_SS)
     GLOBAL_LXDEFS["\\fig"]        = LxDef("\\fig",        1, subs("\\figalt{}{#1}"))
     GLOBAL_LXDEFS["\\file"]       = LxDef("\\file",       2, subs("[#1]()"))
     GLOBAL_LXDEFS["\\tableinput"] = LxDef("\\tableinput", 2, EMPTY_SS)
+    GLOBAL_LXDEFS["\\literate"]   = LxDef("\\literate",   1, EMPTY_SS)
     # text formatting
     GLOBAL_LXDEFS["\\underline"] = LxDef("\\underline", 1,
                             subs("~~~<span style=\"text-decoration:underline;\">!#1</span>~~~"))
diff --git a/test/integration/literate.jl b/test/integration/literate.jl
new file mode 100644
index 000000000..4e7a34717
--- /dev/null
+++ b/test/integration/literate.jl
@@ -0,0 +1,93 @@
+scripts = joinpath(J.PATHS[:folder], "scripts")
+cd(td); J.set_paths!(); mkpath(scripts)
+
+@testset "Literate-a" begin
+    # Post processing: numbering of julia blocks
+    s = raw"""
+        A
+
+        ```julia
+        B
+        ```
+
+        C
+
+        ```julia
+        D
+        ```
+        """
+    @test J.literate_post_process(s) == """
+        A
+
+        ```julia:ex1
+        B
+        ```
+
+        C
+
+        ```julia:ex2
+        D
+        ```
+        """
+end
+
+@testset "Literate-b" begin
+    # Literate to JuDoc
+    s = raw"""
+        # # Rational numbers
+        #
+        # In julia rational numbers can be constructed with the `//` operator.
+        # Lets define two rational numbers, `x` and `y`:
+
+        ## Define variable x and y
+        x = 1//3
+        y = 2//5
+
+        # When adding `x` and `y` together we obtain a new rational number:
+
+        z = x + y
+        """
+    path = joinpath(scripts, "tutorial.jl")
+    write(path, s)
+    opath = J.literate_to_judoc(path)
+    @test endswith(opath, joinpath(J.PATHS[:assets], "literate", "tutorial.md"))
+    out = read(opath, String)
+    @test out == """
+        # Rational numbers
+
+        In julia rational numbers can be constructed with the `//` operator.
+        Lets define two rational numbers, `x` and `y`:
+
+        ```julia:ex1
+        # Define variable x and y
+        x = 1//3
+        y = 2//5
+        ```
+
+        When adding `x` and `y` together we obtain a new rational number:
+
+        ```julia:ex2
+        z = x + y
+        ```
+
+        """
+
+    # Use of `\literate` command
+    h = raw"""
+        @def hascode = true
+        @def showall = true
+
+        \literate{/scripts/tutorial.jl}
+        """ |> jd2html_td
+    @test isapproxstr(h, """
+        <h1 id="rational_numbers"><a href="/index.html#rational_numbers">Rational numbers</a></h1>
+        <p>In julia rational numbers can be constructed with the <code>//</code> operator. Lets define two rational numbers, <code>x</code> and <code>y</code>:</p>
+        <pre><code class="language-julia"># Define variable x and y
+        x = 1//3
+        y = 2//5</code></pre>
+        <div class="code_output"><pre><code>2//5</code></pre></div>
+        <p>When adding <code>x</code> and <code>y</code> together we obtain a new rational number:</p>
+        <pre><code class="language-julia">z = x + y</code></pre>
+        <div class="code_output"><pre><code>11//15</code></pre></div>
+        """)
+end
diff --git a/test/runtests.jl b/test/runtests.jl
index 695228552..7a89f9e33 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -1,4 +1,4 @@
-using JuDoc, Test, Markdown, Dates, Random
+using JuDoc, Test, Markdown, Dates, Random, Literate
 const J = JuDoc
 const D = joinpath(dirname(dirname(pathof(JuDoc))), "test", "_dummies")
 
@@ -41,7 +41,7 @@ include("converter/lx_input.jl")
 include("converter/lx_simple.jl")
 println("🍺")
 
-println("INTEGRATION")
+println("GLOBAL")
 include("global/cases1.jl")
 include("global/cases2.jl")
 include("global/ordering.jl")
@@ -65,5 +65,8 @@ begin
 end
 cd(dirname(dirname(pathof(JuDoc))))
 
+println("INTEGRATION")
+include("integration/literate.jl")
+
 flush_td()
 println("😅 😅 😅 😅")