diff --git a/layerindex/migrations/0055_recipe_text_fields.py b/layerindex/migrations/0055_recipe_text_fields.py
new file mode 100644
index 0000000..0714623
--- /dev/null
+++ b/layerindex/migrations/0055_recipe_text_fields.py
@@ -0,0 +1,58 @@
+# Generated by Django 5.2.18 on 2026-10-19 03:19
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('layerindex', '0054_alter_sitenotice_expires'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='packageconfig',
+            name='with_option',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='packageconfig',
+            name='without_option',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='recipe',
+            name='bbclassextend',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='recipe',
+            name='configopts',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='recipe',
+            name='inherits',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='recipe',
+            name='license',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='recipe',
+            name='pn',
+            field=models.CharField(blank=True, max_length=255),
+        ),
+        migrations.AlterField(
+            model_name='recipe',
+            name='provides',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='recipe',
+            name='summary',
+            field=models.TextField(blank=True),
+        ),
+    ]
diff --git a/layerindex/models.py b/layerindex/models.py
index a9e9bdf..425af53 100644
--- a/layerindex/models.py
+++ b/layerindex/models.py
@@ -469,22 +469,22 @@ class Recipe(models.Model):
     layerbranch = models.ForeignKey(LayerBranch, on_delete=models.CASCADE)
     filename = models.CharField(max_length=255)
     filepath = models.CharField(max_length=255, blank=True)
-    pn = models.CharField(max_length=100, blank=True)
+    pn = models.CharField(max_length=255, blank=True)
     pv = models.CharField(max_length=100, blank=True)
     pr = models.CharField(max_length=100, blank=True)
     pe = models.CharField(max_length=100, blank=True)
-    summary = models.CharField(max_length=200, blank=True)
+    summary = models.TextField(blank=True)
     description = models.TextField(blank=True)
     section = models.CharField(max_length=100, blank=True)
-    license = models.CharField(max_length=3072, blank=True)
+    license = models.TextField(blank=True)
     homepage = models.URLField(blank=True)
     bugtracker = models.URLField(blank=True)
-    provides = models.CharField(max_length=2048, blank=True)
-    bbclassextend = models.CharField(max_length=100, blank=True)
-    inherits = models.CharField(max_length=383, blank=True)
+    provides = models.TextField(blank=True)
+    bbclassextend = models.TextField(blank=True)
+    inherits = models.TextField(blank=True)
     updated = models.DateTimeField(auto_now=True)
     blacklisted = models.CharField(max_length=255, blank=True)
-    configopts = models.CharField(max_length=4096, blank=True)
+    configopts = models.TextField(blank=True)
     srcrev = models.CharField(max_length=64, blank=True)
 
     class Meta:
@@ -639,8 +639,8 @@ class Patch(models.Model):
 class PackageConfig(models.Model):
     recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
     feature = models.CharField(max_length=255)
-    with_option = models.CharField(max_length=255, blank=True)
-    without_option = models.CharField(max_length=255, blank=True)
+    with_option = models.TextField(blank=True)
+    without_option = models.TextField(blank=True)
     build_deps = models.CharField(max_length=255, blank=True)
 
     def __str__(self):
diff --git a/tests/test_recipe_fields.py b/tests/test_recipe_fields.py
new file mode 100644
index 0000000..8b8dc42
--- /dev/null
+++ b/tests/test_recipe_fields.py
@@ -0,0 +1,53 @@
+# layerindex-web - tests for storing long recipe values
+#
+# Licensed under the MIT license, see COPYING.MIT for details
+#
+# SPDX-License-Identifier: MIT
+
+import pytest
+from django.test import TestCase
+
+from layerindex.models import Branch, LayerBranch, LayerItem, PackageConfig, Recipe
+
+
+@pytest.mark.django_db
+class TestLongRecipeValues(TestCase):
+    """Values longer than the old field limits, as seen in real layers
+    (e.g. linux-firmware's LICENSE, nativesdk recipes' inherits), must be
+    stored in full rather than truncated."""
+
+    def setUp(self):
+        branch = Branch.objects.create(name='master', bitbake_branch='master')
+        layer = LayerItem.objects.create(name='meta-test', status='P', layer_type='A',
+                                         summary='test', description='test',
+                                         vcs_url='git://example.com/meta-test.git')
+        self.layerbranch = LayerBranch.objects.create(layer=layer, branch=branch)
+
+    def test_long_values_are_not_truncated(self):
+        values = {
+            'pn': 'p' * 112,
+            'summary': 's' * 264,
+            'license': ' & '.join(['LicenseRef-Firmware-%d' % i for i in range(250)]),
+            'provides': 'virtual/x ' * 270,
+            # As generated by core-image-ptest.bb: one multiconfig variant per ptest
+            'bbclassextend': 'native nativesdk ' + ' '.join(['mcextend:python3-ptest-%d' % i for i in range(150)]),
+            'inherits': 'class ' * 110,
+            'configopts': '--enable-thing ' * 290,
+        }
+        with self.assertNoLogs('LayerIndexModels', 'WARNING'):
+            recipe = Recipe.objects.create(layerbranch=self.layerbranch, filename='test_1.0.bb', **values)
+            pc = PackageConfig.objects.create(recipe=recipe, feature='tests',
+                                              with_option='--with-x ' * 45, without_option='--without-x ' * 30)
+        recipe.refresh_from_db()
+        pc.refresh_from_db()
+        for field, value in values.items():
+            self.assertEqual(getattr(recipe, field), value, field)
+        self.assertEqual(pc.with_option, '--with-x ' * 45)
+        self.assertEqual(pc.without_option, '--without-x ' * 30)
+
+    def test_short_fields_are_still_truncated(self):
+        # Fields that keep a length limit are still truncated, with a warning
+        with self.assertLogs('LayerIndexModels', 'WARNING'):
+            recipe = Recipe.objects.create(layerbranch=self.layerbranch, filename='test_1.0.bb', pv='1' * 150)
+        recipe.refresh_from_db()
+        self.assertEqual(len(recipe.pv), 100)
