gatsby-source-sanity VS Directus

Compare gatsby-source-sanity vs Directus and see what are their differences.

gatsby-source-sanity

Gatsby source plugin for building websites using Sanity.io as a backend. (by sanity-io)

Directus

The Modern Data Stack 🐰 β€” Directus is an instant REST+GraphQL API and intuitive no-code data collaboration app for any SQL database. (by directus)
Our great sponsors
  • SurveyJS - Open-Source JSON Form Builder to Create Dynamic Forms Right in Your App
  • WorkOS - The modern identity platform for B2B SaaS
  • InfluxDB - Power Real-Time Data Analytics at Scale
gatsby-source-sanity Directus
15 206
196 25,113
0.5% 2.3%
6.8 9.9
10 days ago 4 days ago
TypeScript TypeScript
MIT License GNU General Public License v3.0 or later
The number of mentions indicates the total number of mentions that we've tracked plus the number of user suggested alternatives.
Stars - the number of stars that a project has on GitHub. Growth - month over month growth in stars.
Activity is a relative number indicating how actively a project is being developed. Recent commits have higher weight than older ones.
For example, an activity of 9.0 indicates that a project is amongst the top 10% of the most actively developed projects that we are tracking.

gatsby-source-sanity

Posts with mentions or reviews of gatsby-source-sanity. We have used some of these posts to build our list of alternatives and similar projects. The last one was on 2022-09-06.
  • Prismic CMS Limitations/Bugs?
    3 projects | /r/gatsbyjs | 6 Sep 2022
    I linked to the image issue in my post: https://github.com/sanity-io/gatsby-source-sanity/issues/174
    3 projects | /r/gatsbyjs | 6 Sep 2022
    I mentioned in another reply that the issue with images was within rich text, using the Portal text package. As I out described in my issue, it's not an issue of docs. GatsbyImageData is not output in the graphql, just a _ref which appears to be the filename without any path or domain. GatsbyImageData is used to process the image so if a content editor throws in a 2000px wide image, I can use that output to make a smaller image.
    3 projects | /r/gatsbyjs | 6 Sep 2022
    There's a weird edge case where gatsbyImageData doesn't come through the rich text content type and setup was a huge pain in the ass.
  • What CMS system do you use for E-com sites or blogs.
    2 projects | /r/reactjs | 1 Jun 2021
    I'm currently building a site with React and Next.js, and I'm having a good experience with Sanity so far.
  • Form validation with Yup
    3 projects | dev.to | 21 Apr 2021
    In this article, we will build a small application that allows customers to leave product reviews for an e-commerce website. We will build the web application with React while the content (and back end) will be hosted on Sanity. Communication between the web application and back end will be via Graph-Relational Object Queries (GROQ).
  • Can anybody recommend a headless CMS for a full stack vue/node project?
    3 projects | /r/vuejs | 10 Apr 2021
  • Why Typescript and Svelte are a match made in heaven
    7 projects | dev.to | 2 Apr 2021
    Note: If you want to follow along with styling, you can replace public/globals.css with the full example code, and also pull contents from individual component, like this one.

    Render (Static) Inaction Cards

    To bring it to life on the home page, adjust the default intro copy and render a few inactions from the main src/App.svelte component.

    
    </span>
      <span class="k">import</span> <span class="nx">InactionCard</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">./components/InactionCard.svelte</span><span class="dl">"</span><span class="p">;</span>
    <span class="nt">
    
    
      

    To Don't List

    class="intro">Here is a list of things I'm not going to do:

    title="Return VHS to Blockbuster" notes="You've had it since 1998. What's the rush?" /> title="Fix the hole in the wall" notes="Keeping it where it is adds character and nostalgia." /> title="Do the dishes" notes="Someone else will probably get to them. Just leave them in the sink." />
    Enter fullscreen mode Exit fullscreen mode

    Take a look back at your browser and you should see the list! (Refresh if you don't.)

    Static To Don't List Svelte app

    There we go! We have a (very simple) Svelte app with just HTML, CSS, and JavaScript.

    Adding TypeScript to a Svelte project

    Now, suppose we wanted to add a due date. It's not too difficult in this example, right? Let's do it!

    We add a new property to the Inaction Card component:

    
    </span>
      <span class="k">export</span> <span class="kd">let</span> <span class="nx">title</span><span class="p">,</span> <span class="nx">notes</span><span class="p">,</span> <span class="nx">dueDate</span><span class="p">;</span>
    <span class="nt">
    
     class="inaction">
       class="title">{title}
       class="due-date">{dueDate}
       class="notes">{notes}
    Enter fullscreen mode Exit fullscreen mode

    And to the inactions we render, we can add the new prop:

    
    
    
    
        title="Return VHS to Blockbuster"
        dueDate={new Date("1992-02-29")}
        notes="You've had it since 1998. What's the rush?"
    />
    
        title="Fix the hole in the wall"
        dueDate={Date.now()}
        notes="Keeping it where it is adds character and nostalgia."
    />
    
        title="Do the dishes"
        dueDate={new Date("2024-02-29")}
        notes="Someone else will probably get to them. Just leave them in the sink."
    />
    
    
    Enter fullscreen mode Exit fullscreen mode

    Then jump back over to your browser:

    To Don't List with due date attribute

    Notice anything weird? I do. Two things, actually:

    1. The first and the third inactions display an unnecessarily-long date. That could have been easily formatted, but we're not going to worry about that here.
    2. The second date is a number. That's a bigger issue, and I'll explain why.

    What if, we rendered the type of dueDate instead? (i.e. typeof dueDate)

    To Don't List with typeof dueDate field

    We get number for the second one! Even with this small of an application that could absolutely be an issue. Suppose you wanted to better control the formatting of the date. You'd have to first introspect the type of date and then format appropriately. It'd be much easier if we know (with confidence) what type to expect.

    TypeScript Saves the Day!

    We can use TypeScript to tell our application exactly what we expect in dueDate.

    Since our Svelte app is still largely untouched, we can use the built-in utility to convert it to TypeScript. Shut down your development server (ctrl+c), and then run the following commands:

    $ node scripts/setupTypeScript.js
    $ npm install
    
    Enter fullscreen mode Exit fullscreen mode

    This made several changes, but the most important one is that you now need to specify the language in your </code> tags as <code>ts</code>. Take a look at the change in <code>src/App.svelte</code>:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight html"><code><span class="c"><!-- src/App.svelte --></span> <span class="nt"><script </span><span class="na">lang=</span><span class="s">"ts"</span><span class="nt">></span> </code></pre> <div class="highlight__panel js-actions-panel"> <div class="highlight__panel-action js-fullscreen-code-action"> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-on"><title>Enter fullscreen mode</title> <path d="M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewbox="0 0 24 24" class="highlight-action crayons-icon highlight-action--fullscreen-off"><title>Exit fullscreen mode</title> <path d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"></path> </svg> </div> </div> </div> <p>Make this change to your Inaction Card component.</p> <h3> <a name="dry-up-inactions" href="#dry-up-inactions" class="anchor"> </a> DRY Up Inactions </h3> <p>To make this adjustment process smoother, let's <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY up</a> our code. Adjust your <code>App.svelte</code> to loop through an array of inactions that we create in the <code><script></code> section.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight html"><code><span class="c"><!-- src/App.svelte --></span> <span class="nt"><script </span><span class="na">lang=</span><span class="s">"ts"</span><span class="nt">></span> <span class="k">import</span> <span class="nx">InactionCard</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">./components/InactionCard.svelte</span><span class="dl">"</span><span class="p">;</span> <span class="kd">let</span> <span class="nx">inactions</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="na">title</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Return VHS to Blockbuster</span><span class="dl">"</span><span class="p">,</span> <span class="na">dueDate</span><span class="p">:</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="dl">"</span><span class="s2">1992-02-29</span><span class="dl">"</span><span class="p">),</span> <span class="na">notes</span><span class="p">:</span> <span class="dl">"</span><span class="s2">You've had it since 1998. What's the rush?</span><span class="dl">"</span><span class="p">,</span> <span class="p">},</span> <span class="p">{</span> <span class="na">title</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Fix the hole in the wall</span><span class="dl">"</span><span class="p">,</span> <span class="na">dueDate</span><span class="p">:</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">(),</span> <span class="na">notes</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Keeping it where it is adds character and nostalgia.</span><span class="dl">"</span><span class="p">,</span> <span class="p">},</span> <span class="p">{</span> <span class="na">title</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Do the dishes</span><span class="dl">"</span><span class="p">,</span> <span class="na">dueDate</span><span class="p">:</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="dl">"</span><span class="s2">2024-02-29</span><span class="dl">"</span><span class="p">),</span> <span class="na">notes</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Someone else will probably get to them. Just leave them in the sink.</span><span class="dl">"</span><span class="p">,</span> <span class="p">},</span> <span class="p">];</span> <span class="nt">

    To Don't List

    class="intro">Here is a list of things I'm not going to do:

    {#each inactions as inaction} title={inaction.title} dueDate={inaction.dueDate} notes={inaction.notes} /> {/each}
    Enter fullscreen mode Exit fullscreen mode

    Define Inaction Type

    TypeScript is really all about types. (It's in the name, after all!) To add types in a Svelte project, we'll want a separate .ts file. Let's put our types in a types directory, just to stay organized.

    // src/types/Inaction.ts
    export interface Inaction {
      title: string;
      dueDate: Date;
      notes: string;
    }
    
    Enter fullscreen mode Exit fullscreen mode

    This tells us that when we set an object as an Inaction, we expect it to have title and notes as a string, and dueDate as a Date.

    To use it, import the type and then note it. The syntax is a little goofy at first, but you'll get the hang of it.

    
    <span class="na">lang=</span><span class="s">"ts"</span><span class="nt">></span>
      <span class="k">import</span> <span class="nx">type</span> <span class="p">{</span> <span class="nx">Inaction</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">./types/Inaction</span><span class="dl">"</span><span class="p">;</span>
      <span class="k">import</span> <span class="nx">InactionCard</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">./components/InactionCard.svelte</span><span class="dl">"</span><span class="p">;</span>
    
      <span class="c1">// inactions should be an array of items with the Inaction type.</span>
      <span class="kd">let</span> <span class="nx">inactions</span><span class="p">:</span> <span class="nx">Inaction</span><span class="p">[]</span> <span class="o">=</span> <span class="p">[</span>
        <span class="p">{</span>
          <span class="na">title</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Return VHS to Blockbuster</span><span class="dl">"</span><span class="p">,</span>
          <span class="na">dueDate</span><span class="p">:</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="dl">"</span><span class="s2">1992-02-29</span><span class="dl">"</span><span class="p">),</span>
          <span class="na">notes</span><span class="p">:</span> <span class="dl">"</span><span class="s2">You've had it since 1998. What's the rush?</span><span class="dl">"</span><span class="p">,</span>
        <span class="p">},</span>
        <span class="p">{</span>
          <span class="na">title</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Fix the hole in the wall</span><span class="dl">"</span><span class="p">,</span>
          <span class="na">dueDate</span><span class="p">:</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">(),</span>
          <span class="na">notes</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Keeping it where it is adds character and nostalgia.</span><span class="dl">"</span><span class="p">,</span>
        <span class="p">},</span>
        <span class="p">{</span>
          <span class="na">title</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Do the dishes</span><span class="dl">"</span><span class="p">,</span>
          <span class="na">dueDate</span><span class="p">:</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="dl">"</span><span class="s2">2024-02-29</span><span class="dl">"</span><span class="p">),</span>
          <span class="na">notes</span><span class="p">:</span>
            <span class="dl">"</span><span class="s2">Someone else will probably get to them. Just leave them in the sink.</span><span class="dl">"</span><span class="p">,</span>
        <span class="p">},</span>
      <span class="p">];</span>
    <span class="nt">
    
    
    Enter fullscreen mode Exit fullscreen mode

    After I restarted my code editor (VS Code), it told me something was wrong!

    VS Code showing TypeScript error

    This says dueDate on the second inaction is the wrong type!

    The power in this is great! VS Code told me there's an issue with the code without having to open up the browser!

    If that's useful even on this small scale, imagine how helpful it would be in a large application where Inaction may be used dozens or hundreds of times!

    Validating Types

    Aside from the code editor adding little squiggles, nothing would actually appear wrong during the Svelte build. Fortunately, Svelte gives us a tool to make sure everything is okay, svelte-check.

    Try running the following command:

    $ npx svelte-check
    
    Enter fullscreen mode Exit fullscreen mode

    I see an error and three warnings:

    Loading svelte-check in workspace: .../to-dont-list
    Getting Svelte diagnostics...
    ====================================
    
    .../to-dont-list/src/App.svelte:13:7
    Error: Type 'number' is not assignable to type 'Date'. (ts)
          title: "Fix the hole in the wall",
          dueDate: Date.now(),
          notes: "Keeping it where it is adds character and nostalgia.",
    
    .../to-dont-list/src/components/InactionCard.svelte:2:14
    Hint: Variable 'title' implicitly has an 'any' type, but a better type may be inferred from usage. (ts)
    
      export let title, notes, dueDate;
    
    
    .../to-dont-list/src/components/InactionCard.svelte:2:21
    Hint: Variable 'notes' implicitly has an 'any' type, but a better type may be inferred from usage. (ts)
    
      export let title, notes, dueDate;
    
    
    .../to-dont-list/src/components/InactionCard.svelte:2:28
    Hint: Variable 'dueDate' implicitly has an 'any' type, but a better type may be inferred from usage. (ts)
    
      export let title, notes, dueDate;
    
    
    Enter fullscreen mode Exit fullscreen mode

    You can wire up this command to your build process so you don't send invalid typed code to production. Amazing!

    I hope this validates (πŸ˜‰) the use of TypeScript and Svelte enough to entice you to try it out for yourself! But before we go, let's take a look at wiring this up to Sanity so that we can pull in data dynamically from an external source.

    Wiring up Sanity to a Svelte project

    To get Sanity up and running, begin by installing the CLI and bootstrapping a new project.

    $ npm install -g @sanity/cli
    $ sanity init
    
    Enter fullscreen mode Exit fullscreen mode

    After authenticating, choose the appropriate items to get your project started. These were my choices:

    • Select project to use: Create a new project
    • Your project name: To Not Do
    • Use the default dataset configuration? Yes
    • Project output path: (Use recommendation)
    • Select project template: Clean project with no predefined schemas

    That will install dependencies and prepare a Studio project. You should now be able to change into the new directory Sanity created for you and start the Studio.

    $ cd path/to/new/directory
    $ npm start
    
    Enter fullscreen mode Exit fullscreen mode

    By default, the Studio will be available in your browser at http://localhost:3333/. You'll have to sign in again. And when you do, you should see that you have an empty schema.

    Sanity Studio with empty schema

    Add Data Model

    Let's create our data model, which Sanity calls a document type. If you're not familiar with Sanity, here's a nice overview of content modeling.

    To add our model, we're going to edit the (nearly) blank schema file Sanity gave us. This file lives in schemas/schema.js. It should look something like this:

    // First, we must import the schema creator
    import createSchema from "part:@sanity/base/schema-creator";
    
    // Then import schema types from any plugins that might expose them
    import schemaTypes from "all:part:@sanity/base/schema-type";
    
    // Then we give our schema to the builder and provide the result to Sanity
    export default createSchema({
      // We name our schema
      name: "default",
      // Then proceed to concatenate our document type
      // to the ones provided by any plugins that are installed
      types: schemaTypes.concat([
        /* Your types here! */
      ]),
    });
    
    Enter fullscreen mode Exit fullscreen mode

    We're going to put our type in the types object. Let's create an inaction model with the proper fields:

    import createSchema from "part:@sanity/base/schema-creator";
    import schemaTypes from "all:part:@sanity/base/schema-type";
    
    export default createSchema({
      name: "default",
      types: schemaTypes.concat([
        {
          title: "Inaction",
          name: "inaction",
          type: "document",
          fields: [
            { title: "Title", name: "title", type: "string" },
            { title: "Notes", name: "notes", type: "text" },
            { title: "Due Date", name: "dueDate", type: "date" },
          ],
        },
      ]),
    });
    
    Enter fullscreen mode Exit fullscreen mode

    Notice that if you go back to your browser, Studio already picked up your changes! (Science! Or something?)

    Use your new model to recreate the static content from src/App.svelte.

    Create Inaction objects with Sanity Studio

    Pull in Data Dynamically

    Once that content is in place, we can pull it into project. First, install Sanity's JavaScript client.

    $ npm install @sanity/client
    
    Enter fullscreen mode Exit fullscreen mode

    Then we can make some changes to the </code> in our <code>App.svelte</code> component to fetch our inactions from the Sanity API.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight html"><code><span class="c"><!-- src/App.svelte --></span> <span class="nt"><script </span><span class="na">lang=</span><span class="s">"ts"</span><span class="nt">></span> <span class="k">import</span> <span class="p">{</span> <span class="nx">onMount</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">svelte</span><span class="dl">"</span><span class="p">;</span> <span class="k">import</span> <span class="nx">sanityClient</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">@sanity/client</span><span class="dl">"</span><span class="p">;</span> <span class="k">import</span> <span class="nx">type</span> <span class="p">{</span> <span class="nx">Inaction</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">./types/Inaction</span><span class="dl">"</span><span class="p">;</span> <span class="k">import</span> <span class="nx">InactionCard</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">./components/InactionCard.svelte</span><span class="dl">"</span><span class="p">;</span> <span class="c1">// Create a client to connect to the Sanity datastore.</span> <span class="kd">const</span> <span class="nx">sanity</span> <span class="o">=</span> <span class="nx">sanityClient</span><span class="p">({</span> <span class="na">apiVersion</span><span class="p">:</span> <span class="dl">'</span><span class="s1">v2021-03-25</span><span class="dl">'</span><span class="p">,</span> <span class="na">projectId</span><span class="p">:</span> <span class="dl">"</span><span class="s2">...</span><span class="dl">"</span><span class="p">,</span> <span class="na">dataset</span><span class="p">:</span> <span class="dl">"</span><span class="s2">production</span><span class="dl">"</span><span class="p">,</span> <span class="na">useCdn</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span> <span class="p">});</span> <span class="c1">// Initialize our inactions as an empty array.</span> <span class="kd">let</span> <span class="nx">inactions</span><span class="p">:</span> <span class="nx">Inaction</span><span class="p">[]</span> <span class="o">=</span> <span class="p">[];</span> <span class="c1">// Fetch the inactions from Sanity, and replace the array.</span> <span class="k">async</span> <span class="kd">function</span> <span class="nx">fetchInactions</span><span class="p">()</span> <span class="p">{</span> <span class="kd">const</span> <span class="nx">query</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">*[_type == "inaction"]{ _id, title, notes, dueDate }</span><span class="dl">'</span><span class="p">;</span> <span class="nx">inactions</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">sanity</span><span class="p">.</span><span class="nx">fetch</span><span class="p">(</span><span class="nx">query</span><span class="p">);</span> <span class="p">}</span> <span class="c1">// Run the fetch function when the component is ready (mounted).</span> <span class="nx">onMount</span><span class="p">(</span><span class="nx">fetchInactions</span><span class="p">);</span> <span class="nt">

    Enter fullscreen mode Exit fullscreen mode

    And now you are reading dynamic data for the list of things you're never going to have to do!

    Next Steps

    I hope you are intrigued enough by this to to tinker with these super cool tools! And if you want to keep going with this example, here are some ideas on where to go next:

    • Add a form to submit new Inaction objects to Sanity. (The demo and its code have a working example.) Note: If you go this route, you'll want to start thinking about authenticating your API requests.
    • Deploy the project to a build and hosting service, like Vercel.
    • Deploy Sanity Studio so you can make edits in Sanity, without having to run the Studio locally.

    I'd love to learn where you choose to take your project. The things we can build with Svelte, TypeScript, and Sanity are endless! Let's chat!

    Last, here are a few other resources for further reading on Svelte + TypeScript:

  • Sanity Backup Function with GitHub Actions and Artifacts
    4 projects | dev.to | 2 Apr 2021
    Sanity.io is a platform to build websites and applications. It comes with great APIs that let you treat content like data. Give your team exactly what they need to edit and publish their content with the customizable Sanity Studio. Get real-time collaboration out of the box. Sanity.io comes with a hosted datastore for JSON documents, query languages like GROQ and GraphQL, CDNs, on-demand asset transformations, presentation agnostic rich text, plugins, and much more.
  • On the limits of MDX
    9 projects | dev.to | 1 Apr 2021
    I get it. I get the tangibility of flat files. I get that it feels good to take your coding skills into your prose. But it's not the best way to work with content. Text editors with familiar affordances that produce typed rich text that can be queried and serialized into whatever you need are better. Where developers can define the data structures they need, and editors get easy-to-use tools to get their work done. Like what we're building at Sanity with Portable Text.
  • GraphQL vs REST: which API is better for your web app?
    2 projects | dev.to | 30 Mar 2021
    Sanity.io offers an open-source query language called GROQ (Graph-Relational Object Queries). It allows us to describe what information we want in our application, join data from different documents, and generate a response with only the information that is needed.

Directus

Posts with mentions or reviews of Directus. We have used some of these posts to build our list of alternatives and similar projects. The last one was on 2024-02-22.
  • Form to DB
    6 projects | news.ycombinator.com | 22 Feb 2024
    I don't know, it's something I've wanted many times.

    Recently I discovered https://directus.io/ which comes pretty close and it's open source.

  • Open-Source Headless CMS in 2024
    9 projects | dev.to | 30 Jan 2024
    Directus: The Shape-Shifting Maverick
  • A Year of Self-Hosting: 6 Open-Source Projects That Surprised Me in 2023
    2 projects | dev.to | 19 Dec 2023
    The Backend to Build Anything or Everything | Directus
  • Prismic.io is increasing our price by *1900%* over Christmas
    4 projects | /r/webdev | 8 Dec 2023
    Along those lines, I’ve been happy with Directus as a backend for my little blog.
    4 projects | /r/webdev | 8 Dec 2023
    I using Directus CMS on several projects with pretty complicated flows, api extensions etc. probably there will be some work if you move. I liked Directus is because it's standard SQL I can always move my DB and documents to another solution. I don't use their hosted solution but they have an unlimited offering for $100 / month.
  • Why Is the Django Admin "Ugly"?
    3 projects | news.ycombinator.com | 27 Oct 2023
    It depends on your skillsets, but I'd highly recommend https://directus.io/ especially if you need "slickness" to raise money otherwise try a pyhat stack if you hate javascript.
  • Building a Blog in Django
    12 projects | news.ycombinator.com | 12 Sep 2023
    The admin is extremely unacceptable for anything beyond trivial borderline trivial use cases, and the modifications you'd have to make are just awful especially the more interactive something needs to be. The extremely tight integration between models and the modeladmin is a blessing and curse.

    The people who like Django,also tend to overload it to do everything. This makes sense at small companies. The only place I really see Django at large companies is as an api using DRF or something.

    For internal admins, I've been lobbying to use https://directus.io/ at my company.

  • Show HN: I built a Python web framework from scratch
    4 projects | news.ycombinator.com | 9 Sep 2023
  • I need recommendations for creating an API. Start from scratch, or are there projects I can build from?
    2 projects | /r/webdev | 20 Aug 2023
    I initially looked into CMS's like Strapi and Directus to possibly handle my admin UI + API all at once. I haven't found anything that looks like it can do this yet, but I'd be very happy to be proven wrong. I would prefer it to be based in .NET or Node.js since I am more familiar with those, but there's no reason I couldn't do PHP either.
  • Pros and cons of off-the-shelf solutions for creating a control panel
    6 projects | /r/reactjs | 13 Jul 2023
    - We want a solution that creates CRUD (create, read, update, delete) quickly and requires minimal effort. - We want to be able to create some sort of complex interface if the task requires it. - We make cool, beautiful projects, so we want a visually pleasing solution. - We want the solution to be independent of the language on the back-end, because, for example, we started with PHP, Laravel, but over time node.js, Go appeared in the stack. In short, we want fast, beautiful and custom. We've had time to poke at various off-the-shelf solutions that we've been advised. They're good, but: - they are created specifically for some frameworks / languages like laravel, node.js - they can only generate CRUDs with a rigidly defined structure, where you can't implement or customize anything of your own. - they can't be styled Here's what we've been looking at Control Panels for Laravel: https://demo.backpackforlaravel.com/admin/dashboard Not a very pretty solution in our opinion. And the promo page has nice screenshots, not the demo "well such". https://orchid.software/en/ Not particularly functional, but neatly done https://nova.laravel.com They have a beautiful, but rigidly set strutkrua, you can not create castmon interfaces, stylize them. Just do CRUD and that's it. And it's paid https://filamentphp.com/ Analog to Nova, with essentially the same problems. For node.js: https://adminjs.co Nice promo, and the demo is way behind As standalone dashboards: https://strapi.io/ Very cool, but for other purposes. It's more of an entity builder with an interface and API https://pocketbase.io/ Similarly, it's an entity builder with an interface and API https://directus.io/ This is a backend builder. https://filamentphp.com/It is purely for php, you can't customize styles, you can't create your own interfaces. It is possible to create only tables and forms by template, and we remember that we want flexibility, independence from the language and the ability to create their own interfaces and customize them https://flatlogic.com This is also more of a backend builder. Direct competitors: https://github.com/refinedev/refine https://marmelab.com/react-admin/is probably the best solution that is currently on the market, they have been developing for a long time, they are our favorite. To the disadvantages we considered the following points: quite an old project, and somewhere the technology is already outdated, unsympathetic interface, old UI libraries. Huge documentation, it’s simply to create CRUD but hard to work without immersion. After all this there is only one conclusion: you need to do it yourself....

What are some alternatives?

When comparing gatsby-source-sanity and Directus you can also consider the following projects:

supabase - The open source Firebase alternative.

Strapi - πŸš€ Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable and developer-first.

Appwrite - Build like a team of hundreds_

budibase - Budibase is an open-source low code platform that helps you build internal tools in minutes πŸš€

KeystoneJS - The most powerful headless CMS for Node.js β€” built with GraphQL and React

appsmith - Platform to build admin panels, internal tools, and dashboards. Integrates with 25+ databases and any API.

nocodb - πŸ”₯ πŸ”₯ πŸ”₯ Open Source Airtable Alternative

Baserow - Open source no-code database and Airtable alternative. Create your own online database without technical experience. Performant with high volumes of data, can be self hosted and supports plugins

go-admin - A golang framework helps gopher to build a data visualization and admin panel in ten minutes

nextjs-custom-server - A TypeScript boilerplate for combining Payload and Next.js into a single Express server

react-admin - A frontend Framework for building data-driven applications running on top of REST/GraphQL APIs, using TypeScript, React and Material Design

ERPNext - Free and Open Source Enterprise Resource Planning (ERP)