diff --git a/app/controllers/CategoriesController.asp b/app/controllers/CategoriesController.asp
new file mode 100644
index 0000000..0ed91cc
--- /dev/null
+++ b/app/controllers/CategoriesController.asp
@@ -0,0 +1,111 @@
+<%
+' Auto-generated Controller: Categories
+' Generated on 5/2/2026 9:47:37 PM
+' Generator: generateController.vbs v1.0
+'
+' Remember to:
+' 1. Add to app/controllers/autoload_controllers.asp
+' 2. Register in core/lib.ControllerRegistry.asp
+' 3. Add routes in public/Default.asp
+
+
+Class CategoriesController_Class
+ Private m_useLayout
+ Private m_title
+
+ Private Sub Class_Initialize()
+ m_useLayout = True
+ m_title = "Categories"
+ End Sub
+
+ Public Property Get useLayout
+ useLayout = m_useLayout
+ End Property
+
+ Public Property Let useLayout(v)
+ m_useLayout = v
+ End Property
+
+ Public Property Get Title
+ Title = m_title
+ End Property
+
+ Public Property Let Title(v)
+ m_title = v
+ End Property
+
+ '---------------------------------------------------------------
+ ' Action: Index
+ '---------------------------------------------------------------
+ Public Sub Index()
+ ' TODO: Implement Index action
+ Response.Write "Index action called"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: Show
+ '---------------------------------------------------------------
+ Public Sub Show(id)
+ ' TODO: Implement Show action
+ Response.Write "Show called
"
+ Response.Write "Parameters:
"
+ Response.Write "id = " & Server.HTMLEncode(CStr(id)) & "
"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: New
+ '---------------------------------------------------------------
+ Public Sub New()
+ ' TODO: Implement New action
+ Response.Write "New action called"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: Create
+ '---------------------------------------------------------------
+ Public Sub Create()
+ ' TODO: Implement Create action
+ Response.Write "Create action called"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: Edit
+ '---------------------------------------------------------------
+ Public Sub Edit(id)
+ ' TODO: Implement Edit action
+ Response.Write "Edit called
"
+ Response.Write "Parameters:
"
+ Response.Write "id = " & Server.HTMLEncode(CStr(id)) & "
"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: Update
+ '---------------------------------------------------------------
+ Public Sub Update(id)
+ ' TODO: Implement Update action
+ Response.Write "Update called
"
+ Response.Write "Parameters:
"
+ Response.Write "id = " & Server.HTMLEncode(CStr(id)) & "
"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: Delete
+ '---------------------------------------------------------------
+ Public Sub Delete(id)
+ ' TODO: Implement Delete action
+ Response.Write "Delete called
"
+ Response.Write "Parameters:
"
+ Response.Write "id = " & Server.HTMLEncode(CStr(id)) & "
"
+ End Sub
+
+End Class
+
+' Singleton instance
+Dim CategoriesController_Class__Singleton
+Function CategoriesController()
+ If IsEmpty(CategoriesController_Class__Singleton) Then
+ Set CategoriesController_Class__Singleton = New CategoriesController_Class
+ End If
+ Set CategoriesController = CategoriesController_Class__Singleton
+End Function
+%>
diff --git a/app/controllers/CommentsController.asp b/app/controllers/CommentsController.asp
new file mode 100644
index 0000000..9ee675e
--- /dev/null
+++ b/app/controllers/CommentsController.asp
@@ -0,0 +1,65 @@
+<%
+' Auto-generated Controller: Comments
+' Generated on 5/2/2026 9:47:38 PM
+' Generator: generateController.vbs v1.0
+'
+' Remember to:
+' 1. Add to app/controllers/autoload_controllers.asp
+' 2. Register in core/lib.ControllerRegistry.asp
+' 3. Add routes in public/Default.asp
+
+
+Class CommentsController_Class
+ Private m_useLayout
+ Private m_title
+
+ Private Sub Class_Initialize()
+ m_useLayout = True
+ m_title = "Comments"
+ End Sub
+
+ Public Property Get useLayout
+ useLayout = m_useLayout
+ End Property
+
+ Public Property Let useLayout(v)
+ m_useLayout = v
+ End Property
+
+ Public Property Get Title
+ Title = m_title
+ End Property
+
+ Public Property Let Title(v)
+ m_title = v
+ End Property
+
+ '---------------------------------------------------------------
+ ' Action: Create
+ '---------------------------------------------------------------
+ Public Sub Create()
+ ' TODO: Implement Create action
+ Response.Write "Create action called"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: Delete
+ '---------------------------------------------------------------
+ Public Sub Delete(id)
+ ' TODO: Implement Delete action
+ Response.Write "Delete called
"
+ Response.Write "Parameters:
"
+ Response.Write "id = " & Server.HTMLEncode(CStr(id)) & "
"
+ End Sub
+
+End Class
+
+' Singleton instance
+Dim CommentsController_Class__Singleton
+Function CommentsController()
+ If IsEmpty(CommentsController_Class__Singleton) Then
+ Set CommentsController_Class__Singleton = New CommentsController_Class
+ End If
+ Set CommentsController = CommentsController_Class__Singleton
+End Function
+%>
diff --git a/app/controllers/PostsController.asp b/app/controllers/PostsController.asp
new file mode 100644
index 0000000..65dc7ff
--- /dev/null
+++ b/app/controllers/PostsController.asp
@@ -0,0 +1,111 @@
+<%
+' Auto-generated Controller: Posts
+' Generated on 5/2/2026 9:47:38 PM
+' Generator: generateController.vbs v1.0
+'
+' Remember to:
+' 1. Add to app/controllers/autoload_controllers.asp
+' 2. Register in core/lib.ControllerRegistry.asp
+' 3. Add routes in public/Default.asp
+
+
+Class PostsController_Class
+ Private m_useLayout
+ Private m_title
+
+ Private Sub Class_Initialize()
+ m_useLayout = True
+ m_title = "Posts"
+ End Sub
+
+ Public Property Get useLayout
+ useLayout = m_useLayout
+ End Property
+
+ Public Property Let useLayout(v)
+ m_useLayout = v
+ End Property
+
+ Public Property Get Title
+ Title = m_title
+ End Property
+
+ Public Property Let Title(v)
+ m_title = v
+ End Property
+
+ '---------------------------------------------------------------
+ ' Action: Index
+ '---------------------------------------------------------------
+ Public Sub Index()
+ ' TODO: Implement Index action
+ Response.Write "Index action called"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: Show
+ '---------------------------------------------------------------
+ Public Sub Show(slug)
+ ' TODO: Implement Show action
+ Response.Write "Show called
"
+ Response.Write "Parameters:
"
+ Response.Write "slug = " & Server.HTMLEncode(CStr(slug)) & "
"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: New
+ '---------------------------------------------------------------
+ Public Sub New()
+ ' TODO: Implement New action
+ Response.Write "New action called"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: Create
+ '---------------------------------------------------------------
+ Public Sub Create()
+ ' TODO: Implement Create action
+ Response.Write "Create action called"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: Edit
+ '---------------------------------------------------------------
+ Public Sub Edit(id)
+ ' TODO: Implement Edit action
+ Response.Write "Edit called
"
+ Response.Write "Parameters:
"
+ Response.Write "id = " & Server.HTMLEncode(CStr(id)) & "
"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: Update
+ '---------------------------------------------------------------
+ Public Sub Update(id)
+ ' TODO: Implement Update action
+ Response.Write "Update called
"
+ Response.Write "Parameters:
"
+ Response.Write "id = " & Server.HTMLEncode(CStr(id)) & "
"
+ End Sub
+
+ '---------------------------------------------------------------
+ ' Action: Delete
+ '---------------------------------------------------------------
+ Public Sub Delete(id)
+ ' TODO: Implement Delete action
+ Response.Write "Delete called
"
+ Response.Write "Parameters:
"
+ Response.Write "id = " & Server.HTMLEncode(CStr(id)) & "
"
+ End Sub
+
+End Class
+
+' Singleton instance
+Dim PostsController_Class__Singleton
+Function PostsController()
+ If IsEmpty(PostsController_Class__Singleton) Then
+ Set PostsController_Class__Singleton = New PostsController_Class
+ End If
+ Set PostsController = PostsController_Class__Singleton
+End Function
+%>
diff --git a/app/controllers/autoload_controllers.asp b/app/controllers/autoload_controllers.asp
index 425e8a9..aabd073 100644
--- a/app/controllers/autoload_controllers.asp
+++ b/app/controllers/autoload_controllers.asp
@@ -1,2 +1,5 @@
-
\ No newline at end of file
+
+
+
+
\ No newline at end of file
diff --git a/app/models/POBO_Categories.asp b/app/models/POBO_Categories.asp
new file mode 100644
index 0000000..a163f8e
--- /dev/null
+++ b/app/models/POBO_Categories.asp
@@ -0,0 +1,103 @@
+<%
+' Auto-generated POBO for table [Categories]
+' Generated on 5/2/2026 9:48:11 PM
+' Generator: GenerateRepo.vbs v1.0
+'
+' Dependencies: core/helpers.asp (QuoteValue function)
+
+
+Class POBO_Categories
+ ' Public array of all property names
+ Public Properties
+
+ Private pCategoryID
+ Private pDescription
+ Private pName
+ Private pSlug
+
+ Private Sub Class_Initialize()
+ pCategoryID = 0
+ pDescription = Null
+ pName = Null
+ pSlug = Null
+ Properties = Array("CategoryID","Description","Name","Slug")
+ End Sub
+
+ Public Property Get PrimaryKey()
+ PrimaryKey = "CategoryID"
+ End Property
+
+ Public Property Get TableName()
+ TableName = "Categories"
+ End Property
+
+ Public Property Get CategoryID()
+ CategoryID = pCategoryID
+ End Property
+
+ Public Property Let CategoryID(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pCategoryID = CDbl(val)
+ Else
+ pCategoryID = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Categories.CategoryID", "Invalid value for CategoryID: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get Description()
+ Description = pDescription
+ End Property
+
+ Public Property Let Description(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pDescription = CDbl(val)
+ Else
+ pDescription = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Categories.Description", "Invalid value for Description: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get Name()
+ Name = pName
+ End Property
+
+ Public Property Let Name(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pName = CDbl(val)
+ Else
+ pName = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Categories.Name", "Invalid value for Name: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get Slug()
+ Slug = pSlug
+ End Property
+
+ Public Property Let Slug(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pSlug = CDbl(val)
+ Else
+ pSlug = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Categories.Slug", "Invalid value for Slug: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+End Class
+%>
diff --git a/app/models/POBO_Comments.asp b/app/models/POBO_Comments.asp
new file mode 100644
index 0000000..fee10cc
--- /dev/null
+++ b/app/models/POBO_Comments.asp
@@ -0,0 +1,156 @@
+<%
+' Auto-generated POBO for table [Comments]
+' Generated on 5/2/2026 9:48:12 PM
+' Generator: GenerateRepo.vbs v1.0
+'
+' Dependencies: core/helpers.asp (QuoteValue function)
+
+
+Class POBO_Comments
+ ' Public array of all property names
+ Public Properties
+
+ Private pAuthorEmail
+ Private pAuthorName
+ Private pBody
+ Private pCommentID
+ Private pCreatedDate
+ Private pIsApproved
+ Private pPostID
+
+ Private Sub Class_Initialize()
+ pAuthorEmail = Null
+ pAuthorName = Null
+ pBody = Null
+ pCommentID = 0
+ pCreatedDate = #1/1/1970#
+ pIsApproved = 0
+ pPostID = 0
+ Properties = Array("AuthorEmail","AuthorName","Body","CommentID","CreatedDate","IsApproved","PostID")
+ End Sub
+
+ Public Property Get PrimaryKey()
+ PrimaryKey = "CommentID"
+ End Property
+
+ Public Property Get TableName()
+ TableName = "Comments"
+ End Property
+
+ Public Property Get AuthorEmail()
+ AuthorEmail = pAuthorEmail
+ End Property
+
+ Public Property Let AuthorEmail(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pAuthorEmail = CDbl(val)
+ Else
+ pAuthorEmail = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Comments.AuthorEmail", "Invalid value for AuthorEmail: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get AuthorName()
+ AuthorName = pAuthorName
+ End Property
+
+ Public Property Let AuthorName(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pAuthorName = CDbl(val)
+ Else
+ pAuthorName = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Comments.AuthorName", "Invalid value for AuthorName: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get Body()
+ Body = pBody
+ End Property
+
+ Public Property Let Body(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pBody = CDbl(val)
+ Else
+ pBody = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Comments.Body", "Invalid value for Body: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get CommentID()
+ CommentID = pCommentID
+ End Property
+
+ Public Property Let CommentID(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pCommentID = CDbl(val)
+ Else
+ pCommentID = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Comments.CommentID", "Invalid value for CommentID: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get CreatedDate()
+ CreatedDate = pCreatedDate
+ End Property
+
+ Public Property Let CreatedDate(val)
+ On Error Resume Next
+ pCreatedDate = CDate(val)
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Comments.CreatedDate", "Invalid value for CreatedDate: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get IsApproved()
+ IsApproved = pIsApproved
+ End Property
+
+ Public Property Let IsApproved(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pIsApproved = CDbl(val)
+ Else
+ pIsApproved = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Comments.IsApproved", "Invalid value for IsApproved: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get PostID()
+ PostID = pPostID
+ End Property
+
+ Public Property Let PostID(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pPostID = CDbl(val)
+ Else
+ pPostID = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Comments.PostID", "Invalid value for PostID: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+End Class
+%>
diff --git a/app/models/POBO_Posts.asp b/app/models/POBO_Posts.asp
new file mode 100644
index 0000000..5ca99da
--- /dev/null
+++ b/app/models/POBO_Posts.asp
@@ -0,0 +1,205 @@
+<%
+' Auto-generated POBO for table [Posts]
+' Generated on 5/2/2026 9:48:11 PM
+' Generator: GenerateRepo.vbs v1.0
+'
+' Dependencies: core/helpers.asp (QuoteValue function)
+
+
+Class POBO_Posts
+ ' Public array of all property names
+ Public Properties
+
+ Private pBody
+ Private pCategoryID
+ Private pCreatedDate
+ Private pIsPublished
+ Private pPostID
+ Private pPublishedDate
+ Private pSlug
+ Private pSummary
+ Private pTitle
+ Private pUpdatedDate
+
+ Private Sub Class_Initialize()
+ pBody = Null
+ pCategoryID = 0
+ pCreatedDate = #1/1/1970#
+ pIsPublished = 0
+ pPostID = 0
+ pPublishedDate = #1/1/1970#
+ pSlug = Null
+ pSummary = Null
+ pTitle = Null
+ pUpdatedDate = #1/1/1970#
+ Properties = Array("Body","CategoryID","CreatedDate","IsPublished","PostID","PublishedDate","Slug","Summary","Title","UpdatedDate")
+ End Sub
+
+ Public Property Get PrimaryKey()
+ PrimaryKey = "PostID"
+ End Property
+
+ Public Property Get TableName()
+ TableName = "Posts"
+ End Property
+
+ Public Property Get Body()
+ Body = pBody
+ End Property
+
+ Public Property Let Body(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pBody = CDbl(val)
+ Else
+ pBody = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Posts.Body", "Invalid value for Body: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get CategoryID()
+ CategoryID = pCategoryID
+ End Property
+
+ Public Property Let CategoryID(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pCategoryID = CDbl(val)
+ Else
+ pCategoryID = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Posts.CategoryID", "Invalid value for CategoryID: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get CreatedDate()
+ CreatedDate = pCreatedDate
+ End Property
+
+ Public Property Let CreatedDate(val)
+ On Error Resume Next
+ pCreatedDate = CDate(val)
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Posts.CreatedDate", "Invalid value for CreatedDate: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get IsPublished()
+ IsPublished = pIsPublished
+ End Property
+
+ Public Property Let IsPublished(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pIsPublished = CDbl(val)
+ Else
+ pIsPublished = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Posts.IsPublished", "Invalid value for IsPublished: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get PostID()
+ PostID = pPostID
+ End Property
+
+ Public Property Let PostID(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pPostID = CDbl(val)
+ Else
+ pPostID = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Posts.PostID", "Invalid value for PostID: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get PublishedDate()
+ PublishedDate = pPublishedDate
+ End Property
+
+ Public Property Let PublishedDate(val)
+ On Error Resume Next
+ pPublishedDate = CDate(val)
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Posts.PublishedDate", "Invalid value for PublishedDate: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get Slug()
+ Slug = pSlug
+ End Property
+
+ Public Property Let Slug(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pSlug = CDbl(val)
+ Else
+ pSlug = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Posts.Slug", "Invalid value for Slug: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get Summary()
+ Summary = pSummary
+ End Property
+
+ Public Property Let Summary(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pSummary = CDbl(val)
+ Else
+ pSummary = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Posts.Summary", "Invalid value for Summary: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get Title()
+ Title = pTitle
+ End Property
+
+ Public Property Let Title(val)
+ On Error Resume Next
+ If IsNumeric(val) Then
+ pTitle = CDbl(val)
+ Else
+ pTitle = val
+ End If
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Posts.Title", "Invalid value for Title: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+ Public Property Get UpdatedDate()
+ UpdatedDate = pUpdatedDate
+ End Property
+
+ Public Property Let UpdatedDate(val)
+ On Error Resume Next
+ pUpdatedDate = CDate(val)
+ If Err.Number <> 0 Then
+ Err.Raise Err.Number, "POBO_Posts.UpdatedDate", "Invalid value for UpdatedDate: " & Err.Description
+ End If
+ On Error GoTo 0
+ End Property
+
+End Class
+%>
diff --git a/app/models/autoload_models.asp b/app/models/autoload_models.asp
new file mode 100644
index 0000000..e703a37
--- /dev/null
+++ b/app/models/autoload_models.asp
@@ -0,0 +1,3 @@
+
+
+
diff --git a/app/repositories/CategoriesRepository.asp b/app/repositories/CategoriesRepository.asp
new file mode 100644
index 0000000..c7a831f
--- /dev/null
+++ b/app/repositories/CategoriesRepository.asp
@@ -0,0 +1,176 @@
+<%
+' Auto-generated Repository for table [Categories]
+' Generated on 5/2/2026 9:48:11 PM
+' Generator: GenerateRepo.vbs v1.0
+'
+' Dependencies:
+' - core/lib.DAL.asp (DAL singleton for database access)
+' - core/lib.AutoMapper.asp (Automapper for object mapping)
+' - core/lib.Collections.asp (LinkedList_Class)
+' - core/lib.helpers.asp (KVUnzip, BuildOrderBy, QI, Destroy)
+
+
+Class CategoriesRepository_Class
+
+ Public Function FindByID(id)
+ Dim sql : sql = "Select [CategoryID], [Description], [Name], [Slug] FROM [Categories] WHERE [CategoryID] = ?"
+ Dim rs : Set rs = DAL.Query(sql, Array(id))
+ If rs.EOF Then
+ Err.Raise 1, "CategoriesRepository_Class", RecordNotFoundException("CategoryID", id)
+ Else
+ Set FindByID = Automapper.AutoMap(rs, "POBO_Categories")
+ End If
+ Destroy rs
+ End Function
+
+ Public Function GetAll(orderBy)
+ Set GetAll = Find(Empty, orderBy)
+ End Function
+
+ Public Function Find(where_kvarray, order_string_or_array)
+ Dim sql : sql = "Select [CategoryID], [Description], [Name], [Slug] FROM [Categories]"
+ Dim where_keys, where_values, i
+ If Not IsEmpty(where_kvarray) Then
+ KVUnzip where_kvarray, where_keys, where_values
+ If Not IsEmpty(where_keys) Then
+ sql = sql & " WHERE "
+ For i = 0 To UBound(where_keys)
+ If i > 0 Then sql = sql & " AND "
+ sql = sql & " " & QI(where_keys(i)) & " = ?"
+ Next
+ End If
+ End If
+ sql = sql & BuildOrderBy(order_string_or_array, "[CategoryID]")
+ Dim rs : Set rs = DAL.Query(sql, where_values)
+ Dim list : Set list = new LinkedList_Class
+ Do Until rs.EOF
+ list.Push Automapper.AutoMap(rs, "POBO_Categories")
+ rs.MoveNext
+ Loop
+ Set Find = list
+ Destroy rs
+ End Function
+
+ Public Function FindPaged(where_kvarray, order_string_or_array, per_page, page_num, ByRef page_count, ByRef record_count)
+ Dim sql : sql = "Select [CategoryID], [Description], [Name], [Slug] FROM [Categories]"
+ Dim where_keys, where_values, i
+ If Not IsEmpty(where_kvarray) Then
+ KVUnzip where_kvarray, where_keys, where_values
+ If Not IsEmpty(where_keys) Then
+ sql = sql & " WHERE "
+ For i = 0 To UBound(where_keys)
+ If i > 0 Then sql = sql & " AND "
+ sql = sql & " " & QI(where_keys(i)) & " = ?"
+ Next
+ End If
+ End If
+ sql = sql & BuildOrderBy(order_string_or_array, "[CategoryID]")
+ Dim rs : Set rs = DAL.PagedQuery(sql, where_values, per_page, page_num)
+ If Not rs.EOF Then
+ rs.PageSize = per_page
+ rs.AbsolutePage = page_num
+ page_count = rs.PageCount
+ record_count = rs.RecordCount
+ End If
+ Set FindPaged = PagedList(rs, per_page)
+ Destroy rs
+ End Function
+
+ Public Function SearchTablePaged(columns_array, search_value, order_string_or_array, per_page, page_num, ByRef page_count, ByRef record_count)
+ Dim sql : sql = "Select [CategoryID], [Description], [Name], [Slug] FROM [Categories]"
+ Dim i, params()
+ If IsArray(columns_array) And UBound(columns_array) >= 0 Then
+ sql = sql & " WHERE "
+ ReDim params(UBound(columns_array))
+ For i = 0 To UBound(columns_array)
+ If i > 0 Then sql = sql & " OR "
+ sql = sql & " " & QI(columns_array(i)) & " LIKE ?"
+ params(i) = "%" & search_value & "%"
+ Next
+ End If
+ sql = sql & BuildOrderBy(order_string_or_array, "[CategoryID]")
+ Dim rs : Set rs = DAL.PagedQuery(sql, params, per_page, page_num)
+ If Not rs.EOF Then
+ rs.PageSize = per_page
+ rs.AbsolutePage = page_num
+ page_count = rs.PageCount
+ record_count = rs.RecordCount
+ End If
+ Set SearchTablePaged = PagedList(rs, per_page)
+ Destroy rs
+ End Function
+
+ Private Function PagedList(rs, per_page)
+ Dim list : Set list = new LinkedList_Class
+ Dim x : x = 0
+ Do While (per_page <= 0 Or x < per_page) And Not rs.EOF
+ list.Push Automapper.AutoMap(rs, "POBO_Categories")
+ x = x + 1
+ rs.MoveNext
+ Loop
+ Set PagedList = list
+ End Function
+
+ Public Sub AddNew(ByRef model)
+ Dim sql : sql = "INSERT INTO [Categories] ([Description], [Name], [Slug]) VALUES (?, ?, ?)"
+ DAL.Execute sql, Array(model.Description, model.Name, model.Slug)
+
+ ' Retrieve the newly inserted ID
+ On Error Resume Next
+ Dim rsId : Set rsId = DAL.Query("SELECT @@IDENTITY AS NewID", Empty)
+ If Err.Number <> 0 Then
+ ' Fallback for Access databases
+ Err.Clear
+ Set rsId = DAL.Query("SELECT TOP 1 [CategoryID] FROM [Categories] ORDER BY [CategoryID] DESC", Empty)
+ End If
+ On Error GoTo 0
+
+ If Not rsId.EOF Then
+ If Not IsNull(rsId(0)) Then model.CategoryID = rsId(0)
+ End If
+ Destroy rsId
+ End Sub
+
+ Public Sub Update(model)
+ Dim sql : sql = "UPDATE [Categories] SET [Description] = ?, [Name] = ?, [Slug] = ? WHERE [CategoryID] = ?"
+ DAL.Execute sql, Array(model.Description, model.Name, model.Slug, model.CategoryID)
+ End Sub
+
+ Public Sub Delete(id)
+ Dim sql : sql = "DELETE FROM [Categories] WHERE [CategoryID] = ?"
+ DAL.Execute sql, Array(id)
+ End Sub
+
+ Private Function RecordNotFoundException(ByVal field_name, ByVal field_val)
+ RecordNotFoundException = "Categories record was not found with " & field_name & " = '" & field_val & "'."
+ End Function
+
+ Private Function QI(name)
+ QI = "[" & Replace(CStr(name), "]", "]]") & "]"
+ End Function
+
+ Private Function BuildOrderBy(orderArg, defaultCol)
+ Dim s : s = ""
+ If IsEmpty(orderArg) Or IsNull(orderArg) Or orderArg = "" Then
+ s = " ORDER BY " & defaultCol & " ASC"
+ ElseIf IsArray(orderArg) Then
+ Dim i : s = " ORDER BY "
+ For i = 0 To UBound(orderArg)
+ If i > 0 Then s = s & ", "
+ s = s & QI(orderArg(i))
+ Next
+ Else
+ s = " ORDER BY " & QI(orderArg)
+ End If
+ BuildOrderBy = s
+ End Function
+End Class
+
+Dim CategoriesRepository__Singleton
+Function CategoriesRepository()
+ If IsEmpty(CategoriesRepository__Singleton) Then
+ Set CategoriesRepository__Singleton = new CategoriesRepository_Class
+ End If
+ Set CategoriesRepository = CategoriesRepository__Singleton
+End Function
+%>
diff --git a/app/repositories/CommentsRepository.asp b/app/repositories/CommentsRepository.asp
new file mode 100644
index 0000000..6cfea23
--- /dev/null
+++ b/app/repositories/CommentsRepository.asp
@@ -0,0 +1,176 @@
+<%
+' Auto-generated Repository for table [Comments]
+' Generated on 5/2/2026 9:48:12 PM
+' Generator: GenerateRepo.vbs v1.0
+'
+' Dependencies:
+' - core/lib.DAL.asp (DAL singleton for database access)
+' - core/lib.AutoMapper.asp (Automapper for object mapping)
+' - core/lib.Collections.asp (LinkedList_Class)
+' - core/lib.helpers.asp (KVUnzip, BuildOrderBy, QI, Destroy)
+
+
+Class CommentsRepository_Class
+
+ Public Function FindByID(id)
+ Dim sql : sql = "Select [AuthorEmail], [AuthorName], [Body], [CommentID], [CreatedDate], [IsApproved], [PostID] FROM [Comments] WHERE [CommentID] = ?"
+ Dim rs : Set rs = DAL.Query(sql, Array(id))
+ If rs.EOF Then
+ Err.Raise 1, "CommentsRepository_Class", RecordNotFoundException("CommentID", id)
+ Else
+ Set FindByID = Automapper.AutoMap(rs, "POBO_Comments")
+ End If
+ Destroy rs
+ End Function
+
+ Public Function GetAll(orderBy)
+ Set GetAll = Find(Empty, orderBy)
+ End Function
+
+ Public Function Find(where_kvarray, order_string_or_array)
+ Dim sql : sql = "Select [AuthorEmail], [AuthorName], [Body], [CommentID], [CreatedDate], [IsApproved], [PostID] FROM [Comments]"
+ Dim where_keys, where_values, i
+ If Not IsEmpty(where_kvarray) Then
+ KVUnzip where_kvarray, where_keys, where_values
+ If Not IsEmpty(where_keys) Then
+ sql = sql & " WHERE "
+ For i = 0 To UBound(where_keys)
+ If i > 0 Then sql = sql & " AND "
+ sql = sql & " " & QI(where_keys(i)) & " = ?"
+ Next
+ End If
+ End If
+ sql = sql & BuildOrderBy(order_string_or_array, "[CommentID]")
+ Dim rs : Set rs = DAL.Query(sql, where_values)
+ Dim list : Set list = new LinkedList_Class
+ Do Until rs.EOF
+ list.Push Automapper.AutoMap(rs, "POBO_Comments")
+ rs.MoveNext
+ Loop
+ Set Find = list
+ Destroy rs
+ End Function
+
+ Public Function FindPaged(where_kvarray, order_string_or_array, per_page, page_num, ByRef page_count, ByRef record_count)
+ Dim sql : sql = "Select [AuthorEmail], [AuthorName], [Body], [CommentID], [CreatedDate], [IsApproved], [PostID] FROM [Comments]"
+ Dim where_keys, where_values, i
+ If Not IsEmpty(where_kvarray) Then
+ KVUnzip where_kvarray, where_keys, where_values
+ If Not IsEmpty(where_keys) Then
+ sql = sql & " WHERE "
+ For i = 0 To UBound(where_keys)
+ If i > 0 Then sql = sql & " AND "
+ sql = sql & " " & QI(where_keys(i)) & " = ?"
+ Next
+ End If
+ End If
+ sql = sql & BuildOrderBy(order_string_or_array, "[CommentID]")
+ Dim rs : Set rs = DAL.PagedQuery(sql, where_values, per_page, page_num)
+ If Not rs.EOF Then
+ rs.PageSize = per_page
+ rs.AbsolutePage = page_num
+ page_count = rs.PageCount
+ record_count = rs.RecordCount
+ End If
+ Set FindPaged = PagedList(rs, per_page)
+ Destroy rs
+ End Function
+
+ Public Function SearchTablePaged(columns_array, search_value, order_string_or_array, per_page, page_num, ByRef page_count, ByRef record_count)
+ Dim sql : sql = "Select [AuthorEmail], [AuthorName], [Body], [CommentID], [CreatedDate], [IsApproved], [PostID] FROM [Comments]"
+ Dim i, params()
+ If IsArray(columns_array) And UBound(columns_array) >= 0 Then
+ sql = sql & " WHERE "
+ ReDim params(UBound(columns_array))
+ For i = 0 To UBound(columns_array)
+ If i > 0 Then sql = sql & " OR "
+ sql = sql & " " & QI(columns_array(i)) & " LIKE ?"
+ params(i) = "%" & search_value & "%"
+ Next
+ End If
+ sql = sql & BuildOrderBy(order_string_or_array, "[CommentID]")
+ Dim rs : Set rs = DAL.PagedQuery(sql, params, per_page, page_num)
+ If Not rs.EOF Then
+ rs.PageSize = per_page
+ rs.AbsolutePage = page_num
+ page_count = rs.PageCount
+ record_count = rs.RecordCount
+ End If
+ Set SearchTablePaged = PagedList(rs, per_page)
+ Destroy rs
+ End Function
+
+ Private Function PagedList(rs, per_page)
+ Dim list : Set list = new LinkedList_Class
+ Dim x : x = 0
+ Do While (per_page <= 0 Or x < per_page) And Not rs.EOF
+ list.Push Automapper.AutoMap(rs, "POBO_Comments")
+ x = x + 1
+ rs.MoveNext
+ Loop
+ Set PagedList = list
+ End Function
+
+ Public Sub AddNew(ByRef model)
+ Dim sql : sql = "INSERT INTO [Comments] ([AuthorEmail], [AuthorName], [Body], [CreatedDate], [IsApproved], [PostID]) VALUES (?, ?, ?, ?, ?, ?)"
+ DAL.Execute sql, Array(model.AuthorEmail, model.AuthorName, model.Body, model.CreatedDate, model.IsApproved, model.PostID)
+
+ ' Retrieve the newly inserted ID
+ On Error Resume Next
+ Dim rsId : Set rsId = DAL.Query("SELECT @@IDENTITY AS NewID", Empty)
+ If Err.Number <> 0 Then
+ ' Fallback for Access databases
+ Err.Clear
+ Set rsId = DAL.Query("SELECT TOP 1 [CommentID] FROM [Comments] ORDER BY [CommentID] DESC", Empty)
+ End If
+ On Error GoTo 0
+
+ If Not rsId.EOF Then
+ If Not IsNull(rsId(0)) Then model.CommentID = rsId(0)
+ End If
+ Destroy rsId
+ End Sub
+
+ Public Sub Update(model)
+ Dim sql : sql = "UPDATE [Comments] SET [AuthorEmail] = ?, [AuthorName] = ?, [Body] = ?, [CreatedDate] = ?, [IsApproved] = ?, [PostID] = ? WHERE [CommentID] = ?"
+ DAL.Execute sql, Array(model.AuthorEmail, model.AuthorName, model.Body, model.CreatedDate, model.IsApproved, model.PostID, model.CommentID)
+ End Sub
+
+ Public Sub Delete(id)
+ Dim sql : sql = "DELETE FROM [Comments] WHERE [CommentID] = ?"
+ DAL.Execute sql, Array(id)
+ End Sub
+
+ Private Function RecordNotFoundException(ByVal field_name, ByVal field_val)
+ RecordNotFoundException = "Comments record was not found with " & field_name & " = '" & field_val & "'."
+ End Function
+
+ Private Function QI(name)
+ QI = "[" & Replace(CStr(name), "]", "]]") & "]"
+ End Function
+
+ Private Function BuildOrderBy(orderArg, defaultCol)
+ Dim s : s = ""
+ If IsEmpty(orderArg) Or IsNull(orderArg) Or orderArg = "" Then
+ s = " ORDER BY " & defaultCol & " ASC"
+ ElseIf IsArray(orderArg) Then
+ Dim i : s = " ORDER BY "
+ For i = 0 To UBound(orderArg)
+ If i > 0 Then s = s & ", "
+ s = s & QI(orderArg(i))
+ Next
+ Else
+ s = " ORDER BY " & QI(orderArg)
+ End If
+ BuildOrderBy = s
+ End Function
+End Class
+
+Dim CommentsRepository__Singleton
+Function CommentsRepository()
+ If IsEmpty(CommentsRepository__Singleton) Then
+ Set CommentsRepository__Singleton = new CommentsRepository_Class
+ End If
+ Set CommentsRepository = CommentsRepository__Singleton
+End Function
+%>
diff --git a/app/repositories/PostsRepository.asp b/app/repositories/PostsRepository.asp
new file mode 100644
index 0000000..3a50e60
--- /dev/null
+++ b/app/repositories/PostsRepository.asp
@@ -0,0 +1,176 @@
+<%
+' Auto-generated Repository for table [Posts]
+' Generated on 5/2/2026 9:48:11 PM
+' Generator: GenerateRepo.vbs v1.0
+'
+' Dependencies:
+' - core/lib.DAL.asp (DAL singleton for database access)
+' - core/lib.AutoMapper.asp (Automapper for object mapping)
+' - core/lib.Collections.asp (LinkedList_Class)
+' - core/lib.helpers.asp (KVUnzip, BuildOrderBy, QI, Destroy)
+
+
+Class PostsRepository_Class
+
+ Public Function FindByID(id)
+ Dim sql : sql = "Select [Body], [CategoryID], [CreatedDate], [IsPublished], [PostID], [PublishedDate], [Slug], [Summary], [Title], [UpdatedDate] FROM [Posts] WHERE [PostID] = ?"
+ Dim rs : Set rs = DAL.Query(sql, Array(id))
+ If rs.EOF Then
+ Err.Raise 1, "PostsRepository_Class", RecordNotFoundException("PostID", id)
+ Else
+ Set FindByID = Automapper.AutoMap(rs, "POBO_Posts")
+ End If
+ Destroy rs
+ End Function
+
+ Public Function GetAll(orderBy)
+ Set GetAll = Find(Empty, orderBy)
+ End Function
+
+ Public Function Find(where_kvarray, order_string_or_array)
+ Dim sql : sql = "Select [Body], [CategoryID], [CreatedDate], [IsPublished], [PostID], [PublishedDate], [Slug], [Summary], [Title], [UpdatedDate] FROM [Posts]"
+ Dim where_keys, where_values, i
+ If Not IsEmpty(where_kvarray) Then
+ KVUnzip where_kvarray, where_keys, where_values
+ If Not IsEmpty(where_keys) Then
+ sql = sql & " WHERE "
+ For i = 0 To UBound(where_keys)
+ If i > 0 Then sql = sql & " AND "
+ sql = sql & " " & QI(where_keys(i)) & " = ?"
+ Next
+ End If
+ End If
+ sql = sql & BuildOrderBy(order_string_or_array, "[PostID]")
+ Dim rs : Set rs = DAL.Query(sql, where_values)
+ Dim list : Set list = new LinkedList_Class
+ Do Until rs.EOF
+ list.Push Automapper.AutoMap(rs, "POBO_Posts")
+ rs.MoveNext
+ Loop
+ Set Find = list
+ Destroy rs
+ End Function
+
+ Public Function FindPaged(where_kvarray, order_string_or_array, per_page, page_num, ByRef page_count, ByRef record_count)
+ Dim sql : sql = "Select [Body], [CategoryID], [CreatedDate], [IsPublished], [PostID], [PublishedDate], [Slug], [Summary], [Title], [UpdatedDate] FROM [Posts]"
+ Dim where_keys, where_values, i
+ If Not IsEmpty(where_kvarray) Then
+ KVUnzip where_kvarray, where_keys, where_values
+ If Not IsEmpty(where_keys) Then
+ sql = sql & " WHERE "
+ For i = 0 To UBound(where_keys)
+ If i > 0 Then sql = sql & " AND "
+ sql = sql & " " & QI(where_keys(i)) & " = ?"
+ Next
+ End If
+ End If
+ sql = sql & BuildOrderBy(order_string_or_array, "[PostID]")
+ Dim rs : Set rs = DAL.PagedQuery(sql, where_values, per_page, page_num)
+ If Not rs.EOF Then
+ rs.PageSize = per_page
+ rs.AbsolutePage = page_num
+ page_count = rs.PageCount
+ record_count = rs.RecordCount
+ End If
+ Set FindPaged = PagedList(rs, per_page)
+ Destroy rs
+ End Function
+
+ Public Function SearchTablePaged(columns_array, search_value, order_string_or_array, per_page, page_num, ByRef page_count, ByRef record_count)
+ Dim sql : sql = "Select [Body], [CategoryID], [CreatedDate], [IsPublished], [PostID], [PublishedDate], [Slug], [Summary], [Title], [UpdatedDate] FROM [Posts]"
+ Dim i, params()
+ If IsArray(columns_array) And UBound(columns_array) >= 0 Then
+ sql = sql & " WHERE "
+ ReDim params(UBound(columns_array))
+ For i = 0 To UBound(columns_array)
+ If i > 0 Then sql = sql & " OR "
+ sql = sql & " " & QI(columns_array(i)) & " LIKE ?"
+ params(i) = "%" & search_value & "%"
+ Next
+ End If
+ sql = sql & BuildOrderBy(order_string_or_array, "[PostID]")
+ Dim rs : Set rs = DAL.PagedQuery(sql, params, per_page, page_num)
+ If Not rs.EOF Then
+ rs.PageSize = per_page
+ rs.AbsolutePage = page_num
+ page_count = rs.PageCount
+ record_count = rs.RecordCount
+ End If
+ Set SearchTablePaged = PagedList(rs, per_page)
+ Destroy rs
+ End Function
+
+ Private Function PagedList(rs, per_page)
+ Dim list : Set list = new LinkedList_Class
+ Dim x : x = 0
+ Do While (per_page <= 0 Or x < per_page) And Not rs.EOF
+ list.Push Automapper.AutoMap(rs, "POBO_Posts")
+ x = x + 1
+ rs.MoveNext
+ Loop
+ Set PagedList = list
+ End Function
+
+ Public Sub AddNew(ByRef model)
+ Dim sql : sql = "INSERT INTO [Posts] ([Body], [CategoryID], [CreatedDate], [IsPublished], [PublishedDate], [Slug], [Summary], [Title], [UpdatedDate]) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
+ DAL.Execute sql, Array(model.Body, model.CategoryID, model.CreatedDate, model.IsPublished, model.PublishedDate, model.Slug, model.Summary, model.Title, model.UpdatedDate)
+
+ ' Retrieve the newly inserted ID
+ On Error Resume Next
+ Dim rsId : Set rsId = DAL.Query("SELECT @@IDENTITY AS NewID", Empty)
+ If Err.Number <> 0 Then
+ ' Fallback for Access databases
+ Err.Clear
+ Set rsId = DAL.Query("SELECT TOP 1 [PostID] FROM [Posts] ORDER BY [PostID] DESC", Empty)
+ End If
+ On Error GoTo 0
+
+ If Not rsId.EOF Then
+ If Not IsNull(rsId(0)) Then model.PostID = rsId(0)
+ End If
+ Destroy rsId
+ End Sub
+
+ Public Sub Update(model)
+ Dim sql : sql = "UPDATE [Posts] SET [Body] = ?, [CategoryID] = ?, [CreatedDate] = ?, [IsPublished] = ?, [PublishedDate] = ?, [Slug] = ?, [Summary] = ?, [Title] = ?, [UpdatedDate] = ? WHERE [PostID] = ?"
+ DAL.Execute sql, Array(model.Body, model.CategoryID, model.CreatedDate, model.IsPublished, model.PublishedDate, model.Slug, model.Summary, model.Title, model.UpdatedDate, model.PostID)
+ End Sub
+
+ Public Sub Delete(id)
+ Dim sql : sql = "DELETE FROM [Posts] WHERE [PostID] = ?"
+ DAL.Execute sql, Array(id)
+ End Sub
+
+ Private Function RecordNotFoundException(ByVal field_name, ByVal field_val)
+ RecordNotFoundException = "Posts record was not found with " & field_name & " = '" & field_val & "'."
+ End Function
+
+ Private Function QI(name)
+ QI = "[" & Replace(CStr(name), "]", "]]") & "]"
+ End Function
+
+ Private Function BuildOrderBy(orderArg, defaultCol)
+ Dim s : s = ""
+ If IsEmpty(orderArg) Or IsNull(orderArg) Or orderArg = "" Then
+ s = " ORDER BY " & defaultCol & " ASC"
+ ElseIf IsArray(orderArg) Then
+ Dim i : s = " ORDER BY "
+ For i = 0 To UBound(orderArg)
+ If i > 0 Then s = s & ", "
+ s = s & QI(orderArg(i))
+ Next
+ Else
+ s = " ORDER BY " & QI(orderArg)
+ End If
+ BuildOrderBy = s
+ End Function
+End Class
+
+Dim PostsRepository__Singleton
+Function PostsRepository()
+ If IsEmpty(PostsRepository__Singleton) Then
+ Set PostsRepository__Singleton = new PostsRepository_Class
+ End If
+ Set PostsRepository = PostsRepository__Singleton
+End Function
+%>
diff --git a/app/repositories/autoload_repositories.asp b/app/repositories/autoload_repositories.asp
new file mode 100644
index 0000000..37e1f5d
--- /dev/null
+++ b/app/repositories/autoload_repositories.asp
@@ -0,0 +1,3 @@
+
+
+
diff --git a/core/lib.ControllerRegistry.asp b/core/lib.ControllerRegistry.asp
index 0b563d8..49955b8 100644
--- a/core/lib.ControllerRegistry.asp
+++ b/core/lib.ControllerRegistry.asp
@@ -15,6 +15,9 @@ Class ControllerRegistry_Class
' Format: m_controllers.Add "controllername", True
RegisterController "homecontroller"
RegisterController "errorcontroller"
+ RegisterController "categoriescontroller"
+ RegisterController "postscontroller"
+ RegisterController "commentscontroller"
End Sub
Private Sub Class_Terminate()
diff --git a/core/mvc.asp b/core/mvc.asp
index 0bbf373..87db704 100644
--- a/core/mvc.asp
+++ b/core/mvc.asp
@@ -1,3 +1,5 @@
+
+
<%
' Set cache expiration from configuration
diff --git a/db/migrations/20260324110000_add_do_not_call_fields_to_households.asp b/db/migrations/20260324110000_add_do_not_call_fields_to_households.asp
deleted file mode 100644
index f187469..0000000
--- a/db/migrations/20260324110000_add_do_not_call_fields_to_households.asp
+++ /dev/null
@@ -1,23 +0,0 @@
-<%
-'=======================================================================================================================
-' MIGRATION: add_do_not_call_fields_to_households
-'=======================================================================================================================
-
-Sub Migration_Up(migration)
- migration.AddColumn "Households", "DoNotCall", "SMALLINT"
- migration.AddColumn "Households", "DoNotCallDate", "DATETIME"
- migration.AddColumn "Households", "DoNotCallNotes", "LONGTEXT"
- migration.AddColumn "Households", "DoNotCallPrivateNotes", "LONGTEXT"
-
- migration.ExecuteSQL "UPDATE Households SET DoNotCall = 0 WHERE DoNotCall IS NULL"
- migration.CreateIndex "IX_Households_DoNotCall", "Households", "DoNotCall"
-End Sub
-
-Sub Migration_Down(migration)
- migration.DropIndex "IX_Households_DoNotCall", "Households"
- migration.DropColumn "Households", "DoNotCallPrivateNotes"
- migration.DropColumn "Households", "DoNotCallNotes"
- migration.DropColumn "Households", "DoNotCallDate"
- migration.DropColumn "Households", "DoNotCall"
-End Sub
-%>
diff --git a/db/migrations/20260502210000_create_categories_table.asp b/db/migrations/20260502210000_create_categories_table.asp
new file mode 100644
index 0000000..c4035b3
--- /dev/null
+++ b/db/migrations/20260502210000_create_categories_table.asp
@@ -0,0 +1,20 @@
+<%
+'=======================================================================================================================
+' MIGRATION: create_categories_table
+'=======================================================================================================================
+
+Sub Migration_Up(migration)
+ migration.CreateTable "Categories", _
+ "CategoryID COUNTER CONSTRAINT PK_Categories PRIMARY KEY, " & _
+ "Name TEXT(200) NOT NULL, " & _
+ "Slug TEXT(200) NOT NULL, " & _
+ "Description MEMO"
+
+ migration.CreateIndex "IX_Categories_Slug", "Categories", "Slug"
+End Sub
+
+Sub Migration_Down(migration)
+ migration.DropIndex "IX_Categories_Slug", "Categories"
+ migration.DropTable "Categories"
+End Sub
+%>
diff --git a/db/migrations/20260502210100_create_posts_table.asp b/db/migrations/20260502210100_create_posts_table.asp
new file mode 100644
index 0000000..4c08bf2
--- /dev/null
+++ b/db/migrations/20260502210100_create_posts_table.asp
@@ -0,0 +1,31 @@
+<%
+'=======================================================================================================================
+' MIGRATION: create_posts_table
+'=======================================================================================================================
+
+Sub Migration_Up(migration)
+ migration.CreateTable "Posts", _
+ "PostID COUNTER CONSTRAINT PK_Posts PRIMARY KEY, " & _
+ "Title TEXT(200) NOT NULL, " & _
+ "Slug TEXT(200) NOT NULL, " & _
+ "Summary MEMO, " & _
+ "Body MEMO, " & _
+ "CategoryID LONG, " & _
+ "IsPublished SMALLINT NOT NULL, " & _
+ "PublishedDate DATETIME, " & _
+ "CreatedDate DATETIME NOT NULL, " & _
+ "UpdatedDate DATETIME"
+
+ migration.ExecuteSQL "UPDATE Posts SET IsPublished = 0 WHERE IsPublished IS NULL"
+ migration.CreateIndex "IX_Posts_Slug", "Posts", "Slug"
+ migration.CreateIndex "IX_Posts_CategoryID", "Posts", "CategoryID"
+ migration.CreateIndex "IX_Posts_IsPublished", "Posts", "IsPublished"
+End Sub
+
+Sub Migration_Down(migration)
+ migration.DropIndex "IX_Posts_IsPublished", "Posts"
+ migration.DropIndex "IX_Posts_CategoryID", "Posts"
+ migration.DropIndex "IX_Posts_Slug", "Posts"
+ migration.DropTable "Posts"
+End Sub
+%>
diff --git a/db/migrations/20260502210200_create_comments_table.asp b/db/migrations/20260502210200_create_comments_table.asp
new file mode 100644
index 0000000..f4ac25c
--- /dev/null
+++ b/db/migrations/20260502210200_create_comments_table.asp
@@ -0,0 +1,26 @@
+<%
+'=======================================================================================================================
+' MIGRATION: create_comments_table
+'=======================================================================================================================
+
+Sub Migration_Up(migration)
+ migration.CreateTable "Comments", _
+ "CommentID COUNTER CONSTRAINT PK_Comments PRIMARY KEY, " & _
+ "PostID LONG NOT NULL, " & _
+ "AuthorName TEXT(200) NOT NULL, " & _
+ "AuthorEmail TEXT(200), " & _
+ "Body MEMO NOT NULL, " & _
+ "IsApproved SMALLINT NOT NULL, " & _
+ "CreatedDate DATETIME NOT NULL"
+
+ migration.ExecuteSQL "UPDATE Comments SET IsApproved = 0 WHERE IsApproved IS NULL"
+ migration.CreateIndex "IX_Comments_PostID", "Comments", "PostID"
+ migration.CreateIndex "IX_Comments_IsApproved", "Comments", "IsApproved"
+End Sub
+
+Sub Migration_Down(migration)
+ migration.DropIndex "IX_Comments_IsApproved", "Comments"
+ migration.DropIndex "IX_Comments_PostID", "Comments"
+ migration.DropTable "Comments"
+End Sub
+%>
diff --git a/public/Default.asp b/public/Default.asp
index 61c5a91..8702378 100644
--- a/public/Default.asp
+++ b/public/Default.asp
@@ -7,6 +7,28 @@
router.AddRoute "GET", "", "HomeController", "Index"
router.AddRoute "GET", "/404", "ErrorController", "NotFound"
+ ' Categories routes
+ router.AddRoute "GET", "/categories", "CategoriesController", "Index"
+ router.AddRoute "GET", "/categories/new", "CategoriesController", "New"
+ router.AddRoute "POST", "/categories", "CategoriesController", "Create"
+ router.AddRoute "GET", "/categories/{id}", "CategoriesController", "Show"
+ router.AddRoute "GET", "/categories/{id}/edit", "CategoriesController", "Edit"
+ router.AddRoute "POST", "/categories/{id}", "CategoriesController", "Update"
+ router.AddRoute "POST", "/categories/{id}/delete","CategoriesController","Delete"
+
+ ' Posts routes
+ router.AddRoute "GET", "/posts", "PostsController", "Index"
+ router.AddRoute "GET", "/posts/new", "PostsController", "New"
+ router.AddRoute "POST", "/posts", "PostsController", "Create"
+ router.AddRoute "GET", "/posts/{slug}", "PostsController", "Show"
+ router.AddRoute "GET", "/posts/{id}/edit", "PostsController", "Edit"
+ router.AddRoute "POST", "/posts/{id}", "PostsController", "Update"
+ router.AddRoute "POST", "/posts/{id}/delete", "PostsController", "Delete"
+
+ ' Comments routes
+ router.AddRoute "POST", "/comments", "CommentsController", "Create"
+ router.AddRoute "POST", "/comments/{id}/delete", "CommentsController", "Delete"
+
' Dispatch the request (resolves route and executes controller action)
MVC.DispatchRequest Request.ServerVariables("REQUEST_METHOD"), _
TrimQueryParams(Request.ServerVariables("HTTP_X_ORIGINAL_URL"))