sqliteExplorerReact
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
The SQLite Explorer has been successfully migrated from server-rendered JSX with HTMX to a React SPA with Hono backend, following Val Town best practices.
project-sqlite/
├── backend/
│ └── index.http.ts # Main Hono server with API routes
├── frontend/
│ ├── components/
│ │ ├── Icons.tsx # SVG icon components
│ │ ├── Table.tsx # Query results table
│ │ ├── TablesList.tsx # Database schema browser
│ │ ├── EditorSection.tsx # SQL editor with CodeMirror
│ │ └── Separator.tsx # Panel separators
│ ├── hooks/
│ │ ├── useCodeEditor.ts # Editor state & SQL extraction
│ │ ├── useQueryExecution.ts # Query execution logic
│ │ ├── useTableSelection.ts # Table selection & persistence
│ │ └── useDownload.ts # Download functionality
│ ├── App.tsx # Main application component
│ ├── main.tsx # React entry point
│ ├── index.html # HTML template
│ ├── reset.css # CSS reset
│ └── style.css # Application styles
└── shared/
├── types.ts # Shared TypeScript types
├── sqlHelpers.ts # SQL parsing utilities
└── exportHelpers.ts # CSV/JSON export functions
- React 18.2.0 - UI framework
- @uiw/react-codemirror - SQL code editor
- @codemirror/lang-sql - SQL syntax highlighting
- TailwindCSS (twind) - Utility-first CSS via CDN
- Custom CSS - Layout and component styles
- Hono 4 - Lightweight web framework
- Val Town SQLite - Database (Turso/libSQL)
- Val Town utilities - File serving, auth, iframe handling
- sql-query-identifier - SQL statement parsing
- @json2csv/plainjs - CSV export
✅ All original features preserved:
- Database schema browser (tables & views)
- SQL editor with syntax highlighting
- Query execution with results display
- CSV and JSON export
- Query persistence per table (localStorage)
- Keyboard shortcuts (Cmd+Enter to run)
- Password authentication
- Error handling and display
✅ Architecture improvements:
- React state management (hooks-based)
- Clean separation of concerns
- Reusable components
- TypeScript types for type safety
- API-based data fetching
- Better code organization
The backend exposes the following REST API endpoints:
GET /api/schema- Returns all tables and viewsPOST /api/query- Executes SQL query, returns resultsGET /api/download/csv?query=...- Downloads results as CSVGET /api/download/json?query=...- Downloads results as JSONGET /- Serves React applicationGET /frontend/*- Serves frontend assetsGET /shared/*- Serves shared utilities
-
Initial Load
- Backend serves
frontend/index.html - React app bootstraps via
frontend/main.tsx - App component mounts and fetches database schema
- Backend serves
-
Table Selection
- User clicks table/view in sidebar
useTableSelectionhook loads saved query from localStorage OR generates defaultSELECT * FROM table- Editor updates with query
-
Query Execution
- User edits SQL in CodeMirror editor
- Press Cmd+Enter or click Run button
useCodeEditorextracts statement at cursor positionuseQueryExecutionsends POST to/api/query- Results displayed in table below editor
-
Data Export
- Click Download CSV/JSON button
useDownloadhook triggers download from/api/download/*- Browser downloads file
The app uses React hooks for state management:
- App.tsx - Global state (schema, selected table)
- useCodeEditor - Editor content, cursor position, statement extraction
- useQueryExecution - Query results, errors, loading state
- useTableSelection - Table selection, localStorage sync
- useDownload - Download operations
- Application loads without errors
- Database schema loads and displays in sidebar
- Clicking a table loads default SELECT query
- SQL editor has syntax highlighting
- Code editor accepts text input
- Cmd+Enter executes query
- Run button executes query
- Query results display correctly in table
- SQL errors display in red text
- Download CSV button works
- Download JSON button works
- Buttons are disabled when editor is empty
- Buttons are enabled when editor has content
- Loading indicator shows during query execution
- Saved queries persist in localStorage
- Selecting a table loads saved query (if exists)
- Empty query handling
- Invalid SQL error messages
- Multi-statement SQL (executes statement at cursor)
- Large result sets display properly
- Views vs tables distinguished by icons
- Ensure the project is in the Val Town recommended structure
- The main entry point is
backend/index.http.ts - The file should be set as type "http"
- All authentication and iframe handling is already configured
For local development outside Val Town, you'll need to:
-
Replace Val Town-specific imports:
https://esm.town/v/std/sqlite→ Use better-sqlite3 or Turso clienthttps://esm.town/v/std/utils→ Implement file serving manually- Remove Val Town auth middleware (or implement custom auth)
-
Set up a dev server with Vite or similar
- ❌ HTMX (replaced with React state + fetch)
- ❌ Hyperscript (replaced with React event handlers)
- ❌ code-mirror web component (replaced with @uiw/react-codemirror)
- ❌ Server-side JSX rendering (now client-side React)
- ✅ React components and hooks
- ✅ TypeScript types
- ✅ REST API endpoints
- ✅ Client-side state management
- ✅ Better code organization
- ✅ DownloadSVG icon
- 🔄 Form submission → API calls via fetch
- 🔄 Hyperscript click handlers → React onClick
- 🔄 HTMX target swapping → React state updates
- 🔄 Server-rendered components → Client-rendered React
- 🔄 Inline scripts → React hooks
- Panel resizing is visual only (resize functionality not yet implemented)
- Can use
react-resizable-panelslibrary if needed
- Can use
- Authentication still uses Val Town-specific middleware
- File serving uses Val Town utilities
Potential improvements to consider:
- Query history panel (show recent queries)
- Saved queries UI (beyond localStorage)
- Query formatting button (using sql-formatter)
- Dark mode support
- Table schema viewer (show column names/types)
- Query execution time display
- Result pagination for large datasets
- Export options (limit rows, custom filename)
- Keyboard shortcut help panel
- Multiple tabs for queries
- Check browser console for errors
- Verify
/frontend/index.htmlis being served - Check that all imports resolve correctly
- Check backend console for errors
- Verify
/api/queryendpoint is accessible - Check authentication is working
- Verify CodeMirror dependencies loaded from esm.sh
- Check React version is pinned to 18.2.0
- Look for import errors in browser console
- Check
/api/download/*endpoints - Verify query parameter is being passed
- Check browser download settings
Migration completed on: 2025-11-14 Framework: React 18 + Hono 4 Status: Ready for testing
Get started with a template: