@rettangoli/sites 0.2.6 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,325 +1,133 @@
1
1
  # Rettangoli Sites
2
2
 
3
- A straightforward, zero-complexity static site generator that uses Markdown and YAML to build websites. Perfect for landing pages, blogs, documentation, admin dashboards, and more.
3
+ A static site generator using Markdown and YAML.
4
4
 
5
- ## Features
6
-
7
- - 🚀 **Zero Configuration** - Works out of the box with sensible defaults
8
- - 📝 **Markdown & YAML** - Write content in familiar formats
9
- - 🎨 **Full-featured** - Templates, partials, collections, global data, nested pages, static assets, and extensible architecture
10
-
11
- ## Installation
5
+ ## Quick Start
12
6
 
13
7
  ```bash
14
- npm install -g rtgl
15
- ```
8
+ # Create a new site from template
9
+ bunx rtgl sites init my-site # Uses 'default' template
10
+ bunx rtgl sites init my-site -t default # Explicit template name
16
11
 
17
- ## Quick Start
12
+ # Install and build
13
+ cd my-site
14
+ bun install
15
+ bun run build
16
+ ```
18
17
 
19
- ### 1. Create Your Project Structure
18
+ ## Project Structure
20
19
 
21
20
  ```
22
21
  my-site/
23
- ├── pages/ # Your content (YAML and Markdown files)
24
- ├── templates/ # Reusable page templates (YAML)
25
- ├── partials/ # Reusable components (YAML)
26
- ├── data/ # Global data files (YAML)
27
- ├── static/ # Static assets (CSS, JS, images)
28
- └── _site/ # Generated output (created automatically)
22
+ ├── pages/ # Content (YAML and Markdown)
23
+ ├── templates/ # Page layouts
24
+ ├── partials/ # Reusable components
25
+ ├── data/ # Global data files
26
+ ├── static/ # Static assets
27
+ ├── sites.config.js # Optional config
28
+ ├── package.json
29
+ └── _site/ # Generated output
29
30
  ```
30
31
 
31
- ### 2. Create Your First Page
32
+ ## Pages
32
33
 
33
- **pages/index.yaml**
34
+ **YAML page:**
34
35
  ```yaml
35
36
  ---
36
- title: Welcome
37
37
  template: base
38
+ title: Home
38
39
  ---
39
- - heading: Welcome to My Site
40
- - paragraph: This is a simple static site built with Rettangoli Sites.
41
- ```
42
-
43
- ### 3. Create a Template
44
-
45
- **templates/base.yaml**
46
- ```yaml
47
- - tag: html
48
- children:
49
- - tag: head
50
- children:
51
- - tag: title
52
- children: $title
53
- - tag: body
54
- children: $content
40
+ - h1: Welcome
41
+ - p: Hello world
55
42
  ```
56
43
 
57
- ### 4. Build Your Site
58
-
59
- ```bash
60
- npx rtgl sites build
61
- ```
62
-
63
- Your site will be generated in the `_site` directory.
64
-
65
- ## Core Concepts
66
-
67
- ### Pages
68
-
69
- Pages are the content of your site. They can be either:
70
- - **YAML files** (`.yaml`) - Structured content with components
71
- - **Markdown files** (`.md`) - Rich text content with frontmatter
72
-
73
- Every page can have frontmatter (metadata) at the top:
74
-
75
- ```yaml
44
+ **Markdown page:**
45
+ ```markdown
76
46
  ---
77
- title: My Page Title
78
47
  template: base
79
- tags: [blog, tutorial]
48
+ title: About
80
49
  ---
81
- ```
50
+ # About Us
82
51
 
83
- ### Templates
52
+ Content in **markdown**.
53
+ ```
84
54
 
85
- Templates define the HTML structure for your pages. They're YAML files that describe HTML elements and can include dynamic content using the `$` prefix.
55
+ ## Syntax
86
56
 
87
- **Example template:**
88
57
  ```yaml
89
- - tag: article
90
- children:
91
- - tag: h1
92
- children: $title
93
- - tag: div
94
- class: content
95
- children: $content
96
- ```
58
+ # Element with class and id
59
+ - div.container#main:
60
+ - h1: Title
97
61
 
98
- Templates can be organized in subdirectories:
99
- - `templates/base.yaml` Referenced as `template: base`
100
- - `templates/blog/post.yaml` → Referenced as `template: blog/post`
62
+ # Attributes
63
+ - 'a href="/about"': About Us
64
+ - 'img src="/logo.png" alt="Logo"':
101
65
 
102
- ### Partials
66
+ # Variables
67
+ - h1: ${title}
68
+ - p: ${site.description}
103
69
 
104
- Partials are reusable components that can be included in pages and templates using `$partial`:
70
+ # Conditionals
71
+ - $if showBanner:
72
+ - div.banner: Hello!
105
73
 
106
- **partials/header.yaml**
107
- ```yaml
108
- - tag: header
109
- children:
110
- - tag: nav
111
- children:
112
- - tag: a
113
- href: /
114
- children: Home
115
- - tag: a
116
- href: /about
117
- children: About
118
- ```
74
+ # Loops
75
+ - $for item in items:
76
+ - li: ${item.name}
119
77
 
120
- **Using in a page:**
121
- ```yaml
78
+ # Partials
122
79
  - $partial: header
123
- - heading: Welcome
80
+ - $partial: card
81
+ title: My Card
82
+ description: Card content
124
83
  ```
125
84
 
126
- ### Data Files
85
+ ## Data Files
127
86
 
128
- Global data files in the `data/` directory are automatically loaded and available in all pages and templates.
87
+ `data/site.yaml` available as `${site.name}`, `${site.nav}`, etc.
129
88
 
130
- **data/site.yaml**
131
- ```yaml
132
- name: My Awesome Site
133
- author: John Doe
134
- social:
135
- twitter: johndoe
136
- github: johndoe
137
- ```
89
+ ## Collections
138
90
 
139
- **Access in templates:**
140
- ```yaml
141
- - tag: footer
142
- children:
143
- - text: "© 2024 "
144
- - text: $site.author
145
- ```
146
-
147
- ### Collections
148
-
149
- Collections group related content using tags. Any page with a `tags` field in its frontmatter becomes part of a collection.
150
-
151
- **pages/blog/post-1.md**
152
- ```markdown
153
- ---
154
- title: My First Post
155
- tags: blog
156
- date: 2024-01-15
157
- ---
158
- # Hello World
159
- This is my first blog post.
160
- ```
91
+ Tag pages to create collections:
161
92
 
162
- **pages/blog-index.yaml**
163
93
  ```yaml
94
+ # pages/blog/post.md
164
95
  ---
165
- title: Blog
96
+ tags: [blog]
166
97
  ---
167
- - heading: Recent Posts
168
- - ul:
169
- - $for post in collections.blog:
170
- li:
171
- - 'a href="${post.url}"':
172
- - ${post.data.title}
173
98
  ```
174
99
 
175
- ### Page Variables
176
-
177
- Every page has access to a `page.url` variable that contains the page's URL path. All frontmatter variables (like `title`) are available directly:
178
-
179
- **pages/about.yaml**
180
- ```yaml
181
- ---
182
- title: About Us
183
- ---
184
- - paragraph: Current page URL is ${page.url}
185
- ```
186
-
187
- **templates/base.yaml**
188
100
  ```yaml
189
- - tag: head
190
- children:
191
- - tag: title
192
- children: ${title}
193
- - tag: link
194
- rel: canonical
195
- href: ${page.url}
101
+ # pages/blog.yaml
102
+ - $for post in collections.blog:
103
+ - a href="${post.url}": ${post.data.title}
196
104
  ```
197
105
 
198
- The `page.url` variable contains the page's URL path without the `.html` extension, with trailing slashes:
199
- - `/index.html` → `page.url` = `/`
200
- - `/about.html` → `page.url` = `/about/`
201
- - `/docs/guide.html` → `page.url` = `/docs/guide/`
202
-
203
- This variable is available in both pages and templates, making it useful for navigation, breadcrumbs, and canonical URLs.
204
-
205
- ### Static Files
206
-
207
- Everything in the `static/` directory is copied directly to the output:
208
- - `static/css/style.css` → `_site/css/style.css`
209
- - `static/images/logo.png` → `_site/images/logo.png`
210
- - `static/app.js` → `_site/app.js`
211
-
212
- ## Advanced Features
213
-
214
- ### Nested Pages
215
-
216
- Create subdirectories in `pages/` to organize your content:
217
- - `pages/index.yaml` → `_site/index.html`
218
- - `pages/about.yaml` → `_site/about.html`
219
- - `pages/blog/post-1.md` → `_site/blog/post-1.html`
220
- - `pages/docs/api/reference.yaml` → `_site/docs/api/reference.html`
221
-
222
- ### Markdown Support
223
-
224
- Markdown files can use frontmatter and templates:
225
-
226
- ```markdown
227
- ---
228
- title: My Blog Post
229
- template: blog/post
230
- tags: [blog, tutorial]
231
- author: Jane Doe
232
- ---
233
- # Introduction
234
-
235
- This is a **markdown** post with *formatting*.
236
-
237
- ## Code Example
238
-
239
- \`\`\`javascript
240
- console.log('Hello, World!');
241
- \`\`\`
242
- ```
243
-
244
- ### Custom Markdown Renderer
245
-
246
- Configure a custom markdown renderer in `sites.config.js`:
106
+ ## Configuration
247
107
 
108
+ `sites.config.js`:
248
109
  ```javascript
249
- import MarkdownIt from 'markdown-it';
250
- import hljs from 'highlight.js';
251
-
252
- const md = MarkdownIt({
253
- highlight: function (str, lang) {
254
- if (lang && hljs.getLanguage(lang)) {
255
- return hljs.highlight(str, { language: lang }).value;
256
- }
257
- return '';
258
- }
259
- });
260
-
261
110
  export default {
262
- mdRender: md
111
+ mdRender: customMarkdownRenderer,
112
+ functions: {
113
+ sortDate: (list) => list.sort((a, b) =>
114
+ new Date(b.data.date) - new Date(a.data.date)
115
+ )
116
+ }
263
117
  }
264
118
  ```
265
119
 
266
- ### Dynamic Content with Jempl
267
-
268
- Rettangoli Sites uses [Jempl](https://github.com/yuusoft-org/jempl) for templating, which provides powerful features for dynamic content including variable replacement, conditionals, loops, and partials.
120
+ ## Scripts
269
121
 
270
- For detailed syntax and usage examples, please refer to the [Jempl documentation](https://github.com/yuusoft-org/jempl).
122
+ ```bash
123
+ bun run build # Build site to _site/
124
+ bun run watch # Build + watch for changes
125
+ bun run serve # Serve _site/
126
+ bun run screenshot # Generate page screenshots
127
+ ```
271
128
 
129
+ ## Templates
272
130
 
273
- ## Example Projects
131
+ Starter templates in `templates/`:
274
132
 
275
- ### Blog Site Structure
276
- ```
277
- blog-site/
278
- ├── pages/
279
- │ ├── index.yaml # Homepage
280
- │ ├── about.md # About page
281
- │ └── blog/
282
- │ ├── index.yaml # Blog listing
283
- │ ├── 2024-01-15-first-post.md
284
- │ └── 2024-01-20-second-post.md
285
- ├── templates/
286
- │ ├── base.yaml # Main layout
287
- │ └── blog/
288
- │ ├── post.yaml # Blog post template
289
- │ └── listing.yaml # Blog list template
290
- ├── partials/
291
- │ ├── header.yaml
292
- │ ├── footer.yaml
293
- │ └── post-card.yaml
294
- ├── data/
295
- │ └── site.yaml # Site metadata
296
- └── static/
297
- ├── css/
298
- │ └── style.css
299
- └── images/
300
- └── logo.png
301
- ```
302
-
303
- ### Documentation Site Structure
304
- ```
305
- docs-site/
306
- ├── pages/
307
- │ ├── index.yaml
308
- │ └── docs/
309
- │ ├── getting-started.md
310
- │ ├── api/
311
- │ │ ├── overview.md
312
- │ │ └── reference.yaml
313
- │ └── guides/
314
- │ ├── installation.md
315
- │ └── configuration.md
316
- ├── templates/
317
- │ ├── base.yaml
318
- │ └── docs.yaml
319
- ├── partials/
320
- │ ├── nav.yaml
321
- │ └── sidebar.yaml
322
- └── static/
323
- └── css/
324
- └── docs.css
325
- ```
133
+ - **default** - Basic site with homepage, blog, and about page
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rettangoli/sites",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "Generate static sites using Markdown and YAML. Straightforward, zero-complexity. Complete toolkit for landing pages, blogs, documentation, admin dashboards, and more.git remote add origin git@github.com:yuusoft-org/sitic.git",
5
5
  "author": {
6
6
  "name": "Luciano Hanyon Wu",
package/src/cli/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { buildSite } from './build.js';
2
2
  import watchSite from './watch.js';
3
3
  import screenshotCommand from '../screenshotRunner.js';
4
+ import { initSite } from './init.js';
4
5
 
5
6
  export {
6
7
  buildSite,
7
8
  watchSite,
8
9
  screenshotCommand,
10
+ initSite,
9
11
  }
@@ -0,0 +1,38 @@
1
+ import { existsSync, mkdirSync, cpSync, readdirSync } from 'fs';
2
+ import { resolve, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+
7
+ export function initSite({ projectName, template = 'default' }) {
8
+ const templatesDir = resolve(__dirname, '../../templates');
9
+ const templatePath = resolve(templatesDir, template);
10
+ const targetPath = resolve(process.cwd(), projectName);
11
+
12
+ // Check if template exists
13
+ if (!existsSync(templatePath)) {
14
+ const available = readdirSync(templatesDir).filter(f =>
15
+ existsSync(resolve(templatesDir, f, 'package.json'))
16
+ );
17
+ console.error(`Template "${template}" not found.`);
18
+ console.error(`Available templates: ${available.join(', ')}`);
19
+ process.exit(1);
20
+ }
21
+
22
+ // Check if target directory already exists
23
+ if (existsSync(targetPath)) {
24
+ console.error(`Directory "${projectName}" already exists.`);
25
+ process.exit(1);
26
+ }
27
+
28
+ // Create target directory and copy template
29
+ mkdirSync(targetPath, { recursive: true });
30
+ cpSync(templatePath, targetPath, { recursive: true });
31
+
32
+ console.log(`Created "${projectName}" from template "${template}"`);
33
+ console.log('');
34
+ console.log('Next steps:');
35
+ console.log(` cd ${projectName}`);
36
+ console.log(' bun install');
37
+ console.log(' bun run build');
38
+ }
@@ -32,7 +32,7 @@ export async function loadSiteConfig(rootDir, throwOnError = true, bustCache = f
32
32
  return configExport || {};
33
33
  } catch (e) {
34
34
  // Only ignore file not found errors
35
- if (e.code === 'ENOENT') {
35
+ if (e.code === 'ENOENT' || e.code === 'ERR_MODULE_NOT_FOUND') {
36
36
  // Config file is optional, return empty config
37
37
  return {};
38
38
  } else if (throwOnError) {
@@ -0,0 +1,212 @@
1
+ # My Site
2
+
3
+ A static site built with [Rettangoli Sites](https://github.com/yuusoft-org/rettangoli) using the [rtgl UI](https://github.com/yuusoft-org/rettangoli/tree/main/packages/rettangoli-ui) framework.
4
+
5
+ ## Getting Started
6
+
7
+ ```bash
8
+ bun install
9
+ bun run build
10
+ bun run serve
11
+ ```
12
+
13
+ ## Scripts
14
+
15
+ | Script | Description |
16
+ |--------|-------------|
17
+ | `bun run build` | Build site to `_site/` |
18
+ | `bun run watch` | Build and watch for changes |
19
+ | `bun run serve` | Serve `_site/` locally |
20
+ | `bun run screenshot` | Build and capture screenshots |
21
+
22
+ ## Project Structure
23
+
24
+ ```
25
+ ├── pages/ # Content (YAML and Markdown files)
26
+ ├── templates/ # Page layouts
27
+ ├── partials/ # Reusable components
28
+ ├── data/ # Global data files
29
+ ├── static/ # Static assets (copied as-is)
30
+ ├── sites.config.js # Configuration and custom functions
31
+ └── _site/ # Generated output
32
+ ```
33
+
34
+ ## Pages
35
+
36
+ Pages can be **YAML** or **Markdown** files in `pages/`.
37
+
38
+ **YAML page:**
39
+ ```yaml
40
+ ---
41
+ template: base
42
+ title: Home
43
+ ---
44
+ - rtgl-text s="h1": Welcome
45
+ - rtgl-text: Hello world
46
+ ```
47
+
48
+ **Markdown page:**
49
+ ```markdown
50
+ ---
51
+ template: base
52
+ title: About
53
+ ---
54
+ # About Us
55
+
56
+ Content in **markdown**.
57
+ ```
58
+
59
+ ### Frontmatter
60
+
61
+ | Field | Description |
62
+ |-------|-------------|
63
+ | `template` | Template to use (e.g., `base`, `post`) |
64
+ | `title` | Page title |
65
+ | `tags` | Array of tags for collections (e.g., `[blog]`) |
66
+
67
+ ### URL Mapping
68
+
69
+ - `pages/index.yaml` → `/`
70
+ - `pages/about.md` → `/about/`
71
+ - `pages/blog/post.md` → `/blog/post/`
72
+
73
+ ## rtgl UI Components
74
+
75
+ ```yaml
76
+ # Layout with rtgl-view
77
+ - rtgl-view d="h" g="lg" av="c": # horizontal, gap, align vertical center
78
+ - rtgl-view flex="1": # flex grow
79
+ - rtgl-view w="200" h="100": # fixed width/height
80
+
81
+ # Text with rtgl-text
82
+ - rtgl-text s="h1": Heading 1
83
+ - rtgl-text s="lg" c="mu-fg": Large muted text
84
+ - rtgl-text fw="bold" ta="c": Bold centered
85
+
86
+ # Buttons
87
+ - rtgl-button: Click me
88
+ - rtgl-button v="se": Secondary
89
+
90
+ # Links with hover states
91
+ - 'a href="/about" style="text-decoration: none"':
92
+ - rtgl-text h-c="pr" h-cur="p": Hover link
93
+ ```
94
+
95
+ ### Common Attributes
96
+
97
+ | Attr | Description | Values |
98
+ |------|-------------|--------|
99
+ | `w` | Width | `f` (full), number, `100vw` |
100
+ | `h` | Height | number, `100vh` |
101
+ | `d` | Direction | `h` (horizontal), `v` (vertical) |
102
+ | `g` | Gap | `xs`, `sm`, `md`, `lg`, `xl` |
103
+ | `p` | Padding | `xs`, `sm`, `md`, `lg`, `xl` |
104
+ | `m` | Margin | `xs`, `sm`, `md`, `lg`, `xl` |
105
+ | `av` | Align vertical | `s` (start), `c` (center), `e` (end) |
106
+ | `ah` | Align horizontal | `s`, `c`, `e` |
107
+ | `bgc` | Background color | `bg`, `su`, `mu`, `pr` |
108
+ | `c` | Text color | `fg`, `mu-fg`, `pr` |
109
+ | `s` | Text size | `h1`, `h2`, `h3`, `h4`, `lg`, `md`, `sm` |
110
+ | `br` | Border radius | `xs`, `sm`, `md`, `lg`, `xl` |
111
+ | `flex` | Flex grow | `1`, `2`, etc. |
112
+
113
+ ### Responsive Prefixes
114
+
115
+ ```yaml
116
+ - rtgl-view md-w="100vw" lg-w="768" w="1024":
117
+ ```
118
+
119
+ | Prefix | Breakpoint |
120
+ |--------|------------|
121
+ | `md-` | Mobile (< 768px) |
122
+ | `lg-` | Tablet (< 1024px) |
123
+ | (none) | Desktop |
124
+
125
+ ### Hover States
126
+
127
+ Prefix with `h-` for hover:
128
+ ```yaml
129
+ - rtgl-text h-c="pr" h-cur="p": Hover to highlight
130
+ - rtgl-view h-bgc="suv": Hover background
131
+ ```
132
+
133
+ ## Syntax
134
+
135
+ ```yaml
136
+ # Variables
137
+ - rtgl-text: ${title}
138
+ - rtgl-text: ${site.name}
139
+
140
+ # Conditionals
141
+ - $if showBanner:
142
+ - rtgl-view bgc="pr" p="lg":
143
+ - rtgl-text: Hello!
144
+
145
+ # Loops
146
+ - $for item in items:
147
+ - rtgl-text: ${item.name}
148
+
149
+ # Partials
150
+ - $partial: header
151
+ - $partial: card
152
+ title: My Card
153
+ ```
154
+
155
+ ## Data Files
156
+
157
+ Files in `data/` are available globally. Filename becomes the variable name.
158
+
159
+ `data/site.yaml` → `${site.name}`, `${site.nav}`, etc.
160
+
161
+ ## Collections
162
+
163
+ Tag pages to create collections:
164
+
165
+ ```yaml
166
+ # pages/blog/post.md
167
+ ---
168
+ tags: [blog]
169
+ date: '2024-01-15'
170
+ ---
171
+ ```
172
+
173
+ ```yaml
174
+ # List posts
175
+ - rtgl-view g="md":
176
+ - $for post in collections.blog:
177
+ - 'a href="${post.url}" style="text-decoration: none"':
178
+ - rtgl-view p="lg" bgc="su" br="lg" h-bgc="suv" h-cur="p":
179
+ - rtgl-text s="lg": ${post.data.title}
180
+ - rtgl-text s="sm" c="mu-fg": ${post.data.date}
181
+ ```
182
+
183
+ Collection item properties:
184
+ - `item.url` - Page URL
185
+ - `item.data` - Frontmatter (title, date, etc.)
186
+ - `item.content` - Raw content
187
+
188
+ ## Configuration
189
+
190
+ `sites.config.js` for custom functions:
191
+
192
+ ```javascript
193
+ export default {
194
+ functions: {
195
+ sortDate: (list) => [...list].sort((a, b) =>
196
+ new Date(b.data.date) - new Date(a.data.date)
197
+ ),
198
+ },
199
+ }
200
+ ```
201
+
202
+ Use in templates:
203
+ ```yaml
204
+ - $for post in sortDate(collections.blog):
205
+ ```
206
+
207
+ ## Static Files
208
+
209
+ Everything in `static/` is copied to `_site/`:
210
+
211
+ - `static/css/theme.css` → `_site/css/theme.css`
212
+ - `static/images/logo.png` → `_site/images/logo.png`
@@ -0,0 +1,25 @@
1
+ name: My Site
2
+
3
+ nav:
4
+ - text: Home
5
+ href: /
6
+ - text: Blog
7
+ href: /blog/
8
+ - text: About
9
+ href: /about/
10
+
11
+ footer:
12
+ links:
13
+ - text: Privacy
14
+ href: /privacy/
15
+ - text: Terms
16
+ href: /terms/
17
+
18
+ landing:
19
+ features:
20
+ - title: Simple
21
+ description: Write content in YAML and Markdown
22
+ - title: Fast
23
+ description: Static site generation for optimal performance
24
+ - title: Flexible
25
+ description: Templates, partials, and collections
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "my-site",
3
+ "type": "module",
4
+ "scripts": {
5
+ "build": "rtgl sites build",
6
+ "watch": "rtgl sites watch",
7
+ "serve": "serve _site",
8
+ "screenshot": "rtgl sites build -s"
9
+ },
10
+ "devDependencies": {
11
+ "rtgl": "0.0.37",
12
+ "serve": "latest"
13
+ }
14
+ }
@@ -0,0 +1,16 @@
1
+ ---
2
+ template: base
3
+ title: About
4
+ ---
5
+
6
+ # About Us
7
+
8
+ This is a sample page written in **Markdown**.
9
+
10
+ ## Our Mission
11
+
12
+ We build great things with simple tools.
13
+
14
+ ## Contact
15
+
16
+ Feel free to reach out!
@@ -0,0 +1,14 @@
1
+ ---
2
+ template: post
3
+ title: Hello World
4
+ tags: [blog]
5
+ date: '2024-01-15'
6
+ ---
7
+
8
+ # Hello World
9
+
10
+ This is my first blog post.
11
+
12
+ ## What's Next
13
+
14
+ Stay tuned for more updates!
@@ -0,0 +1,14 @@
1
+ ---
2
+ template: base
3
+ title: Blog
4
+ ---
5
+ - rtgl-text s="h1" mb="xl": Blog
6
+
7
+ - rtgl-view g="md" w="f":
8
+ - $for post in collections.blog:
9
+ - 'a href="${post.url}" style="text-decoration: none"':
10
+ - rtgl-view w="f" p="lg" bgc="su" br="lg" h-bgc="suv" h-cur="p":
11
+ - rtgl-view d="h" av="c" w="f":
12
+ - rtgl-text s="lg": ${post.data.title}
13
+ - rtgl-view flex="1":
14
+ - rtgl-text s="sm" c="mu-fg": ${post.data.date}
@@ -0,0 +1,21 @@
1
+ ---
2
+ template: base
3
+ title: My Site
4
+ ---
5
+ - rtgl-view ah="c" pv="xl":
6
+ - rtgl-text s="h1" ta="c": Welcome to My Site
7
+ - rtgl-view h="lg":
8
+ - rtgl-text s="lg" c="mu-fg" ta="c": Built with Rettangoli Sites
9
+ - rtgl-view h="xl":
10
+ - 'a href="/about/" style="text-decoration: none"':
11
+ - rtgl-button: Learn More
12
+
13
+ - rtgl-view h="100":
14
+
15
+ - rtgl-view w="f":
16
+ - rtgl-text s="h2" mb="lg": Features
17
+ - rtgl-view d="h" g="lg" w="f" md-d="v":
18
+ - $for feature in site.landing.features:
19
+ - rtgl-view flex="1" p="lg" bgc="su" br="lg":
20
+ - rtgl-text s="h4" mb="sm": ${feature.title}
21
+ - rtgl-text c="mu-fg": ${feature.description}
@@ -0,0 +1,9 @@
1
+ - rtgl-view h="1" w="f" bgc="bo":
2
+ - rtgl-view md-w="100vw" lg-w="768" w="1024" ph="lg" pv="xl":
3
+ - rtgl-view d="h" w="f" av="c":
4
+ - rtgl-text s="sm" c="mu-fg": © 2024 ${site.name}
5
+ - rtgl-view flex="1":
6
+ - rtgl-view d="h" g="lg":
7
+ - $for link in site.footer.links:
8
+ - 'a href="${link.href}" style="text-decoration: none"':
9
+ - rtgl-text s="sm" c="mu-fg" h-c="fg" h-cur="p": ${link.text}
@@ -0,0 +1,9 @@
1
+ - rtgl-view bwb="xs" w="f" ah="c" pos="fix" bgc="bg":
2
+ - rtgl-view md-w="100vw" lg-w="768" w="1024" d="h" av="c" h="64" ph="lg":
3
+ - 'a href="/" style="text-decoration: none"':
4
+ - rtgl-text s="lg" fw="bold": ${site.name}
5
+ - rtgl-view flex="1":
6
+ - rtgl-view d="h" g="lg" av="c":
7
+ - $for link in site.nav:
8
+ - 'a href="${link.href}" style="text-decoration: none"':
9
+ - rtgl-text c="mu-fg" h-c="fg" h-cur="p": ${link.text}
@@ -0,0 +1,9 @@
1
+ export default {
2
+ // Custom template functions
3
+ functions: {
4
+ // Sort by date descending
5
+ sortDate: (list) => [...list].sort((a, b) =>
6
+ new Date(b.data.date) - new Date(a.data.date)
7
+ ),
8
+ },
9
+ }
@@ -0,0 +1,224 @@
1
+ html {
2
+ margin: 0;
3
+ -ms-overflow-style: none;
4
+ scrollbar-width: none;
5
+ width: 100%;
6
+ }
7
+
8
+ html::-webkit-scrollbar {
9
+ display: none;
10
+ }
11
+
12
+ body::-webkit-scrollbar {
13
+ display: none;
14
+ }
15
+
16
+ * {
17
+ scrollbar-color: var(--input) transparent;
18
+ }
19
+
20
+ body {
21
+ -ms-overflow-style: none;
22
+ scrollbar-width: none;
23
+ height: 100%;
24
+ width: 100%;
25
+ margin: 0;
26
+ font-family: system-ui, -apple-system, "Helvetica Neue", sans-serif;
27
+ display: flex;
28
+ flex-direction: column;
29
+ background-color: var(--background);
30
+ color: var(--foreground);
31
+ overscroll-behavior: none;
32
+ overflow: auto;
33
+ -webkit-overflow-scrolling: touch;
34
+ }
35
+
36
+ a {
37
+ color: inherit;
38
+ text-decoration: underline;
39
+ text-decoration-thickness: 1px;
40
+ text-underline-offset: 4px;
41
+ text-decoration-color: var(--muted-foreground);
42
+ }
43
+
44
+ a:hover {
45
+ text-decoration-color: var(--foreground);
46
+ }
47
+
48
+ ::selection {
49
+ background-color: var(--accent);
50
+ }
51
+
52
+ :root {
53
+ --width-stretch: 100%;
54
+
55
+ --spacing-xs: 2px;
56
+ --spacing-sm: 4px;
57
+ --spacing-md: 8px;
58
+ --spacing-lg: 16px;
59
+ --spacing-xl: 32px;
60
+
61
+ --border-radius-xs: 1px;
62
+ --border-radius-sm: 2px;
63
+ --border-radius-md: 4px;
64
+ --border-radius-lg: 8px;
65
+ --border-radius-xl: 16px;
66
+ --border-radius-f: 50%;
67
+
68
+ --border-width-xs: 1px;
69
+ --border-width-sm: 2px;
70
+ --border-width-md: 4px;
71
+ --border-width-lg: 8px;
72
+ --border-width-xl: 16px;
73
+
74
+ --shadow-sm: 0px 2px 6px rgba(0, 0, 0, .45);
75
+ --shadow-md: 0px 5px 12px rgba(0, 0, 0, .45);
76
+ --shadow-lg: 0px 10px 24px rgba(0, 0, 0, .45);
77
+
78
+ --h1-font-size: 3rem;
79
+ --h1-font-weight: 600;
80
+ --h1-line-height: 1;
81
+ --h1-letter-spacing: -.025em;
82
+
83
+ --h2-font-size: 1.875rem;
84
+ --h2-font-weight: 500;
85
+ --h2-line-height: 2.25rem;
86
+ --h2-letter-spacing: -.025em;
87
+
88
+ --h3-font-size: 1.5rem;
89
+ --h3-font-weight: 600;
90
+ --h3-line-height: 2rem;
91
+ --h3-letter-spacing: -.025em;
92
+
93
+ --h4-font-size: 1.25rem;
94
+ --h4-font-weight: 600;
95
+ --h4-line-height: 1.75rem;
96
+ --h4-letter-spacing: -.025em;
97
+
98
+ --lg-font-size: 1.125rem;
99
+ --lg-font-weight: 400;
100
+ --lg-line-height: 1.75rem;
101
+ --lg-letter-spacing: normal;
102
+
103
+ --md-font-size: 1rem;
104
+ --md-font-weight: normal;
105
+ --md-line-height: 1.625rem;
106
+ --md-letter-spacing: normal;
107
+
108
+ --sm-font-size: .875rem;
109
+ --sm-font-weight: 400;
110
+ --sm-line-height: 1.25;
111
+ --sm-letter-spacing: normal;
112
+
113
+ --xs-font-size: .75rem;
114
+ --xs-font-weight: normal;
115
+ --xs-line-height: 1;
116
+ --xs-letter-spacing: normal;
117
+
118
+ --primary: oklch(0.205 0 0);
119
+ --primary-foreground: oklch(0.985 0 0);
120
+ --secondary: oklch(0.97 0 0);
121
+ --secondary-foreground: oklch(0.205 0 0);
122
+ --background: oklch(1 0 0);
123
+ --foreground: oklch(0.145 0 0);
124
+ --muted: oklch(0.97 0 0);
125
+ --muted-foreground: oklch(0.556 0 0);
126
+ --accent: oklch(0.95 0 0);
127
+ --accent-foreground: oklch(0.205 0 0);
128
+ --border: oklch(0.922 0 0);
129
+ --input: oklch(0.922 0 0);
130
+ --ring: oklch(0.708 0 0);
131
+ }
132
+
133
+ .dark {
134
+ --background: oklch(0.145 0 0);
135
+ --foreground: oklch(0.985 0 0);
136
+ --primary: oklch(0.922 0 0);
137
+ --primary-foreground: oklch(0.305 0 0);
138
+ --secondary: oklch(0.269 0 0);
139
+ --secondary-foreground: oklch(0.985 0 0);
140
+ --muted: oklch(0.269 0 0);
141
+ --muted-foreground: oklch(0.708 0 0);
142
+ --accent: oklch(0.371 0 0);
143
+ --accent-foreground: oklch(0.985 0 0);
144
+ --border: oklch(1 0 0 / 10%);
145
+ --input: oklch(1 0 0 / 15%);
146
+ --ring: oklch(0.556 0 0);
147
+ }
148
+
149
+ h1 {
150
+ font-size: var(--h1-font-size);
151
+ font-weight: var(--h1-font-weight);
152
+ line-height: var(--h1-line-height);
153
+ letter-spacing: var(--h1-letter-spacing);
154
+ margin-top: 32px;
155
+ margin-bottom: 16px;
156
+ }
157
+
158
+ h2 {
159
+ font-size: var(--h2-font-size);
160
+ font-weight: var(--h2-font-weight);
161
+ line-height: var(--h2-line-height);
162
+ letter-spacing: var(--h2-letter-spacing);
163
+ margin-top: 32px;
164
+ margin-bottom: 16px;
165
+ }
166
+
167
+ h3 {
168
+ font-size: var(--h3-font-size);
169
+ font-weight: var(--h3-font-weight);
170
+ line-height: var(--h3-line-height);
171
+ letter-spacing: var(--h3-letter-spacing);
172
+ margin-top: 32px;
173
+ margin-bottom: 16px;
174
+ }
175
+
176
+ h4 {
177
+ font-size: var(--h4-font-size);
178
+ font-weight: var(--h4-font-weight);
179
+ line-height: var(--h4-line-height);
180
+ letter-spacing: var(--h4-letter-spacing);
181
+ margin-top: 32px;
182
+ margin-bottom: 16px;
183
+ }
184
+
185
+ p {
186
+ font-size: var(--md-font-size);
187
+ font-weight: var(--md-font-weight);
188
+ line-height: var(--md-line-height);
189
+ letter-spacing: var(--md-letter-spacing);
190
+ margin-top: 0;
191
+ margin-bottom: 16px;
192
+ }
193
+
194
+ ul {
195
+ margin-top: 0;
196
+ margin-bottom: 16px;
197
+ margin-left: 4px;
198
+ padding-left: 16px;
199
+ }
200
+
201
+ li {
202
+ margin-bottom: 8px;
203
+ font-size: var(--md-font-size);
204
+ font-weight: var(--md-font-weight);
205
+ line-height: var(--md-line-height);
206
+ letter-spacing: var(--md-letter-spacing);
207
+ }
208
+
209
+ blockquote {
210
+ margin-top: 0;
211
+ margin-bottom: 16px;
212
+ margin-left: 0;
213
+ margin-right: 0;
214
+ padding-left: 16px;
215
+ border-left: 2px solid var(--foreground);
216
+ }
217
+
218
+ blockquote > p {
219
+ margin-bottom: 0px;
220
+ }
221
+
222
+ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
223
+ scroll-margin-top: 80px;
224
+ }
@@ -0,0 +1,18 @@
1
+ - html lang="en":
2
+ - head:
3
+ - meta charset="utf-8":
4
+ - meta name="viewport" content="width=device-width,initial-scale=1":
5
+ - title: ${title} - ${site.name}
6
+ - link rel="stylesheet" href="/css/theme.css":
7
+ - script src="https://cdn.jsdelivr.net/npm/construct-style-sheets-polyfill@3.1.0/dist/adoptedStyleSheets.min.js":
8
+ - script src="https://cdn.jsdelivr.net/npm/@rettangoli/ui@0.1.31/dist/rettangoli-iife-ui.min.js":
9
+ - body.dark:
10
+ - rtgl-view w="f":
11
+ - rtgl-view h="64":
12
+ - rtgl-view w="f" ah="c":
13
+ - rtgl-view w="f" ph="lg" pb="lg" ah="c" md-w="100vw" lg-w="768" w="1024":
14
+ - "${content}"
15
+ - rtgl-view h="30vh":
16
+ - $partial: footer
17
+ - rtgl-view pos="abs" cor="top" ah="c" bgc="bg":
18
+ - $partial: header
@@ -0,0 +1,24 @@
1
+ - html lang="en":
2
+ - head:
3
+ - meta charset="utf-8":
4
+ - meta name="viewport" content="width=device-width,initial-scale=1":
5
+ - title: ${title} - ${site.name}
6
+ - link rel="stylesheet" href="/css/theme.css":
7
+ - script src="https://cdn.jsdelivr.net/npm/construct-style-sheets-polyfill@3.1.0/dist/adoptedStyleSheets.min.js":
8
+ - script src="https://cdn.jsdelivr.net/npm/@rettangoli/ui@0.1.31/dist/rettangoli-iife-ui.min.js":
9
+ - body.dark:
10
+ - rtgl-view h="64":
11
+ - rtgl-view w="f" ah="c":
12
+ - rtgl-view d="h" g="xl" pb="lg" md-w="100vw" lg-w="768" w="1024" ph="lg":
13
+ - rtgl-view id="content-container" lg-w="100%" w="624":
14
+ - rtgl-text s="sm" c="mu-fg" mb="md": ${date}
15
+ - "${content}"
16
+ - rtgl-view h="xl":
17
+ - 'a href="/blog/" style="text-decoration: none"':
18
+ - rtgl-text c="pr" h-cur="p": ← Back to Blog
19
+ - 'rtgl-view lg-hide flex="1" style="position: sticky; top: 64px;"':
20
+ - rtgl-page-outline id="page-outline" target-id="content-container":
21
+ - rtgl-view h="30vh":
22
+ - $partial: footer
23
+ - rtgl-view pos="abs" cor="top" ah="c" bgc="bg":
24
+ - $partial: header