diff of 2359b53912b3eb167072e1f83da49c0869d32515

2359b53912b3eb167072e1f83da49c0869d32515
diff --git a/aggressive-murja.asd b/aggressive-murja.asd
index e8245db..58bc4f5 100644
--- a/aggressive-murja.asd
+++ b/aggressive-murja.asd
@@ -41,7 +41,8 @@
 			       (:file "migrations")
 			       (:file "json")))
 		 (:module "murja-newui"
-		  :components ((:file "newui")))		  
+		  :components ((:file "newui")
+			       (:file "simpledate")))
 		 (:file "migration-list")
 		 (:file "settings")
 		 
@@ -76,11 +77,18 @@
 		   (:file "user-editor")
 		   (:file "root-routes")))
 
+		 (:module "models"
+		  :components
+		  ((:file "user")
+		   (:file "post")))
+
 		 (:module "views"
 		  :components
 		  ((:module "components"
 		    :components ((:file "tab")
-				 (:file "root")))
+				 (:file "root")
+				 (:file "post")
+				 (:file "page")))
 		   (:file "blog-main")))
 		 
 		 (:file "main"))))
diff --git a/src/models/post.lisp b/src/models/post.lisp
new file mode 100644
index 0000000..c83a7b6
--- /dev/null
+++ b/src/models/post.lisp
@@ -0,0 +1,77 @@
+(defpackage murja.models.post
+  (:use :cl)
+  (:export :get-page :get-post :post-id :post-title :article :creator :tags :created-at :post-hidden? :post-unlisted?)
+  (:import-from :com.inuoe.jzon :parse))
+
+(in-package :murja.models.post)
+
+;; fuck it we're moving from hashmaps to clos now 
+(defclass Post ()
+  ;; slots are copied from the table blog.Post, accessors are what I might call these were I designing the db nowadays 
+  ((id :initarg :id :accessor post-id :col-type integer)
+   (title :initarg :title :accessor post-title :col-type string)
+   (content :initarg :content :accessor article :col-type string)
+   (creator :initarg :creator :initform nil :accessor creator)
+   (creator-id :col-type string :reader creator-id)
+   (tags :initarg :tags :accessor tags :col-type string)
+   (created-at :initarg :created-at :accessor created-at :col-type simple-date:timestamp)
+   (hidden :initarg :hidden? :accessor post-hidden? :col-type boolean)
+   (unlisted :initarg :unlisted? :accessor post-unlisted? :col-type boolean))
+  (:metaclass postmodern:dao-class)
+  (:keys id)
+  (:table-name "blog.Post"))
+
+(defmethod print-object ((p Post) output)
+  (with-slots (creator id title content creator-id tags created-at hidden unlisted) p
+    
+    (format output "#<POST: ~{~{~a: ~s~}~^,~%~t ~}>" (list
+						(list :id id)
+						(list :title title)
+						(list :content
+						      (if (> (length content) 50)
+							  (format nil "~a..."
+								  (str:substring 0 50 content))
+							  content))
+						(list :creator-id creator-id)
+						(list :creator creator)
+						(list :tags tags)
+						(list :created-at created-at)
+						(list :hidden hidden)
+						(list :unlisted unlisted)))))
+
+;; (postmodern:query "SELECT * FROM blog.Post limit 1" (:dao post :single))
+;; (postmodern:get-dao 'Post 349)
+;; #<POST: ID: 349, TITLE: "Lisp webapps ", CONTENT: "<p>So, after <a href=\"https://feuerx.net/blog/post...", CREATOR-ID: 1, TAGS: "[\"postgresql\", \"hunchentoot\", \"lisp\", \"programming\"]", CREATED-AT: #<SIMPLE-DATE:TIMESTAMP 22-02-2025T09:31:40,016>, HIDDEN: NIL, UNLISTED: NIL>
+
+(defun fix-post (p) 
+  (setf (tags p) (parse (tags p)))
+  (setf (creator p) (postmodern:get-dao 'murja.models.user:user (creator-id p)))
+  p)
+
+(defun get-post (id)
+  (let ((p (postmodern:get-dao 'Post id)))
+    (fix-post p)
+    p))
+
+(defun get-page (page page-size &key allow-hidden? modified-since)
+  (let* ((page (if (< page 1)
+		   1
+		   page)))
+    (map 'list
+	 #'fix-post 
+	 (postmodern:query
+	  "SELECT p.*
+FROM blog.Post p
+WHERE ((NOT p.unlisted) OR $3)
+  AND ((NOT p.hidden) OR $3)
+  AND (($4::timestamp IS NULL) OR p.created_at > $4::timestamp)
+ORDER BY p.created_at DESC
+LIMIT $2
+OFFSET $1"
+	  (* (1- page) page-size)
+	  page-size
+	  allow-hidden?
+	  (if modified-since
+	      modified-since
+	      :null)
+	  (:dao Post)))))
diff --git a/src/models/user.lisp b/src/models/user.lisp
new file mode 100644
index 0000000..3158fec
--- /dev/null
+++ b/src/models/user.lisp
@@ -0,0 +1,28 @@
+(defpackage murja.models.user
+  (:use :cl)
+  (:export :User :user-id :user-username :user-password :user-nickname :user-img-location))
+
+(in-package :murja.models.user)
+
+(defclass User ()
+  ((id :initarg :id :accessor user-id :col-type integer)
+   (username :initarg :username :accessor user-username :col-type string)
+   (password :initarg :password :accessor user-password :col-type string)
+   (nickname :initarg :nickname :accessor user-nickname :col-type string)
+   (img-location :initarg :img-location :accessor user-img-location :col-type string))   
+
+  (:metaclass postmodern:dao-class)
+  (:keys id)
+  (:table-name "blog.Users"))
+
+(defmethod print-object ((usr User) output)
+  (with-slots (id username nickname img-location) usr
+    
+    (format output "#<USER: ~{~{~a: ~s~}~^,~%~t ~}>" (list
+						  (list :id id)
+						  (list :username username)
+						  (list :nickname nickname)
+						  (list :password "******")
+						  (list :img-location img-location)))))
+
+;; (postmodern:get-dao 'User 1)
diff --git a/src/murja-newui/newui.lisp b/src/murja-newui/newui.lisp
index 187fe51..9280cb7 100644
--- a/src/murja-newui/newui.lisp
+++ b/src/murja-newui/newui.lisp
@@ -103,7 +103,7 @@
 (defmethod render ((s t))
   (prin1-to-string s))
 
-(defparameter *single-element-tags* (list :link :meta :input)
+(defparameter *single-element-tags* (list :link :meta :input :img)
   "Contains tags that don't expand to <:tag attrs>children</:tag> but instead into <:tag attrs />")
 
 (defmethod render ((c component))
diff --git a/src/murja-newui/simpledate.lisp b/src/murja-newui/simpledate.lisp
new file mode 100644
index 0000000..3a3a8e2
--- /dev/null
+++ b/src/murja-newui/simpledate.lisp
@@ -0,0 +1,11 @@
+(defpackage murja.newui.simpledate
+  (:documentation "Provides render method for postmodern's simpledate classes. Do not load if you do not use :D")
+  (:use :cl)
+  (:import-from :murja.newui :render))
+
+(in-package :murja.newui.simpledate)
+
+(defmethod render ((ts simple-date:timestamp))
+  (multiple-value-bind (year month day hour minute second millisec)
+      (simple-date:decode-timestamp ts)
+    (format nil "~2,'0d.~2,'0d.~d ~2,'0d:~2,'0d" day month year hour minute)))
diff --git a/src/views/blog-main.lisp b/src/views/blog-main.lisp
index cb8cd57..a15a0e6 100644
--- a/src/views/blog-main.lisp
+++ b/src/views/blog-main.lisp
@@ -4,7 +4,6 @@
   (:import-from :murja.routes.root-routes :@check-if-initial)
   (:import-from :murja.routes.settings-routes :get-settings)
   (:import-from :murja.middleware.db :@transaction)
-  (:import-from :murja.posts.post-db :get-titles-by-year :get-page )
   (:import-from :murja.newui :@newui :c :with-state)
   (:import-from :easy-routes :defroute))
 
@@ -16,9 +15,8 @@
   (let* ((settings (get-settings))
 	 (page-size (gethash "recent-post-count" settings))
 	 (page 1)
-	 (page-posts (get-page page page-size)))
+	 (page-posts (murja.models.post:get-page page page-size)))
     (root-component
      (tabs "Home"
 	   (hash
-	    ("Home" (c :p () "lol")))))))
-	     
+	    ("Home" (murja.views.components.page:page page-posts)))))))
diff --git a/src/views/components/page.lisp b/src/views/components/page.lisp
new file mode 100644
index 0000000..7b87de5
--- /dev/null
+++ b/src/views/components/page.lisp
@@ -0,0 +1,11 @@
+(defpackage murja.views.components.page
+  (:use :cl :murja.newui :cl-hash-util :binding-arrows )
+  (:export :page))
+
+(in-package :murja.views.components.page)
+
+(defun page (list-of-posts)
+  (component :div (:class "page")
+	     (map 'list (lambda (post)
+			  (murja.views.components.post:post post))
+		  list-of-posts)))
diff --git a/src/views/components/post.lisp b/src/views/components/post.lisp
new file mode 100644
index 0000000..4f8d274
--- /dev/null
+++ b/src/views/components/post.lisp
@@ -0,0 +1,21 @@
+(defpackage murja.views.components.post
+  (:use :cl :murja.newui :cl-hash-util :binding-arrows :murja.models.user :murja.models.post)
+  (:export :post))
+
+(in-package :murja.views.components.post)
+
+(defun post (post)
+  (let ((creator (creator post)))
+    (c :article (:class "post")
+       (c :h2 ()
+	  (c :a (:href (format nil "/blog/post/~d" (post-id post)))
+	     (post-title post)))
+       (c :section (:class "meta")
+	  (c :img (:class "user_avatar" :src (user-img-location creator)))
+	  (c :p () (format nil "By ~a" (user-nickname creator)))
+	  (c :p () "Written at"
+	     (c :time (:datetime (created-at post))
+		(created-at post))))
+
+       (c :section (:class "content") (article post)))))
+