diff --git a/bin/bootstrap.sh b/bin/bootstrap.sh
index 398c526219..263f615d0a 100755
--- a/bin/bootstrap.sh
+++ b/bin/bootstrap.sh
@@ -6,6 +6,7 @@ set -ev
# Runs the following tasks in order:
# - Install dependencies
# - Build `@zooniverse/react-components`
+# - Build `@zooniverse/lib-user`
# - Build `@zooniverse/lib-classifier`
@@ -16,6 +17,10 @@ printf 'Building `lib-react-components`...\n'
yarn workspace @zooniverse/react-components install --frozen-lockfile
printf '\n'
+printf 'Building `lib-user`...\n'
+yarn workspace @zooniverse/user install --frozen-lockfile
+printf '\n'
+
printf 'Building `lib-classifier`...\n'
yarn workspace @zooniverse/classifier install --frozen-lockfile
printf '\n'
diff --git a/bin/bootstrap:es6.sh b/bin/bootstrap:es6.sh
index 29da7431cf..83ea8d71ad 100755
--- a/bin/bootstrap:es6.sh
+++ b/bin/bootstrap:es6.sh
@@ -6,6 +6,7 @@ set -ev
# Runs the following tasks in order:
# - Install dependencies
# - Build `@zooniverse/react-components`
+# - Build `@zooniverse/lib-user`
# - Build `@zooniverse/lib-classifier`
@@ -20,6 +21,10 @@ printf 'Building `lib-react-components`...\n'
yarn workspace @zooniverse/react-components build:es6
printf '\n'
+printf 'Building `lib-user`...\n'
+yarn workspace @zooniverse/user build:es6
+printf '\n'
+
printf 'Building `lib-classifier`...\n'
yarn workspace @zooniverse/classifier build:es6
printf '\n'
diff --git a/docs/arch/README.md b/docs/arch/README.md
index 090fa8fea0..628bcdc814 100644
--- a/docs/arch/README.md
+++ b/docs/arch/README.md
@@ -54,3 +54,4 @@
- [ADR 52: User Stats Page](adr-52.md)
- [ADR 53: Logged-In User Homepage](adr-53.md)
- [ADR 54: app-root](adr-54.md)
+- [ADR 55: lib-user](adr-55.md)
diff --git a/docs/arch/adr-51.md b/docs/arch/adr-51.md
index f3c446e750..d4fc9d8a40 100644
--- a/docs/arch/adr-51.md
+++ b/docs/arch/adr-51.md
@@ -30,7 +30,7 @@ Create export member statistics to CSV functionality for applicable user groups.
## Status
-Proposed
+Accepted
## Consequences
diff --git a/docs/arch/adr-52.md b/docs/arch/adr-52.md
index abebabf65b..da85f78603 100644
--- a/docs/arch/adr-52.md
+++ b/docs/arch/adr-52.md
@@ -24,7 +24,7 @@ Create PDF generation feature to document user contributions.
## Status
-Proposed
+Accepted
## Consequences
diff --git a/docs/arch/adr-53.md b/docs/arch/adr-53.md
index 8a78f34ad2..fa959591d6 100644
--- a/docs/arch/adr-53.md
+++ b/docs/arch/adr-53.md
@@ -24,7 +24,7 @@ Refactor recent classifications cards for redesigned logged-in user homepage.
## Status
-Proposed
+Accepted
## Consequences
diff --git a/docs/arch/adr-55.md b/docs/arch/adr-55.md
new file mode 100644
index 0000000000..cde38fc641
--- /dev/null
+++ b/docs/arch/adr-55.md
@@ -0,0 +1,21 @@
+# ADR 55: lib-user
+
+October 2023
+
+## Context
+
+We've decided to build a user stats page ([ADR 52](adr-52.md)), a user group stats page ([ADR 51](adr-51.md)), and a logged-in user homepage ([ADR 53](adr-53.md)). The components for these pages will be built in a new "user library" - `lib-user`. This is in accordance with the decision to build app-root ([ADR 54](adr-54.md)). The app-root will serve the homepage and handle traffic for the domain root, https://zooniverse.org, including `/users` stats pages and `/groups` stats pages, utilizing Next.js 13's App Router and by importing components from `lib-user`.
+
+## Decision
+
+Create a new library `lib-user` to house the components for the user stats page, user group stats page, and logged-in user homepage. The components will be based on the [related Figma designs](https://www.figma.com/file/qbqbmR3t5XV6eKcpuRj7mG/Group-Stats) and will utilize the Zooniverse stats service [ERAS](https://github.com/zooniverse/eras) (Enhanced Running Average Stats Service) and [Panoptes](https://github.com/zooniverse/panoptes) resources.
+
+Initially, the components created in `lib-user` will be related to the user stats page, user group stats page, and logged-in user homepage. Subsequently, additional user related components can be added to `lib-user` as needed (for user profile, collections, settings, etc.).
+
+## Status
+
+Proposed
+
+## Consequences
+
+Create `lib-user` and components noted.
diff --git a/packages/lib-user/.babelrc b/packages/lib-user/.babelrc
new file mode 100644
index 0000000000..00e4b83163
--- /dev/null
+++ b/packages/lib-user/.babelrc
@@ -0,0 +1,37 @@
+{
+ "plugins": [
+ ["@babel/plugin-transform-runtime", {
+ "helpers": false
+ }],
+ ["module-resolver", {
+ "alias": {
+ "@components": "./src/components",
+ "@hooks": "./src/hooks",
+ "@utils": "./src/utils"
+ }
+ }]
+ ],
+ "presets": [
+ ["@babel/preset-react", {
+ "runtime": "automatic"
+ }],
+ ["@babel/preset-env", {
+ "modules": "auto"
+ }]
+ ],
+ "env": {
+ "es6": {
+ "presets": [
+ ["@babel/preset-react", {
+ "runtime": "automatic"
+ }],
+ ["@babel/preset-env", {
+ "modules": false,
+ "targets": {
+ "esmodules": true
+ }
+ }]
+ ]
+ }
+ }
+}
diff --git a/packages/lib-user/.gitignore b/packages/lib-user/.gitignore
new file mode 100644
index 0000000000..9d0b71a3c7
--- /dev/null
+++ b/packages/lib-user/.gitignore
@@ -0,0 +1,2 @@
+build
+dist
diff --git a/packages/lib-user/README.md b/packages/lib-user/README.md
new file mode 100644
index 0000000000..b312af129a
--- /dev/null
+++ b/packages/lib-user/README.md
@@ -0,0 +1,55 @@
+# Zooniverse User and User Group Library
+
+A library for the Zooniverse user stats, user group stats, and home pages. The components in this library are intended to be imported into app-root as part of `zooniverse.org/users` and `zooniverse.org/groups`. For example, the UserStats component from this library will be imported into the app-root page at `zooniverse.org/users/[login]/stats`.
+
+
+
+## Run
+
+### Node/yarn
+```sh
+yarn dev
+# yarn storybook
+```
+
+Starts a development server on port 8080 ~~and a Storybook on port 6006~~ by default.
+
+Use `yarn dev` to run a small development environment app at `localhost:8080`.
+
+- a staging user stats page can be loaded by query param: `https://localhost:8080?users=[login]/stats`
+- a staging user group stats page can be loaded by query param: `https://localhost:8080?groups=[user group ID]`
+
+Note: query params are used for local development work, but are not used in production. The production urls related to this library are:
+
+- `https://www.zooniverse.org/users/[login]/stats`
+- `https://www.zooniverse.org/users/[login]/stats/certificate`
+- `https://www.zooniverse.org/groups/[user group ID]`
+
+
+
+
+
+### Technologies
+
+- @zooniverse/panoptes-js - Panoptes API javascript client
+- @zooniverse/react-components - Zooniverse common React components
+- @zooniverse/grommet-theme - Zooniverse brand Grommet theme
+- [React.js](https://reactjs.org/) - Component, virtual DOM based javascript library
+- [Grommet](https://v2.grommet.io/components) - React UI component library
+- [styled-components](https://www.styled-components.com/) - CSS in JS styling library.
diff --git a/packages/lib-user/dev/components/App/App.js b/packages/lib-user/dev/components/App/App.js
new file mode 100644
index 0000000000..331df6caad
--- /dev/null
+++ b/packages/lib-user/dev/components/App/App.js
@@ -0,0 +1,132 @@
+import oauth from 'panoptes-client/lib/oauth.js'
+import { useEffect, useState } from 'react'
+
+import { GroupStats, UserStats } from '@components/index.js'
+
+function App ({
+ groups = null,
+ users = null
+}) {
+ const [loading, setLoading] = useState(false)
+ const [userAuth, setUserAuth] = useState(null)
+
+ useEffect(() => {
+ async function initAuthorization () {
+ setLoading(true)
+
+ try {
+ const userAuth = await oauth.init('357ac7e0e17f6d9b05587477ca98fdb69d70181e674be8e20142e1df97a84d2d')
+ setUserAuth(userAuth)
+ setLoading(false)
+ history.replaceState(null, document.title, location.pathname + location.search)
+ } catch (error) {
+ console.error(error)
+ setLoading(false)
+ }
+ }
+
+ initAuthorization()
+ }, [])
+
+ const login = () => oauth.signIn(window.location.origin)
+ const logout = () => oauth.signOut().then(setUserAuth)
+
+ let content = (
+