Build and deploy lightweight Flask web tools (file managers, dashboards, admin panels) on Linux servers. Covers Chinese/i18n filenames, mobile touch UX, simple auth, and Docker-free deployment.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Build and deploy lightweight Flask web tools (file managers, dashboards, admin panels) on Linux servers. Covers Chinese/i18n filenames, mobile touch UX, simple auth, and Docker-free deployment.
triggers
["user asks to build a web UI, file manager, admin panel, or dashboard","user asks to deploy a Python web app on a server","user mentions 文件管理, 网盘, file manager, or web tool","user needs a simple internal tool with a web interface"]
Flask Web Tools
Build lightweight, single-file Flask web tools for server deployment. No heavy frameworks — Flask + inline HTML templates + vanilla JS.
werkzeug.utils.secure_filename removes ALL non-ASCII characters. Chinese filenames become empty strings.
Fix — custom safe_filename:
defsafe_filename(name):
"""安全文件名:支持中文,防止路径穿越"""
name = name.replace("\\", "/").split("/")[-1]
name = name.replace("\x00", "")
name = name.replace("..", "")
name = name.strip(". ")
ifnot name:
return""return name
Use this instead of secure_filename for all user-provided filenames.
Pitfall: Hover-only buttons invisible on mobile
CSS opacity: 0 with :hover { opacity: 1 } makes buttons invisible on touch devices (no hover state).
Long-press action sheet (better UX): Add touch event handlers for mobile context menu
Pitfall: AJAX login forms can fail silently
Complex fetch()-based login can fail due to CORS, content-type mismatch, or JS errors. For simple tools, use plain HTML form POST — it's more reliable and works without JavaScript.
Using secrets.token_hex(32) generates a new key each restart, invalidating all session cookies. Use a fixed secret key for tools that need persistent sessions.
Pitfall: Python version mismatch on pip install
On systems with multiple Python versions, pip3 install may install to the wrong Python. Use the specific python binary:
/home/admin/.hermes/hermes-agent/venv/bin/python -m pip install flask
# or
uv pip install flask # if using uv-managed venv
Mobile Long-Press Context Menu
For file managers and list-based UIs, add touch-based long-press:
let pressTimer = null;
let actionFile = null;
functionpressStart(e, idx) {
pressEnd(e);
pressTimer = setTimeout(() => {
const f = window._files[idx];
showActionSheet(f);
if (navigator.vibrate) navigator.vibrate(50); // haptic feedback
}, 500); // 500ms threshold
}
functionpressEnd(e) {
if (pressTimer) { clearTimeout(pressTimer); pressTimer = null; }
}
Attach to rows: ontouchstart, ontouchend, ontouchmove, ontouchcancel, onmousedown, onmouseup, onmouseleave.
Always validate file paths to prevent ../../../etc/passwd attacks:
defget_safe_path(path):
path = path.strip('/')
parts = []
for part in path.split('/'):
if part in ('', '.'): continueif part == '..':
if parts: parts.pop()
continue
parts.append(part)
safe_path = STORAGE_ROOT.joinpath(*parts)
try:
safe_path.resolve().relative_to(STORAGE_ROOT.resolve())
return safe_path
except ValueError:
return STORAGE_ROOT # fallback to root if path escapes
File Viewer / Preview
Add inline file viewing so users can click a file and see it without downloading.
⚠️ PITFALL: This route MUST be placed BEFORE if __name__ == '__main__':.
Flask ignores routes defined after the main block. If you append with cat >>, the route won't register.
Viewer CSS: full-screen dark overlay (z-index: 200), top bar with filename + close + download buttons, body centered with scrollable content.
Office preview caveat: Microsoft's online viewer requires the file URL to be publicly accessible. Works on public servers, won't work on localhost/LAN.
Critical Pitfall: Flask Route Placement
⚠️ Routes defined AFTER if __name__ == '__main__': are NOT registered.
When appending routes (e.g., cat >> app.py), always insert BEFORE the main block:
Use case: Self-contained tools where the admin UI and API client scripts are served from the same Flask app. Users access http://server/admin.html directly without logging into the file manager.