Making Your First Frontend Change
This guide walks you through the practical steps of making a frontend change to Open Library. It assumes you've read the Frontend overview and completed the Quick Start.
Before You Start
Before writing any code, take a few minutes to set yourself up for success:
Find an issue. Look for issues labeled
Good First Issueif you're new to the project. Avoid issues with labels likeNeeds: Staff Decision,Needs: Designs, orNeeds: Lead— these haven't been vetted yet. Some issues have been previously discussed and declined — check for linked issues or PRs.Get assigned. Comment on the issue to express interest and wait for assignment. This prevents duplicate work.
Understand the scope. Keep your change focused on what the issue asks for. If you notice other things to fix along the way, file separate issues for those. PRs that mix unrelated changes are harder to review and more likely to be sent back.
Build and Watch Commands
CSS and JavaScript changes require a rebuild. See the Quick Reference on the Frontend Reference page for all build, watch, and lint commands.
Template (HTML) changes auto-reload with no build step needed.
Finding the Right File
The most common question: "I want to change X — where do I look?"
"I want to change how a page looks"
Find the template. Use the URL to trace the route. Routing lives in openlibrary/plugins — view classes point to templates in
openlibrary/templates/. For example,/books/OL...Mrenderstemplates/type/edition/view.html.Find the CSS. Use your browser's developer tools to inspect the element and find the CSS class name. Then search for it in
static/css/:sh# From the openlibrary repo root grep -r "book-card" static/css/Check for a design token. If you're changing a color, spacing, border radius, or font, the value likely comes from
static/css/tokens/. Use a token instead of hardcoding values. If you need a new semantic token, add it to the appropriate token file and reference the primitive. See the Design Token Guide for details.Rebuild CSS and verify in the browser.
"I want to change text or layout on a page"
Templates are in openlibrary/templates/. The site wrapper (header, footer, navigation) is in templates/site/ and templates/lib/. Edit the .html file — changes auto-reload in your local instance. Templetor uses $variable for rendering values and $:variable for raw HTML. See the Template Rendering Guide for syntax details.
"I want to change a component's behavior"
Lit web components live in openlibrary/components/lit/. Each component is a single JS file registered in openlibrary/components/lit/index.js. See Building Components for details.
"I want to add JavaScript to an existing page"
JavaScript files live in openlibrary/plugins/openlibrary/js/. New JS is connected to templates through DOM-based loading in index.js — look for an element on the page, then dynamically import the JS file when that element exists. The Frontend Reference's JS tutorial walks through this pattern step by step.
For interactive UI that needs encapsulation, consider a Lit web component instead.
Testing Your Changes
After making your change, verify it works in the local Docker environment.
Finding the right page
Some common pages to test:
- Book page:
localhost:8080/books/OL1M(edition) orlocalhost:8080/works/OL1W(work) - Author page:
localhost:8080/authors/OL1A - Search results:
localhost:8080/search?q=test - Homepage:
localhost:8080/ - Lists:
localhost:8080/people/openlibrary/lists
Testing components
Lit web components render on the pages that use them. To find where a component appears, search for its tag name (e.g., <ol-read-more>) in the templates:
grep -r "ol-read-more" openlibrary/templates/Vue components (merge UI, reading stats, library explorer) are accessed through specific URLs. If you're unsure where a component appears, ask in the issue or on Slack.
What to check
- Both browsers: Test in Firefox and a Chromium-based browser (Chrome, Edge)
- Mobile widths: Resize your browser or use device emulation to check responsive behavior
- Without JavaScript: Disable JS in your browser briefly to confirm the page degrades gracefully — content should still be visible even if interactivity is lost
- Page load: Watch for content that flashes or shifts as JavaScript loads (layout shift). Components should render at their final size from the start, or use a placeholder that matches the final dimensions
Before You Submit
Before opening a pull request, run through this checklist:
- [ ] Lint passes: Run
npm run lintfor JS/CSS andmake lintfor Python - [ ] Tested in browser: Verify your change works locally in the browser at both desktop and mobile widths
- [ ] Uses design tokens: No hardcoded colors, spacing, or radii — use tokens from
static/css/tokens/ - [ ] Follows conventions: BEM naming for CSS classes,
ol-prefix for web components, semantic HTML - [ ] Screenshots included: Add before/after screenshots for any visual change. Screen recordings are even better for interactive changes.