A web application for managing your comic collection. Built with Node.js and vanilla JavaScript. Vibe-coded by godai using Cursor.
See CHANGELOG.md for release history and notable updates.
- View and search your comic collection
- Add new comics with detailed information
- Edit existing comic entries
- Sort by any column (hierarchical: series → title → issue number)
- Dynamic search suggestions
- Import from Google Sheets using a pasted shared URL
- Export to CSV (compatible with Google Docs/Sheets)
- Record count display
- Clone the repository:
git clone https://github.com/godai78/ComicBookDataBase.git
cd ComicBookDataBase- Install dependencies:
npm install- Start the server:
node server.js- Open your browser and navigate to:
http://localhost:3000
Each comic entry contains:
idseriesTitleissueTitleissueNumberwriters(array)artists(array)languagepublisherpublicationYear
For an empty database, comics.json should contain:
[]- Node.js
- Express.js
- Vanilla JavaScript
- Google Sheets CSV export endpoint
The application supports multiple languages through a translation system. Currently available languages:
- English (en)
- Polish (pl)
- German (de)
- Swedish (sv)
- French (fr)
To add a new language:
- Create a new JSON file in the
translationsdirectory with the language code (e.g.,fr.jsonfor French) - Copy the structure from
en.jsonand translate all values - The language will be automatically detected and added to the language selector
To make an element translatable, add the data-translate attribute with the appropriate translation key:
<label data-translate="comic.fields.series">Series</label>For input placeholders:
<input type="text" data-translate-placeholder="search.seriesPlaceholder" placeholder="Search by series name...">The translation files follow this structure:
{
"app": {
"pageTitle": "Comic collection manager",
"recordCount": "({count} records)"
},
"search": {
"title": "Search comics",
"seriesPlaceholder": "Search by series name...",
"issueTitlePlaceholder": "Search by title...",
"writerPlaceholder": "Search by writer...",
"artistPlaceholder": "Search by artist...",
"languageFilter": "All languages",
"publisherFilter": "All publishers",
"yearFilter": "All years",
"searchButton": "Search",
"addButton": "Add new comic",
"importButton": "Import from Google Sheets",
"exportButton": "Export to CSV"
},
"comic": {
"title": {
"add": "Add new comic",
"edit": "Edit comic"
},
"fields": {
"series": "Series",
"issueTitle": "Title",
"issueNumber": "Number",
"writers": "Writers",
"artists": "Artists",
"language": "Language",
"publisher": "Publisher",
"year": "Year"
},
"form": {
"writersHint": "Separate multiple writers with commas",
"artistsHint": "Separate multiple artists with commas"
},
"actions": {
"edit": "Edit",
"delete": "Delete",
"save": "Save comic",
"cancel": "Cancel",
"backToList": "← Back to comics list"
}
},
"messages": {
"deleteConfirm": "Are you sure you want to delete this comic?",
"deleteSuccess": "Comic deleted successfully",
"saveSuccess": "Comic saved successfully",
"error": "An error occurred",
"loadingError": "Error loading comics. Please try again.",
"import": {
"promptUrl": "Paste the shared Google Sheets URL:",
"errorPrefix": "Error importing comics:",
"noValidRows": "No valid comic rows found. Check sheet columns and ensure at least series or issue title is present.",
"notShared": "The spreadsheet is not publicly shared. Please share it with \"Anyone with the link can view\".",
"invalidGoogleUrl": "URL must be a docs.google.com Google Sheets link"
}
},
"navigation": {
"backToMain": "← Back to main page",
"backToTop": "Back to top"
}
}