@sunnysideup/npm-page-favourites-bookmarker
Version:
NPM package - to bookmark / favourite any page on a website
180 lines (129 loc) • 5.12 kB
Markdown
Tiny in-page bookmark manager with a heart button, overlay list, and optional server sync (email/phone verification supported).
## Features
- Heart button on every page to toggle bookmark (saves URL + title).
- Overlay list of bookmarks (hotkey toggle), with remove and drag-to-sort.
- Uses `localStorage` or `sessionStorage`.
- Optional server sync:
- Sends events on add/remove/sort.
- If logged in, it can sync with existing lists
- Zero dependencies, plain ESM.
## Install
```bash
npm i @sunnysideup/npm-page-favourites-bookmarker
```
## Usage
### with a bundler (Vite/Webpack/Rollup)
```js
import { PageFaves } from '@sunnysideup/npm-page-favourites-bookmarker';
```
```scss
@import "@sunnysideup/npm-page-favourites-bookmarker/styles";
```
Check where `node_modules` lives ...and then add this (with additional path segments, if needed).
```html
<link rel="stylesheet" href="/node_modules/@sunnysideup/npm-page-favourites-bookmarker/src/index.css">
<script type="module">
import { PageFaves } from '/node_modules/@sunnysideup/npm-page-favourites-bookmarker/src/index.js'
</script>
```
```js
import { PageFaves } from '@sunnysideup/npm-page-favourites-bookmarker'
const pf = new PageFaves({
storage: 'local', // or 'session'
baseUrl: 'https://api.example.com/my-controller', // enables server I/O
endpoints: {
events: '/track',
bookmarks: '/user/bookmarks'
},
heartPositionLeftRight: 'right', // 'left' | 'right'
heartPositionTopBottom: 'bottom', // 'top' | 'bottom'
overlayHotkey: 'KeyB', // press CTRL+SHIFT+B
syncOnLoad: true
})
pf.init()
```
Add a small script before you import/initialise:
```html
<script>
window.npmPageFavouritesBookmarker = {
// whether to render on this page (overrides defaults and constructor opts)
loadOnThisPage: true,
// login awareness for overlay
userIsLoggedIn: false,
loginUrl: '/account/login',
// optional positioning overrides
heartPositionLeftRight: 'right',
heartPositionTopBottom: 'bottom'
}
</script>
```
You can override any template in templates. Example:
```js
import { PageFaves } from '@sunnysideup/npm-page-favourites-bookmarker'
import { defaultTemplates } from '@sunnysideup/npm-page-favourites-bookmarker/src/ui/templates.js'
import '@sunnysideup/npm-page-favourites-bookmarker/src/index.css'
const pf = new PageFaves({
templates: {
heart: ({ onClick, onShowOverlay, position, isOn }) => {
const wrap = document.createElement('div')
wrap.className = `my-heart-wrap my-${position.leftRight} my-${position.topBottom}`
const open = document.createElement('button')
open.textContent = '≡'
open.addEventListener('click', e => { e.preventDefault(); onShowOverlay() })
wrap.append(open)
const btn = document.createElement('button')
btn.textContent = isOn() ? '★' : '☆'
btn.addEventListener('click', e => { e.preventDefault(); onClick() })
wrap.append(btn)
return wrap
},
overlayBar: (args) => defaultTemplates.overlayBar(args),
overlayShell: () => {
const wrap = document.createElement('div'); wrap.className = 'my-overlay'
const list = document.createElement('div'); list.className = 'my-overlay-list'
wrap.append(list); return { wrap, list }
},
overlayRow: ({ item }) => {
const row = document.createElement('div')
row.className = 'my-row'
row.textContent = item.title || item.url
row.addEventListener('click', () => window.open(item.url, '_blank'))
return row
}
}
})
pf.init()
```
- **Open overlay:** CTRL + SHIFT + B (uses overlayHotkey: 'KeyB').
- **Close overlay:** ESC.
No network calls are made unless `baseUrl` is provided.
On `init()`, if `syncOnLoad` is true and `userIsLoggedIn` is true, the client pulls bookmarks from {bookmarks} and merges with local.
This initial pull is throttled to at most once every 10 minutes.
Every add/remove/reorder triggers a POST {events}.
- `add(url, title)` → add a bookmark
- `remove(url)` → remove bookmark
- `toggleCurrent()` → toggle current page
- `list()` → get all bookmarks
- `isBookmarked(url)` → check if URL is saved
- `showOverlay()`
- `hideOverlay()`
- `syncFromServer()` → pull bookmarks and and merge with local (only if baseUrl set)
#### Server Endpoints
You can override each endpoint individually in `endpoints`.
- `POST {events}` → `{ type, payload, at }` (called on add/remove/reorder)
- `GET {bookmarks}` → `[{ url, title, ts }]`
If you use Silverstripe CMS, check out the integration package:
[](https://github.com/sunnysideup/silverstripe-page-favourites-bookmarker)