blob-viewer 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. blob_viewer-0.1.0/.gitignore +220 -0
  2. blob_viewer-0.1.0/CHANGELOG.md +24 -0
  3. blob_viewer-0.1.0/LICENSE +21 -0
  4. blob_viewer-0.1.0/PKG-INFO +206 -0
  5. blob_viewer-0.1.0/README.md +144 -0
  6. blob_viewer-0.1.0/docs/api.md +80 -0
  7. blob_viewer-0.1.0/docs/architecture.md +86 -0
  8. blob_viewer-0.1.0/docs/cli.md +78 -0
  9. blob_viewer-0.1.0/docs/docker.md +73 -0
  10. blob_viewer-0.1.0/docs/faq.md +47 -0
  11. blob_viewer-0.1.0/docs/getting-started.md +71 -0
  12. blob_viewer-0.1.0/docs/index.md +49 -0
  13. blob_viewer-0.1.0/docs/install.md +59 -0
  14. blob_viewer-0.1.0/docs/preview-cache.md +52 -0
  15. blob_viewer-0.1.0/docs/security.md +53 -0
  16. blob_viewer-0.1.0/docs/themes.md +40 -0
  17. blob_viewer-0.1.0/docs/workspaces.md +70 -0
  18. blob_viewer-0.1.0/pyproject.toml +86 -0
  19. blob_viewer-0.1.0/src/blob_viewer/__init__.py +17 -0
  20. blob_viewer-0.1.0/src/blob_viewer/api.py +469 -0
  21. blob_viewer-0.1.0/src/blob_viewer/auth.py +115 -0
  22. blob_viewer-0.1.0/src/blob_viewer/cache.py +218 -0
  23. blob_viewer-0.1.0/src/blob_viewer/cli.py +723 -0
  24. blob_viewer-0.1.0/src/blob_viewer/db.py +143 -0
  25. blob_viewer-0.1.0/src/blob_viewer/desktop.py +92 -0
  26. blob_viewer-0.1.0/src/blob_viewer/paths.py +75 -0
  27. blob_viewer-0.1.0/src/blob_viewer/preview.py +106 -0
  28. blob_viewer-0.1.0/src/blob_viewer/secrets.py +79 -0
  29. blob_viewer-0.1.0/src/blob_viewer/server.py +93 -0
  30. blob_viewer-0.1.0/src/blob_viewer/service.py +97 -0
  31. blob_viewer-0.1.0/src/blob_viewer/static/css/base.css +489 -0
  32. blob_viewer-0.1.0/src/blob_viewer/static/css/themes.css +214 -0
  33. blob_viewer-0.1.0/src/blob_viewer/static/favicon.svg +5 -0
  34. blob_viewer-0.1.0/src/blob_viewer/static/js/api.js +71 -0
  35. blob_viewer-0.1.0/src/blob_viewer/static/js/app.js +1026 -0
  36. blob_viewer-0.1.0/src/blob_viewer/static/js/icons.js +65 -0
  37. blob_viewer-0.1.0/src/blob_viewer/static/js/ui.js +126 -0
  38. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/github-dark.min.css +10 -0
  39. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/github.min.css +10 -0
  40. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/highlight.min.js +1244 -0
  41. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/bash.min.js +21 -0
  42. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/c.min.js +41 -0
  43. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/cpp.min.js +47 -0
  44. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/csharp.min.js +49 -0
  45. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/css.min.js +31 -0
  46. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/dockerfile.min.js +8 -0
  47. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/go.min.js +20 -0
  48. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/graphql.min.js +12 -0
  49. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/ini.min.js +15 -0
  50. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/java.min.js +38 -0
  51. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/javascript.min.js +81 -0
  52. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/json.min.js +8 -0
  53. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/kotlin.min.js +46 -0
  54. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/lua.min.js +15 -0
  55. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/markdown.min.js +32 -0
  56. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/perl.min.js +41 -0
  57. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/php.min.js +59 -0
  58. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/protobuf.min.js +11 -0
  59. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/python.min.js +42 -0
  60. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/ruby.min.js +54 -0
  61. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/rust.min.js +27 -0
  62. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/sql.min.js +21 -0
  63. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/swift.min.js +68 -0
  64. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/typescript.min.js +99 -0
  65. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/xml.min.js +29 -0
  66. blob_viewer-0.1.0/src/blob_viewer/static/vendor/highjs/languages/yaml.min.js +28 -0
  67. blob_viewer-0.1.0/src/blob_viewer/static/vendor/marked.min.js +69 -0
  68. blob_viewer-0.1.0/src/blob_viewer/static/vendor/pdfjs/pdf.min.mjs +21 -0
  69. blob_viewer-0.1.0/src/blob_viewer/static/vendor/pdfjs/pdf.worker.min.mjs +21 -0
  70. blob_viewer-0.1.0/src/blob_viewer/static/vendor/purify.min.js +3 -0
  71. blob_viewer-0.1.0/src/blob_viewer/storage/__init__.py +13 -0
  72. blob_viewer-0.1.0/src/blob_viewer/storage/base.py +73 -0
  73. blob_viewer-0.1.0/src/blob_viewer/storage/factory.py +26 -0
  74. blob_viewer-0.1.0/src/blob_viewer/storage/local.py +152 -0
  75. blob_viewer-0.1.0/src/blob_viewer/storage/s3.py +191 -0
  76. blob_viewer-0.1.0/src/blob_viewer/templates/index.html +35 -0
  77. blob_viewer-0.1.0/src/blob_viewer/themes.py +31 -0
  78. blob_viewer-0.1.0/src/blob_viewer/workspaces.py +299 -0
  79. blob_viewer-0.1.0/tests/__init__.py +0 -0
  80. blob_viewer-0.1.0/tests/conftest.py +100 -0
  81. blob_viewer-0.1.0/tests/test_api.py +150 -0
  82. blob_viewer-0.1.0/tests/test_core.py +193 -0
  83. blob_viewer-0.1.0/tests/test_e2e_browser.py +154 -0
  84. blob_viewer-0.1.0/tests/test_e2e_rustfs.py +81 -0
@@ -0,0 +1,220 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ *.lcov
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ # Pipfile.lock
97
+
98
+ # uv
99
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ # uv.lock
103
+
104
+ # poetry
105
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
106
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
107
+ # commonly ignored for libraries.
108
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
109
+ # poetry.lock
110
+ # poetry.toml
111
+
112
+ # pdm
113
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
114
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
115
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
116
+ # pdm.lock
117
+ # pdm.toml
118
+ .pdm-python
119
+ .pdm-build/
120
+
121
+ # pixi
122
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
123
+ # pixi.lock
124
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
125
+ # in the .venv directory. It is recommended not to include this directory in version control.
126
+ .pixi/*
127
+ !.pixi/config.toml
128
+
129
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
130
+ __pypackages__/
131
+
132
+ # Celery stuff
133
+ celerybeat-schedule*
134
+ celerybeat.pid
135
+
136
+ # Redis
137
+ *.rdb
138
+ *.aof
139
+ *.pid
140
+
141
+ # RabbitMQ
142
+ mnesia/
143
+ rabbitmq/
144
+ rabbitmq-data/
145
+
146
+ # ActiveMQ
147
+ activemq-data/
148
+
149
+ # SageMath parsed files
150
+ *.sage.py
151
+
152
+ # Environments
153
+ .env
154
+ .envrc
155
+ .venv
156
+ env/
157
+ venv/
158
+ ENV/
159
+ env.bak/
160
+ venv.bak/
161
+
162
+ # Spyder project settings
163
+ .spyderproject
164
+ .spyproject
165
+
166
+ # Rope project settings
167
+ .ropeproject
168
+
169
+ # mkdocs/Zensical documentation
170
+ /site
171
+
172
+ # mypy
173
+ .mypy_cache/
174
+ .dmypy.json
175
+ dmypy.json
176
+
177
+ # Pyre type checker
178
+ .pyre/
179
+
180
+ # pytype static type analyzer
181
+ .pytype/
182
+
183
+ # Cython debug symbols
184
+ cython_debug/
185
+
186
+ # PyCharm
187
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
188
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
189
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
190
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
191
+ # .idea/
192
+
193
+ # Abstra
194
+ # Abstra is an AI-powered process automation framework.
195
+ # Ignore directories containing user credentials, local state, and settings.
196
+ # Learn more at https://abstra.io/docs
197
+ .abstra/
198
+
199
+ # Visual Studio Code
200
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore that
201
+ # can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
202
+ # and can be added to the global gitignore or merged into this file. However, if you prefer, you
203
+ # could uncomment the following to ignore the entire vscode folder
204
+ # .vscode/
205
+ # Temporary file for partial code execution
206
+ tempCodeRunnerFile.py
207
+
208
+ # Ruff stuff:
209
+ .ruff_cache/
210
+
211
+ # PyPI configuration file
212
+ .pypirc
213
+
214
+ # Marimo
215
+ marimo/_static/
216
+ marimo/_lsp/
217
+ __marimo__/
218
+
219
+ # Streamlit
220
+ .streamlit/secrets.toml
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ All notable changes to Blob Viewer are documented here. Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows [SemVer](https://semver.org/).
4
+
5
+ ## [0.1.0] — 2026-10-11
6
+
7
+ First public release.
8
+
9
+ ### Added
10
+
11
+ - Multiple workspaces: S3-compatible buckets (AWS S3, MinIO, RustFS, Backblaze B2, Cloudflare R2, DigitalOcean Spaces, Wasabi…) and local folders.
12
+ - Universal file preview: markdown (sanitised), source code with syntax highlighting (26 languages), PDF (pdf.js), images, audio, video, CSV tables and plain text.
13
+ - Local download cache with ETag-based version tracking, "update available" badges and one-click sync. Download-once semantics; offline access to cached files.
14
+ - OneDrive/MinIO-style web UI: sidebar workspaces, breadcrumbs, list/grid views, sorting, workspace-wide search, context menus, toasts.
15
+ - Eight themes (5 dark, 3 light) switchable live from the UI or CLI.
16
+ - Fully vendored frontend (marked, DOMPurify, highlight.js, pdf.js) — no CDN, air-gap friendly.
17
+ - Encrypted credential storage (Fernet at rest, redacted everywhere else).
18
+ - Locked mode (`--locked`) with master-admin bootstrap, PBKDF2 password hashing and server-side sessions.
19
+ - Guided CLI: `init`, `run`, `serve`, `workspace`, `user`, `cache`, `theme`, `doctor`, `version` — interactive and scriptable.
20
+ - Desktop app (pywebview) with automatic server-mode fallback.
21
+ - Docker image (multi-stage, non-root, ~195 MB) with healthcheck and volume-based persistence.
22
+ - Comprehensive docs, HTTP API reference and tests (unit, API, real-S3 e2e, Playwright browser e2e).
23
+
24
+ [0.1.0]: https://github.com/jasonjimnz/blob-viewer/releases/tag/v0.1.0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jason Jiménez Cruz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.5
2
+ Name: blob-viewer
3
+ Version: 0.1.0
4
+ Summary: A personal S3/MinIO bucket browser and file previewer. Desktop app (pywebview) and server, with a local download cache, multiple workspaces and a guided CLI.
5
+ Project-URL: Homepage, https://github.com/jasonjimnz/blob-viewer
6
+ Project-URL: Documentation, https://github.com/jasonjimnz/blob-viewer#readme
7
+ Project-URL: Repository, https://github.com/jasonjimnz/blob-viewer
8
+ Project-URL: Issues, https://github.com/jasonjimnz/blob-viewer/issues
9
+ Project-URL: Changelog, https://github.com/jasonjimnz/blob-viewer/blob/main/CHANGELOG.md
10
+ Author-email: Jason Jiménez Cruz <jasonjimenezcruz@gmail.com>
11
+ License: MIT License
12
+
13
+ Copyright (c) 2026 Jason Jiménez Cruz
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
32
+ License-File: LICENSE
33
+ Keywords: blob,boto3,bucket-browser,file-preview,minio,pywebview,s3,viewer
34
+ Classifier: Development Status :: 4 - Beta
35
+ Classifier: Environment :: Web Environment
36
+ Classifier: Environment :: X11 Applications
37
+ Classifier: Intended Audience :: End Users/Desktop
38
+ Classifier: License :: OSI Approved :: MIT License
39
+ Classifier: Operating System :: OS Independent
40
+ Classifier: Programming Language :: Python :: 3
41
+ Classifier: Programming Language :: Python :: 3.11
42
+ Classifier: Programming Language :: Python :: 3.12
43
+ Classifier: Programming Language :: Python :: 3.13
44
+ Classifier: Topic :: Desktop Environment :: File Managers
45
+ Classifier: Topic :: Utilities
46
+ Requires-Python: >=3.11
47
+ Requires-Dist: boto3>=1.35
48
+ Requires-Dist: cryptography>=43.0
49
+ Requires-Dist: flask>=3.1
50
+ Requires-Dist: pywebview>=5.4; python_version >= '3.11'
51
+ Requires-Dist: rich>=13.9
52
+ Requires-Dist: waitress>=3.0
53
+ Provides-Extra: dev
54
+ Requires-Dist: build>=1.2; extra == 'dev'
55
+ Requires-Dist: hatchling>=1.27; extra == 'dev'
56
+ Requires-Dist: markdown>=3.7; extra == 'dev'
57
+ Requires-Dist: pytest-cov>=6.0; extra == 'dev'
58
+ Requires-Dist: pytest>=8.3; extra == 'dev'
59
+ Requires-Dist: ruff>=0.8; extra == 'dev'
60
+ Requires-Dist: twine>=6.0; extra == 'dev'
61
+ Description-Content-Type: text/markdown
62
+
63
+ # Blob Viewer
64
+
65
+ **A personal S3/MinIO bucket browser and file previewer.**
66
+
67
+ Blob Viewer connects to any S3-compatible bucket — AWS S3, MinIO, Backblaze B2, Cloudflare R2, DigitalOcean Spaces, Wasabi — or to a plain local folder, and gives you a fast, modern file browser with previews for markdown, source code, PDFs, images, audio, video, CSV and more. Every file you open is cached locally, so your workspace is always available — even offline — and nothing is downloaded twice.
68
+
69
+ > Built for personal use by [Jason Jiménez Cruz](https://github.com/jasonjimnz).
70
+
71
+ ## Highlights
72
+
73
+ - **Many workspaces** — register as many S3 buckets or local folders as you want and switch between them instantly.
74
+ - **Universal preview** — markdown, code with syntax highlighting, PDF, images, audio, video, CSV tables, plain text. Anything else is one click away as a download.
75
+ - **Local download cache** — files are fetched once and reused. When a newer version exists upstream, Blob Viewer tells you and lets you sync.
76
+ - **Remote workspaces are read-only** — blobs are never modified in place. Local workspaces stay fully writable.
77
+ - **Encrypted credentials** — access keys are encrypted at rest and always redacted in the UI and API; nobody can read them back from a config dump.
78
+ - **Locked mode** — start with `--locked` to require a master-admin login in the desktop app and the server.
79
+ - **Runs anywhere** — as a desktop app (pywebview), a headless server, or a small Docker container. The frontend is plain HTML/JS/CSS with vendored libraries: no CDN, no build step, works in isolated environments.
80
+ - **Many themes** — dark, light and coloured themes switchable from the UI.
81
+
82
+ ## Install
83
+
84
+ ```bash
85
+ pip install blob-viewer
86
+ ```
87
+
88
+ Python 3.11+ (3.13 recommended). For the desktop window on Linux you may need GTK/Qt libraries (`sudo apt install python3-gi gir1.2-webkit2-4.1` on Debian/Ubuntu); on Windows and macOS there are no extra requirements. If a GUI is unavailable, use server mode — everything works in the browser.
89
+
90
+ ## Quick start
91
+
92
+ ```bash
93
+ # guided setup: create your first workspace, pick a theme
94
+ blob-viewer init
95
+
96
+ # open the desktop app
97
+ blob-viewer run
98
+
99
+ # or serve it on the network (e.g. a home server / container)
100
+ blob-viewer serve --host 0.0.0.0 --port 8585
101
+ ```
102
+
103
+ Then open <http://127.0.0.1:8585> if you used `serve`.
104
+
105
+ ### Locked mode
106
+
107
+ ```bash
108
+ # first run asks you to create the master admin
109
+ blob-viewer run --locked
110
+
111
+ # CLI login is enforced in the desktop app and the server
112
+ blob-viewer serve --locked
113
+ ```
114
+
115
+ ## Managing workspaces
116
+
117
+ ```bash
118
+ blob-viewer workspace add # guided wizard (S3 or local)
119
+ blob-viewer workspace list
120
+ blob-viewer workspace test my-bucket
121
+ blob-viewer workspace remove my-bucket
122
+ ```
123
+
124
+ Or do everything from the UI: **Settings → Workspaces → Add workspace**.
125
+
126
+ | Field | S3 workspace | Local workspace |
127
+ |---|---|---|
128
+ | Endpoint | `https://s3.amazonaws.com`, `http://localhost:9000`, ... | — |
129
+ | Bucket | required | — |
130
+ | Access / Secret key | encrypted at rest | — |
131
+ | Region | optional (`us-east-1` default) | — |
132
+ | Prefix | optional root path inside the bucket | — |
133
+ | Path style | on by default (MinIO/R2/B2) | — |
134
+ | Folder | — | any local path |
135
+ | Writable | never (read-only by design) | yes |
136
+
137
+ ## CLI overview
138
+
139
+ ```
140
+ blob-viewer init Guided first-run configuration
141
+ blob-viewer run [--locked] [--port] Launch the desktop app
142
+ blob-viewer serve [--locked] Headless server mode
143
+ blob-viewer workspace add|list|show|test|remove|edit
144
+ blob-viewer user create|reset|status Master admin for locked mode
145
+ blob-viewer cache stats|clear Inspect / empty the download cache
146
+ blob-viewer theme list|set Change the UI theme
147
+ blob-viewer doctor Diagnose installation problems
148
+ blob-viewer version Show version
149
+ ```
150
+
151
+ Run `blob-viewer <command> --help` for details on every command.
152
+
153
+ ## Where is my data?
154
+
155
+ Everything lives in one folder (default `~/.blob-viewer`, override with `BLOB_VIEWER_HOME` or `--home`):
156
+
157
+ ```
158
+ ~/.blob-viewer/
159
+ ├── blob-viewer.db # workspaces, settings, cache index (secrets encrypted)
160
+ ├── secrets.key # per-installation encryption key (chmod 600)
161
+ └── cache/ # downloaded files, one folder per workspace
162
+ ```
163
+
164
+ Delete the folder = factory reset. Credentials are encrypted with a key that never leaves your machine; the API never returns secret values, only masked hints like `••••ab12`.
165
+
166
+ ## Docker
167
+
168
+ ```bash
169
+ docker run -d --name blob-viewer \
170
+ -p 8585:8585 -v blob-viewer-data:/data \
171
+ ghcr.io/jasonjimnz/blob-viewer:latest
172
+ ```
173
+
174
+ The image is multi-stage, runs as a non-root user and stores state in the `/data` volume. `--locked` is honoured via the `BLOB_VIEWER_LOCKED=1` environment variable or the container command.
175
+
176
+ ## Documentation
177
+
178
+ Full documentation lives in [`docs/`](docs/index.md):
179
+
180
+ - [Installation](docs/install.md)
181
+ - [Getting started](docs/getting-started.md)
182
+ - [Workspaces](docs/workspaces.md)
183
+ - [File preview & the cache](docs/preview-cache.md)
184
+ - [Security & locked mode](docs/security.md)
185
+ - [CLI reference](docs/cli.md)
186
+ - [HTTP API reference](docs/api.md)
187
+ - [Themes & customisation](docs/themes.md)
188
+ - [Docker deployment](docs/docker.md)
189
+ - [Architecture](docs/architecture.md)
190
+ - [Troubleshooting / FAQ](docs/faq.md)
191
+
192
+ ## Development
193
+
194
+ ```bash
195
+ git clone https://github.com/jasonjimnz/blob-viewer.git
196
+ cd blob-viewer
197
+ python -m venv .venv && .venv/Scripts/pip install -e .[dev] # POSIX: .venv/bin/pip
198
+ pytest # unit tests
199
+ pytest -m e2e # end-to-end tests (needs Docker; uses a throwaway MinIO)
200
+ ```
201
+
202
+ See [docs/architecture.md](docs/architecture.md) for a tour of the codebase and how the pieces fit together.
203
+
204
+ ## License
205
+
206
+ [MIT](LICENSE) © Jason Jiménez Cruz
@@ -0,0 +1,144 @@
1
+ # Blob Viewer
2
+
3
+ **A personal S3/MinIO bucket browser and file previewer.**
4
+
5
+ Blob Viewer connects to any S3-compatible bucket — AWS S3, MinIO, Backblaze B2, Cloudflare R2, DigitalOcean Spaces, Wasabi — or to a plain local folder, and gives you a fast, modern file browser with previews for markdown, source code, PDFs, images, audio, video, CSV and more. Every file you open is cached locally, so your workspace is always available — even offline — and nothing is downloaded twice.
6
+
7
+ > Built for personal use by [Jason Jiménez Cruz](https://github.com/jasonjimnz).
8
+
9
+ ## Highlights
10
+
11
+ - **Many workspaces** — register as many S3 buckets or local folders as you want and switch between them instantly.
12
+ - **Universal preview** — markdown, code with syntax highlighting, PDF, images, audio, video, CSV tables, plain text. Anything else is one click away as a download.
13
+ - **Local download cache** — files are fetched once and reused. When a newer version exists upstream, Blob Viewer tells you and lets you sync.
14
+ - **Remote workspaces are read-only** — blobs are never modified in place. Local workspaces stay fully writable.
15
+ - **Encrypted credentials** — access keys are encrypted at rest and always redacted in the UI and API; nobody can read them back from a config dump.
16
+ - **Locked mode** — start with `--locked` to require a master-admin login in the desktop app and the server.
17
+ - **Runs anywhere** — as a desktop app (pywebview), a headless server, or a small Docker container. The frontend is plain HTML/JS/CSS with vendored libraries: no CDN, no build step, works in isolated environments.
18
+ - **Many themes** — dark, light and coloured themes switchable from the UI.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pip install blob-viewer
24
+ ```
25
+
26
+ Python 3.11+ (3.13 recommended). For the desktop window on Linux you may need GTK/Qt libraries (`sudo apt install python3-gi gir1.2-webkit2-4.1` on Debian/Ubuntu); on Windows and macOS there are no extra requirements. If a GUI is unavailable, use server mode — everything works in the browser.
27
+
28
+ ## Quick start
29
+
30
+ ```bash
31
+ # guided setup: create your first workspace, pick a theme
32
+ blob-viewer init
33
+
34
+ # open the desktop app
35
+ blob-viewer run
36
+
37
+ # or serve it on the network (e.g. a home server / container)
38
+ blob-viewer serve --host 0.0.0.0 --port 8585
39
+ ```
40
+
41
+ Then open <http://127.0.0.1:8585> if you used `serve`.
42
+
43
+ ### Locked mode
44
+
45
+ ```bash
46
+ # first run asks you to create the master admin
47
+ blob-viewer run --locked
48
+
49
+ # CLI login is enforced in the desktop app and the server
50
+ blob-viewer serve --locked
51
+ ```
52
+
53
+ ## Managing workspaces
54
+
55
+ ```bash
56
+ blob-viewer workspace add # guided wizard (S3 or local)
57
+ blob-viewer workspace list
58
+ blob-viewer workspace test my-bucket
59
+ blob-viewer workspace remove my-bucket
60
+ ```
61
+
62
+ Or do everything from the UI: **Settings → Workspaces → Add workspace**.
63
+
64
+ | Field | S3 workspace | Local workspace |
65
+ |---|---|---|
66
+ | Endpoint | `https://s3.amazonaws.com`, `http://localhost:9000`, ... | — |
67
+ | Bucket | required | — |
68
+ | Access / Secret key | encrypted at rest | — |
69
+ | Region | optional (`us-east-1` default) | — |
70
+ | Prefix | optional root path inside the bucket | — |
71
+ | Path style | on by default (MinIO/R2/B2) | — |
72
+ | Folder | — | any local path |
73
+ | Writable | never (read-only by design) | yes |
74
+
75
+ ## CLI overview
76
+
77
+ ```
78
+ blob-viewer init Guided first-run configuration
79
+ blob-viewer run [--locked] [--port] Launch the desktop app
80
+ blob-viewer serve [--locked] Headless server mode
81
+ blob-viewer workspace add|list|show|test|remove|edit
82
+ blob-viewer user create|reset|status Master admin for locked mode
83
+ blob-viewer cache stats|clear Inspect / empty the download cache
84
+ blob-viewer theme list|set Change the UI theme
85
+ blob-viewer doctor Diagnose installation problems
86
+ blob-viewer version Show version
87
+ ```
88
+
89
+ Run `blob-viewer <command> --help` for details on every command.
90
+
91
+ ## Where is my data?
92
+
93
+ Everything lives in one folder (default `~/.blob-viewer`, override with `BLOB_VIEWER_HOME` or `--home`):
94
+
95
+ ```
96
+ ~/.blob-viewer/
97
+ ├── blob-viewer.db # workspaces, settings, cache index (secrets encrypted)
98
+ ├── secrets.key # per-installation encryption key (chmod 600)
99
+ └── cache/ # downloaded files, one folder per workspace
100
+ ```
101
+
102
+ Delete the folder = factory reset. Credentials are encrypted with a key that never leaves your machine; the API never returns secret values, only masked hints like `••••ab12`.
103
+
104
+ ## Docker
105
+
106
+ ```bash
107
+ docker run -d --name blob-viewer \
108
+ -p 8585:8585 -v blob-viewer-data:/data \
109
+ ghcr.io/jasonjimnz/blob-viewer:latest
110
+ ```
111
+
112
+ The image is multi-stage, runs as a non-root user and stores state in the `/data` volume. `--locked` is honoured via the `BLOB_VIEWER_LOCKED=1` environment variable or the container command.
113
+
114
+ ## Documentation
115
+
116
+ Full documentation lives in [`docs/`](docs/index.md):
117
+
118
+ - [Installation](docs/install.md)
119
+ - [Getting started](docs/getting-started.md)
120
+ - [Workspaces](docs/workspaces.md)
121
+ - [File preview & the cache](docs/preview-cache.md)
122
+ - [Security & locked mode](docs/security.md)
123
+ - [CLI reference](docs/cli.md)
124
+ - [HTTP API reference](docs/api.md)
125
+ - [Themes & customisation](docs/themes.md)
126
+ - [Docker deployment](docs/docker.md)
127
+ - [Architecture](docs/architecture.md)
128
+ - [Troubleshooting / FAQ](docs/faq.md)
129
+
130
+ ## Development
131
+
132
+ ```bash
133
+ git clone https://github.com/jasonjimnz/blob-viewer.git
134
+ cd blob-viewer
135
+ python -m venv .venv && .venv/Scripts/pip install -e .[dev] # POSIX: .venv/bin/pip
136
+ pytest # unit tests
137
+ pytest -m e2e # end-to-end tests (needs Docker; uses a throwaway MinIO)
138
+ ```
139
+
140
+ See [docs/architecture.md](docs/architecture.md) for a tour of the codebase and how the pieces fit together.
141
+
142
+ ## License
143
+
144
+ [MIT](LICENSE) © Jason Jiménez Cruz