A brutally minimalist stack for building persistent web apps.
TinyHind is a full-stack starter kit for developers who believe in radical simplicity. It's built on a dynamic .NET backend and a dependency-free TypeScript workflow, designed to produce fast, miniature web applications with persistence.
No node_modules
, no config hell. Just lean, powerful code.
- 🚀 Dynamic Backend: A schema-driven .NET API powered by SQLite. Define your data structures on the fly.
- ✍️ Type-Safe Frontend: Write clean TypeScript with an awesome developer experience, powered by a client library that's auto-generated from your live backend schema.
- ⚡️ Zero-Dependency Build: A wicked-fast build process using a standalone esbuild binary. No
npm
, nopackage.json
, no bloat. - 🛠️ Simple Tooling: A lightweight set of tools to manage your development workflow without a complex setup.
Get up and running in minutes.
- .NET 8 SDK
- Python 3 (for the development CLI)
Clone or download this repository. The project is structured into three main parts: backend
, frontend
, and tools
.
Open a terminal in the backend
directory and run the API:
cd backend
dotnet run
Your TinyHind API is now running on http://localhost:5087
.
The project includes a simple CLI to manage your frontend workflow.
Open a second terminal in the root of the project and run the manager:
python tools/manager.py
You'll see a menu. Here's the typical workflow:
- Choose
3. Pull Latest Schema
to generate yourapi-types.ts
file from the running backend. - Choose
1. Build Project
to compile your TypeScript with esbuild. - Choose
2. Serve Project
to start the development server onhttp://localhost:8776
.
Open http://localhost:8776
in your browser, and you'll see your app running!
Building your application is simple. The developer experience is built around the auto-generated TinyHindClient
, which gives you full type safety and autocomplete for your backend API.
Here’s how you’d use it in your frontend/src/main.ts
:
// Import the client and the auto-generated types
import { TinyHindClient } from './tinyhind-client.ts';
import { DbSchema } from './api-types.ts';
// Configure your client to connect to the backend
const API_BASE_URL = 'http://localhost:5087';
const TENANT_ID = 'd95cc89b-e287-47d0-996a-508df06d520f';
const tiny = new TinyHindClient(API_BASE_URL, TENANT_ID);
// Now, just use the methods!
async function main() {
// Create a new record. TypeScript knows the shape of 'Users'!
const newUser: Partial<DbSchema['Users']> = {
name: 'John Wick',
email: '[email protected]',
age: 45
};
const result = await tiny.insertRecord('Users', newUser);
console.log(`New user created with ID: ${result.id}`);
// Query for records with full type-safety
const users = await tiny.queryRecords({
from: 'Users', // Autocomplete for table names!
select: ['name', 'email'], // Autocomplete for column names!
where: {
name: { like: '%Wick%' } // Type-checked conditions!
}
});
console.log('Found users:', users);
}
main();
TinyHind is an opinionated stack. It believes that you can have a modern, type-safe developer experience without the heavy tooling and dependency trees common in web development today. It's for building small, fast, and persistent things with tools that get out of your way.