diff --git a/.gitignore b/.gitignore
index ed7273e..aeb16ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
-.scratch-build-cache
+# scratch build cache and config
+.scratch/cache/
# dependencies (bun install)
node_modules
diff --git a/.scratch/project.toml b/.scratch/project.toml
new file mode 100644
index 0000000..40a34eb
--- /dev/null
+++ b/.scratch/project.toml
@@ -0,0 +1,13 @@
+# Scratch Cloud Project Configuration
+#
+# This file configures how your project deploys to Scratch Cloud.
+# Run `scratch cloud config` to update these settings interactively.
+
+# Project name
+name = "scratch-dev"
+
+# Server URL (overrides global default)
+server_url = "https://app.scratch.dev"
+
+# Visibility
+visibility = "public"
diff --git a/pages/components/BouncingDvdLogo.tsx b/pages/components/BouncingDvdLogo.tsx
index ec3cf37..6dcc5b7 100644
--- a/pages/components/BouncingDvdLogo.tsx
+++ b/pages/components/BouncingDvdLogo.tsx
@@ -99,7 +99,7 @@ export default function BouncingDvdLogo() {
}, [velocity]);
return (
-
+
{/* TV outer frame */}
, og:title, twitter:title)
+description: "Complete documentation for the Scratch CLI" # SEO description
+keywords: ["MDX", "static site", "React", "Bun", "markdown"] # SEO keywords
+author: "Pete Koomen" # Page author
+robots: "index, follow" # Search engine directives
+lang: "en" # HTML lang attribute
+canonical: "https://scratch.dev/docs/" # Canonical URL ()
+
+# Open Graph (social sharing)
+image: "https://scratch.dev/scratch-social.png" # Social sharing image (og:image, twitter:image)
+url: "https://scratch.dev/docs/" # Open Graph URL (og:url)
+type: "website" # Content type (og:type) - "website" or "article"
+siteName: "Scratch" # Site name (og:site_name)
+locale: "en_US" # Locale (og:locale)
+siteUrl: "https://scratch.dev" # Base URL for resolving relative image paths
---
# Documentation
@@ -38,9 +47,9 @@ A simple Scratch project (created with `scratch create my-scratch-project`) look
```
my-scratch-project/
- pages/ # put markdown and components here
+ pages/ # put markdown pages and components here
posts/ (collapsed)
- post1.md # accessible at /posts/post1
+ post1.md # accessible at /posts/post1
post2.md # /posts/post2
blog.png # static assets in pages/ or public/
index.mdx # accessible at root path (/)
@@ -53,7 +62,12 @@ my-scratch-project/
CodeBlock.tsx
Heading.tsx
Link.tsx
- PageWrapper.jsx # wraps every page
+ template/ (collapsed) # page template components
+ Copyright.jsx
+ Footer.jsx
+ Header.jsx
+ PageWrapper.jsx # wraps every page
+ ScratchBadge.jsx
tailwind.css # global styles
AGENTS.md # agent context
package.json # dependencies
@@ -87,9 +101,10 @@ Add static content like a favicon or `_redirects` file to the `public/` director
`src/` is for CSS files, components and JS/TS libraries. New Scratch projects will contain the following:
-- `src/PageWrapper.jsx` - your Markdown contents will be "wrapped" with this component. Modify it to change page headers, footers, nav bars and other global components.
+- `src/template/PageWrapper.jsx` - your Markdown contents will be "wrapped" with this component. Modify it to change page headers, footers, nav bars and other global components.
+- `src/template/` - contains page template components like `Header.jsx`, `Footer.jsx`, `Copyright.jsx`, and `ScratchBadge.jsx`.
- `src/tailwind.css` - global styles. Edit this to change the look and feel of your compiled Markdown.
-- `src/markdown` - a directory containing default Markdown components. For example, edit `src/markdown/CodeBlock.tsx` to change how Markdown code blocks are rendered.
+- `src/markdown` - a directory containing default Markdown components. For example, edit `src/markdown/CodeBlock.tsx` to change how Markdown code blocks are rendered.
### package.json
@@ -217,19 +232,70 @@ These options work with all commands:
### Frontmatter
-Add YAML frontmatter to set page metadata:
+Add YAML frontmatter at the top of your MDX files to set page metadata. These properties are automatically converted to HTML meta tags for SEO and social sharing.
-```mdx
+#### Basic Properties
+
+| Property | Description |
+|----------|-------------|
+| `title` | Page title. Sets ``, `og:title`, and `twitter:title` |
+| `description` | Page description for SEO. Sets meta description, `og:description`, and `twitter:description` |
+| `keywords` | Keywords for SEO. Can be a string or array (arrays are joined with ", ") |
+| `author` | Page author. Sets `meta[name="author"]` |
+| `robots` | Robots directive (e.g., `"index, follow"`) |
+| `lang` | HTML language attribute (e.g., `"en"`) |
+| `canonical` | Canonical URL. Sets `` |
+
+#### Open Graph Properties
+
+| Property | Description | Default |
+|----------|-------------|---------|
+| `image` | Social sharing image URL. Sets `og:image` and `twitter:image` | - |
+| `url` | Canonical Open Graph URL. Sets `og:url` | - |
+| `type` | Content type. Sets `og:type` | `"article"` |
+| `siteName` | Site name. Sets `og:site_name` | - |
+| `locale` | Locale (e.g., `"en_US"`). Sets `og:locale` | - |
+| `siteUrl` | Base URL for resolving relative image paths | - |
+
+#### Twitter Card Properties
+
+| Property | Description | Default |
+|----------|-------------|---------|
+| `twitterCard` | Card type. Sets `twitter:card` | `"summary_large_image"` |
+| `twitterSite` | Site's Twitter handle (e.g., `"@mysite"`). Sets `twitter:site` | - |
+| `twitterCreator` | Author's Twitter handle. Sets `twitter:creator` | - |
+
+#### Article Properties
+
+| Property | Description |
+|----------|-------------|
+| `publishDate` | Publication date (ISO format). Sets `article:published_time` |
+| `modifiedDate` | Last modified date (ISO format). Sets `article:modified_time` |
+| `tags` | Article tags. Can be string or array. Sets `article:tag` |
+
+#### Example
+
+```yaml
---
-title: My Page
-description: A description for SEO
-image: /og-image.png
-keywords: ["react", "markdown"]
-author: Your Name
+title: "My Page Title"
+description: "A brief description for SEO and social sharing"
+keywords: ["react", "markdown", "static site"]
+author: "Your Name"
+image: "/og-image.png"
+type: "article"
+siteName: "My Site"
+locale: "en_US"
+twitterCard: "summary_large_image"
+twitterSite: "@mysite"
+publishDate: "2025-01-01"
+tags: ["tutorial", "guide"]
+canonical: "https://example.com/my-page"
+lang: "en"
+siteUrl: "https://example.com"
---
```
-These are automatically injected as HTML meta tags.
+**Note:** Image URLs can be absolute (starting with `http://` or `https://`) or relative paths. Relative paths are resolved against `siteUrl` if provided.
### Using Components
@@ -286,7 +352,7 @@ Scratch uses Tailwind CSS. Edit `src/tailwind.css` for global styles:
### Typography
-Markdown content is styled with [Tailwind Typography](https://github.com/tailwindlabs/tailwindcss-typography). Use prose modifiers in `PageWrapper.jsx`:
+Markdown content is styled with [Tailwind Typography](https://github.com/tailwindlabs/tailwindcss-typography). Use prose modifiers in `src/template/PageWrapper.jsx`:
```jsx
@@ -308,7 +374,7 @@ Use the `not-prose` class to exclude elements from typography styling:
## PageWrapper
-Create `src/PageWrapper.jsx` to wrap all pages with a layout:
+Create `src/template/PageWrapper.jsx` to wrap all pages with a layout:
```jsx
export default function PageWrapper({ children }) {
diff --git a/pages/index.mdx b/pages/index.mdx
index 17bb519..ce430e3 100644
--- a/pages/index.mdx
+++ b/pages/index.mdx
@@ -1,32 +1,43 @@
---
-title: "Scratch"
-image: "/scratch-logo.svg"
-description: "Write with Markdown and React"
-keywords: ["MDX", "static site", "React", "Bun", "markdown"]
-author: "Scratch"
-type: "website"
-lang: "en"
+# Basic metadata
+title: "Scratch" # Page title (, og:title, twitter:title)
+description: "Write with Markdown and React" # SEO description
+keywords: ["MDX", "static site", "React", "Bun", "markdown"] # SEO keywords
+author: "Pete Koomen" # Page author
+robots: "index, follow" # Search engine directives
+lang: "en" # HTML lang attribute
+canonical: "https://scratch.dev/" # Canonical URL ()
+
+# Open Graph (social sharing)
+image: "https://scratch.dev/scratch-social.png" # Social sharing image (og:image, twitter:image)
+url: "https://scratch.dev/" # Open Graph URL (og:url)
+type: "website" # Content type (og:type) - "website" or "article"
+siteName: "Scratch" # Site name (og:site_name)
+locale: "en_US" # Locale (og:locale)
+siteUrl: "https://scratch.dev" # Base URL for resolving relative image paths
---
-
-
-
+
-Scratch is a tool for writing with [Markdown](https://daringfireball.net/projects/markdown/) and [React](https://react.dev/).
+Scratch is a tool for writing with [Markdown](https://daringfireball.net/projects/markdown/) and [React](https://react.dev/).
-Write in Markdown and embed React components right in your text. Scratch compiles your work into beautiful static websites (like [this one](https://github.com/scratch/scratch.dev)) that can be hosted anywhere.
+Write in Markdown and embed React components right in your text. Scratch compiles your work into beautiful static websites that can be hosted anywhere.
-Scratch was designed for collaborative writing with coding agents like [Claude Code](https://www.claude.com/product/claude-code). Use your favorite editor to write in Markdown, and ask an agent for help when it's easier to express yourself with code.
+Scratch was designed for collaborative writing with coding agents like [Claude Code](https://www.claude.com/product/claude-code). Use your favorite editor to write in Markdown and ask a coding agent for help when it's easier to express yourself with code.
## Quick Start
-Scratch requires no configuration so it's easy to get started:
+Scratch requires no configuration so it's easy to get started. First, install:
```bash
# Install scratch
curl -fsSL https://scratch.dev/install.sh | bash
+```
+
+Then create a project and start the dev server:
+```bash
# Create a new project
scratch create
@@ -34,7 +45,12 @@ scratch create
scratch dev
```
-Now you're ready to start writing in `pages/index.mdx`.
+Now you're ready to start writing in `pages/index.mdx`. When you're ready, use the `publish` command to share with specific people, your team, or the world:
+
+```bash
+# Publish with a Scratch Server on Cloudflare
+scratch publish
+```
## What can you do with Scratch?
diff --git a/public/scratch-social.png b/public/scratch-social.png
new file mode 100644
index 0000000..cc4205e
Binary files /dev/null and b/public/scratch-social.png differ
diff --git a/src/index.css b/src/tailwind.css
similarity index 98%
rename from src/index.css
rename to src/tailwind.css
index b081768..678c7b5 100644
--- a/src/index.css
+++ b/src/tailwind.css
@@ -18,7 +18,7 @@
/* H1 - center and add extra top margin */
.prose :where(h1):not(:where([class~='not-prose'] *)) {
- @apply text-center mt-24;
+ @apply text-center mt-16;
}
/* Inline code - add background and padding, remove backticks */
diff --git a/src/template/Copyright.jsx b/src/template/Copyright.jsx
new file mode 100644
index 0000000..131a290
--- /dev/null
+++ b/src/template/Copyright.jsx
@@ -0,0 +1,14 @@
+export default function Copyright({ name }) {
+ const author = name || (typeof window !== 'undefined' && window.__scratch_author__);
+ const year = new Date().getFullYear();
+
+ if (!author) {
+ return null;
+ }
+
+ return (
+