Thin Backend is a Blazing Fast, Universal Web App Backend for Making Realtime Single Page Apps

Overview

MIT License

Website | Documentation

About Thin

Thin Backend is a blazing fast, universal web app backend for making realtime single page apps.

Instead of manually writing REST API endpoints or GraphQL resolvers you can use a Thin Backend server to automatically get a fully feature web application backend. Thin exposes high level functions to create, read, update and delete delete database record.

Code Examples

This example shows a simple CRUD example for building a Todo app with Thin:

import { useQuery, query, createRecord, updateRecord, deleteRecord, Task } from 'ihp-backend';

function Tasks() {
    // `useQuery` automatically triggers a re-render on new data
    const tasks = useQuery(query('tasks').orderBy('createdAt'));

    return <div>
        <h1>Tasks</h1>
        {tasks.map(task => <Task task={task} key={task.id} />)}
    </div>
}

interface TaskProps {
    task: Task; // <- The `Task` type is provided by Thin, auto-generated from the database schema
}
function Task({ task }: TaskProps) {
    const handleEdit = () => {
        const patch = {
            title: window.prompt('New Title:') || task.title
        };

        // `updateRecord` already updates the UI state (e.g. the <Tasks /> component above)
        // even before the server completed the operation.
        updateRecord('tasks', task.id, patch);
    }

    const handleDelete = () => {
        // `deleteRecord` already hides the record from the UI state
        // even before the server completed the operation.
        deleteRecord('tasks', task.id);
    }

    return <div onDoubleClick={handleEdit}>
        {task.title}

        <button onClick={handleDelete}>delete</button>
    </div>
}

function AddTaskButton() {
    const handleClick = () => {
        const task = {
            title: window.prompt('Title:')
        };

        // `createRecord` already shows the new task in the UI
        // even before the server completed the operation.
        createRecord('tasks', task);
    }

    return <button onClick={handleClick}>Add Task</button>
}

function App() {
    // No need for redux or other state management libs
    // `useQuery` automatically triggers a re-render on new data
    return <div>
        <Tasks />
        <AddTaskButton />
    </div>
}

Design Ideas

We believe that web application development can be fundamentally simplified by working with two principles:

  1. All data is realtime and reflects the latest database state: Local state management is fundamentally hard as it's dealing with distributed system problems. Best to avoid it alltogether.
  2. All database operations go through a unified standard interface, IHP DataSync in our case.

Thin Backend comes with everything needed to build blazing fast, realtime single page apps.

Feature Overview

  • Blazing Fast, Low Latency: Delight your end-users with superior speed and lowest latency. With built-in Optimistic Updates your app doesn't need to wait for the server to respond back until the changes are visible on the screen.

  • Realtime: Provide a delightful experience to your end users: With Thin Backend Live Queries your app state is synchronized in real-time across all users.

    function Tasks() {
        // `useQuery` always returns the latest database state
        // The component automatically re-renders when a record is inserted,
        // updated, or deleted in the `tasks` table
        const tasks = useQuery(query('tasks').orderBy('createdAt'));
    
        return <div>...</div>
    }
  • Zero-setup Login: To get your started quickly every Thin Backend project comes with zero-setup login, user management and permissions system included.

    Already have an existing login system? No problem, you can disable the built-in login and provide Thin Backend with a JWT.

  • Secure Authorization: Thin Backend uses Postgres Policies to make sure that users can only see what they're allowed to see.

    Based on naming conventions Thin Backend will automatically generate the initial policies for you. You then only need to adjust the default policies based on your needs.

  • Powerful Schema Designer: Thin Backend has a built-in GUI-based schema designer. The schema designer helps to quickly build the DDL statements for your database schema without remembering all the PostgreSQL syntax and data types.

    But keep in mind: The schema designer is just a GUI tool to edit the underlying SQL statements. The schema designer parses the SQL statements, applies changes to the syntax tree, and then writes it back.

    Rather work with your keyboard? You can always skip the GUI and go straight to the code editor. If you need to do something advanced which is not supported by the GUI, just manually do it with your code editor of choice.

  • Git-like Migrations: Whenever you add or change a table in the Schema Designer, the changes will only be applied to the in-memory schema. The actual postgres database will only be touched when you run migrations.

    You can think of this like in a git workflow: In git changes are only applied to the repository history when you do a git commit. In Thin Backend this git commit is running a database migration.

  • Prooven Architecture:

    Thin Backend is designed by the company that makes IHP, Haskell's most successful web framework. Thin Backend is built on top of the production-prooven IHP architecture & libraries.

    IHP was recognized as a High Performer in G2's Winter 2022 Web Framework Report:

    G2 Badge
  • Transactions:

    You can use withTransaction to run a set of operations within a database transaction. If an exception is thrown within the transaction callback, the transaction will automatically be rolled back and the exception is re-thrown. If the callback executes successfully, the transaction will automatically be committed:

    import { withTransaction } from 'ihp-datasync';
    
    await withTransaction(async transaction => {
        const team = await transaction.createRecord('teams', { title: 'New Team' });
        
        const project = await transaction.createRecord('projects', {
            title: 'Project 1',
            teamId: team.id
        });
    
        return [ team, project ];
    })

    Learn more in the Docs

  • Batch Operations:

    You can use createRecords, updateRecords and deleteRecords to effiently run operations on a large set of database records:

    // Example:
    const todoA = { title: 'Finish Guide', userId: '49946f4d-8a2e-4f18-a399-58e3296ecff5' };
    const todoB = { title: 'Learn Haskell', userId: '49946f4d-8a2e-4f18-a399-58e3296ecff5' };
    
    const todos = await createRecord('todos', [ todoA, todoB ]);

    Learn more about Batch Operations in the Docs

Documentation

You can find extensive documentation on the Thin Backend website.

Getting Started

Learn how to get started in the Getting Started Guide

Commercial Support

Thin Backend is built on the IHP platform, Haskell's leading web framework. IHP is used in production by digitally induced since 2017. You can expect continuous support and development in the future.

Additionally we're happy to provide commercial support for your Thin Backend project, either directly by digitally induced or through the di Partners network

digitally induced Partners

The digitally induced Partners offer you professional IHP development, consulting and support. All partners have experience in working with IHP projects in production can help you build fast and well-architected projects.

You can find details on the Partners page.

Example Apps

You can find some example apps inside the Examples directory of this repository:

Community

Questions, or need help? Join our Slack Community

Also check out the Forum!

Contributing

We are happy to merge your pull requests! 😄

See CONTRIBUTING.md for more info.

Comments
  • Switching to Schema deletes WIP query

    Switching to Schema deletes WIP query

    I was working on a little test query and wanted to check something in the Schema. Switching between the tabs deletes the in-progress query, meaning I have to start over.

    Could be considered obsolete once introspection is supported, which would allow usage of the Docs panel.

    opened by jeyj0 6
  • Infinite redirect loop after login with `<ThinBackend requireLogin>`

    Infinite redirect loop after login with ``

    I am testing a completely vanilla Vercel template repo here

    I get presented with a login screen. After a successful signup and login I get redirected back but in a loop bringing it back to login, the redirecting etc.

    opened by jokull 5
  • react type definitions installed from schema type definitions not working

    react type definitions installed from schema type definitions not working

    After making a schema change, I installed new type definitions using the npm install script on the schema type definitions page. After installing this new version of the type definitions, I am getting TS errors in vscode saying that there are no type definitions for thin-backend/react.

    the npm install command I used (redacted):

    npm install --save-dev "https://thin.dev/ShowTypescriptDeclarationFile?typescriptDeclarationFileId=[redacted]&accessToken=[redacted]"
    

    The error (pathname edited to relative to project root):

    Could not find a declaration file for module 'thin-backend/react'. './node_modules/thin-backend/react.js' implicitly has an 'any' type.
      If the 'thin-backend' package actually exposes this module, consider sending a pull request to amend 'https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/thin-backend'ts(7016)
    

    Before installing the type definitions from my latest schema change, everything was working fine. I had previously installed new updates to my type definitions several times for this project, and there were no issues with those versions.

    opened by chadlavi 3
  • thin-backend-vue package has no code

    thin-backend-vue package has no code

    I recently install v0.10.0 of thin-backend-vue via npm and it only has the package.json and the README. Screen Shot 2022-07-29 at 11 46 05

    I am able to downgrade to get things working again.

    opened by JamesTeague 2
  • Todo App Link `404` in README.md Example Apps Section

    Todo App Link `404` in README.md Example Apps Section

    Hey! 👋 Was just reading through your docs [looking good!] but noted that: https://github.com/digitallyinduced/thin-backend/blame/6e376d3861370e58aea83dfe5eabf8f0a2924ed0/README.md#L221 links to: https://github.com/digitallyinduced/ihp-backend-todo-app which is 404 image

    Should be: https://github.com/digitallyinduced/thin-backend-todo-app image

    opened by nelsonic 2
  • Confusing message on startup

    Confusing message on startup

    When starting the container, the IHP message:

    Success. You can now start the database server using:
    
        /nix/store/30ipyij1cdm1fkz0c0bkmdpx43521mv0-postgresql-14.1/bin/pg_ctl -D build/db/state -l logfile start
    

    is shown, which could be confusing because there's no need to start the database manually.

    opened by jeyj0 2
  • Overly complex error for

    Overly complex error for "Address already in use"

    This is the error that is thrown if 8000/8001 are already in use, which seems overly long and complex for a probably relatively common error:

    docker: Error response from daemon: driver failed programming external connectivity on endpoint vibrant_banach (b72db00e7396d0f1bc7602e1c468a5de6ef48482d54542e38acd6e73d558b826): Error starting userland proxy: listen tcp4 0.0.0.0:8001: bind: address already in use.
    
    opened by jeyj0 2
  • Explorer: `id` checkbox is always selected

    Explorer: `id` checkbox is always selected

    When toggling the task id on a new project with the field tool on the left, the checkbox never becomes unchecked, though the code is updated. Other fields work fine.

    bug 
    opened by jeyj0 2
  • Deleting a table tries to drop table before its policy

    Deleting a table tries to drop table before its policy

    Steps to reproduce:

    1. Create a new table, and apply the change to the database by performing the generated migration.
    2. In the Schema tab, right click on the table name and click Delete Table. Accept the warning.
    3. Click "Run Migrations" and attempt to run the migration.

    Expected result: The migration runs successfully and drops the table. Actual result: An error is displayed- relation "test" does not exist

    It's producing this SQL:

    DROP TABLE test;
    DROP POLICY "Users can manage their test" ON test;
    

    Presumably dropping the policy needs to be done first, as this SQL seems to work:

    DROP POLICY "Users can manage their test" ON test;
    DROP TABLE test;
    
    bug 
    opened by pythia-dev 1
  • Renaming table migration fails

    Renaming table migration fails

    When a table is renamed the migration renames the table first, but refers to the original name in subsequent statements, e.g. renaming media to artefacts produces the following migration which won't run:

    ALTER TABLE media RENAME TO artefacts;
    DROP INDEX media_created_at_index;
    DROP INDEX media_user_id_index;
    ALTER TABLE media DROP CONSTRAINT media_ref_user_id;
    DROP POLICY "Users can manage their media" ON media;
    
    bug 
    opened by jolonf 1
  • Peer Dependencies listing React

    Peer Dependencies listing React

    The thin-backend package has a peer dependency on React. In testing, this seems not to be the case. I've been able to use it in a vue project, so far without issue. I noticed that the react.js functionality was moved to a separate published package.

    I'd like, if possible to remove the peer dependency on thin-backend so when installing in my Vue app, I am not getting output from the console about missing dependencies, if possible.

    opened by JamesTeague 1
  • Self-hosted version: pd_dump failed

    Self-hosted version: pd_dump failed

    https://thin.dev/docs/self-hosting

    after docker compose up

    I'm trying to access web page on localhost:8000 and it fails

    An error happened
    An exception was raised while running the action
    

    meanwhile in console:

    thin_1  | pg_dump: error: server version: 15.0; pg_dump version: 14.3 (Debian 14.3-1.pgdg110+1)
    thin_1  | pg_dump: error: aborting because of server version mismatch
    thin_1  | readCreateProcess: pg_dump "-s" "--no-owner" "--no-acl" "postgres://postgres:examplepassword@db/postgres" (exit 1): failed
    
    opened by romanesko 0
  • Duplicate id Primary Key in Migration

    Duplicate id Primary Key in Migration

    I created a new table, and not realising an id column is already created, created a new id column and selected primary key. After realising my error I deleted the id column I just created but in the migration it still had both id columns in the Primary Key:

    CREATE TABLE art (
        id UUID DEFAULT uuid_generate_v4() NOT NULL,
        PRIMARY KEY(id, id)
    );
    
    bug 
    opened by jolonf 0
  • Issue, Self-hosted Thin Backend

    Issue, Self-hosted Thin Backend

    Hi guys, I followed the tutorial on https://thin.dev/docs/self-hosting

    I copied and pasted

    services:
      db:
        image: postgres:alpine3.16
        restart: always
        environment:
          POSTGRES_PASSWORD: examplepassword
        ports:
          - '5432:5432'
      thin:
        image: downloads.digitallyinduced.com/digitallyinduced/thin-backend:latest
        restart: always
        ports:
          - 8000:8000
        depends_on:
          - db
        environment:
          DATABASE_URL: "postgres://postgres:examplepassword@db/postgres"
          TYPE_DEFINITONS_BASE_PATH: "$PWD"
        volumes:
          - ".:/home/app/Application:rw"
    

    and after that I run docker-compose up

    I'm getting this issue

    Screen Shot 2022-10-01 at 16 20 14

    thanks in advance, nice project!

    PD: there is a typo here in the documentation

    Screen Shot 2022-10-01 at 16 21 55
    opened by wzalazar 0
  • Add Twitch Auth

    Add Twitch Auth

    As the marketplace for Twitch grows and solutions like Truffle.dev become realized there is more of a need for authentication with Twitch. There are currently 140 million monthly active Twitch users and many apps catered to the platform require Twitch auth. This would be a great feature to add, and Twitch has good support for auth.

    enhancement 
    opened by B3nten 0
  • Add support for cronjobs

    Add support for cronjobs

    opened by mpscholten 0
  • Comparison with Supabase

    Comparison with Supabase

    Supabase is another bridge between Postgres and the front-end. How does Thin compare with Supabase? This is the main question preventing me from choosing Thin, as Supabase is more mature, popular, and has many features.

    opened by klavinski 7
Owner
digitally induced GmbH
We combine extensive software expertise with startup mindset
digitally induced GmbH
Lovefield is a relational database for web apps. Written in JavaScript, works cross-browser. Provides SQL-like APIs that are fast, safe, and easy to use.

Lovefield Lovefield is a relational database written in pure JavaScript. It provides SQL-like syntax and works cross-browser (currently supporting Chr

Google 6.8k Jan 3, 2023
curl for GraphQL with autocomplete, subscriptions and GraphiQL. Also a dead-simple universal javascript GraphQL client.

graphqurl graphqurl is a curl like CLI for GraphQL. It's features include: CLI for making GraphQL queries. It also provisions queries with autocomplet

Hasura 3.2k Jan 3, 2023
🔄 A realtime Database for JavaScript Applications

RxDB A realtime Database for JavaScript Applications RxDB (short for Reactive Database) is a NoSQL-database for JavaScript Applications like Websites,

Daniel Meyer 18.6k Dec 31, 2022
A Gmail Clone which built with ReactJS and Redux. You can sign in with your Google Account, compose a new e-mail and send realtime emails to the project.

Gmail Clone with ReactJS A Gmail Clone that you can sign in with your Google Account, compose a new e-mail and send realtime emails to the project. Cl

Özge Coşkun Gürsucu 49 Nov 14, 2022
A beautiful error page for PHP apps

DO NOT USE YET, THIS PACKAGE IS IN DEVELOPMENT Ignition: a beautiful error page for PHP apps Ignition is a beautiful and customizable error page for P

Spatie 237 Dec 30, 2022
Jsynchronous.js - Data synchronization for games and real-time web apps.

Jsynchronous.js Synchronize your rapidly changing app state with all connected browsers. Jsynchronous ensures all clients see the same data as what’s

Sirius 111 Dec 16, 2022
Ecommerce-backend-nestjs - Ecommerce app with Nestjs + Prisma ORM + GraphQL + SQLite

ECOMMERCE BACKEND NESTJS APP Nestjs + Prisma ORM + GraphQL + SQLite USER Create Account Login Product Create Product Get Products Get Product Search P

Rui Paulo Calei 5 Apr 6, 2022
A postgraphile plugin that allows you to expose only a single direction of connections exposed by foreign key constraints

A postgraphile plugin that allows you to expose only a single direction of connections exposed by foreign key constraints

Chandler Gonzales 4 Mar 13, 2022
🍉 Reactive & asynchronous database for powerful React and React Native apps ⚡️

A reactive database framework Build powerful React and React Native apps that scale from hundreds to tens of thousands of records and remain fast ⚡️ W

Nozbe 8.8k Jan 5, 2023
🍹 MongoDB ODM for Node.js apps based on Redux

Lightweight and flexible MongoDB ODM for Node.js apps based on Redux. Features Flexible Mongorito is based on Redux, which opens the doors for customi

Vadim Demedes 1.4k Nov 30, 2022
Illustration of issues around use of top-level await in Vite apps

vite-top-level-await-repro Illustration of issues around use of top-level await in Vite apps: https://github.com/vitejs/vite/issues/5013 Top-level awa

Rich Harris 6 Apr 25, 2022
📠 The backend of the Fairfield Programming Association website.

Backend Server Features Duck Generator We didn't want to use people's faces for the profile pictures. This was for three reasons: we didn't want to pa

Fairfield Programming Association 25 Nov 23, 2022
Auth model created by Using nodeJs for backend & reactJs for frontend with the help of TailwindCss in styling

The Universal Auth System Using The MERN Stack Including Mysql --> The project is divded to two separte projects 1- The Client side -> containing the

m.bebars 1 Aug 22, 2022
The Firma Project - Backend

Firma About This is a backend for Firma Project. The Firma project is another corporate piece of software to engage employees to collaborate with othe

Firma 8 Feb 5, 2022
A simple comment system with backend support.

Waline A simple comment system with backend support. 中文 README Documatation English | 简体中文 Feature Fast Really Safe Support full markdown syntax Simpl

Waline 1.2k Jan 9, 2023
Fast and advanced, document based and key-value based NoSQL database that able to work as it is installed.

About Fast and advanced, document based and key-value based NoSQL database that able to work as it is installed. Features NoSQL database Can be run as

null 6 Dec 7, 2022
Database in JSON, fast and optimize

?? Database-Dev ?? DevNetwork#2103 ?? V 1.0.0 ?? Dependence Libs use ?? NodeJs V 16.14.2 (NodeJs) ?? fs (nodeFS) ?? Use libs import the file in your p

DevNetwork™️ 3 Apr 21, 2022
Fast and advanced, document-based and key-value-based NoSQL database.

Contents About Features Installation Links About Fast and advanced, document-based and key-value-based NoSQL database. Features NoSQL database Can be

null 6 Dec 7, 2022
A fast, synchronized and dynamic query builder package.

@ssibrahimbas/query A fast, synchronized and dynamic query builder package. What is? In short, the query builder. You can write complex and parameteri

Sami Salih İbrahimbaş 7 Jun 13, 2022