diff --git a/backend/knexfile.ts b/backend/knexfile.ts
index 03b1e733a..100629cc7 100644
--- a/backend/knexfile.ts
+++ b/backend/knexfile.ts
@@ -5,7 +5,7 @@
  */
 import type { Knex } from 'knex';
 
-/** This is used for the Knex CLI to create migrations during development */
+/** This is used for the Knex CLI to create migrations and a seeded database during development */
 const config: { [key: string]: Knex.Config } = {
   development: {
     client: 'better-sqlite3',
@@ -15,6 +15,9 @@ const config: { [key: string]: Knex.Config } = {
     migrations: {
       directory: './src/database/migrations',
     },
+    seeds: {
+      directory: './src/database/seeds',
+    },
   },
 };
 
diff --git a/backend/src/database/seeds/01_user.ts b/backend/src/database/seeds/01_user.ts
new file mode 100644
index 000000000..80c23e5f2
--- /dev/null
+++ b/backend/src/database/seeds/01_user.ts
@@ -0,0 +1,48 @@
+/*
+ * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+import { Knex } from 'knex';
+
+import { ProviderType } from '../../auth/provider-type.enum';
+import { hashPassword } from '../../utils/password';
+import {
+  FieldNameIdentity,
+  FieldNameUser,
+  TableIdentity,
+  TableUser,
+} from '../types';
+
+export async function seed(knex: Knex): Promise<void> {
+  // Clear tables beforehand
+  await knex(TableUser).del();
+  await knex(TableIdentity).del();
+
+  // Insert user accounts and identities
+  await knex(TableUser).insert([
+    {
+      [FieldNameUser.username]: null,
+      [FieldNameUser.guestUuid]: '55b4618a-d5f3-4320-93d3-f3501c73d72b',
+      [FieldNameUser.displayName]: null,
+      [FieldNameUser.photoUrl]: null,
+      [FieldNameUser.email]: null,
+      [FieldNameUser.authorStyle]: 1,
+    },
+    {
+      [FieldNameUser.username]: 'test',
+      [FieldNameUser.guestUuid]: null,
+      [FieldNameUser.displayName]: 'Local Test User',
+      [FieldNameUser.photoUrl]: null,
+      [FieldNameUser.email]: null,
+      [FieldNameUser.authorStyle]: 2,
+    },
+  ]);
+  await knex(TableIdentity).insert({
+    [FieldNameIdentity.userId]: 2,
+    [FieldNameIdentity.providerType]: ProviderType.LOCAL,
+    [FieldNameIdentity.providerIdentifier]: null,
+    [FieldNameIdentity.providerUserId]: null,
+    [FieldNameIdentity.passwordHash]: await hashPassword('test123'),
+  });
+}
diff --git a/backend/src/database/seeds/02_api_token.ts b/backend/src/database/seeds/02_api_token.ts
new file mode 100644
index 000000000..435e0ecb4
--- /dev/null
+++ b/backend/src/database/seeds/02_api_token.ts
@@ -0,0 +1,30 @@
+/*
+ * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+import { createHash } from 'crypto';
+import { Knex } from 'knex';
+
+import { FieldNameApiToken, TableApiToken } from '../types';
+
+export async function seed(knex: Knex): Promise<void> {
+  // Clear table beforehand
+  await knex(TableApiToken).del();
+
+  // Insert an api token
+  const apiToken =
+    'LaD52wgw7pi5zVitv4gR5lxoUa6ncTQGASPmXDSdppB9xcd9kCtqjlrdQ8OOfmG9DNXGvfkIwaOCAv8nRp8IoQ';
+  await knex(TableApiToken).insert({
+    [FieldNameApiToken.id]: 'pA4mOf51bpY',
+    [FieldNameApiToken.userId]: 2,
+    [FieldNameApiToken.label]: 'Local Test User API Token',
+    [FieldNameApiToken.secretHash]: createHash('sha512')
+      .update(apiToken)
+      .digest('hex'),
+    // Token is valid for 2 years
+    [FieldNameApiToken.validUntil]: new Date(
+      new Date().getTime() + 2 * 365 * 24 * 60 * 60 * 1000,
+    ),
+  });
+}
diff --git a/backend/src/database/seeds/03_note.ts b/backend/src/database/seeds/03_note.ts
new file mode 100644
index 000000000..28074b357
--- /dev/null
+++ b/backend/src/database/seeds/03_note.ts
@@ -0,0 +1,199 @@
+/*
+ * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+import { NoteType } from '@hedgedoc/commons';
+import { createPatch } from 'diff';
+import { readFileSync } from 'fs';
+import { Knex } from 'knex';
+
+import { extractRevisionMetadataFromContent } from '../../revisions/utils/extract-revision-metadata-from-content';
+import {
+  FieldNameAlias,
+  FieldNameAuthorshipInfo,
+  FieldNameNote,
+  FieldNameNoteGroupPermission,
+  FieldNameNoteUserPermission,
+  FieldNameRevision,
+  FieldNameRevisionTag,
+  TableAlias,
+  TableAuthorshipInfo,
+  TableNote,
+  TableNoteGroupPermission,
+  TableNoteUserPermission,
+  TableRevision,
+  TableRevisionTag,
+} from '../types';
+
+export async function seed(knex: Knex): Promise<void> {
+  // Clear tables beforehand
+  await knex(TableNote).del();
+  await knex(TableAlias).del();
+  await knex(TableRevision).del();
+  await knex(TableRevisionTag).del();
+  await knex(TableAuthorshipInfo).del();
+  await knex(TableNoteGroupPermission).del();
+  await knex(TableNoteUserPermission).del();
+
+  const guestNoteAlias = 'guest-note';
+  const userNoteAlias = 'user-note';
+  const userSlideAlias = 'user-slide';
+
+  const guestNoteContent = readFileSync('./notes/guest_note.md', 'utf-8');
+  const userNoteContent = readFileSync('./notes/local_user_note.md', 'utf-8');
+  const userSlideContent = readFileSync('./notes/local_user_slide.md', 'utf-8');
+
+  const {
+    title: guestNoteTitle,
+    description: guestNoteDescription,
+    tags: guestNoteTags,
+  } = extractRevisionMetadataFromContent(guestNoteContent);
+  const {
+    title: userNoteTitle,
+    description: userNoteDescription,
+    tags: userNoteTags,
+  } = extractRevisionMetadataFromContent(userNoteContent);
+  const {
+    title: userSlideTitle,
+    description: userSlideDescription,
+    tags: userSlideTags,
+  } = extractRevisionMetadataFromContent(userSlideContent);
+
+  // Insert a few notes and revisions
+  await knex(TableNote).insert([
+    {
+      [FieldNameNote.ownerId]: 1,
+      [FieldNameNote.version]: 2,
+    },
+    {
+      [FieldNameNote.ownerId]: 2,
+      [FieldNameNote.version]: 2,
+    },
+    {
+      [FieldNameNote.ownerId]: 2,
+      [FieldNameNote.version]: 2,
+    },
+  ]);
+  await knex(TableAlias).insert([
+    {
+      [FieldNameAlias.noteId]: 1,
+      [FieldNameAlias.alias]: guestNoteAlias,
+      [FieldNameAlias.isPrimary]: true,
+    },
+    {
+      [FieldNameAlias.noteId]: 2,
+      [FieldNameAlias.alias]: userNoteAlias,
+      [FieldNameAlias.isPrimary]: true,
+    },
+    {
+      [FieldNameAlias.noteId]: 1,
+      [FieldNameAlias.alias]: userSlideAlias,
+      [FieldNameAlias.isPrimary]: true,
+    },
+  ]);
+  await knex(TableRevision).insert([
+    {
+      [FieldNameRevision.noteId]: 1,
+      [FieldNameRevision.patch]: createPatch(
+        guestNoteAlias,
+        '',
+        guestNoteContent,
+      ),
+      [FieldNameRevision.content]: guestNoteContent,
+      [FieldNameRevision.yjsStateVector]: null,
+      [FieldNameRevision.noteType]: NoteType.DOCUMENT,
+      [FieldNameRevision.title]: guestNoteTitle,
+      [FieldNameRevision.description]: guestNoteDescription,
+    },
+    {
+      [FieldNameRevision.noteId]: 1,
+      [FieldNameRevision.patch]: createPatch(
+        userNoteAlias,
+        '',
+        userNoteContent,
+      ),
+      [FieldNameRevision.content]: userNoteContent,
+      [FieldNameRevision.yjsStateVector]: null,
+      [FieldNameRevision.noteType]: NoteType.DOCUMENT,
+      [FieldNameRevision.title]: userNoteTitle,
+      [FieldNameRevision.description]: userNoteDescription,
+    },
+    {
+      [FieldNameRevision.noteId]: 1,
+      [FieldNameRevision.patch]: createPatch(
+        userSlideAlias,
+        '',
+        userSlideContent,
+      ),
+      [FieldNameRevision.content]: userSlideContent,
+      [FieldNameRevision.yjsStateVector]: null,
+      [FieldNameRevision.noteType]: NoteType.SLIDE,
+      [FieldNameRevision.title]: userSlideTitle,
+      [FieldNameRevision.description]: userSlideDescription,
+    },
+  ]);
+  await knex(TableRevisionTag).insert([
+    ...guestNoteTags.map((tag) => ({
+      [FieldNameRevisionTag.revisionId]: 1,
+      [FieldNameRevisionTag.tag]: tag,
+    })),
+    ...userNoteTags.map((tag) => ({
+      [FieldNameRevisionTag.revisionId]: 2,
+      [FieldNameRevisionTag.tag]: tag,
+    })),
+    ...userSlideTags.map((tag) => ({
+      [FieldNameRevisionTag.revisionId]: 3,
+      [FieldNameRevisionTag.tag]: tag,
+    })),
+  ]);
+  await knex(TableAuthorshipInfo).insert([
+    {
+      [FieldNameAuthorshipInfo.revisionId]: 1,
+      [FieldNameAuthorshipInfo.authorId]: 1,
+      [FieldNameAuthorshipInfo.startPosition]: 0,
+      [FieldNameAuthorshipInfo.endPosition]: guestNoteContent.length,
+    },
+    {
+      [FieldNameAuthorshipInfo.revisionId]: 2,
+      [FieldNameAuthorshipInfo.authorId]: 2,
+      [FieldNameAuthorshipInfo.startPosition]: 0,
+      [FieldNameAuthorshipInfo.endPosition]: userNoteContent.length,
+    },
+    {
+      [FieldNameAuthorshipInfo.revisionId]: 3,
+      [FieldNameAuthorshipInfo.authorId]: 2,
+      [FieldNameAuthorshipInfo.startPosition]: 0,
+      [FieldNameAuthorshipInfo.endPosition]: userSlideContent.length,
+    },
+  ]);
+  await knex(TableNoteGroupPermission).insert([
+    {
+      [FieldNameNoteGroupPermission.noteId]: 1,
+      [FieldNameNoteGroupPermission.groupId]: 1,
+      [FieldNameNoteGroupPermission.canEdit]: true,
+    },
+    {
+      [FieldNameNoteGroupPermission.noteId]: 2,
+      [FieldNameNoteGroupPermission.groupId]: 1,
+      [FieldNameNoteGroupPermission.canEdit]: false,
+    },
+    {
+      [FieldNameNoteGroupPermission.noteId]: 3,
+      [FieldNameNoteGroupPermission.groupId]: 1,
+      [FieldNameNoteGroupPermission.canEdit]: false,
+    },
+  ]);
+  await knex(TableNoteUserPermission).insert([
+    {
+      [FieldNameNoteUserPermission.noteId]: 2,
+      [FieldNameNoteUserPermission.userId]: 2,
+      [FieldNameNoteUserPermission.canEdit]: true,
+    },
+    {
+      [FieldNameNoteUserPermission.noteId]: 3,
+      [FieldNameNoteUserPermission.userId]: 2,
+      [FieldNameNoteUserPermission.canEdit]: true,
+    },
+  ]);
+}
diff --git a/backend/src/database/seeds/notes/guest_note.md b/backend/src/database/seeds/notes/guest_note.md
new file mode 100644
index 000000000..b81ebaf15
--- /dev/null
+++ b/backend/src/database/seeds/notes/guest_note.md
@@ -0,0 +1,9 @@
+---
+title: Guest User Note
+description: A test note for the guest user
+tags:
+  - guest
+  - note
+---
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.`;
diff --git a/backend/src/database/seeds/notes/local_user_note.md b/backend/src/database/seeds/notes/local_user_note.md
new file mode 100644
index 000000000..2e0cbaf3e
--- /dev/null
+++ b/backend/src/database/seeds/notes/local_user_note.md
@@ -0,0 +1,14 @@
+---
+title: Local Test User Note 1
+description: A test note for the local test user
+tags:
+  - user
+  - note
+---
+
+# Title
+
+Some Text
+
+- [ ] Write A ToDo-List
+- [ ] Check some items
diff --git a/backend/src/database/seeds/notes/local_user_slide.md b/backend/src/database/seeds/notes/local_user_slide.md
new file mode 100644
index 000000000..dd0280494
--- /dev/null
+++ b/backend/src/database/seeds/notes/local_user_slide.md
@@ -0,0 +1,29 @@
+---
+title: Local Test User SlideDeck
+description: A test SlideDeck for the local test user
+tags:
+  - user
+  - slide
+---
+
+## First slide
+
+\`---\`
+
+Is the divider of slides
+
+----
+
+### First branch of first the slide
+
+\`----\`
+
+Is the divider of branches
+
+Use the *Space* key to navigate through all slides.
+
+---
+
+## Point of View
+
+Press **ESC** to enter the slide overview.
diff --git a/backend/src/ormconfig.ts b/backend/src/ormconfig.ts
deleted file mode 100644
index 9ef531b20..000000000
--- a/backend/src/ormconfig.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
- *
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-import { NestFactory } from '@nestjs/core';
-import { NestExpressApplication } from '@nestjs/platform-express';
-import { DataSource } from 'typeorm';
-
-import { AppModule } from './app.module';
-import { AppConfig } from './config/app.config';
-import { Loglevel } from './config/loglevel.enum';
-import { ConsoleLoggerService } from './logger/console-logger.service';
-
-async function buildDataSource(): Promise<DataSource> {
-  // We create a new app instance to let it discover entities
-  const app = await NestFactory.create<NestExpressApplication>(AppModule, {
-    logger: new ConsoleLoggerService({ loglevel: Loglevel.TRACE } as AppConfig),
-  });
-  const dataSource = app.get(DataSource);
-
-  // The migration CLI does not want an existing connection
-  await dataSource.destroy();
-
-  return dataSource;
-}
-
-export default buildDataSource();
diff --git a/backend/src/seed.ts b/backend/src/seed.ts
deleted file mode 100644
index 07c3020a0..000000000
--- a/backend/src/seed.ts
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
- *
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-import { ProviderType } from '@hedgedoc/commons';
-import { DataSource } from 'typeorm';
-
-import { ApiToken } from './api-token/api-token.entity';
-import { Identity } from './auth/identity.entity';
-import { Author } from './authors/author.entity';
-import { User } from './database/user.entity';
-import { Group } from './groups/group.entity';
-import { HistoryEntry } from './history/history-entry.entity';
-import { MediaUpload } from './media/media-upload.entity';
-import { Alias } from './notes/alias.entity';
-import { Note } from './notes/note.entity';
-import { Tag } from './notes/tag.entity';
-import { NoteGroupPermission } from './permissions/note-group-permission.entity';
-import { NoteUserPermission } from './permissions/note-user-permission.entity';
-import { Edit } from './revisions/edit.entity';
-import { Revision } from './revisions/revision.entity';
-import { Session } from './sessions/session.entity';
-import { hashPassword } from './utils/password';
-
-/**
- * This function creates and populates a sqlite db for manual testing
- */
-const dataSource = new DataSource({
-  type: 'sqlite',
-  database: './hedgedoc.sqlite',
-  entities: [
-    User,
-    Note,
-    Revision,
-    Edit,
-    NoteGroupPermission,
-    NoteUserPermission,
-    Group,
-    HistoryEntry,
-    MediaUpload,
-    Tag,
-    ApiToken,
-    Identity,
-    Author,
-    Session,
-    Alias,
-  ],
-  synchronize: true,
-  logging: false,
-  dropSchema: true,
-});
-
-dataSource
-  .initialize()
-  .then(async () => {
-    const password = 'test_password';
-    const users = [];
-    users.push(User.create('hardcoded', 'Test User 1'));
-    users.push(User.create('hardcoded_2', 'Test User 2'));
-    users.push(User.create('hardcoded_3', 'Test User 3'));
-    const notes: Note[] = [];
-    notes.push(Note.create(null, 'test') as Note);
-    notes.push(Note.create(null, 'test2') as Note);
-    notes.push(Note.create(null, 'test3') as Note);
-
-    for (let i = 0; i < 3; i++) {
-      const author = (await dataSource.manager.save(
-        Author.create(1),
-      )) as Author;
-      const user = (await dataSource.manager.save(users[i])) as User;
-      const identity = Identity.create(user, ProviderType.LOCAL, null);
-      identity.passwordHash = await hashPassword(password);
-      dataSource.manager.create(Identity, identity);
-      author.user = dataSource.manager.save(user);
-      const revision = Revision.create(
-        'This is a test note',
-        'This is a test note',
-        notes[i],
-        null,
-        'Test note',
-        '',
-        [],
-      ) as Revision;
-      const edit = Edit.create(author, 1, 42) as Edit;
-      revision.edits = Promise.resolve([edit]);
-      notes[i].revisions = Promise.all([revision]);
-      notes[i].userPermissions = Promise.resolve([]);
-      notes[i].groupPermissions = Promise.resolve([]);
-      user.ownedNotes = Promise.resolve([notes[i]]);
-      await dataSource.manager.save([
-        notes[i],
-        user,
-        revision,
-        edit,
-        author,
-        identity,
-      ]);
-    }
-    const createdUsers = await dataSource.manager.find(User);
-    const groupEveryone = Group.create('_EVERYONE', 'Everyone', true) as Group;
-    const groupLoggedIn = Group.create(
-      '_LOGGED_IN',
-      'Logged-in users',
-      true,
-    ) as Group;
-    await dataSource.manager.save([groupEveryone, groupLoggedIn]);
-
-    for (let i = 0; i < 3; i++) {
-      if (i === 0) {
-        const permission1 = NoteUserPermission.create(
-          createdUsers[0],
-          notes[i],
-          true,
-        );
-        const permission2 = NoteUserPermission.create(
-          createdUsers[1],
-          notes[i],
-          false,
-        );
-        notes[i].userPermissions = Promise.resolve([permission1, permission2]);
-        notes[i].groupPermissions = Promise.resolve([]);
-        await dataSource.manager.save([notes[i], permission1, permission2]);
-      }
-
-      if (i === 1) {
-        const readPermission = NoteGroupPermission.create(
-          groupEveryone,
-          notes[i],
-          false,
-        );
-        notes[i].userPermissions = Promise.resolve([]);
-        notes[i].groupPermissions = Promise.resolve([readPermission]);
-        await dataSource.manager.save([notes[i], readPermission]);
-      }
-
-      if (i === 2) {
-        notes[i].owner = Promise.resolve(createdUsers[0]);
-        await dataSource.manager.save([notes[i]]);
-      }
-    }
-
-    const foundUsers = await dataSource.manager.find(User);
-    if (!foundUsers) {
-      throw new Error('Could not find freshly seeded users. Aborting.');
-    }
-    const foundNotes = await dataSource.manager.find(Note, {
-      relations: ['aliases'],
-    });
-    if (!foundNotes) {
-      throw new Error('Could not find freshly seeded notes. Aborting.');
-    }
-    for (const note of foundNotes) {
-      if (!(await note.aliases)[0]) {
-        throw new Error(
-          'Could not find alias of freshly seeded notes. Aborting.',
-        );
-      }
-    }
-    for (const user of foundUsers) {
-      console.log(
-        `Created User '${user.username}' with password '${password}'`,
-      );
-    }
-    for (const note of foundNotes) {
-      console.log(`Created Note '${(await note.aliases)[0].name ?? ''}'`);
-    }
-    for (const user of foundUsers) {
-      for (const note of foundNotes) {
-        const historyEntry = HistoryEntry.create(user, note);
-        await dataSource.manager.save(historyEntry);
-        console.log(
-          `Created HistoryEntry for user '${user.username}' and note '${
-            (await note.aliases)[0].name ?? ''
-          }'`,
-        );
-      }
-    }
-  })
-  .catch((error) => console.log(error));