diff --git a/.changeset/five-toes-swim.md b/.changeset/five-toes-swim.md
new file mode 100644
index 000000000000..ac8d04b7a6d3
--- /dev/null
+++ b/.changeset/five-toes-swim.md
@@ -0,0 +1,5 @@
+---
+"astro": minor
+---
+
+in this release we can support .toml file as data entry for in the /src/content folder
diff --git a/examples/with-data/.codesandbox/Dockerfile b/examples/with-data/.codesandbox/Dockerfile
new file mode 100644
index 000000000000..c3b5c81a121d
--- /dev/null
+++ b/examples/with-data/.codesandbox/Dockerfile
@@ -0,0 +1 @@
+FROM node:18-bullseye
diff --git a/examples/with-data/.gitignore b/examples/with-data/.gitignore
new file mode 100644
index 000000000000..016b59ea143d
--- /dev/null
+++ b/examples/with-data/.gitignore
@@ -0,0 +1,24 @@
+# build output
+dist/
+
+# generated types
+.astro/
+
+# dependencies
+node_modules/
+
+# logs
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# environment variables
+.env
+.env.production
+
+# macOS-specific files
+.DS_Store
+
+# jetbrains setting folder
+.idea/
diff --git a/examples/with-data/.vscode/extensions.json b/examples/with-data/.vscode/extensions.json
new file mode 100644
index 000000000000..22a15055d638
--- /dev/null
+++ b/examples/with-data/.vscode/extensions.json
@@ -0,0 +1,4 @@
+{
+ "recommendations": ["astro-build.astro-vscode"],
+ "unwantedRecommendations": []
+}
diff --git a/examples/with-data/.vscode/launch.json b/examples/with-data/.vscode/launch.json
new file mode 100644
index 000000000000..d6422097621f
--- /dev/null
+++ b/examples/with-data/.vscode/launch.json
@@ -0,0 +1,11 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "command": "./node_modules/.bin/astro dev",
+ "name": "Development server",
+ "request": "launch",
+ "type": "node-terminal"
+ }
+ ]
+}
diff --git a/examples/with-data/README.md b/examples/with-data/README.md
new file mode 100644
index 000000000000..1db3fb3991a8
--- /dev/null
+++ b/examples/with-data/README.md
@@ -0,0 +1,54 @@
+# Astro Starter Kit: Basics
+
+```sh
+npm create astro@latest -- --template basics
+```
+
+[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/basics)
+[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/basics)
+[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/basics/devcontainer.json)
+
+> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
+
+![just-the-basics](https://github.com/withastro/astro/assets/2244813/a0a5533c-a856-4198-8470-2d67b1d7c554)
+
+## 🚀 Project Structure
+
+Inside of your Astro project, you'll see the following folders and files:
+
+```text
+/
+├── public/
+│ └── favicon.svg
+├── src/
+│ ├── components/
+│ │ └── Card.astro
+│ ├── layouts/
+│ │ └── Layout.astro
+│ └── pages/
+│ └── index.astro
+└── package.json
+```
+
+Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
+
+There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
+
+Any static assets, like images, can be placed in the `public/` directory.
+
+## 🧞 Commands
+
+All commands are run from the root of the project, from a terminal:
+
+| Command | Action |
+| :------------------------ | :----------------------------------------------- |
+| `npm install` | Installs dependencies |
+| `npm run dev` | Starts local dev server at `localhost:4321` |
+| `npm run build` | Build your production site to `./dist/` |
+| `npm run preview` | Preview your build locally, before deploying |
+| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
+| `npm run astro -- --help` | Get help using the Astro CLI |
+
+## 👀 Want to learn more?
+
+Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
diff --git a/examples/with-data/astro.config.mjs b/examples/with-data/astro.config.mjs
new file mode 100644
index 000000000000..882e6515a67e
--- /dev/null
+++ b/examples/with-data/astro.config.mjs
@@ -0,0 +1,4 @@
+import { defineConfig } from 'astro/config';
+
+// https://astro.build/config
+export default defineConfig({});
diff --git a/examples/with-data/package.json b/examples/with-data/package.json
new file mode 100644
index 000000000000..4fd5d4fb15c9
--- /dev/null
+++ b/examples/with-data/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "@example/with-data",
+ "type": "module",
+ "version": "0.0.1",
+ "private": true,
+ "scripts": {
+ "dev": "astro dev",
+ "start": "astro dev",
+ "build": "astro build",
+ "preview": "astro preview",
+ "astro": "astro"
+ },
+ "dependencies": {
+ "astro": "^4.8.2"
+ }
+}
diff --git a/examples/with-data/public/favicon.svg b/examples/with-data/public/favicon.svg
new file mode 100644
index 000000000000..f157bd1c5e28
--- /dev/null
+++ b/examples/with-data/public/favicon.svg
@@ -0,0 +1,9 @@
+
diff --git a/examples/with-data/src/components/Card.astro b/examples/with-data/src/components/Card.astro
new file mode 100644
index 000000000000..bd6d5971ebf3
--- /dev/null
+++ b/examples/with-data/src/components/Card.astro
@@ -0,0 +1,61 @@
+---
+interface Props {
+ title: string;
+ body: string;
+ href: string;
+}
+
+const { href, title, body } = Astro.props;
+---
+
+
+
+
+ {title}
+ →
+
+
+ {body}
+
+
+
+
diff --git a/examples/with-data/src/content/config.ts b/examples/with-data/src/content/config.ts
new file mode 100644
index 000000000000..1762cc064ccf
--- /dev/null
+++ b/examples/with-data/src/content/config.ts
@@ -0,0 +1,13 @@
+import { defineCollection, z } from 'astro:content';
+
+const siteCollection = defineCollection({
+ type: 'data',
+ schema: z.object({
+ title: z.string(),
+ description: z.string(),
+ })
+});
+
+export const collections = {
+ 'site': siteCollection,
+};
\ No newline at end of file
diff --git a/examples/with-data/src/content/site/about.toml b/examples/with-data/src/content/site/about.toml
new file mode 100644
index 000000000000..308df43a569e
--- /dev/null
+++ b/examples/with-data/src/content/site/about.toml
@@ -0,0 +1,2 @@
+title = "About Us"
+description = "Welcome to our website! Learn more about our company and what we do."
\ No newline at end of file
diff --git a/examples/with-data/src/content/site/home.yaml b/examples/with-data/src/content/site/home.yaml
new file mode 100644
index 000000000000..0133c0cb6c27
--- /dev/null
+++ b/examples/with-data/src/content/site/home.yaml
@@ -0,0 +1,3 @@
+title: Home Page
+description: description of website
+slug: home
\ No newline at end of file
diff --git a/examples/with-data/src/layouts/Layout.astro b/examples/with-data/src/layouts/Layout.astro
new file mode 100644
index 000000000000..98c71bb54449
--- /dev/null
+++ b/examples/with-data/src/layouts/Layout.astro
@@ -0,0 +1,52 @@
+---
+interface Props {
+ title: string;
+ description?: string;
+}
+
+const { title, description = "Astro description" } = Astro.props;
+---
+
+
+
+
+
+
+
+
+
+ {title}
+
+
+
+
+
+
diff --git a/examples/with-data/src/pages/about.astro b/examples/with-data/src/pages/about.astro
new file mode 100644
index 000000000000..2a3e729fc61a
--- /dev/null
+++ b/examples/with-data/src/pages/about.astro
@@ -0,0 +1,102 @@
+---
+import Layout from '../layouts/Layout.astro';
+import { getEntry } from "astro:content";
+
+const aboutpage = await getEntry('site', 'about');
+console.log(aboutpage)
+---
+
+
+
+
+ {aboutpage.data.title}
+
+ {aboutpage.data.description}
+
+
+
+
+
diff --git a/examples/with-data/src/pages/index.astro b/examples/with-data/src/pages/index.astro
new file mode 100644
index 000000000000..6fdba65ba944
--- /dev/null
+++ b/examples/with-data/src/pages/index.astro
@@ -0,0 +1,127 @@
+---
+import Layout from '../layouts/Layout.astro';
+import Card from '../components/Card.astro';
+import { getEntry } from "astro:content";
+
+const homepage = await getEntry('site', 'home');
+console.log(homepage)
+---
+
+
+
+
+ Welcome to Astro
+
+ To get started, open the directory src/pages
in your project.
+ Code Challenge: Tweak the "Welcome to Astro" message above.
+
+
+
+
+
+
diff --git a/examples/with-data/tsconfig.json b/examples/with-data/tsconfig.json
new file mode 100644
index 000000000000..d78f81ec4e8e
--- /dev/null
+++ b/examples/with-data/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "astro/tsconfigs/base"
+}
diff --git a/packages/astro/package.json b/packages/astro/package.json
index 6f416a61e1e4..a8e02ec462ea 100644
--- a/packages/astro/package.json
+++ b/packages/astro/package.json
@@ -158,6 +158,7 @@
"html-escaper": "^3.0.3",
"http-cache-semantics": "^4.1.1",
"js-yaml": "^4.1.0",
+ "js-toml": "^1.0.0",
"kleur": "^4.1.5",
"magic-string": "^0.30.10",
"mrmime": "^2.0.0",
diff --git a/packages/astro/src/core/config/settings.ts b/packages/astro/src/core/config/settings.ts
index d01e4299c42a..487f5722f314 100644
--- a/packages/astro/src/core/config/settings.ts
+++ b/packages/astro/src/core/config/settings.ts
@@ -1,6 +1,7 @@
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import yaml from 'js-yaml';
+import { load as tomlParse } from 'js-toml';
import type { AstroConfig, AstroSettings } from '../../@types/astro.js';
import { getContentPaths } from '../../content/index.js';
import createPreferences from '../../preferences/index.js';
@@ -96,6 +97,44 @@ export function createBaseSettings(config: AstroConfig): AstroSettings {
}
},
},
+ {
+ extensions: ['.toml'],
+ getEntryInfo({ contents, fileUrl }) {
+ if (contents === undefined || contents === '') return { data: {} };
+
+ const pathRelToContentDir = path.relative(
+ fileURLToPath(contentDir),
+ fileURLToPath(fileUrl)
+ );
+ let data;
+ try {
+ data = tomlParse(contents);
+ } catch (e) {
+ throw new AstroError({
+ ...AstroErrorData.DataCollectionEntryParseError,
+ message: AstroErrorData.DataCollectionEntryParseError.message(
+ pathRelToContentDir,
+ e instanceof Error ? e.message : 'contains invalid TOML.'
+ ),
+ location: { file: fileUrl.pathname },
+ stack: e instanceof Error ? e.stack : undefined,
+ });
+ }
+
+ if (data == null || typeof data !== 'object') {
+ throw new AstroError({
+ ...AstroErrorData.DataCollectionEntryParseError,
+ message: AstroErrorData.DataCollectionEntryParseError.message(
+ pathRelToContentDir,
+ 'data is not an object.'
+ ),
+ location: { file: fileUrl.pathname },
+ });
+ }
+
+ return { data };
+ },
+ },
],
renderers: [],
scripts: [],
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d2ec86c1f0d1..01ecc9e5815e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -393,6 +393,12 @@ importers:
specifier: ^4.8.6
version: link:../../packages/astro
+ examples/with-data:
+ dependencies:
+ astro:
+ specifier: ^4.8.2
+ version: link:../../packages/astro
+
examples/with-markdoc:
dependencies:
'@astrojs/markdoc':
@@ -617,6 +623,9 @@ importers:
http-cache-semantics:
specifier: ^4.1.1
version: 4.1.1
+ js-toml:
+ specifier: ^1.0.0
+ version: 1.0.0
js-yaml:
specifier: ^4.1.0
version: 4.1.0
@@ -6227,6 +6236,14 @@ packages:
'@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5)
dev: false
+ /@babel/runtime-corejs3@7.24.5:
+ resolution: {integrity: sha512-GWO0mgzNMLWaSYM4z4NVIuY0Cd1fl8cPnuetuddu5w/qGuvt5Y7oUi/kvvQGK9xgOkFJDQX2heIvTRn/OQ1XTg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ core-js-pure: 3.37.0
+ regenerator-runtime: 0.14.1
+ dev: false
+
/@babel/runtime@7.24.4:
resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==}
engines: {node: '>=6.9.0'}
@@ -6565,6 +6582,33 @@ packages:
prettier: 2.8.8
dev: true
+ /@chevrotain/cst-dts-gen@11.0.3:
+ resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==}
+ dependencies:
+ '@chevrotain/gast': 11.0.3
+ '@chevrotain/types': 11.0.3
+ lodash-es: 4.17.21
+ dev: false
+
+ /@chevrotain/gast@11.0.3:
+ resolution: {integrity: sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==}
+ dependencies:
+ '@chevrotain/types': 11.0.3
+ lodash-es: 4.17.21
+ dev: false
+
+ /@chevrotain/regexp-to-ast@11.0.3:
+ resolution: {integrity: sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==}
+ dev: false
+
+ /@chevrotain/types@11.0.3:
+ resolution: {integrity: sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==}
+ dev: false
+
+ /@chevrotain/utils@11.0.3:
+ resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==}
+ dev: false
+
/@clack/core@0.3.4:
resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==}
dependencies:
@@ -10033,6 +10077,17 @@ packages:
parse5-htmlparser2-tree-adapter: 7.0.0
dev: true
+ /chevrotain@11.0.3:
+ resolution: {integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==}
+ dependencies:
+ '@chevrotain/cst-dts-gen': 11.0.3
+ '@chevrotain/gast': 11.0.3
+ '@chevrotain/regexp-to-ast': 11.0.3
+ '@chevrotain/types': 11.0.3
+ '@chevrotain/utils': 11.0.3
+ lodash-es: 4.17.21
+ dev: false
+
/chokidar@3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 8.10.0'}
@@ -10295,6 +10350,11 @@ packages:
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
engines: {node: '>= 0.6'}
+ /core-js-pure@3.37.0:
+ resolution: {integrity: sha512-d3BrpyFr5eD4KcbRvQ3FTUx/KWmaDesr7+a3+1+P46IUnNoEt+oiLijPINZMEon7w9oGkIINWxrBAU9DEciwFQ==}
+ requiresBuild: true
+ dev: false
+
/cross-argv@2.0.0:
resolution: {integrity: sha512-YIaY9TR5Nxeb8SMdtrU8asWVM4jqJDNDYlKV21LxtYcfNJhp1kEsgSa6qXwXgzN0WQWGODps0+TlGp2xQSHwOg==}
dev: false
@@ -12543,6 +12603,13 @@ packages:
resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==}
dev: false
+ /js-toml@1.0.0:
+ resolution: {integrity: sha512-G757004huuG5Cjg8KUoVTS4zNRR4449KG8kjtFQS0yyQnceq3KfxcArThcqUV2cwdpd0C9I+e1WciK3Xm4cWJw==}
+ dependencies:
+ chevrotain: 11.0.3
+ xregexp: 5.1.1
+ dev: false
+
/js-yaml@3.14.1:
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
hasBin: true
@@ -12787,6 +12854,10 @@ packages:
dependencies:
p-locate: 5.0.0
+ /lodash-es@4.17.21:
+ resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
+ dev: false
+
/lodash.chunk@4.2.0:
resolution: {integrity: sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w==}
dev: false
@@ -15014,7 +15085,6 @@ packages:
/regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
- dev: true
/regexp-ast-analysis@0.7.1:
resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==}
@@ -17470,6 +17540,12 @@ packages:
engines: {node: '>=0.1'}
dev: true
+ /xregexp@5.1.1:
+ resolution: {integrity: sha512-fKXeVorD+CzWvFs7VBuKTYIW63YD1e1osxwQ8caZ6o1jg6pDAbABDG54LCIq0j5cy7PjRvGIq6sef9DYPXpncg==}
+ dependencies:
+ '@babel/runtime-corejs3': 7.24.5
+ dev: false
+
/y18n@4.0.3:
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
dev: true