diff --git a/.forgejo/workflows/pull_request.yaml b/.forgejo/workflows/pull_request.yaml
new file mode 100644
index 0000000..ef3461d
--- /dev/null
+++ b/.forgejo/workflows/pull_request.yaml
@@ -0,0 +1,40 @@
+on:
+  pull_request:
+    types: [opened, synchronize, reopened]
+
+defaults:
+  run:
+    shell: bash
+
+jobs:
+  library_snapshot:
+    runs-on: docker
+    container:
+      image: registry.garrity.co:8443/gs/ci-scala:latest
+    name: 'Build and Test Application Snapshot'
+    env:
+      GS_MAVEN_USER: ${{ vars.GS_MAVEN_USER }}
+      GS_MAVEN_TOKEN: ${{ secrets.GS_MAVEN_TOKEN }}
+    steps:
+      - uses: actions/checkout@v4
+        name: 'Checkout Repository'
+        with:
+          fetch-depth: 0
+      - name: 'Pre-Commit'
+        run: |
+          pre-commit install
+          pre-commit run --all-files
+      - name: 'Prepare Versioned Build'
+        run: |
+          latest_git_tag="$(git describe --tags --abbrev=0 || echo 'No Tags')"
+          latest_commit_message="$(git show -s --format=%s HEAD)"
+          echo "Previous Git Tag: $latest_git_tag"
+          echo "Latest Commit: $latest_commit_message (SNAPSHOT)"
+          sbtn -Dsnapshot=true "api/calVerInfo"
+      - name: 'Unit Tests and Code Coverage'
+        run: |
+          sbtn clean
+          sbtn coverage
+          sbtn test
+          sbtn coverageReport
+          sbtn coverageAggregate
diff --git a/.forgejo/workflows/release.yaml b/.forgejo/workflows/release.yaml
new file mode 100644
index 0000000..618672a
--- /dev/null
+++ b/.forgejo/workflows/release.yaml
@@ -0,0 +1,53 @@
+on:
+  push:
+    branches:
+      - main
+
+defaults:
+  run:
+    shell: bash
+
+jobs:
+  application_release:
+    runs-on: docker
+    container:
+      image: registry.garrity.co:8443/gs/ci-scala:latest
+    name: 'Build and Release Application'
+    env:
+      GS_MAVEN_USER: ${{ vars.GS_MAVEN_USER }}
+      GS_MAVEN_TOKEN: ${{ secrets.GS_MAVEN_TOKEN }}
+    steps:
+      - uses: actions/checkout@v4
+        name: 'Checkout Repository'
+        with:
+          fetch-depth: 0
+      - name: 'Pre-Commit'
+        run: |
+          pre-commit install
+          pre-commit run --all-files
+      - name: 'Prepare Versioned Build'
+        run: |
+          latest_git_tag="$(git describe --tags --abbrev=0 || echo 'No Tags')"
+          latest_commit_message="$(git show -s --format=%s HEAD)"
+          echo "Previous Git Tag: $latest_git_tag"
+          echo "Latest Commit: $latest_commit_message"
+          sbtn -Drelease=true api/calVerInfo
+      - name: 'Unit Tests and Code Coverage'
+        run: |
+          sbtn clean
+          sbtn coverage
+          sbtn test
+          sbtn coverageReport
+          sbtn coverageAggregate
+      - name: 'Publish Release'
+        run: |
+          sbtn coverageOff
+          sbtn clean
+          sbtn api/calVerWriteVersionToFile
+          sbtn compile
+      - name: 'Create Git Tag'
+        run: |
+          selected_version="$(cat .version)"
+          echo "TAGGING IS CURRENTLY TURNED OFF -- $selected_version"
+          #git tag "$selected_version"
+          #git push origin "$selected_version"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0e79824
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+target/
+project/target/
+project/project/
+.version
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..fbcf79c
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,16 @@
+---
+repos:
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v4.5.0
+    hooks:
+      - id: end-of-file-fixer
+      - id: trailing-whitespace
+      - id: fix-byte-order-marker
+      - id: mixed-line-ending
+        args: ['--fix=lf']
+        description: Enforces using only 'LF' line endings.
+      - id: trailing-whitespace
+  - repo: https://git.garrity.co/garrity-software/gs-pre-commit-scala
+    rev: v1.0.1
+    hooks:
+      - id: scalafmt
diff --git a/.scalafmt.conf b/.scalafmt.conf
new file mode 100644
index 0000000..9c7929b
--- /dev/null
+++ b/.scalafmt.conf
@@ -0,0 +1,72 @@
+// See: https://github.com/scalameta/scalafmt/tags for the latest tags.
+version = 3.8.1
+runner.dialect = scala3
+maxColumn = 80
+
+rewrite {
+    rules = [RedundantBraces, RedundantParens, Imports, SortModifiers]
+    imports.expand = true
+    imports.sort = scalastyle
+    redundantBraces.ifElseExpressions = true
+    redundantBraces.stringInterpolation = true
+}
+
+indent {
+    main = 2
+    callSite = 2
+    defnSite = 2
+    extendSite = 4
+    withSiteRelativeToExtends = 2
+    commaSiteRelativeToExtends = 2
+}
+
+align {
+    preset = more
+    openParenCallSite = false
+    openParenDefnSite = false
+}
+
+newlines {
+    implicitParamListModifierForce = [before,after]
+    topLevelStatementBlankLines = [
+        {
+            blanks = 1
+        }
+    ]
+    afterCurlyLambdaParams = squash
+}
+
+danglingParentheses {
+    defnSite = true
+    callSite = true
+    ctrlSite = true
+    exclude = []
+}
+
+verticalMultiline {
+    atDefnSite = true
+    arityThreshold = 2
+    newlineAfterOpenParen = true
+}
+
+comments {
+    wrap = standalone
+}
+
+docstrings {
+    style = "SpaceAsterisk"
+    oneline = unfold
+    wrap = yes
+    forceBlankLineBefore = true
+}
+
+project {
+  excludePaths = [
+    "glob:**target/**",
+    "glob:**.metals/**",
+    "glob:**.bloop/**",
+    "glob:**.bsp/**",
+    "glob:**metals.sbt",
+    "glob:**.git/**"
+  ]
+}
diff --git a/build.sbt b/build.sbt
new file mode 100644
index 0000000..43a1894
--- /dev/null
+++ b/build.sbt
@@ -0,0 +1,98 @@
+val scala3: String = "3.4.1"
+
+ThisBuild / scalaVersion  := scala3
+ThisBuild / gsProjectName := "smolban"
+
+ThisBuild / externalResolvers := Seq(
+  "Garrity Software Mirror" at "https://maven.garrity.co/releases",
+  "Garrity Software Releases" at "https://maven.garrity.co/gs"
+)
+
+lazy val sharedSettings = Seq(
+  scalaVersion        := scala3,
+  version             := calVer.value,
+  publish / skip      := true,
+  publishLocal / skip := true,
+  publishArtifact     := false
+)
+
+val Deps = new {
+  val Cats = new {
+    val Core: ModuleID   = "org.typelevel" %% "cats-core"   % "2.10.0"
+    val Effect: ModuleID = "org.typelevel" %% "cats-effect" % "3.5.4"
+  }
+
+  val Fs2 = new {
+    val Core: ModuleID = "co.fs2" %% "fs2-core" % "3.10.2"
+  }
+
+  val Doobie = new {
+    val Core: ModuleID = "org.tpolecat" %% "doobie-core" % "1.0.0-M5"
+  }
+
+  val Http4s = new {
+    val Core: ModuleID = "org.http4s" %% "http4s-core" % "1.0.0-M41"
+    val Dsl: ModuleID  = "org.http4s" %% "http4s-dsl"  % "1.0.0-M41"
+    val EmberServer: ModuleID =
+      "org.http4s" %% "http4s-ember-server" % "1.0.0-M41"
+  }
+
+  val Gs = new {
+    val Uuid: ModuleID    = "gs" %% "gs-uuid-v0"         % "0.2.4"
+    val Slug: ModuleID    = "gs" %% "gs-slug-v0"         % "0.1.3"
+    val Config: ModuleID  = "gs" %% "gs-config-v0"       % "0.1.1"
+    val Datagen: ModuleID = "gs" %% "gs-datagen-core-v0" % "0.1.1"
+  }
+
+  val MUnit: ModuleID = "org.scalameta" %% "munit" % "1.0.0-RC1"
+}
+
+lazy val testSettings = Seq(
+  libraryDependencies ++= Seq(
+    Deps.MUnit      % Test,
+    Deps.Gs.Datagen % Test
+  )
+)
+
+lazy val smolban = project
+  .in(file("."))
+  .aggregate(model, db, api)
+  .settings(sharedSettings)
+  .settings(name := s"${gsProjectName.value}")
+
+lazy val model = project
+  .in(file("modules/model"))
+  .settings(sharedSettings)
+  .settings(testSettings)
+  .settings(name := s"${gsProjectName.value}-model")
+  .settings(
+    libraryDependencies ++= Seq(
+      Deps.Gs.Uuid,
+      Deps.Gs.Slug,
+      Deps.Cats.Core
+    )
+  )
+
+lazy val db = project
+  .in(file("modules/db"))
+  .settings(sharedSettings)
+  .settings(testSettings)
+  .settings(name := s"${gsProjectName.value}-db")
+  .settings(
+    libraryDependencies ++= Seq(
+      Deps.Doobie.Core
+    )
+  )
+
+lazy val api = project
+  .in(file("modules/api"))
+  .settings(sharedSettings)
+  .settings(testSettings)
+  .settings(name := s"${gsProjectName.value}-api")
+  .settings(
+    libraryDependencies ++= Seq(
+      Deps.Http4s.Core,
+      Deps.Http4s.Dsl,
+      Deps.Http4s.EmberServer
+    )
+  )
diff --git a/modules/model/src/main/scala/gs/smolban/model/CreatedAt.scala b/modules/model/src/main/scala/gs/smolban/model/CreatedAt.scala
new file mode 100644
index 0000000..243c775
--- /dev/null
+++ b/modules/model/src/main/scala/gs/smolban/model/CreatedAt.scala
@@ -0,0 +1,34 @@
+package gs.smolban.model
+
+import java.time.Instant
+import cats.Show
+
+/**
+  * Describes an instant at which something was created. Opaque type for 
+  * `java.time.Instant`.
+  */
+opaque type CreatedAt = Instant
+
+object CreatedAt:
+
+  /**
+   * Instantiate a new [[CreatedAt]].
+   *
+   * @param timestamp The underlying timestamp.
+   * @return The new instance.
+   */
+  def apply(timestamp: Instant): CreatedAt = timestamp
+
+  given CanEqual[CreatedAt, CreatedAt] = CanEqual.derived
+
+  given Show[CreatedAt] = _.toInstant().toString()
+
+  extension (createdAt: CreatedAt)
+    /**
+     * Unwrap this value.
+     *
+     * @return The underlying `Instant` value.
+     */
+    def toInstant(): Instant = createdAt
+
+end CreatedAt
diff --git a/modules/model/src/main/scala/gs/smolban/model/Group.scala b/modules/model/src/main/scala/gs/smolban/model/Group.scala
new file mode 100644
index 0000000..f161145
--- /dev/null
+++ b/modules/model/src/main/scala/gs/smolban/model/Group.scala
@@ -0,0 +1,52 @@
+package gs.smolban.model
+
+import gs.uuid.v0.UUID
+import gs.slug.v0.Slug
+import cats.Show
+
+/**
+  * Groups are the basic unit of organization in Smolban. Each [[Ticket]] 
+  * belongs to a single `Group`.
+  *
+  * @param id The unique identifier for the group.
+  * @param slug The unique slug for the group.
+  * @param createdAt The instant at which this group was created.
+  */
+case class Group(
+  id: Group.Id,
+  slug: Slug,
+  createdAt: CreatedAt
+)
+
+object Group:
+
+  /**
+   * Unique identifier for a [[Group]]. This is an opaque type for a UUID.
+   */
+  opaque type Id = UUID
+
+  object Id:
+
+    /**
+     * Instantiate a new [[Group.Id]].
+     *
+     * @param id The underlying UUID.
+     * @return The new [[Group.Id]] instance.
+     */
+    def apply(id: UUID): Id = id
+
+    given CanEqual[Id, Id] = CanEqual.derived
+
+    given Show[Id] = _.toUUID().withoutDashes()
+
+    extension (id: Id)
+      /**
+       * Unwrap this Group ID.
+       *
+       * @return The underlying UUID value.
+       */
+      def toUUID(): UUID = id
+
+  end Id
+
+end Group
diff --git a/modules/model/src/main/scala/gs/smolban/model/Ticket.scala b/modules/model/src/main/scala/gs/smolban/model/Ticket.scala
new file mode 100644
index 0000000..c9eef9c
--- /dev/null
+++ b/modules/model/src/main/scala/gs/smolban/model/Ticket.scala
@@ -0,0 +1,44 @@
+package gs.smolban.model
+
+import cats.Show
+
+case class Ticket(
+  id: Long,
+  group: Group.Id,
+  createdAt: CreatedAt
+)
+
+object Ticket:
+
+  /**
+   * Unique identifier - relative to some [[Group]] - for a [[Ticket]]. This is 
+   * an opaque type for a Long. In general, [[Ticket]] identifiers are sequences 
+   * within a group.
+   */
+  opaque type Id = Long
+
+  object Id:
+
+    /**
+     * Instantiate a new [[Ticket.Id]].
+     *
+     * @param id The underlying Long.
+     * @return The new [[Ticket.Id]] instance.
+     */
+    def apply(id: Long): Id = id
+
+    given CanEqual[Id, Id] = CanEqual.derived
+
+    given Show[Id] = _.toLong().toString()
+
+    extension (id: Id)
+      /**
+       * Unwrap this Ticket ID.
+       *
+       * @return The underlying Long value.
+       */
+      def toLong(): Long = id
+
+  end Id
+
+end Ticket
diff --git a/project/build.properties b/project/build.properties
new file mode 100644
index 0000000..081fdbb
--- /dev/null
+++ b/project/build.properties
@@ -0,0 +1 @@
+sbt.version=1.10.0
diff --git a/project/plugins.sbt b/project/plugins.sbt
new file mode 100644
index 0000000..776be07
--- /dev/null
+++ b/project/plugins.sbt
@@ -0,0 +1,33 @@
+def selectCredentials(): Credentials =
+  if ((Path.userHome / ".sbt" / ".credentials").exists())
+    Credentials(Path.userHome / ".sbt" / ".credentials")
+  else
+    Credentials.apply(
+      realm = "Reposilite",
+      host = "maven.garrity.co",
+      userName = sys.env
+        .get("GS_MAVEN_USER")
+        .getOrElse(
+          throw new RuntimeException(
+            "You must either provide ~/.sbt/.credentials or specify the GS_MAVEN_USER environment variable."
+          )
+        ),
+      passwd = sys.env
+        .get("GS_MAVEN_TOKEN")
+        .getOrElse(
+          throw new RuntimeException(
+            "You must either provide ~/.sbt/.credentials or specify the GS_MAVEN_TOKEN environment variable."
+          )
+        )
+    )
+
+credentials += selectCredentials()
+
+externalResolvers := Seq(
+  "Garrity Software Mirror" at "https://maven.garrity.co/releases",
+  "Garrity Software Releases" at "https://maven.garrity.co/gs"
+)
+
+addSbtPlugin("org.scoverage" % "sbt-scoverage"        % "2.0.8")
+addSbtPlugin("gs"            % "sbt-garrity-software" % "0.2.0")
+addSbtPlugin("gs"            % "sbt-gs-calver"        % "0.2.0")