by Arno L.

Audiobookshelf is an open-source, self-hosted server for streaming audiobooks and podcasts, with multi-user support, progress sync, and mobile apps for Android and iOS.
This block delivers the complete Node.js/Express server subtree of audiobookshelf — a self-hosted audiobook and podcast platform. It includes authentication, REST controllers, database models, file scanning, socket management, and all vendored libraries. The typical buyer is a developer embedding a media-server backend into an existing Node.js or Express application, or forking audiobookshelf's server layer for custom deployment.
auth/ — LocalStrategy, OIDC strategy, and JWT token management for Passportcontrollers/ — Express route handlers for every API surface (libraries, items, users, sessions, podcasts, etc.)finders/ — Metadata lookup helpers for books, authors, and podcastslibs/ — Vendored runtime libraries (archiver, bcryptjs, busboy, ffmpeg wrappers, fusejs, jsonwebtoken, sequelize umzug, etc.)managers/ — Background process managers (cron, notifications, backups, email, RSS, etc.)migrations/ — Sequelize/umzug database migration scriptsmodels/ — Sequelize ORM model definitionsobjects/ — Plain JS domain objects (Library, Book, Podcast, User, etc.)providers/ — Third-party metadata provider integrations (Audible, Google Books, iTunes, etc.)routers/ — Express Router instances that mount all controllersscanner/ — File-system library scanner and audio metadata parserutils/ — Shared utility functions (file helpers, string ops, logging helpers)Auth.js — Top-level authentication orchestrator (Passport init, session, JWT)Database.js — Sequelize connection bootstrap and model registrationLogger.js — Winston-based structured logger singletonServer.js — Express app factory and HTTP/Socket.IO server entry pointSocketAuthority.js — Socket.IO namespace manager and authenticated event busWatcher.js — chokidar-backed file-system watcher that triggers library rescansnpm install axios cookie-parser express express-rate-limit express-session \
graceful-fs htmlparser2 lru-cache node-unrar-js nodemailer openid-client \
p-throttle passport passport-jwt semver sequelize socket.io sqlite3 \
ssrf-req-filter xml2js
# ffmpeg binaries must be available on PATH (or set FFMPEG_PATH / FFPROBE_PATH)
# sqlite3 requires native compilation — ensure python3 and a C++ toolchain are present:
npm install --build-from-source sqlite3
# On Debian/Ubuntu:
# apt-get install -y ffmpeg build-essential python3
Spin up an isolated sandbox and run it server-side — no local setup.
Tetrees AI Review of this version
This JavaScript cli / script completed archive review with strong static results. Structure, dependency manifests, documentation, functional source, and common risk patterns were checked by the Tetrees verification pipeline; runtime phases are stated separately.
Deterministic AVCP artifact review
Pipeline avcp-2026-08-04.1 · SHA-256 7a80862767def945…
This version-scoped review deterministically inspects the submitted archive for structure, dependencies, documentation, functional source, and common malicious or high-risk signals. Build and test phases are reported as passed only after an isolated sandbox audition. It is not a guarantee of perfect security.
Reviewed Aug 4, 2026
Push this product straight into your AI IDE, web builder or cloud IDE.
Connect Tetrees to a compatible AI IDE, list products you own, and request the verified ZIP without exposing seller upload controls.
No reviews yet.
Sign in to join the discussion
Loading discussion…
No iOS/Android/Expo steps — this is a pure Node.js backend.
source/ into your project root (e.g. myapp/server/)..env or process environment):NODE_ENV=production
PORT=3000
HOST=0.0.0.0
# Data and metadata paths
CONFIG_PATH=/data/config
METADATA_PATH=/data/metadata
# ffmpeg (if not on PATH)
FFMPEG_PATH=/usr/bin/ffmpeg
FFPROBE_PATH=/usr/bin/ffprobe
# JWT secret
TOKEN_SECRET=replace_with_a_long_random_string
package.json set "main": "server/Server.js" or import it explicitly.tsconfig.json:{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@server/*": ["server/*"]
}
}
}
server/Server.js. Instantiate and call init():const Server = require('./server/Server')
const server = new Server()
server.init()
CONFIG_PATH/absdatabase.sqlite on first run.// libs/archiver/index.js
function vending(format: string, options?: object): Archiver
vending.create(format: string, options?: object): Archiver
vending.registerFormat(format: string, module: Function): void
Dispenses a configured Archiver instance for a registered format (e.g. "zip", "tar"). Use vending.registerFormat once at startup to add a format module, then call vending(format, options) or vending.create(format, options) to get a streaming archiver. Throws if the format is not registered or the module is missing append/finalize prototype methods.
// libs/archiver/archiverUtils/balancedMatch/index.js
function balanced(
a: string | RegExp,
b: string | RegExp,
str: string
): { start: number; end: number; pre: string; body: string; post: string } | null
balanced.range(a: string, b: string, str: string): [number, number] | undefined
Finds the first balanced pair of delimiters a…b inside str. Returns a result object with pre, body, and post segments, or null if no match. Use it when parsing brace-expanded glob patterns or any nested delimiter structure.
// libs/archiver/archiverUtils/fsRealpath/index.js
function realpath(p: string, cache: object | null, cb: (err: Error | null, result: string) => void): void
function realpathSync(p: string, cache?: object): string
A Node.js version-aware wrapper around fs.realpath that falls back to a pure-JS implementation for ELOOP, ENOMEM, and ENAMETOOLONG errors on older runtimes. Use it anywhere you resolve symlinks inside the scanner or file-upload pipeline to avoid silent failures on path-too-long errors.
Start Express, Socket.IO, Passport, and the SQLite database in one call using the provided Server class entry point.
// main.ts
process.env.CONFIG_PATH = '/data/config'
process.env.METADATA_PATH = '/data/metadata'
process.env.TOKEN_SECRET = 'my_secret_32_chars_minimum'
process.env.PORT = '3000'
const Server = require('./server/Server')
async function main() {
const server = new Server()
await server.init()
console.log('Audiobookshelf server running on port 3000')
}
main().catch(console.error)
Use the vendored archiver to stream a ZIP of metadata files to an HTTP response.
// routes/exportMetadata.ts
import express from 'express'
const archiver = require('./server/libs/archiver')
// Register zip format once at startup
archiver.registerFormat('zip', require('./server/libs/archiver/lib/plugins/zip'))
const router = express.Router()
router.get('/export-zip', (req, res) => {
const archive = archiver.create('zip', { zlib: { level: 9 } })
res.setHeader('Content-Type', 'application/zip')
res.setHeader('Content-Disposition', 'attachment; filename="metadata.zip"')
archive.pipe(res)
archive.directory('/data/metadata/items', 'items')
archive.finalize()
archive.on('error', (err: Error) => {
console.error('Archive error', err)
res.status(500).end()
})
})
export default router
Use the fsRealpath wrapper to canonicalize a user-supplied library folder path before adding it to the database.
// utils/resolveLibraryPath.ts
const { realpathSync } = require('./server/libs/archiver/archiverUtils/fsRealpath')
export function resolveLibraryPath(rawPath: string): string {
try {
const resolved = realpathSync(rawPath, null)
return resolved
} catch (err: any) {
if (err.code === 'ENOENT') {
throw new Error(`Library path does not exist: ${rawPath}`)
}
throw err
}
}
// Usage
const safePath = resolveLibraryPath('/mnt/nas/audiobooks')
console.log('Canonical path:', safePath)
Use balanced to extract the body of a brace expression when building custom scanner include/exclude rules.
// scanner/parseGlob.ts
const balanced = require('./server/libs/archiver/archiverUtils/balancedMatch')
export function extractBraceBody(pattern: string): string | null {
const result = balanced('{', '}', pattern)
if (!result) return null
console.log('pre:', result.pre) // text before '{'
console.log('body:', result.body) // text inside '{}'
console.log('post:', result.post) // text after '}'
return result.body
}
// Example: "{mp3,m4b,flac}" => "mp3,m4b,flac"
const body = extractBraceBody('{mp3,m4b,flac}')
Auth.js — Initializes Passport strategies (local + JWT + OIDC), attaches session middleware, and exposes token issuance helpers.Database.js — Opens the SQLite connection via Sequelize, runs pending umzug migrations, and registers all models.Logger.js — Exports a singleton Winston logger; imported throughout the codebase as Logger.Server.js — Constructs the Express app, mounts all routers, starts the HTTP server, and bootstraps Socket.IO.SocketAuthority.js — Wraps Socket.IO namespaces; handles per-socket authentication and event broadcasting.Watcher.js — Uses chokidar to watch library directories and enqueues rescan tasks when files are added, changed, or removed.auth/ — Passport strategy implementations: LocalAuthStrategy.js, OidcAuthStrategy.js, and TokenManager.js for JWT lifecycle.controllers/ — One Express controller file per API resource; each exports middleware-compatible handler functions.finders/ — BookFinder.js, AuthorFinder.js, PodcastFinder.js aggregate metadata from multiple providers.libs/ — All vendored third-party libraries pinned to specific versions to avoid external network resolution at runtime.managers/ — Long-lived singleton managers (CronManager, NotificationManager, BackupManager, EmailManager, etc.).migrations/ — Numbered Sequelize migration files executed by umzug on startup.models/ — Sequelize model files (Library, LibraryItem, User, Podcast, etc.).objects/ — Plain-JS domain objects that mirror database models for in-memory manipulation.providers/ — HTTP clients for Audible, Google Books, OpenLibrary, iTunes metadata APIs.routers/ — Express Router instances that group and mount controller handlers.scanner/ — Library scanner, audio-file probe, cover extraction, and metadata normalization pipeline.utils/ — Cross-cutting helpers: path normalization, string sanitization, date formatting, cover image utilities.sqlite3 native build fails — Run npm install --build-from-source sqlite3 with python3, make, and a C++ compiler present; on Alpine use apk add python3 make g++.ffmpeg not found at runtime — Set FFMPEG_PATH and FFPROBE_PATH env vars explicitly; do not rely on PATH inside Docker containers with minimal images.TOKEN_SECRET not set — Auth.js will throw or produce unverifiable JWTs; always set a 32+ character random string before starting the server.archiver.registerFormat(name, plugin) exactly once before any archiver.create() call; registering twice throws "format already registered".openid-client version mismatch — The OIDC strategy targets a specific API surface; pin openid-client to the version in the upstream package.json (^5.x) to avoid breaking issuer discovery.CONFIG_PATH directory must pre-exist — Database.js does not mkdirSync the config directory; create it before starting the server or the SQLite file open will fail with ENOENT.I have dropped the audiobookshelf server source tree into `./server/` in my
Node.js project. The integration guide is in `./USAGE.md`. The upstream
package is `user@example.com`.
Please help me integrate this step by step:
1. Read `USAGE.md` fully before writing any code.
2. Set up the required environment variables listed in USAGE.md § "Project setup".
3. Wire `./server/Server.js` as the backend entry point in my project's `index.ts`.
4. Ensure all runtime dependencies from USAGE.md § "Required dependencies" are
installed and that native modules (sqlite3, ffmpeg) are available.
5. Mount the Express routers from `./server/routers/` onto my existing Express app,
or explain how to delegate to the audiobookshelf `Server` instance cleanly.
6. Show me how to use the archiver from `./server/libs/archiver/index.js` to ZIP
a directory and stream it to an HTTP response, exactly as shown in USAGE.md.
7. Identify any conflicts with my existing auth middleware and suggest how to
coexist with `./server/Auth.js` (Passport + JWT).
8. Do not invent any imports — only use symbols documented in USAGE.md § "Public API"
and visible in the source files under `./server/`.
The audiobookshelf server source is released under the MIT License — see source/LICENSE if present, or refer to the upstream repository. Upstream package: user@example.com by advplyr. Vendored libraries under source/libs/ retain their individual licenses as noted in each subdirectory.
This product’s unique contribution is clean room implementation of valuable code block into AVCP compatible standard.
The full install guide and integration prompts unlock after purchase.
PHP, Laravel & Business Scripts
Free