Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b85e46c
feat(web): migrate sidebar to shadcn and convert entity editors to pa…
RockChinQ Mar 26, 2026
2f8f3a2
feat(web): enhance sidebar with sections, collapsible persistence, su…
RockChinQ Mar 26, 2026
f5e90cd
fix(web): fix scroll behavior - constrain layout to viewport, fix fix…
RockChinQ Mar 26, 2026
97b3beb
style(web): polish UI - dashboard i18n, sidebar create text, cursor-p…
RockChinQ Mar 26, 2026
24933d7
feat(web): add plugin context menu to sidebar sub-items
RockChinQ Mar 26, 2026
6d5eab0
fix(web): prevent plugin sidebar text from overlapping menu button
RockChinQ Mar 26, 2026
cce4830
feat(web): show update indicator on sidebar plugin menu
RockChinQ Mar 26, 2026
061ce32
refactor(web): remove entity list pages, back buttons, and make sideb…
RockChinQ Mar 26, 2026
3521490
feat(web): enhance bot session monitor with refresh functionality and…
RockChinQ Mar 26, 2026
763db91
refactor(web): optimize pipeline detail page with vertical config nav…
RockChinQ Mar 26, 2026
709bab7
fix(web): improve dark mode contrast and relocate WebSocket status in…
RockChinQ Mar 26, 2026
44304c8
fix(web): increase dark mode contrast for muted/accent/secondary to o…
RockChinQ Mar 26, 2026
da6c34d
style(web): replace hardcoded colors with theme tokens in monitoring …
RockChinQ Mar 26, 2026
f562733
feat(web): show debug indicator for debugging plugins in sidebar
RockChinQ Mar 26, 2026
b62932b
feat(web): show install source and debug badge on plugin detail page
RockChinQ Mar 26, 2026
b4e4027
fix(web): resolve eslint errors for CI - remove unused imports and va…
RockChinQ Mar 26, 2026
1f63034
fix(web): remove stale setSubtitle call and fix prettier formatting
RockChinQ Mar 26, 2026
1e712c2
Refactor code formatting and improve readability
RockChinQ Mar 26, 2026
28cbaa9
fix(ci): use local prettier instead of mirrors-prettier to avoid vers…
RockChinQ Mar 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ repos:
# Run the formatter of backend.
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.1.0
- repo: local
hooks:
- id: prettier
name: prettier
entry: npx --prefix web prettier --write --ignore-unknown
language: system
types_or: [javascript, jsx, ts, tsx, css, scss]
additional_dependencies:
- prettier@3.1.0

- repo: local
hooks:
- id: lint-staged
name: lint-staged
entry: cd web && pnpm lint-staged
Expand Down
22 changes: 22 additions & 0 deletions src/langbot/pkg/api/http/controller/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,28 @@ async def static_file(path: str):
):
if os.path.exists(os.path.join(frontend_path, path + '.html')):
path += '.html'
elif path.startswith('home/'):
# SPA fallback for /home/* sub-routes.
# Entity detail views use query params (e.g. /home/bots?id=uuid),
# so the pre-rendered list page is served directly via path + '.html'.
# This fallback handles any remaining unmatched sub-paths.
segments = path.rstrip('/').split('/')

# Walk up parent segments looking for matching .html files
for i in range(len(segments) - 1, 0, -1):
parent_path = '/'.join(segments[:i]) + '.html'
if os.path.exists(os.path.join(frontend_path, parent_path)):
response = await quart.send_from_directory(frontend_path, parent_path, mimetype='text/html')
response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '0'
return response
# Final fallback to index.html for /home/* routes
response = await quart.send_from_directory(frontend_path, 'index.html', mimetype='text/html')
response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '0'
return response
else:
return await quart.send_from_directory(frontend_path, '404.html')

Expand Down
1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@dnd-kit/utilities": "^3.2.2",
"@hookform/resolvers": "^5.0.1",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-avatar": "^1.1.11",
"@radix-ui/react-checkbox": "^1.3.1",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-context-menu": "^2.2.15",
Expand Down
Loading
Loading