{"id":46663644,"url":"https://github.com/zeetlex/knitting-library","last_synced_at":"2026-04-05T19:00:35.304Z","repository":{"id":343055384,"uuid":"1176117203","full_name":"ZeetLex/knitting-library","owner":"ZeetLex","description":"Knitting Library for knitting recipies and yarns. Selvhosted. Created for local network only. ","archived":false,"fork":false,"pushed_at":"2026-04-01T09:31:09.000Z","size":403,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-01T11:36:33.880Z","etag":null,"topics":["docker","dockercompose","knitting","selfhosted"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ZeetLex.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES-unreleased.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-08T16:35:22.000Z","updated_at":"2026-04-01T09:31:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"2ec708f2-8a0d-4652-8a56-41b6a9308449","html_url":"https://github.com/ZeetLex/knitting-library","commit_stats":null,"previous_names":["zeetlex/knitting-library"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/ZeetLex/knitting-library","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZeetLex%2Fknitting-library","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZeetLex%2Fknitting-library/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZeetLex%2Fknitting-library/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZeetLex%2Fknitting-library/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ZeetLex","download_url":"https://codeload.github.com/ZeetLex/knitting-library/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZeetLex%2Fknitting-library/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31446531,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T15:22:31.103Z","status":"ssl_error","status_checked_at":"2026-04-05T15:22:00.205Z","response_time":75,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","dockercompose","knitting","selfhosted"],"created_at":"2026-03-08T15:03:13.359Z","updated_at":"2026-04-05T19:00:35.297Z","avatar_url":"https://github.com/ZeetLex.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Knitting Library\n\nA self-hosted knitting pattern manager. Upload PDF patterns or scanned images, browse them in a searchable grid, annotate pages, track active projects, and manage a full yarn inventory — all from a single Docker container.\n\nBuilt for personal use: my wife needed somewhere to store her knitting patterns without paying a subscription or giving her data to a third party.\n\n\u003e **Built with AI assistance.** This project was developed with Claude (Anthropic) as a coding assistant. The architecture, feature decisions, and direction are mine — the AI helped write and debug the code. The codebase has not been formally reviewed by a professional developer or security auditor, and you may encounter rough edges. See the [Security](#security) section for what has been implemented and what the limits are.\n\n---\n\n## Requirements\n\n**Docker Desktop** — nothing else.\nDownload at: https://www.docker.com/products/docker-desktop/\nWorks on Windows, Mac, and Linux.\n\n---\n\n## Getting Started\n\n**Terminal:**\n```bash\ndocker-compose up -d\n```\nThen open `http://localhost:3000`.\n\n**Docker Desktop GUI:**\nOpen the Compose section, point it at `docker-compose.yml`, and hit Start.\n\n**Unraid / home server:**\n```yaml\nservices:\n  app:\n    image: zeetlex/knitting-library:latest\n    restart: unless-stopped\n    ports:\n      - \"3000:8080\"\n    volumes:\n      - /path/to/your/data:/data\n      - /path/to/your/logs:/logs\n```\n\n**iPhone home screen:**\nOpen `http://YOUR-SERVER-IP:3000` in Safari → Share → Add to Home Screen.\n\n---\n\n## First Login\n\nDefault credentials: `admin` / `admin`\nChange your password immediately — **Settings → My Account → Change Password**.\n\n---\n\n## Features\n\n### Recipe Library\nVisual grid with thumbnails and adjustable card size. Search by name or tag; filter by category, tag, or project status.\n\n### Importing\nUpload PDFs or images — single file, multiple images, or a whole folder. The **Bulk Import Wizard** lets you work through a folder one file at a time, adding metadata as you go, with automatic progress saving so you can stop and resume.\n\n### Recipe Viewer\nScrollable pages with zoom and fullscreen. Swipe on mobile, arrow keys on desktop. **Custom cover image** — set any page or image as the recipe thumbnail.\n\n### Annotations\nDraw or highlight directly on any recipe page. Adjustable brush, opacity, and colour. Strokes are saved per-page to the database and persist across sessions.\n\n### Project Tracking\nMark recipes as In Progress or Finished. Link a yarn and colour variant when starting, optionally deducting skeins from inventory. Full session history with timestamps. **Feedback** — rate finished projects on quality, difficulty, and result with optional notes; average score appears as a ★ badge on the card.\n\n### Yarn Database\nCatalogue yarn types with full specs: material, yardage, needle size, tension, seller, and price. Multiple colour variants per yarn, each with name, price, and photo. URL import to auto-fill fields *(early beta — works best with Sandnes Garn)*.\n\n### Inventory\nTrack yarn skeins, needles, tools, and notions. Yarn entries link to the Yarn Database for specs. +/− buttons for quick quantity adjustments with a full history log per item.\n\n### User Accounts\nUsername/password login with bcrypt hashing. Login rate limiting. Optional two-factor authentication (TOTP). Per-user settings: theme, colour theme, language (English/Norwegian), currency.\n\n### Admin Panel\nCreate and manage user accounts, view live API logs, configure SMTP mail, and manage 2FA status for all users.\n\n### Themes\nLight and dark mode. Seven colour themes: Terracotta, Rose Garden, Lavender Mist, Sage \u0026 Linen, Berry Bloom, Ocean, and Willow. Settings are per-user and saved to the database.\n\n### Statistics\nHigh-level metrics: recipe count, yarn entries, users, categories, tags, active and finished projects, inventory items, and total knitting sessions.\n\n### Backup \u0026 Export\nData lives in `./data/` — copy it to back up. Export as ZIP from **Settings → Data → Export Library**.\n\n---\n\n## Folder Structure\n\nAfter first run, your directory will contain:\n\n```\nyour-folder/\n  docker-compose.yml\n  data/\n    knitting.db       \u003c- database\n    recipes/          \u003c- recipe files and thumbnails\n    yarns/            \u003c- yarn images\n  logs/\n    uvicorn.log       \u003c- all API requests and errors\n    auth.log          \u003c- failed logins (readable by fail2ban)\n```\n\nLogs rotate automatically (10 MB per file, 5 backups).\n\n---\n\n## Backups\n\nCopy the `data/` folder — that is everything. The database, all recipe files, yarn images, annotations, session history, and settings are all in there.\n\nTo restore: copy `data/` back and restart the container.\n\n---\n\n## Security\n\nThe following measures are implemented:\n\n| Area | Status |\n|---|---|\n| Password hashing | bcrypt (rounds=12) |\n| Login rate limiting | 10 attempts per 15 min per IP, plus fail2ban support |\n| Two-factor authentication | TOTP (Google Authenticator, Authy, etc.) |\n| Session expiry | 30 days; 2FA challenges expire in 5 minutes |\n| File upload validation | Magic-byte checks + size limits (50 MB PDF, 20 MB image) |\n| CORS | Same-origin only (set `ALLOWED_ORIGINS` env var if needed) |\n| Security headers | CSP, X-Frame-Options, Referrer-Policy, Permissions-Policy |\n| API documentation | Disabled in production |\n| SQL injection | Parameterised queries throughout |\n| Path traversal | Filename sanitisation on all uploads |\n| SSRF | Private IP blocking on yarn URL scraper |\n| HTTPS | Not built in — use a reverse proxy |\n\n**These measures were implemented in good faith but have not been reviewed by a security professional. You run this software at your own risk.**\n\nRecommended deployment options, in order of preference:\n\n- **Home network only** — safest, no external exposure\n- **VPN access** (Tailscale, WireGuard) — safe for remote access\n- **Reverse proxy with HTTPS** (Nginx Proxy Manager) — acceptable, see the Fail2ban section\n- **Direct port forward to the internet** — not recommended\n\nThe author takes no responsibility for data loss, unauthorised access, or any issues arising from how you choose to deploy this application.\n\n---\n\n## Fail2ban (optional)\n\nIf you expose the app through a reverse proxy, fail2ban can block IPs that repeatedly fail to log in.\n\nThe app writes a dedicated auth log at `logs/auth.log`. Every failed login and bad 2FA code is recorded with the real client IP (extracted from `X-Forwarded-For`).\n\nExample log line:\n```\n2025-01-15 14:23:45 AUTH_FAIL ip=1.2.3.4 user=admin reason=bad_password\n```\n\n**Filter** (`filter.d/knitting-library.conf`):\n```ini\n[Definition]\nfailregex = ^%Y-%m-%d %H:%M:%S AUTH_FAIL ip=\u003cHOST\u003e\\b\nignoreregex =\ndatepattern = ^%%Y-%%m-%%d %%H:%%M:%%S\n```\n\n**Jail** (`jail.d/knitting-library.conf`):\n```ini\n[knitting-library]\nenabled  = true\nfilter   = knitting-library\nlogpath  = /path/to/your/logs/auth.log\nmaxretry = 5\nfindtime = 600\nbantime  = 3600\naction   = iptables-multiport[name=knitting-library, port=\"80,443,3000\", protocol=tcp]\n```\n\nMake sure Nginx Proxy Manager forwards the real client IP — add this to the **Advanced** tab of your proxy host:\n```nginx\nproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\nproxy_set_header X-Real-IP $remote_addr;\n```\n\nReload fail2ban after placing the files:\n```bash\nfail2ban-client reload\nfail2ban-client status knitting-library\n```\n\n---\n\n## Troubleshooting\n\n| Problem | Fix |\n|---|---|\n| Blank page or won't load | Make sure Docker Desktop is running and the container is started |\n| \"Not logged in\" error | Refresh the page — session may have expired after 30 days |\n| PDF thumbnail not showing | PDF processing can be slow for large files — give it a moment |\n| Can't reach it on phone | Use the server's IP, not `localhost`. Phone must be on the same Wi-Fi |\n| Annotations not saving | Check that the `./data` volume is mounted correctly in your compose file |\n| URL import didn't fill everything | Early beta — fill in missing fields manually |\n| Live Logs shows nothing | Check that `./logs:/logs` is mounted in your compose file |\n| All requests show same IP in logs | Set `X-Forwarded-For` in your reverse proxy (see Fail2ban section) |\n| Port 8080 shows nothing | Check container logs: `docker logs knitting-library` |\n\n---\n\n## Status\n\nThis project is in active use but should be considered **beta software**. Things may change between versions. Keep backups of your `data/` folder before updating.\n\nOpen an issue if you find bugs or want to suggest something.\n\n---\n\n*Built with FastAPI · React · SQLite · Docker*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeetlex%2Fknitting-library","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzeetlex%2Fknitting-library","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeetlex%2Fknitting-library/lists"}