'
+
+src_root = Path(__file__).parent.parent
+package_root = src_root / package_name
+
+
+for path in sorted(package_root.rglob("*.py")):
+ module_path = path.with_suffix("")
+ doc_path = path.with_suffix(".md")
+ full_doc_path = Path("reference/api", doc_path)
+
+ parts = tuple(module_path.parts)
+
+ if parts[-1] == "__init__":
+ parts = parts[:-1]
+ doc_path = doc_path.with_name("index.md")
+ full_doc_path = full_doc_path.with_name("index.md")
+ elif parts[-1].startswith("_"):
+ continue
+
+ nav[parts] = doc_path.as_posix()
+
+ with mkdocs_gen_files.open(full_doc_path, "w") as fd:
+ ident = ".".join(parts)
+ fd.write(f"::: {ident}")
+
+ mkdocs_gen_files.set_edit_path(full_doc_path, path)
+
+with mkdocs_gen_files.open("reference/api/SUMMARY.md", "w") as nav_file:
+ nav_file.writelines(nav.build_literate_nav())
diff --git a/docs/glossary.md b/docs/glossary.md
new file mode 100644
index 0000000..6d0e8f1
--- /dev/null
+++ b/docs/glossary.md
@@ -0,0 +1,11 @@
+---
+title: Glossary
+summary: A glossary of terminology used in the Project Forge package and documentation.
+date: 2024-08-26
+---
+
+A glossary of terminology and nomenclature used in the project-forge package and documentation.
+
+!!! warning
+
+ Glossary not implemented yet! Recommend each item has its own anchor link.
diff --git a/docs/howtos/index.md b/docs/howtos/index.md
new file mode 100644
index 0000000..51b49f4
--- /dev/null
+++ b/docs/howtos/index.md
@@ -0,0 +1,15 @@
+---
+title: How Tos
+summary: Recipes for common tasks using Project Forge.
+date: 2024-08-26
+---
+
+The *How To's* are intended as recipes for common tasks using project-forge. See the API reference for detailed reference documentation and function, class etc definitions.
+
+!!! warning
+
+ How Tos not implemented yet!
+
+How-to guides are directions that take the reader through the steps required to solve a real-world problem. How-to guides are **goal-oriented.**
+
+[More information](https://diataxis.fr/how-to-guides/)
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..b1aea5f
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,16 @@
+---
+title: project-forge
+summary: a tool that combines one or more templates and the user's answers to questions to generate a code project
+date: 2024-08-26
+comments: true
+---
+
+# Project Forge
+
+{%
+ include-markdown
+ "../README.md"
+ start=""
+ end=""
+ rewrite-relative-urls=false
+%}
diff --git a/docs/installation.md b/docs/installation.md
new file mode 100644
index 0000000..f0662ca
--- /dev/null
+++ b/docs/installation.md
@@ -0,0 +1,20 @@
+---
+title: Installation
+summary: How to install project-forge.
+date: 2024-08-26
+---
+
+!!! warning
+
+ Installation instructions not implemented yet!
+
+
+## Installing the Stable Release from PyPI
+
+To install project-forge, run this command in your terminal:
+
+``` console
+$ pip install project-forge
+```
+
+This is the preferred method to install project-forge, as it will always install the most recent stable release. You can also replace `pip` with `pipx`.
diff --git a/docs/quickstart.md b/docs/quickstart.md
new file mode 100644
index 0000000..93c106e
--- /dev/null
+++ b/docs/quickstart.md
@@ -0,0 +1,31 @@
+---
+title: Quickstart
+summary: Quickstart instructions for Project Forge.
+date: 2024-08-26
+---
+
+Getting started quickly with Project Forge.
+
+!!! warning
+
+ Quickstart instructions not implemented yet!
+
+## Prerequisites
+
+## Installation
+
+From source...from pypi?
+
+## The Basics
+To use `project-forge` in a project:
+
+```python
+import project_forge
+```
+
+
+## Basic Operations
+
+## Tips and Tricks
+
+## Further Reading
diff --git a/docs/reference/index.md b/docs/reference/index.md
new file mode 100644
index 0000000..b61d8f6
--- /dev/null
+++ b/docs/reference/index.md
@@ -0,0 +1,15 @@
+---
+title: Reference
+summary: Technical reference of Project Forge.
+date: 2024-08-26
+---
+
+The *Reference* is intended as technical descriptions of the parts of project-forge.
+
+!!! warning
+
+ Reference not implemented yet!
+
+Reference guides are technical descriptions of the machinery and how to operate it. Reference material is **information-oriented.**
+
+[More information](https://diataxis.fr/reference/)
diff --git a/docs/reference/validations.md b/docs/reference/validations.md
new file mode 100644
index 0000000..b50eb05
--- /dev/null
+++ b/docs/reference/validations.md
@@ -0,0 +1,33 @@
+
+is_boolean | Return true if the object is a boolean value.
+is_defined | Checks if a value is defined.
+is_divisibleby | Return true if the value is divisible by another one.
+is_endingwith | Checks if the value is ending with a string.
+is_eq | Test version of ==.
+is_even | Checks if a value is even.
+is_false | Checks if a value is false.
+is_filter | Checks if a filter with a given name is available.
+is_float | Checks if this value is a float
+is_ge | Test version of >=.
+is_gt | Test version of >.
+is_in | Test version of in.
+is_integer | Checks if this value is an integer.
+is_iterable | Checks if this value can be iterated over.
+is_le | Test version of <=.
+is_lower | Checks if a string is all lowercase.
+is_lt | Test version of <.
+is_mapping | Checks if this value is a mapping
+is_ne | Test version of !=.
+is_none | Checks if a value is none.
+is_number | Checks if this value is a number.
+is_odd | Checks if a value is odd.
+is_safe | Checks if a value is safe.
+is_sequence | Checks if this value is a sequence
+is_startingwith | Checks if the value is starting with a string.
+is_string | Checks if this value is a string.
+is_test | Checks if a test with a given name is available.
+is_true | Checks if a value is true.
+is_undefined | Checks if a value is undefined.
+is_upper | Checks if a string is all uppercase.
+
+- pattern
diff --git a/docs/tutorials/create_a_pattern.md b/docs/tutorials/create_a_pattern.md
new file mode 100644
index 0000000..79e2cc7
--- /dev/null
+++ b/docs/tutorials/create_a_pattern.md
@@ -0,0 +1,92 @@
+---
+title: Create a Pattern
+description: Create a pattern
+icon:
+date: 2024-08-28
+comments: true
+---
+# Create a Pattern
+
+We are going to convert an existing project into a pattern. This process is going to require _lots_ of search and replace.
+
+In another tutorial, we will break it into several patterns.
+
+## Setup
+
+1. Create a new directory named `patterns.`
+2. Download the example project as a `.zip` file from TODO
+
+3. Decompress the file and copy the `todo-manager` project into `patterns/`.
+
+!!! Note
+
+ If you are doing this with an actual project, remove the `.git` directory if it exists.
+
+4. Inside the `patterns/` directory, create a file named `core_pattern.toml`
+
+## Extracting questions
+
+Questions are asked of the user during the project generation. Each answer is set as the value of a variable used in patterns. We will go through this example project and highlight information that would or could vary between projects. We will create questions to get the data from the user, and then we will replace the existing values in the example project with placeholders.
+
+### Different names in different places
+
+The outer folder is named `todo-manager`, the code folder is named `todo_manager`, and the title of the `README.md` file is `Todo Manager`. Are these three different variables that require three different questions? Is this one variable with three permutations that only require one question?
+
+We will treat them as three variables. However, we don't necessarily require three answers.
+
+### Project name
+
+Let's start with the title of the `README.md` file. We'll call this the `project_name`. We want to use this wherever we need a human-friendly name. Add a question to `core_pattern.toml`
+
+```toml title="patterns/core_pattern.toml"
+[[questions]]
+name = "project_name"
+prompt = "What is the human-friendly name of the project?"
+type = "str"
+default = "My Project"
+```
+
+### Package name
+
+Now, let's deal with the outer folder name and the code folder. Python package names (the package name registered with the Python package index) are [normalized](https://packaging.python.org/en/latest/specifications/name-normalization/) using hyphens. However, hyphens are not allowed in [Python identifiers](https://docs.python.org/3.12/reference/lexical_analysis.html#identifiers).
+
+We'll call the name of the code folder the `package_name`. Add this question to `core_pattern.toml`:
+
+```toml title="patterns/core_pattern.toml"
+# ... previous question
+
+[[questions]]
+name = "package_name"
+promp = "What is the name of the Python package?"
+type = "str"
+default = "{{ project_name|lower|replace(' ', '_') }}"
+```
+
+This sets the default answer to a modification of the previous question's answer. It converts the answer to lowercase and replaces all spaces with underscores. This is likely what the user wants, and if so, they can accept the default without having to type anything.
+
+### Repo name
+
+We'll call the name of the outer folder the `repo_name`. Add this question to `core_pattern.toml`:
+
+```toml title="patterns/core_pattern.toml"
+# ... previous questions
+
+[[questions]]
+name = "repo_name"
+prompt = "What is the name of the project repository?"
+type = "str"
+default = "{{ package_name|replace('_', '-') }}"
+```
+
+This question modifies the answer from `package_name`, replacing the underscores with hyphens.
+
+### Set the placeholders in files
+
+- Search for `Todo Manager` and replace it with `{{ project_name }}`
+- Search for `todo_manager` and replace it with `{{ package_name }}`
+- Search for `todo-manager` and replace it with `{{ repo_name }}`
+
+### Renaming files and directories with placeholders
+
+- Rename the `todo-manager` directory to `{{ repo_name }}`
+- Rename the `todo_manager` directory to `{{ package_name }}`
diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md
new file mode 100644
index 0000000..7a02777
--- /dev/null
+++ b/docs/tutorials/index.md
@@ -0,0 +1,22 @@
+---
+title: Tutorials
+summary: Tutorials for how to use a tool that combines one or more templates and the user's answers to questions to generate a code project.
+date: 2024-08-26
+---
+
+This page provides tutorials on how to use project-forge.
+
+!!! warning
+
+ Tutorials not implemented yet! Tutorials are for learning how to use the package.
+
+Tutorials are lessons that take the reader by the hand through a series of steps to complete a project of some kind. Tutorials are **learning-oriented.**
+
+- Help newcomers with getting started
+- Teach readers about your library by making them write code
+- Inspire confidence through examples that work for everyone, repeatably
+- Give readers an immediate sense of achievement
+- Show concrete examples, no abstractions
+- Provide the minimum necessary explanation
+- Avoid any distractions
+- [More information](https://diataxis.fr/tutorials/)
diff --git a/overrides/mkdocstrings/python/material/docstring/attributes.html b/overrides/mkdocstrings/python/material/docstring/attributes.html
new file mode 100644
index 0000000..ce50d65
--- /dev/null
+++ b/overrides/mkdocstrings/python/material/docstring/attributes.html
@@ -0,0 +1,90 @@
+{{ log.debug("Rendering attributes section") }}
+
+{% import "language.html" as lang with context %}
+
+{% if config.docstring_section_style == "table" %}
+ {% block table_style scoped %}
+ {{ section.title or lang.t("Attributes:") }}
+{{ lang.t("Name") }} | +{{ lang.t("Type") }} | +{{ lang.t("Description") }} | +
---|---|---|
{{ attribute.name }} |
+
+ {% if attribute.annotation %}
+ {% with expression = attribute.annotation %}
+ {% include "expression.html" with context %}
+ {% endwith %}
+ {% endif %}
+ |
+
+
+ {{ attribute.description|convert_markdown(heading_level, html_id) }}
+
+ |
+
{{ section.title or lang.t("Attributes:") }}
+{{ attribute.name }}
+ {% if attribute.annotation %}
+ {% with expression = attribute.annotation %}
+ ({% include "expression.html" with context %}
)
+ {% endwith %}
+ {% endif %}
+ –
+ {{ (section.title or lang.t("ATTRIBUTE")).rstrip(":").upper() }} | +{{ lang.t("DESCRIPTION") }} | +
---|---|
{{ attribute.name }} |
+
+
+ {{ attribute.description|convert_markdown(heading_level, html_id) }}
+
+
+ {% if attribute.annotation %}
+
+ TYPE:
+ {% with expression = attribute.annotation %}
+ |
+
{{ section.title or lang.t("Parameters:") }}
+{{ lang.t("Name") }} | +{{ lang.t("Type") }} | +{{ lang.t("Description") }} | +{{ lang.t("Default") }} | +
---|---|---|---|
{{ parameter.name }} |
+
+ {% if parameter.annotation %}
+ {% with expression = parameter.annotation %}
+ {% include "expression.html" with context %}
+ {% endwith %}
+ {% endif %}
+ |
+
+
+ {{ parameter.description|convert_markdown(heading_level, html_id) }}
+
+ |
+
+ {% if parameter.default %}
+ {% with expression = parameter.default %}
+ {% include "expression.html" with context %}
+ {% endwith %}
+ {% else %}
+ {{ lang.t("required") }}
+ {% endif %}
+ |
+
{{ section.title or lang.t("Parameters:") }}
+{{ parameter.name }}
+ {% if parameter.annotation %}
+ {% with expression = parameter.annotation %}
+ ({% include "expression.html" with context %}
+ {%- if parameter.default %}, {{ lang.t("default:") }}
+ {% with expression = parameter.default %}
+ {% include "expression.html" with context %}
+ {% endwith %}
+ {% endif %})
+ {% endwith %}
+ {% endif %}
+ –
+ {{ section.title or lang.t("Parameters:") }}
+{{ parameter.name }}
+ {{ lang.t("TYPE:") }}
+ {% with expression = parameter.annotation %}
+ {% include "expression.html" with context %}
+ {% endwith %}
+
+ {{ lang.t("DEFAULT:") }}
+ {% with expression = parameter.default %}
+ {% include "expression.html" with context %}
+ {% endwith %}
+
{{ section.title or lang.t("Raises:") }}
+{{ lang.t("Type") }} | +{{ lang.t("Description") }} | +
---|---|
+ {% if raises.annotation %}
+ {% with expression = raises.annotation %}
+ {% include "expression.html" with context %}
+ {% endwith %}
+ {% endif %}
+ |
+
+
+ {{ raises.description|convert_markdown(heading_level, html_id) }}
+
+ |
+
{{ lang.t(section.title) or lang.t("Raises:") }}
+{% include "expression.html" with context %}
+ {% endwith %}
+ –
+ {% endif %}
+ {{ (section.title or lang.t("Raises:")) }}
+{% include "expression.html" with context %}
+ {% endwith %}
+ {{ section.title or lang.t("Returns:") }}
+{{ lang.t("Name") }} | {% endif %} +{{ lang.t("Type") }} | +{{ lang.t("Description") }} | +
---|---|---|
{% if returns.name %}{{ returns.name }} {% endif %} | {% endif %}
+
+ {% if returns.annotation %}
+ {% with expression = returns.annotation %}
+ {% include "expression.html" with context %}
+ {% endwith %}
+ {% endif %}
+ |
+
+
+ {{ returns.description|convert_markdown(heading_level, html_id) }}
+
+ |
+
{{ section.title or lang.t("Returns:") }}
+{{ returns.name }}
{% endif %}
+ {% if returns.annotation %}
+ {% with expression = returns.annotation %}
+ {% if returns.name %} ({% endif %}
+ {% include "expression.html" with context %}
+ {% if returns.name %}){% endif %}
+ {% endwith %}
+ {% endif %}
+ –
+ {{ (section.title or lang.t("Returns:")) }}
+{{ returns.name }}
+ {% elif returns.annotation %}
+
+ {% with expression = returns.annotation %}
+ {% include "expression.html" with context %}
+ {% endwith %}
+
+ {% endif %}
+
+
+ {{ lang.t("TYPE:") }}
+ {% with expression = returns.annotation %}
+ {% include "expression.html" with context %}
+ {% endwith %}
+
+