Conversation
Import the keepsimple Library feature source from github.com/keepsimpleio/library into keepsimple's existing folder structure, namespaced under `library/` to avoid collisions: - components atoms/molecules/organisms -> src/components/library/ - templates -> src/layouts/library/ - types (+ d.ts type shims) -> src/local-types/library/ - utils -> src/utils/library/ - hooks -> src/hooks/library/ - constants (+ config/seo.config.ts) -> src/constants/library/ - contexts -> src/components/Context/library/ - axios/cookie libs -> src/lib/library/ - client services (src/api + app/api) -> src/api/library/ - code-imported assets -> src/assets/library/ - shared scss -> src/styles/library/ - AGENT.md -> src/components/library/LIBRARY_AGENT.md Excluded per task: package.json/lockfile, node_modules, CI/workflows, .claude/.husky/.idea, eslint/tsconfig, README/docs, Storybook (.storybook + *.stories.*), App-Router routing/infra (app/page, app/layout, loading, app/auth), all NextAuth setup, and route handlers (libraries proxy, geoip /api/user, test-login mock). Imports/deps/auth/route are fixed in later steps.
Copy Library's public/images into public/library/images so they don't collide with keepsimple's public root, and rewrite the three absolute public references in the imported code from /images/... to /library/images/...: - atoms/Icon/Icon.tsx — SVG sprite href (/library/images/icons/all.svg) - constants/library/seo.config.ts — default OG image path - layouts/library/Home/Home.tsx — landing cover image JS module imports of assets (@/assets/images/*) are alias rewrites, handled in Step 4.
Add only the runtime packages the migrated Library code imports that
keepsimple was missing (versions from Library, since these are new —
no shared-version conflict). Shared packages (react, react-dom, next,
next-auth, classnames, react-tooltip, date-fns, sass, geoip-lite) keep
keepsimple's existing versions.
Added (dependencies):
- axios ^1.13.4 — Library Strapi client (src/lib/library/axios)
- js-cookie ^3.0.5 — cookie helper (src/lib/library/cookie)
- zod ^4.3.6 — form/validation schemas (src/utils/library/schema)
- react-hook-form ^7.71.1 — forms in modals
- @hookform/resolvers ^5.2.2 — zod<->react-hook-form bridge
- react-dropzone ^15.0.0 — ImageDropzone molecule
- react-day-picker ^10.0.0 — DatePicker molecule
- @dnd-kit/core ^6.3.1, @dnd-kit/sortable ^10.0.0, @dnd-kit/utilities ^3.2.2
— ReorderGrid drag-and-drop
Added (devDependencies):
- @types/js-cookie ^3.0.6 — js-cookie ships no types
Not added: commander/fs-extra (Library generators — not migrated),
Storybook/vitest/playwright tooling (excluded). Single yarn install run
with yarn classic (v1) to keep yarn.lock in its canonical v1 format.
Rewrite Library's @/* aliases to keepsimple's per-folder aliases, relocate assets under @iCons, strip 'use client', convert next/navigation to next/router, and rewire auth to keepsimple's NextAuth + @api/auth. Make the next-auth.d.ts a proper module augmentation so it no longer clobbers next-auth's default export. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add Pages Router entry points for the migrated Library feature: /library (Home) and /library/[username] (dashboard). Both use getServerSideProps for SSR and reuse keepsimple's SeoGenerator instead of next/head blocks. Scope a sassOptions.additionalData injection in next.config.js to library SCSS modules only, so the placeholder selectors the original app injected globally resolve without touching keepsimple's own styles. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add the Library nav item (flagged via isLibraryEnabled), a "My Library" shortcut in the user-profile dropdown, and notFound guards on the library pages when the feature is disabled. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Switch the sticky global header to #F8F1E5 on /library paths (including the dark-theme variant, since the library has no dark mode) so it blends with the library surface. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Retire the old library Header organism in favor of a sticky LibraryToolbar: shelf jump-pills with overflow arrows, a Search Everywhere input, and an Add shelf control that disables at the 21-shelf cap. Adds Input onKeyDown for the search and MAX_SHELVES_PER_LIBRARY. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Move the library's global CSS behind a single library-global entry imported from _app, scope resets under .library, and wrap portaled menus/modals in a .library container so they inherit the tokens. Self-host Source Serif 4 (the Google Fonts @import is blocked by CSP) and declare font-family vars. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Override SVGO's removeViewBox in the SVGR loader so downscaled shelf icons keep their coordinate system instead of cropping, and strip stray blue frame-outline artifacts from the book and video glyphs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Edit a shelf name by clicking it (drop the settings-menu edit entry), drop the doubled brown border on the settings-trigger dropdown, append new shelves at the end with an inline loader instead of a full-screen swap, hide private shelves from non-owners, give overflowing object rows a 12px #C0B6AE scrollbar with 40px top headroom, and glide cards to their new slots after a reorder via a FLIP animation. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add the reorderObjects/reorderShelves endpoints and wire the step-2 ReorderGrid to persist on save. Resolve the shelf id from a passed-in fallback so edit mode no longer silently skips, and sort populated shelves/objects by order:asc so the saved sequence survives a refetch. Stop swallowing reorder errors — log status + body, roll back the optimistic order, and message the user. Also derive the ImageDropzone preview synchronously so the cover no longer flashes empty. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Prefer the optimistically updated currentShelves over the stale one-shot library fetch for the sidebar book/video/song totals so counts bump on upload, and load the tag list on mount so the Tags panel isn't empty until the first mutation. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Always render the tag column (even when empty) and fix container dimensions so book/audio/video cards keep a consistent width with or without tags, and paint the book cover gradient immediately so freshly uploaded covers don't flash blank. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Stamp publishedAt when creating a tag (the content type is draftAndPublish), so newly created tags don't vanish on the next load. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- flatten src/api/library/library/ up one level and split strapi.ts into per-call files (getLibrariesList, getLibrariesPaginated, getSingleLibrary, user/getUserInfo, shared libraryCardPopulate); drop dead getShelves - remove App-Router leftovers: molecules/SEO, molecules/SignInModal, molecules/UserDropDown, utils/library/seo.ts (host reuses SeoGenerator, login modal, and keepsimple header) - consolidate library fonts into globals.scss; delete styles/library/fonts.scss - Dropdown: move inline styles into module.scss classes - AudioCard: replace hardcoded focus color with --focus-ring var - AuthContext: reset in-memory token/account on logout, use js-cookie helpers - GlobalStateContext: drop unconditional first fetch (double-load), type libraries as StrapiLibrariesResponse; simplify Sidebar narrowing - createTag: explicit response type; getTagsList: drop dead SSR header branch - UserProfile: fill in hy (Armenian) menu labels - gitignore LIBRARY_TODO.md scratch file Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- gate /library/:username create UI + right panel on the can-create-library flag from /api/users/me - warn instead of crashing when a shelf, object, or tag name already exists - bundles in-progress object-select, shelf-rename, and share-URL work already in the tree Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- navigate the sidebar library dropdown by username slug (?? id) so it lands on /library/[username] instead of a 404 at /library/[numericId]; key selectedLibrary lookup on the same slug so live counts resolve - suffix tag slugs with Date.now() instead of a hardcoded -1 so names that normalize alike no longer collide on Strapi's unique-slug constraint - sanitize object description with sanitizeHtml before dangerouslySetInnerHTML to close a stored-XSS vector on user-supplied CKEditor content Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Feat/library
Drop NEXT_PUBLIC_ENABLE_LIBRARY and gate the Library feature on the shared NEXT_PUBLIC_ENV (enabled on dev + staging, hidden on prod). Removes a redundant build-time flag — the env var already drives other env-specific gating (admin copilot pages, _app), so a second flag was dead weight. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
library: gate on NEXT_PUBLIC_ENV instead of a dedicated flag
…ists Decide the Sidebar panel by whether the viewed library is mine: my own shows my account identity and is editable, anyone else's (or logged out) shows that library's public data only. Ownership now matches the loaded owner's account id/username, and stale owner data is dropped on navigation so my identity never bleeds onto someone else's page. Let a permitted owner edit their About panel before any library row exists — the row is bootstrapped lazily on first save (like adding the first shelf), and the page reloads by direct id instead of the restricted owner relation-filter. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Owner-only flow to mint a share link for a curated set of public-shelf objects: a context-backed selection (one link spans the whole library, capped at 21 objects), a Select chip on the cards, a ShareSelectionPanel to reorder/remove/clear, and a SharedWithYou modal for the recipient. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace the single `[username].tsx` page with an optional catch-all so `/library/[username]` and `/library/[username]/[slug]` share one module. The opened object is addressed by the URL (slugified title + id), and open/close are shallow `router.push` transitions so the overview modal appears over the already-loaded library with no refetch or remount. The shelf that actually holds the object resolves it from the slug's trailing id, keeping its real shelf context. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`/library/[username]/share/[token]` is a literal sibling of the object catch-all (and wins for that path). It resolves the token via getShareLink and renders the curated objects in the SharedWithYou view. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The dropdown sourced options from a global `/single-shelves` fetch, so it offered every user's public shelves (and the backend then 403s the move). Drive it from the viewed library's own shelves (currentShelves in GlobalState), filtered to the object's type, and exclude the object's current shelf — falling back to defaultShelfId since a PUT response doesn't populate the shelf relation. Disable the dropdown when no eligible shelf remains. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`currentLibraryId` was the last path segment of asPath, which on the new object (`/[slug]`) and share (`/share/[token]`) routes is the slug/token, not the username — breaking the sidebar's share-library URL and the ownership fallback. Read `[username]` from the router params instead. Also remove the temporary getMyLibrary debug effect that logged account data and fired an extra request on every authenticated page load. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wire the previously no-op "Select shelf" button to bulk-toggle the whole shelf into the share selection (new selectMany/removeMany context helpers, capped at 21). It's owner- and public-only like the per-card chip, and disabled when the shelf is empty or at the cap. Switching a shelf to private now strips its objects from the selection, so a link is never minted with objects the backend would reject. Also relocate the new objectSlug/mapSharedObject utils from the legacy src/utils tree to src/lib per AGENTS.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
library: source right panel by ownership and edit before a library exsts
…ects on shelves - next.config: add SVGO prefixIds so SVGR-inlined icons (book, video, their shadows, delete, edit) stop colliding on minified ids on the Library page. - BookCard/AudioCard: drop the BookShadowIcon + alpha overlay and use the book-cover.png / audio-cover.png placeholders (which bake in their own spine/shadow), filling the card; covers loading state too. - Shelf: raise the shelf board above the cards (z-index) so each object rests on the shelf with its base behind the front edge instead of floating over it.
…eOSS into feat/uxcore-cybersecurity
…om scrollbar, upload size errors - Shelf: drop scroll arrows, ride custom #C0B6AE scrollbar on the board, fix card bleed-through - Object modal: reflect shelf renames instantly from live GlobalState shelves - Cards: book/audio placeholders + sizing, video drop shadow - StepIndicator: larger circles, green double-ring active state, long connector - Guest mode: hide owner-only edit/add controls via viewAsOwner - Uploads: pre-flight 5 MB size error instead of a raw network failure - TagMultiSelect: keep the menu anchored to the trigger when chips appear Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
library: fix broken icons + replace book/audio placeholders, seat objects on shelves
- Replace the plain "Loading…" text with the library Loader spinner, centered in the content area - Hide WebKit's native search-cancel button so it no longer doubles up with the custom clear icon Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…c case rework - bias modal on mobile is a full-height bottom sheet (dvh-safe on iOS), header icons aligned, vertical use-case switcher - restore swipe left/right bias navigation directly in UXCoreModal (legacy UXCoreModalMobile stopped rendering after repo merge) - rating block moved inside the scrollable body instead of a sticky footer - Ask widget pill: dark surface in dark theme, no pulse on touch devices - offsec cases #2-#4 reworked for distinct scenarios; left/right wording replaced with first/second for stacked mobile layout
…e, bias popup, route loaders Revive the orphaned uxcore useMobile hook (dead since the UXCoreOSS fold-in, so phones got desktop layout) and pin slug pages to the new modals. UXCG question modal goes fullscreen on mobile with sticky rating row and nav pills; add theme toggle to its header; restyle the mobile bias popup as a centered card with dark-theme support and same-tab bias links. Route loading overlay on UXCG/Table navigation, tooltip viewport clamp, dark widget pill, UXCAT guest-profile clipping fixes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Page-element highlighting fired on every new answer regardless of widget state, so a returning visitor with a collapsed pill saw host elements glow with no obvious cause. Highlight is now allowed only while the panel is open (active); collapsing clears it, reopening re-applies it. Same path on mobile and desktop. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The "how useful…" NPS row sat outside the scrollable modal body and stayed pinned above the nav controls. Moved it inside the body so it scrolls with the answer; only Previous/Next stay sticky at the bottom. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Cybersecurity (OffSec) layer is still work-in-progress. Surface its switcher and view only when NEXT_PUBLIC_ENV is dev, and treat a persisted isOffsecView flag as inactive off-dev so a prior dev session can't leak the half-baked layer onto staging or prod. Building continues on dev as before. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add client-side search that filters shelf objects by title, author, and tag name with a smooth card-enter animation and empty-results state. Wire up title autocomplete and autofill (books/video via Google APIs, audio via iTunes) with server-side API routes. Make object modals responsive with visible custom scrollbars, fix mobile toolbar/header overlap, keep the Select-shelf button visible on private shelves, add a mobile trigger for the right info panel, gate the Tags Edit button on having at least one tag, and derive object Source from the form URL. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Feat/uxcore cybersecurity
# Conflicts: # src/uxcore/components/UXCoreModal/UXCoreModal.tsx
library: spinner loader + hide native search clear button
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.