diff --git a/setup.py b/setup.py
index b8728b1678822f8e48b2d61025d3300f721d22d5..36c5650a6c93050e03a6ebaa9d17bf69665cbab6 100644
--- a/setup.py
+++ b/setup.py
@@ -13,7 +13,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
 
 setuptools.setup(
     name="coursebox",
-    version="0.1.19.6",
+    version="0.1.19.11",
     author="Tue Herlau",
     author_email="tuhe@dtu.dk",
     description="A course management system currently used at DTU",
diff --git a/src/coursebox.egg-info/PKG-INFO b/src/coursebox.egg-info/PKG-INFO
index 9308c52893204fe82071e6771b2662bc53558b40..a5537f7baac9745949e772a7594d2b97a9dd15a0 100644
--- a/src/coursebox.egg-info/PKG-INFO
+++ b/src/coursebox.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: coursebox
-Version: 0.1.19.5
+Version: 0.1.19.11
 Summary: A course management system currently used at DTU
 Home-page: https://lab.compute.dtu.dk/tuhe/coursebox
 Author: Tue Herlau
diff --git a/src/coursebox/core/info.py b/src/coursebox/core/info.py
index 9ccfaf1a9f62d13dc80724825ba4ed5db19bcb73..2123b5d303326aea9ee42f88241b4fe9f8db2cee 100644
--- a/src/coursebox/core/info.py
+++ b/src/coursebox/core/info.py
@@ -94,7 +94,7 @@ def first_day_of_class(info):
     if continuing_education():
         first_day_of_class = datetime(year=year(), month=info['first-month'], day=info['first-day'], hour=info['hour'][0], minute=info['minute'][0])
     else:
-        mo_first = datetime(year=year(), month=1 if semester() == 'spring' else 8, day=1, hour=13, minute=0)
+        mo_first = datetime(year=year(), month=1 if semester() == 'spring' else 8, day=1, hour=info.get('lecture_start_hour', 13), minute=0)
         # scroll to monday
         while mo_first.weekday() != 0: #strftime('%A') is not 'Monday':
             mo_first -= timedelta(days=1)
@@ -398,9 +398,7 @@ def class_information(verbose=False,
             nd = d['lectures'][r-1]['date'] + timedelta(days=int(d['handin_day_delta']))
             ri['date'] = nd
             ri['html'] = f"{nd.day} {nd.strftime('%b')}"
-
             ri = {**ri, **date2format(nd)}
-
             d['reports_info'][k] = ri
 
 
@@ -447,7 +445,7 @@ def class_information(verbose=False,
         n = l['number']
         date = l['date']
 
-        dd = timedelta(days=l.get('show_solutions_after', 1))
+        dd = timedelta(days=l.get('show_solutions_after', 1), hours=4)
         d['release_rules'][str(n)] = dict(start=date+dd, end=date+timedelta(days=2000))
     # Update with section information.
     if sections is not None:
diff --git a/src/coursebox/core/info_paths.py b/src/coursebox/core/info_paths.py
index 23306c73ba72e43416eca42a27579ca25a9f5a18..042733e1919ef2d27ee5d66fa3080e7734f9e62d 100644
--- a/src/coursebox/core/info_paths.py
+++ b/src/coursebox/core/info_paths.py
@@ -14,11 +14,15 @@ def get_paths():
     # num = cd[:cd.find("public")]
     CDIR = core_conf['working_dir']
     course_number = core_conf['course_number']
+    layout = core_conf.get('directory_layout', {})
+    if layout is None:
+        layout = {}
+
 
     root_02450public = os.path.normpath(CDIR + "/../..")
-    root_02450private = os.path.normpath(root_02450public + "/../%sprivate"%num)
-    root_02450instructors = os.path.normpath(root_02450private + "/../%sinstructors"%num)
-    root_02450students = os.path.normpath(root_02450private + "/../%sstudents" % num)
+    root_02450private = os.path.normpath( layout.get('private', root_02450public + "/../%sprivate"%num  ))
+    root_02450instructors = os.path.normpath( layout.get('instructors', root_02450private + "/../%sinstructors"%num))
+    root_02450students = os.path.normpath( layout.get('students', root_02450private + "/../%sstudents" % num) )
 
     root_02450public = root_02450public.replace("\\", "/")
     root_02450private = root_02450private.replace("\\", "/")
diff --git a/src/coursebox/core/projects_plagiarism.py b/src/coursebox/core/projects_plagiarism.py
index 7dd7dafef760d38f20a2d95a149e4a735132d65a..460c931f55873f76abc89371e5d36423b7d4f521 100644
--- a/src/coursebox/core/projects_plagiarism.py
+++ b/src/coursebox/core/projects_plagiarism.py
@@ -1,3 +1,4 @@
+
 from tinydb import TinyDB, Query
 import os
 import zipfile
diff --git a/src/coursebox/material/documentation.py b/src/coursebox/material/documentation.py
index 9b9dff5b5cfcec84ad539e25024fb1196ce101e1..7b74dd0830f798f877fa247b651473dd54bf47ac 100644
--- a/src/coursebox/material/documentation.py
+++ b/src/coursebox/material/documentation.py
@@ -126,6 +126,7 @@ def build_sphinx_documentation(cut_files=False, open_browser=True, build_and_cop
     WEEKS = list(core_conf['weeks_all'].keys())
 
 
+
     pdfs = []
     for g in glob.glob(paths['pdf_out'] +"/handout/*.pdf"):
         dst = paths['02450public'] + "/src/docs/assets/"+os.path.basename(g)[:-4] + "-handout.pdf"
@@ -148,6 +149,16 @@ def build_sphinx_documentation(cut_files=False, open_browser=True, build_and_cop
         shutil.copy(g, dst)
         pdfs.append(dst)
 
+    for g in glob.glob(paths['02450public'] + "/pensum/*.pdf"):
+        if "02450" in g or "sutton" in g:
+            continue
+        dst = paths['02450public'] + "/src/docs/assets/" + os.path.basename(g)
+        if not os.path.isdir(os.path.dirname(dst)):
+            os.makedirs(os.path.dirname(dst))
+        shutil.copy(g, dst)
+        pdfs.append(dst)
+
+
     # Copy shared templates.
     if not os.path.isdir(paths['02450public'] + "/src/docs/source/templates_generated"):
         os.mkdir(paths['02450public'] + "/src/docs/source/templates_generated")
@@ -218,6 +229,7 @@ def build_sphinx_documentation(cut_files=False, open_browser=True, build_and_cop
 
         my_env = os.environ.copy()
         my_env['PYTHONPATH'] = (paths['02450students'] + '_complete').replace("\\", "/")
+        print("Running", cmd)
         process = run(cmd, print_output=True, log_output=True, check=False, env=my_env)
 
         """r 
@@ -426,6 +438,7 @@ def fix_all_shared_files(paths=None, dosvg=False,compile_templates=True, verbose
     if os.path.isdir(out):
         # I feel we need to convert the SVG images?
         fix_shared(paths, out, pdf2png=dosvg, dosvg=dosvg, compile_templates=compile_templates, verbose=verbose)  # , dosvg=dosvg  <--- please update coursebox (script broken as is)
-
+    else:
+        print("Coursebox> No documentation shared directory. This is very, very odd indeed. I am stopping now. ")
 
 
diff --git a/src/coursebox/setup_coursebox.py b/src/coursebox/setup_coursebox.py
index 3b46bc81b1c0717f6eed1fb0ac69d77ae0af7ddf..07b8c39787cb80793e79ffc20884eedca9775da4 100644
--- a/src/coursebox/setup_coursebox.py
+++ b/src/coursebox/setup_coursebox.py
@@ -15,6 +15,7 @@ def setup_coursebox(working_dir, course_number="02450", semester='spring', year=
     continuing_education_month = "March", post_process_info=None,
                     setup_student_files=None,
                     fix_all_shared_files=None,
+                    directory_layout=None, # Base layout of the project directories. Contains keys like public, private, students, etc.
                     **kwargs):
     funcs['setup_student_files'] = setup_student_files
     funcs['fix_all_shared_files'] = fix_all_shared_files
@@ -29,6 +30,7 @@ def setup_coursebox(working_dir, course_number="02450", semester='spring', year=
     info_paths.core_conf['continuing_education_month'] = continuing_education_month
     info_paths.core_conf['slides_shownotes'] = slides_shownotes
     info_paths.core_conf['post_process_info'] = post_process_info
+    info_paths.core_conf['directory_layout'] = directory_layout
 
     for a, val in kwargs.items():
         info_paths.core_conf[a] = val
diff --git a/src/coursebox/student_files/student_files.py b/src/coursebox/student_files/student_files.py
index ef310ac719f75d0e1988cc17bffc254f9d6747fb..5d9c782c431761293905df0c9c03031515fa926f 100644
--- a/src/coursebox/student_files/student_files.py
+++ b/src/coursebox/student_files/student_files.py
@@ -72,9 +72,10 @@ def setup_student_files(run_files=True,
     censor_file(init_dest)
 
     # Check for exclusion mask.
-    exclude = info_paths.core_conf.get('student_files', {}).get('exclude', [])
+    exclude = list( info_paths.core_conf.get('student_files', {}).get('exclude', []) )
+
     if extra_dirs is None:
-        extra_dirs = info_paths.core_conf.get('student_files', {}).get('extra_dirs', [])
+        extra_dirs = list(info_paths.core_conf.get('student_files', {}).get('extra_dirs', []))
 
     print("Extra dirs are", extra_dirs)
     exclude += [f'tests_week{w if w >= 10 else f"0{w}"}.py' for w in range(0,14) if w not in week]
@@ -222,6 +223,10 @@ def fix_hw(paths, info, hw, out, output_dir, run_files=False, cut_files=False, c
                  run_files=run_files, cut_files=cut_files, license_head=info.get('code_copyright', None),
                  censor_files=censor_files,verbose=verbose,package_base_dir=package_base_dir)
 
+    if "tests" in hw['base']:
+        print(hw)
+        print("Doing the base.")
+
     if include_solutions:
         wk = hw['base'].split("/")[-1]
         sp = paths['02450students'] + "/solutions/"