Skip to main content
The BookmarkStore manages the application’s bookmark state, including CRUD operations, filtering by tags, sorting, and time period selection. Built with Zustand for global state management.

Import

import { useBookmarkStore } from "../stores/BookmarkStore"

Usage

const AddBookmark = () => {
  const { 
    fetch: getBookmarks, 
    add: createBookmark, 
    bookmarks, 
    loading, 
    setSelectedTag, 
    order, 
    setOrder 
  } = useBookmarkStore(state => ({
    fetch: state.fetch,
    add: state.add,
    bookmarks: state.bookmarks,
    loading: state.loading,
    setSelectedTag: state.setSelectedTag,
    order: state.order,
    setOrder: state.setOrder
  }))

  const userId = session?.user.id

  const handleCreate = async () => {
    const response = await createBookmark(url, userId)
    if (response.success) {
      await getBookmarks(userId)
      setSelectedTag("all")
    }
  }

  return (
    <button onClick={() => setOrder(order === "asc" ? "desc" : "asc")}>
      {order === "asc" ? "Oldest first" : "Newest first"}
    </button>
  )
}

State Properties

bookmarks
Bookmark[]
default:"[]"
Array of bookmark objects. Each bookmark contains id, title, domain, url, description, image, created_at, saved_by, tags, and pinned properties.
loading
boolean
default:"false"
Loading state for async operations (fetch, add, delete, update).
selectedTag
string
default:"'all'"
Currently selected tag filter. Set to "all" to show all bookmarks.
order
Order
default:"'desc'"
Sort order for bookmarks. Can be "asc" (oldest first) or "desc" (newest first).
timePeriod
TimePeriod
default:"'all'"
Time period filter for bookmarks. Options: "all", "month", or "week".

Methods

fetch

Fetches all bookmarks for a specific user from Supabase.
userId
string
required
The user ID to fetch bookmarks for.
Returns: Promise<StoreResponse>
success
boolean
Whether the operation succeeded.
data
Bookmark[] | string
Array of bookmarks on success, error message string on failure.
const getBookmarks = useBookmarkStore(state => state.fetch)

const loadBookmarks = async () => {
  const response = await getBookmarks(userId)
  if (response.success) {
    console.log("Bookmarks loaded:", response.data)
  } else {
    console.error("Error:", response.data)
  }
}

add

Adds a new bookmark by fetching metadata from the URL.
url
string
required
The URL to bookmark. Must be a valid URL starting with https://.
savedBy
string
required
The user ID of the person saving the bookmark.
Returns: Promise<StoreResponse>
const createBookmark = useBookmarkStore(state => state.add)

const handleCreate = async () => {
  const response = await createBookmark("https://example.com", userId)
  if (!response.success) {
    showErrorToast(response.data)
  } else {
    showSuccessToast("Bookmark added successfully!")
  }
}

delete

Deletes a bookmark and updates the local state.
bookmarkId
number
required
The ID of the bookmark to delete.
Returns: Promise<StoreResponse>
const deleteBookmark = useBookmarkStore(state => state.delete)

const handleDelete = async (id: number) => {
  const response = await deleteBookmark(id)
  if (response.success) {
    console.log("Bookmark deleted")
  }
}

update

Updates an existing bookmark.
bookmarkId
number
required
The ID of the bookmark to update.
updatedBookmark
Bookmark
required
The updated bookmark object with new values.
Returns: Promise<StoreResponse>
const updateBookmark = useBookmarkStore(state => state.update)

const handleUpdate = async (id: number, bookmark: Bookmark) => {
  const response = await updateBookmark(id, bookmark)
  if (response.success) {
    await getBookmarks(userId)
  }
}

setSelectedTag

Sets the currently selected tag filter.
tag
string
required
The tag name to filter by, or "all" to show all bookmarks.
const setSelectedTag = useBookmarkStore(state => state.setSelectedTag)

setSelectedTag("design")
setSelectedTag("all") // Show all bookmarks

setOrder

Sets the sort order for bookmarks.
order
Order
required
The sort order: "asc" (oldest first) or "desc" (newest first).
const { order, setOrder } = useBookmarkStore(state => ({
  order: state.order,
  setOrder: state.setOrder
}))

const toggleOrder = () => {
  setOrder(order === "asc" ? "desc" : "asc")
}

setTimePeriod

Sets the time period filter for bookmarks.
period
TimePeriod
required
The time period: "all", "month", or "week".
const setTimePeriod = useBookmarkStore(state => state.setTimePeriod)

setTimePeriod("week") // Show bookmarks from last week
setTimePeriod("all")  // Show all bookmarks

Type Definitions

type Order = "asc" | "desc"
type TimePeriod = "all" | "month" | "week"

type Bookmark = {
  id: number
  title: string
  domain: string
  url: string
  description: string
  image: string
  created_at: string
  saved_by: string
  tags: string[]
  pinned: boolean
}

type StoreResponse = 
  | { data: Bookmark[], success: true }
  | { data: string, success: false }

Implementation Details

  • State Management: Uses Zustand for lightweight, hook-based state management
  • Database: All CRUD operations interact with Supabase
  • Metadata Fetching: The add method automatically fetches page metadata (title, description, images) from the provided URL
  • Optimistic Updates: Delete and update methods immediately update local state for responsive UI
  • Error Handling: All async methods return a StoreResponse object with success flag and data payload
  • Automatic Sorting: Bookmarks are fetched sorted by pinned status (descending) then created_at (descending)

Build docs developers (and LLMs) love