1
0
Fork
You've already forked bookpile
0
forked from bitboxer/bookpile
This project tries to create a page that you can link to so that your readers have an easy way to buy the book you are talking about on social media or in your blog.
  • HTML 54.2%
  • Elixir 30.5%
  • TypeScript 9%
  • CSS 5.8%
  • Dockerfile 0.3%
  • Other 0.1%
2026年06月07日 18:12:20 +02:00
assets
config
importers
lib Add error section 2026年06月07日 18:12:20 +02:00
priv
test
.check.exs
.credo.exs
.dockerignore
.env.example
.formatter.exs
.gitignore
CODE_OF_CONDUCT
docker-compose.yml
Dockerfile
entrypoint.sh
justfile
LICENSE
mix.exs
mix.lock
README.md

Bookpile

Enter an ISBN, get a list of bookshops and libraries near you. No affiliate links, no cookies. AGPL-3.0-or-later.

How it works

bookpile.org/b/<isbn> looks up book metadata, detects the visitor's location from their IP address (server-side, using a local MaxMind database), and returns nearby shops and libraries. The URL works for everyone - each visitor sees results for their own location.

The list of shops and libraries lives in priv/data/websites.json. Pull requests to add or fix entries are welcome.

websites.json format

See priv/data/websites.md for the full format reference.

Dependencies

  • Elixir ≥ 1.14 and Erlang/OTP ≥ 25
  • PostgreSQL ≥ 14
  • Node.js and yarn (for esbuild asset bundling and importers)
  • A Google Books API key
  • A MaxMind GeoLite2-City database file (free, requires registration)

Running locally

# 1. Install Elixir dependencies
mix deps.get
# 2. Copy the environment template and fill in your values
cp .env.example .env
# Set BOOKPILE_GOOGLE_API_KEY in .env
# 3. Place the MaxMind database
mkdir -p priv/geo
cp /path/to/GeoLite2-City.mmdb priv/geo/
# 4. Create and migrate the database
mix ecto.setup
# 5. Start the server
mix phx.server

Visit localhost:4000.

S3 cover image caching (optional)

Set these environment variables to have book cover images downloaded and stored in S3 instead of served from external sources:

Variable Description
BOOKPILE_S3_BUCKET Bucket name — setting this enables the feature
BOOKPILE_S3_REGION Region (default: us-east-1)
BOOKPILE_S3_ENDPOINT S3 API host for non-AWS providers (e.g. fsn1.your-objectstorage.com)
BOOKPILE_S3_PUBLIC_URL Public base URL for stored files (e.g. https://my-bucket.fsn1.your-objectstorage.com) — defaults to the AWS URL pattern
AWS_ACCESS_KEY_ID Access key
AWS_SECRET_ACCESS_KEY Secret key

Covers are stored as covers/<isbn>.<ext> with public-read ACL. If the bucket variable is not set the feature is disabled and external image URLs are used as-is. Works with any S3-compatible storage (AWS, Hetzner, etc.).

Development

mix test # run tests
mix check # tests + credo + dialyzer + formatter (run before committing)
mix format # format code

Assets are bundled with esbuild - no separate Node build step needed during development.