A lightweight browser-based SQL Server management tool built with Angular 21 and ASP.NET Core 10. Think minimal SSMS in the browser — browse databases, run queries, edit master/config data, and manage stored procedures and views, all from a clean dark-mode UI.
- JWT-based login with role-based access (admin / dba / viewer)
- Post-login Connection Selector — pick a saved connection or enter a custom server, database, username, and password
- Encrypted per-session connection tokens sent on every API request via
X-Db-Connectionheader - Viewer role: read-only everywhere — no CRUD, no query execute, no ALTER
- Live stats cards: Databases, Tables, Views, Procedures, Functions, Active Queries, CPU %, RAM, Uptime, Server Version
- Auto-refreshes every 10 seconds
- Click-through CPU and RAM cards expand an inline line chart showing the last ~30 metric snapshots
- Tree view of all databases on the connected server
- Expand any database to see Tables, Views, Stored Procedures, and Functions sub-nodes
- Filterable table list showing Master and Config tables from
TableMetadata - Slide-in side panel for Add / Edit rows — scales to any number of columns
- Smart input types auto-detected from SQL
dataType:int→ number,bit→ checkbox,datetime2→ datetime picker,nvarchar(MAX)→ textarea, etc. - Delete with confirmation dialog
- Pagination (50 rows per page)
- When editing
ConfigEntriesrows, theConfigValuefield renders a structured form editor instead of a raw textarea - JSON — flattens nested JSON to dot-path key/value pairs; add/remove/edit fields; un-flattens on save
- XML — parses element tree to tag/value rows; reconstructs XML on save
- Hierarchical — splits by
Separatorfield into key:value pairs or a flat-value list - Form / Raw toggle — switch between structured form and raw text editing at any time
- Monaco Editor (VS Code engine) with SQL syntax highlighting
- Database selector; results grid with column headers
- Results capped at 1000 rows (configurable via
app.featuresconfig entry)
- Browse and edit stored procedures and views with Monaco Editor
- Save runs
ALTER PROCEDURE/ALTER VIEWagainst the connected server - Viewer role: editor is read-only, no Save button
- App Users tab — CRUD on
AppUserstable (admin only) - SQL Server Logins tab — read-only grid from
sys.server_principals
- Every CRUD operation and query execution is written to
AuditLogtable - Recent activity shown on dashboard
| Layer | Technology |
|---|---|
| Frontend | Angular 21, signals, standalone components, Catppuccin Mocha dark theme |
| Query Editor | Monaco Editor (ngx-monaco-editor-v2) |
| Charts | ng2-charts + chart.js |
| Backend | ASP.NET Core 10, Dapper, Microsoft.Data.SqlClient |
| Database project | Microsoft.Build.Sql SQLPROJ (SSDT-compatible) |
| Auth | JWT Bearer tokens + AES-256 encrypted session connection tokens |
- Node.js 20+ and npm (for Angular dev server)
- .NET 10 SDK
- SQL Server 2019 or later (local or remote)
- A
SqlBrowserDBdatabase deployed from the.sqlprojproject
Open sqlserverbrowser.db/sqlserverbrowser.db.sqlproj in Visual Studio or VS Code (with the SQL Database Projects extension). Use Schema Compare to publish to a SQL Server instance as SqlBrowserDB.
After publishing, run the seed scripts manually (in order) via SSMS or sqlcmd:
sqlserverbrowser.db/Seeds/001_AppUsers_seed.sql
sqlserverbrowser.db/Seeds/002_Country_seed.sql
sqlserverbrowser.db/Seeds/003_Currency_seed.sql
sqlserverbrowser.db/Seeds/004_Category_seed.sql
sqlserverbrowser.db/Seeds/005_ConfigEntries_seed.sql
Copy sqlserverbrowser.api/appsettings.json and set your credentials via .NET User Secrets (recommended) or directly in the file:
cd sqlserverbrowser.api
dotnet user-secrets set "ConnectionStrings:SqlBrowserDB" \
"Server=YOUR_SERVER;Database=SqlBrowserDB;User Id=YOUR_USER;Password=YOUR_PASSWORD;TrustServerCertificate=True"Or update appsettings.json directly (do not commit credentials):
{
"ConnectionStrings": {
"SqlBrowserDB": "Server=localhost;Database=SqlBrowserDB;User Id=YOUR_SQL_USER;Password=YOUR_PASSWORD;TrustServerCertificate=True"
},
"SavedConnections": [
{
"Name": "Local Dev - SQL Auth",
"ConnectionString": "Server=localhost;Database=master;User Id=YOUR_SQL_USER;Password=YOUR_PASSWORD;TrustServerCertificate=True"
}
]
}cd sqlserverbrowser.api
dotnet runAPI starts on http://localhost:5055.
cd sqlserverbrowser.web
npm install
npx ng serveApp opens on http://localhost:4200.
Default seed credentials:
| Username | Password | Role |
|---|---|---|
admin |
Admin@123 |
admin |
dba |
Dba@123 |
dba |
viewer |
Viewer@123 |
viewer |
After login you will be redirected to the Connection Selector. Select a saved connection, enter your SQL Server password, and click Connect.
sqlserverbrowser/
├── sqlserverbrowser.api/ # ASP.NET Core 10 API
│ ├── Controllers/ # Auth, Connection, Tables, Query, Procedures, Views, Users, Dashboard
│ ├── Infrastructure/ # SqlConnectionFactory, AuditService, JWT helpers
│ └── appsettings.json # Saved connections & JWT config (no credentials)
│
├── sqlserverbrowser.web/ # Angular 21 frontend
│ └── src/app/
│ ├── pages/ # login, connect, dashboard, tables, query, databases, procedures, views, users
│ ├── components/ # config-value-editor (smart JSON/XML/Hierarchical form)
│ ├── services/ # AuthService, ConnectionService
│ ├── interceptors/ # authInterceptor (attaches JWT + X-Db-Connection)
│ └── guards/ # authGuard, connectionGuard
│
├── sqlserverbrowser.db/ # SQL Database Project (.sqlproj)
│ ├── Tables/ # AppUsers, TableMetadata, ConfigEntries, AuditLog, Country, etc.
│ └── Seeds/ # Seed scripts (run manually, not in DACPAC)
│
└── docs/screenshots/ # App screenshots
| Feature | viewer | dba | admin |
|---|---|---|---|
| Read tables / query | ✅ | ✅ | ✅ |
| CRUD on master/config tables | ❌ | ✅ | ✅ |
| Execute queries | ❌ | ✅ | ✅ |
| ALTER procedures / views | ❌ | ✅ | ✅ |
| Manage app users | ❌ | ❌ | ✅ |
- The JWT signing key in
appsettings.json(Jwt:Key) must be at least 32 characters. Change it in production. - The connection token encryption key (
ConnectionToken:EncryptionKey) must be changed in production. - The
SqlBrowserDBconnection string should point to a dedicated low-privilege SQL login (notsa) in production. - Query results are hard-capped at 1000 rows server-side regardless of
app.features.maxQueryRows.


















