diff --git a/PSModuleTemplate/PSModuleTemplate.psd1 b/PSModuleTemplate/PSModuleTemplate.psd1
new file mode 100644
index 0000000..548391c
--- /dev/null
+++ b/PSModuleTemplate/PSModuleTemplate.psd1
@@ -0,0 +1,132 @@
+#
+# Module manifest for module 'PSModuleTemplate'
+#
+# Generated by: James
+#
+# Generated on: 22/02/2026
+#
+
+@{
+
+# Script module or binary module file associated with this manifest.
+RootModule = 'PSModuleTemplate.psm1'
+
+# Version number of this module.
+ModuleVersion = '0.1.0'
+
+# Supported PSEditions
+# CompatiblePSEditions = @()
+
+# ID used to uniquely identify this module
+GUID = '3101ef4b-0651-47b8-ac62-adbe531f52fe'
+
+# Author of this module
+Author = 'James'
+
+# Company or vendor of this module
+CompanyName = 'Unknown'
+
+# Copyright statement for this module
+Copyright = '(c) James. All rights reserved.'
+
+# Description of the functionality provided by this module
+Description = 'PSModuleTemplate'
+
+# Minimum version of the PowerShell engine required by this module
+# PowerShellVersion = ''
+
+# Name of the PowerShell host required by this module
+# PowerShellHostName = ''
+
+# Minimum version of the PowerShell host required by this module
+# PowerShellHostVersion = ''
+
+# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
+# DotNetFrameworkVersion = ''
+
+# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
+# ClrVersion = ''
+
+# Processor architecture (None, X86, Amd64) required by this module
+# ProcessorArchitecture = ''
+
+# Modules that must be imported into the global environment prior to importing this module
+# RequiredModules = @()
+
+# Assemblies that must be loaded prior to importing this module
+# RequiredAssemblies = @()
+
+# Script files (.ps1) that are run in the caller's environment prior to importing this module.
+# ScriptsToProcess = @()
+
+# Type files (.ps1xml) to be loaded when importing this module
+# TypesToProcess = @()
+
+# Format files (.ps1xml) to be loaded when importing this module
+# FormatsToProcess = @()
+
+# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
+# NestedModules = @()
+
+# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
+FunctionsToExport = @('Get-Greeting', 'Set-SimpleMessage', 'Invoke-ClassDemo')
+
+# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
+CmdletsToExport = @()
+
+# Variables to export from this module
+VariablesToExport = @()
+
+# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
+AliasesToExport = @()
+
+# DSC resources to export from this module
+# DscResourcesToExport = @()
+
+# List of all modules packaged with this module
+# ModuleList = @()
+
+# List of all files packaged with this module
+# FileList = @()
+
+# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
+PrivateData = @{
+
+ PSData = @{
+
+ # Tags applied to this module. These help with module discovery in online galleries.
+ # Tags = @()
+
+ # A URL to the license for this module.
+ # LicenseUri = ''
+
+ # A URL to the main website for this project.
+ # ProjectUri = ''
+
+ # A URL to an icon representing this module.
+ # IconUri = ''
+
+ # ReleaseNotes of this module
+ # ReleaseNotes = ''
+
+ # Prerelease string of this module
+ # Prerelease = ''
+
+ # Flag to indicate whether the module requires explicit user acceptance for install/update/save
+ # RequireLicenseAcceptance = $false
+
+ # External dependent modules of this module
+ # ExternalModuleDependencies = @()
+
+ } # End of PSData hashtable
+
+} # End of PrivateData hashtable
+
+# HelpInfo URI of this module
+# HelpInfoURI = ''
+
+# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
+# DefaultCommandPrefix = ''
+
+}
+
diff --git a/PSModuleTemplate/PSModuleTemplate.psm1 b/PSModuleTemplate/PSModuleTemplate.psm1
new file mode 100644
index 0000000..a29ab77
--- /dev/null
+++ b/PSModuleTemplate/PSModuleTemplate.psm1
@@ -0,0 +1,79 @@
+#region Authoring
+
+###########################################################################
+# PSModuleTemplate
+# Author: James D'Arcy Ryan
+# GitHub: https://github.com/jdarcyryan/PSModuleTemplate
+# License: https://github.com/jdarcyryan/PSModuleTemplate/blob/main/LICENSE
+#
+# A standardized template for creating PowerShell modules with support for
+# classes (PowerShell and C#), private functions, and public functions with
+# automatic discovery and export of commands and aliases.
+#
+# LEGAL NOTICE:
+# The license referenced above applies to the PSModuleTemplate repository
+# and template structure only. Any module created using this template is
+# subject to its own license as specified in the module's LICENSE file,
+# which supersedes the template license for that specific module.
+###########################################################################
+
+#region Authoring
+
+#region Classes
+
+$classesPath = "$PSScriptRoot\classes"
+$classesDataFilePath = "$classesPath\classes.psd1"
+
+if (Test-Path -Path $classesDataFilePath) {
+ $classes = (Import-PowerShellDataFile -Path $classesDataFilePath).classes
+
+ $classes | foreach {
+ $currentClassPath = "$classesPath\$_"
+
+ if (!(Test-Path -Path $currentClassPath)) {
+ throw "Class '$_' does not exist."
+ }
+
+ $extension = (Get-Item -Path $currentClassPath).Extension
+
+ switch ($extension) {
+ '.ps1' {
+ # Process standard classes
+ . $currentClassPath
+ }
+ '.cs' {
+ # Process CSharp classes
+ Add-Type -Path $currentClassPath
+ }
+ default {
+ throw "Unable to process class '$_', $extension is an unsupported file type."
+ }
+ }
+ }
+}
+
+#endregion Classes
+
+#region Private
+
+$privatePath = "$PSScriptRoot\private"
+
+if (Test-Path -Path $privatePath) {
+ Get-ChildItem -Path $privatePath -Filter '*.ps1' | where PSIsContainer -eq $false | foreach {
+ . $_.FullName
+ }
+}
+
+#endregion Private
+
+#region Public
+
+$publicPath = "$PSScriptRoot\public"
+
+if (Test-Path -Path $publicPath) {
+ Get-ChildItem -Path $publicPath -Filter '*.ps1' | where PSIsContainer -eq $false | foreach {
+ . $_.FullName
+ }
+}
+
+#endregion Public
diff --git a/PSModuleTemplate/classes/SimpleCalculator.ps1 b/PSModuleTemplate/classes/SimpleCalculator.ps1
new file mode 100644
index 0000000..2b221ec
--- /dev/null
+++ b/PSModuleTemplate/classes/SimpleCalculator.ps1
@@ -0,0 +1,29 @@
+<#
+.SYNOPSIS
+A simple PowerShell class for basic arithmetic operations.
+
+.DESCRIPTION
+This class provides basic arithmetic functionality including addition and subtraction.
+It demonstrates PowerShell class implementation within the module template.
+#>
+class SimpleCalculator {
+ [int] $LastResult
+
+ SimpleCalculator() {
+ $this.LastResult = 0
+ }
+
+ [int] Add([int] $a, [int] $b) {
+ $this.LastResult = $a + $b
+ return $this.LastResult
+ }
+
+ [int] Subtract([int] $a, [int] $b) {
+ $this.LastResult = $a - $b
+ return $this.LastResult
+ }
+
+ [int] GetLastResult() {
+ return $this.LastResult
+ }
+}
diff --git a/PSModuleTemplate/classes/StringHelper.cs b/PSModuleTemplate/classes/StringHelper.cs
new file mode 100644
index 0000000..145b954
--- /dev/null
+++ b/PSModuleTemplate/classes/StringHelper.cs
@@ -0,0 +1,40 @@
+using System;
+
+namespace PSModuleTemplate
+{
+ ///
+ /// A simple C# class for string manipulation operations.
+ ///
+ public class StringHelper
+ {
+ ///
+ /// Reverses the characters in a string.
+ ///
+ /// The string to reverse.
+ /// The reversed string.
+ public static string ReverseString(string input)
+ {
+ if (string.IsNullOrEmpty(input))
+ return input;
+
+ char[] charArray = input.ToCharArray();
+ Array.Reverse(charArray);
+ return new string(charArray);
+ }
+
+ ///
+ /// Counts the number of words in a string.
+ ///
+ /// The string to count words in.
+ /// The number of words.
+ public static int CountWords(string input)
+ {
+ if (string.IsNullOrWhiteSpace(input))
+ return 0;
+
+ string[] words = input.Split(new char[] { ' ', '\t', '\n', '\r' },
+ StringSplitOptions.RemoveEmptyEntries);
+ return words.Length;
+ }
+ }
+}
diff --git a/PSModuleTemplate/classes/classes.psd1 b/PSModuleTemplate/classes/classes.psd1
new file mode 100644
index 0000000..3fd24df
--- /dev/null
+++ b/PSModuleTemplate/classes/classes.psd1
@@ -0,0 +1,6 @@
+@{
+ classes = @(
+ ,'SimpleCalculator.ps1'
+ ,'StringHelper.cs'
+ )
+}
diff --git a/PSModuleTemplate/private/Get-CurrentUser.ps1 b/PSModuleTemplate/private/Get-CurrentUser.ps1
new file mode 100644
index 0000000..aa39e25
--- /dev/null
+++ b/PSModuleTemplate/private/Get-CurrentUser.ps1
@@ -0,0 +1,22 @@
+<#
+.SYNOPSIS
+Gets the current user's name from the environment.
+
+.DESCRIPTION
+This private function retrieves the current user's name from the Windows environment variables.
+It provides a simple way to get the logged-in user's identity.
+
+.EXAMPLE
+Get-CurrentUser
+
+Returns the current user's name, e.g., "JohnDoe"
+
+.NOTES
+This is a private helper function used internally by the module.
+#>
+function Get-CurrentUser {
+ [CmdletBinding()]
+ param()
+
+ return $env:USERNAME
+}
diff --git a/PSModuleTemplate/private/Test-StringLength.ps1 b/PSModuleTemplate/private/Test-StringLength.ps1
new file mode 100644
index 0000000..077a56b
--- /dev/null
+++ b/PSModuleTemplate/private/Test-StringLength.ps1
@@ -0,0 +1,48 @@
+<#
+.SYNOPSIS
+Tests if a string meets the specified length requirements.
+
+.DESCRIPTION
+This private function validates whether a given string meets minimum and maximum length requirements.
+It returns a boolean value indicating whether the string passes the length validation.
+
+.PARAMETER InputString
+The string to test for length requirements.
+
+.PARAMETER MinLength
+The minimum required length for the string. Default is 1.
+
+.PARAMETER MaxLength
+The maximum allowed length for the string. Default is 100.
+
+.EXAMPLE
+Test-StringLength -InputString "Hello" -MinLength 3 -MaxLength 10
+
+Returns: $true
+
+.EXAMPLE
+Test-StringLength -InputString "Hi" -MinLength 5
+
+Returns: $false
+
+.NOTES
+This is a private helper function for string validation within the module.
+#>
+function Test-StringLength {
+ [CmdletBinding()]
+ param(
+ [Parameter(Mandatory = $true)]
+ [AllowEmptyString()]
+ [string]
+ $InputString,
+
+ [int]
+ $MinLength = 1,
+
+ [int]
+ $MaxLength = 100
+ )
+
+ $length = $InputString.Length
+ return ($length -ge $MinLength -and $length -le $MaxLength)
+}
diff --git a/PSModuleTemplate/public/Get-Greeting.ps1 b/PSModuleTemplate/public/Get-Greeting.ps1
new file mode 100644
index 0000000..fd600b1
--- /dev/null
+++ b/PSModuleTemplate/public/Get-Greeting.ps1
@@ -0,0 +1,48 @@
+<#
+.SYNOPSIS
+Gets a personalised greeting message.
+
+.DESCRIPTION
+This function creates a friendly greeting message for the specified person.
+It can optionally include the current time in the greeting.
+
+.PARAMETER Name
+The name of the person to greet. This parameter is mandatory.
+
+.PARAMETER IncludeTime
+When specified, includes the current time in the greeting message.
+
+.EXAMPLE
+Get-Greeting -Name "Alice"
+
+Returns: "Hello Alice, how are you today?"
+
+.EXAMPLE
+Get-Greeting -Name "Bob" -IncludeTime
+
+Returns: "Hello Bob, how are you today? The time is 14:30:25"
+
+.NOTES
+This is a simple demonstration function for the PSModuleTemplate.
+#>
+function Get-Greeting {
+ [CmdletBinding()]
+ param(
+ [Parameter(Mandatory = $true)]
+ [ValidateNotNullOrEmpty()]
+ [string]
+ $Name,
+
+ [switch]
+ $IncludeTime
+ )
+
+ $greeting = "Hello $Name, how are you today?"
+
+ if ($IncludeTime) {
+ $currentTime = Get-Date -Format "HH:mm:ss"
+ $greeting += " The time is $currentTime"
+ }
+
+ return $greeting
+}
diff --git a/PSModuleTemplate/public/Invoke-ClassDemo.ps1 b/PSModuleTemplate/public/Invoke-ClassDemo.ps1
new file mode 100644
index 0000000..810c6ab
--- /dev/null
+++ b/PSModuleTemplate/public/Invoke-ClassDemo.ps1
@@ -0,0 +1,68 @@
+<#
+.SYNOPSIS
+Demonstrates the use of both PowerShell and C# classes.
+
+.DESCRIPTION
+This function showcases the SimpleCalculator PowerShell class and StringHelper C# class
+by performing basic operations and returning the results in a formatted object.
+
+.PARAMETER FirstNumber
+The first number for the calculation. Default is 10.
+
+.PARAMETER SecondNumber
+The second number for the calculation. Default is 5.
+
+.PARAMETER TestString
+The string to manipulate using the C# StringHelper class. Default is "Hello World".
+
+.EXAMPLE
+Invoke-ClassDemo
+
+Uses default values to demonstrate both classes.
+
+.EXAMPLE
+Invoke-ClassDemo -FirstNumber 20 -SecondNumber 8 -TestString "PowerShell Rocks"
+
+Performs calculations with 20 and 8, and manipulates the string "PowerShell Rocks".
+
+.NOTES
+This function demonstrates integration between PowerShell and C# classes within the module.
+#>
+function Invoke-ClassDemo {
+ [CmdletBinding()]
+ param(
+ [int]
+ $FirstNumber = 10,
+
+ [int]
+ $SecondNumber = 5,
+
+ [string]
+ $TestString = "Hello World"
+ )
+
+ # Create an instance of the PowerShell class
+ $calculator = [SimpleCalculator]::new()
+
+ # Perform calculations
+ $addResult = $calculator.Add($FirstNumber, $SecondNumber)
+ $subtractResult = $calculator.Subtract($FirstNumber, $SecondNumber)
+
+ # Use the C# class static methods
+ $reversedString = [PSModuleTemplate.StringHelper]::ReverseString($TestString)
+ $wordCount = [PSModuleTemplate.StringHelper]::CountWords($TestString)
+
+ # Return results as a custom object
+ return [PSCustomObject]@{
+ CalculatorResults = @{
+ Addition = $addResult
+ Subtraction = $subtractResult
+ LastResult = $calculator.GetLastResult()
+ }
+ StringResults = @{
+ OriginalString = $TestString
+ ReversedString = $reversedString
+ WordCount = $wordCount
+ }
+ }
+}
diff --git a/PSModuleTemplate/public/Set-SimpleMessage.ps1 b/PSModuleTemplate/public/Set-SimpleMessage.ps1
new file mode 100644
index 0000000..4aa5ff1
--- /dev/null
+++ b/PSModuleTemplate/public/Set-SimpleMessage.ps1
@@ -0,0 +1,45 @@
+<#
+.SYNOPSIS
+Sets a simple message to display.
+
+.DESCRIPTION
+This function allows you to set a custom message that can be displayed.
+The message is returned as output and can be stored or displayed as needed.
+
+.PARAMETER Message
+The message text to set. This parameter is mandatory.
+
+.PARAMETER ToUpper
+When specified, converts the message to uppercase before returning it.
+
+.EXAMPLE
+Set-SimpleMessage -Message "Welcome to PowerShell"
+
+Returns: "Welcome to PowerShell"
+
+.EXAMPLE
+Set-SimpleMessage -Message "hello world" -ToUpper
+
+Returns: "HELLO WORLD"
+
+.NOTES
+This function demonstrates basic parameter handling and string manipulation.
+#>
+function Set-SimpleMessage {
+ [CmdletBinding()]
+ param(
+ [Parameter(Mandatory = $true)]
+ [ValidateNotNullOrEmpty()]
+ [string]
+ $Message,
+
+ [switch]
+ $ToUpper
+ )
+
+ if ($ToUpper) {
+ return $Message.ToUpper()
+ }
+
+ return $Message
+}
diff --git a/docs/.gitkeep b/docs/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/docs/Get-Greeting.md b/docs/Get-Greeting.md
new file mode 100644
index 0000000..a1883c0
--- /dev/null
+++ b/docs/Get-Greeting.md
@@ -0,0 +1,56 @@
+# Get-Greeting
+
+## Synopsis
+
+Gets a personalised greeting message.
+
+## Description
+
+This function creates a friendly greeting message for the specified person.
+It can optionally include the current time in the greeting.
+
+## Syntax
+
+```powershell
+Get-Greeting [-Name ] [-IncludeTime] [-Verbose] [-Debug] [-ErrorAction ] [-WarningAction ] [-InformationAction ] [-ProgressAction ] [-ErrorVariable ] [-WarningVariable ] [-InformationVariable ] [-OutVariable ] [-OutBuffer ] [-PipelineVariable ]
+```
+
+## Parameters
+
+### -Name
+
+The name of the person to greet. This parameter is mandatory.
+
+- **Type**: String
+- **Required**: true
+- **Position**: 1
+- **Default value**: None
+- **Accepts pipeline input**: false
+
+### -IncludeTime
+
+When specified, includes the current time in the greeting message.
+
+- **Type**: SwitchParameter
+- **Required**: false
+- **Position**: named
+- **Default value**: False
+- **Accepts pipeline input**: false
+
+## Examples
+
+### Example 1
+
+Returns: "Hello Alice, how are you today?"
+
+```powershell
+Get-Greeting -Name "Alice"
+```
+
+### Example 2
+
+Returns: "Hello Bob, how are you today? The time is 14:30:25"
+
+```powershell
+Get-Greeting -Name "Bob" -IncludeTime
+```
diff --git a/docs/Invoke-ClassDemo.md b/docs/Invoke-ClassDemo.md
new file mode 100644
index 0000000..eb62ad9
--- /dev/null
+++ b/docs/Invoke-ClassDemo.md
@@ -0,0 +1,66 @@
+# Invoke-ClassDemo
+
+## Synopsis
+
+Demonstrates the use of both PowerShell and C# classes.
+
+## Description
+
+This function showcases the SimpleCalculator PowerShell class and StringHelper C# class
+by performing basic operations and returning the results in a formatted object.
+
+## Syntax
+
+```powershell
+Invoke-ClassDemo [[-FirstNumber ]] [[-SecondNumber ]] [[-TestString ]] [-Verbose] [-Debug] [-ErrorAction ] [-WarningAction ] [-InformationAction ] [-ProgressAction ] [-ErrorVariable ] [-WarningVariable ] [-InformationVariable ] [-OutVariable ] [-OutBuffer ] [-PipelineVariable ]
+```
+
+## Parameters
+
+### -FirstNumber
+
+The first number for the calculation. Default is 10.
+
+- **Type**: Int32
+- **Required**: false
+- **Position**: 1
+- **Default value**: 10
+- **Accepts pipeline input**: false
+
+### -SecondNumber
+
+The second number for the calculation. Default is 5.
+
+- **Type**: Int32
+- **Required**: false
+- **Position**: 2
+- **Default value**: 5
+- **Accepts pipeline input**: false
+
+### -TestString
+
+The string to manipulate using the C# StringHelper class. Default is "Hello World".
+
+- **Type**: String
+- **Required**: false
+- **Position**: 3
+- **Default value**: Hello World
+- **Accepts pipeline input**: false
+
+## Examples
+
+### Example 1
+
+Uses default values to demonstrate both classes.
+
+```powershell
+Invoke-ClassDemo
+```
+
+### Example 2
+
+Performs calculations with 20 and 8, and manipulates the string "PowerShell Rocks".
+
+```powershell
+Invoke-ClassDemo -FirstNumber 20 -SecondNumber 8 -TestString "PowerShell Rocks"
+```
diff --git a/docs/Set-SimpleMessage.md b/docs/Set-SimpleMessage.md
new file mode 100644
index 0000000..179611c
--- /dev/null
+++ b/docs/Set-SimpleMessage.md
@@ -0,0 +1,56 @@
+# Set-SimpleMessage
+
+## Synopsis
+
+Sets a simple message to display.
+
+## Description
+
+This function allows you to set a custom message that can be displayed.
+The message is returned as output and can be stored or displayed as needed.
+
+## Syntax
+
+```powershell
+Set-SimpleMessage [-Message ] [-ToUpper] [-Verbose] [-Debug] [-ErrorAction ] [-WarningAction ] [-InformationAction ] [-ProgressAction ] [-ErrorVariable ] [-WarningVariable ] [-InformationVariable ] [-OutVariable ] [-OutBuffer ] [-PipelineVariable ]
+```
+
+## Parameters
+
+### -Message
+
+The message text to set. This parameter is mandatory.
+
+- **Type**: String
+- **Required**: true
+- **Position**: 1
+- **Default value**: None
+- **Accepts pipeline input**: false
+
+### -ToUpper
+
+When specified, converts the message to uppercase before returning it.
+
+- **Type**: SwitchParameter
+- **Required**: false
+- **Position**: named
+- **Default value**: False
+- **Accepts pipeline input**: false
+
+## Examples
+
+### Example 1
+
+Returns: "Welcome to PowerShell"
+
+```powershell
+Set-SimpleMessage -Message "Welcome to PowerShell"
+```
+
+### Example 2
+
+Returns: "HELLO WORLD"
+
+```powershell
+Set-SimpleMessage -Message "hello world" -ToUpper
+```