You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In this inaugural post we'll explore the development of the blog engine we're using on this site. Our tagline is *Practical User Interfaces Built Simply* and creating this blog couldn't have been simpler. The whole site, of which the blog is now a part, is an XMLUI app built with components including [NavPanel](https://docs.xmlui.org/components/NavPanel), [NavLink](https://docs.xmlui.org/components/NavLink), [Pages](https://docs.xmlui.org/components/Pages), [Page](https://docs.xmlui.org/components/Page), and [Markdown](https://docs.xmlui.org/components/Markdown).
2
-
3
-
Let's see how it evolved.
1
+
In this inaugural post we'll explore the development of the blog engine we're using on this site. Our tagline is *Practical User Interfaces Built Simply* and creating this blog couldn't have been simpler. It's an XMLUI app built with a handful of core components (including [NavPanel](https://docs.xmlui.org/components/NavPanel), [NavLink](https://docs.xmlui.org/components/NavLink), [Pages](https://docs.xmlui.org/components/Pages), [Page](https://docs.xmlui.org/components/Page), and [Markdown](https://docs.xmlui.org/components/Markdown)) and a couple of [user-defined components](https://docs.xmlui.org/user-defined-components).
4
2
5
3
## The simplest possible thing
6
4
@@ -50,7 +48,7 @@ We started with the simplest possible approach: post metadata and data as litera
50
48
51
49
You can use it right here or you can click the  icon to open a playground where you can make live changes.
52
50
53
-
This is a pretty good start! We can write posts, arrange them in reverse chronological order, and hey, it's the essence of a blog. Since it's a blog about XMLUI the live playground is a nice bonus that any XMLUI app might put to good use. The user interfaces that you build with XMLUI will require some explaining, it's handy to explain with working examples as well as images, text, and video.
51
+
This is a pretty good start! We can write posts, arrange them in reverse chronological order, and hey, it's the essence of a blog. The live playground is a nice bonus that any XMLUI app might put to good use. The user interfaces that you build with XMLUI will require some explaining, it's handy to explain with working examples as well as images, text, and video.
54
52
55
53
Let's unpack how this works, there isn't much to it. The `App` declared in `Main.xmlui` sets up navigation.
56
54
@@ -66,9 +64,9 @@ Let's unpack how this works, there isn't much to it. The `App` declared in `Main
66
64
</App>
67
65
```
68
66
69
-
Each Page contains a [user-defined component](https://docs.xmlui.org/user-defined-components) called `BlogPage`. In the prototype, the `BlogPage` component receives page content as `$props.content`.
67
+
Each Page contains a user-defined component called `BlogPage` that receives the properties `content`, `title`, `author`, and `date`.
70
68
71
-
```xmlui copy {4}
69
+
```xmlui
72
70
<Pages>
73
71
<Page url="/newest-post">
74
72
<BlogPage
@@ -80,21 +78,16 @@ Each Page contains a [user-defined component](https://docs.xmlui.org/user-define
80
78
</Pages>
81
79
```
82
80
83
-
Here's how the prototype `BlogPage` assembles data and metadata to create a post.
81
+
Here's how `BlogPage` assembles data and metadata to create a post.
@@ -192,7 +185,7 @@ The `NavLink` uses the post's slug to bind to its corresponding `Page`.
192
185
</Page>
193
186
```
194
187
195
-
And the `Page` passes the complete post object to `BlogPage`. In v1 we used the `content` property of the `Markdown` component to pass a string. In v2 we use the `data` property to pass an URL constructed from the post slug.
188
+
And the `Page` passes the complete post object to `BlogPage`. In v1 we used the `content` property of the `Markdown` component to pass a string. In v2 we use the `data` property to pass a URL constructed from the post slug.
196
189
197
190
```xmlui copy {11}
198
191
<Component name="BlogPage">
@@ -216,31 +209,32 @@ Although it's feasible to use a `NavGroup` to list the posts, a blog should real
216
209
217
210
```xmlui copy
218
211
<Component name="BlogOverview">
219
-
<Stack width="85%">
220
-
<H1>XMLUI Blog</H1>
221
-
<Text>Latest updates, tutorials, and insights for building with XMLUI</Text>
222
-
</Stack>
223
-
<List
224
-
data="{
212
+
<CVStack>
213
+
<VStack width="100%">
214
+
<H1>XMLUI Blog</H1>
215
+
<Text>Latest updates, tutorials, and insights for building with XMLUI</Text>
216
+
<List data="{
225
217
$props.posts.sort(function(a, b) {
226
218
return new Date(b.date) - new Date(a.date);
227
219
})
228
220
}">
229
-
<VStack gap="$space-2" width="90%">
230
-
<Link to="/blog/{$item.slug}">
231
-
<Text fontSize="larger">
232
-
{$item.title}
233
-
</Text>
234
-
</Link>
235
-
<Text>
236
-
{$item.date} • {$item.author}
237
-
</Text>
238
-
<Link to="/blog/{$item.slug}">
239
-
<Image src="/blog/images/{$item.image}" />
240
-
</Link>
241
-
<Stack height="3rem" />
221
+
<VStack gap="$space-2">
222
+
<Link to="/blog/{$item.slug}">
223
+
<Text fontSize="larger">
224
+
{$item.title}
225
+
</Text>
226
+
</Link>
227
+
<Text>
228
+
{$item.date} • {$item.author}
229
+
</Text>
230
+
<Link to="/blog/{$item.slug}">
231
+
<Image src="/blog/images/{$item.image}" />
232
+
</Link>
233
+
<Stack height="$space-8" />
234
+
</VStack>
235
+
</List>
242
236
</VStack>
243
-
</List>
237
+
</CVStack>
244
238
</Component>
245
239
```
246
240
@@ -271,7 +265,8 @@ We can't call it a blog unless it provides an RSS feed. For that we've added a s
271
265
272
266
## Deploy standalone
273
267
274
-
Suppose you wanted to decouple the blog engine from the monorepo and use it standalone? Let's start with this footprint.
268
+
Our blog lives in the XMLUI monorepo where it coordinates with the landing page and docs.
269
+
But it can exist standalone, you only need a folder with a handful of files.
That's all we need to serve the blog. Note that we include `xmlui-playground.js`. The live playgrounds you can use here are provided by an extension, and a standalone app can use that extension in the same way our main site does. So when you serve the blog from a static webserver, the playground examples work the same way.
394
-
395
-
You can host the standalone blog on any static webserver. We'll do that, but first let's create a search mechanism that's decoupled from the monorepo's build and works entirely client-side. We'll create two user-defined components: `SearchPrep` and `BlogSearch`.
console.log('Added to blogPosts:', '/blog/' + $item.slug);
420
-
count++;
421
-
422
-
if (window.getBlogSearchCount() >= $props.posts.length) {
423
-
window.stopBlogIndexing();
424
-
console.log('Blog indexing complete!');
425
-
426
-
}
427
-
}" />
428
-
429
-
</List>
430
-
431
-
</Component>
432
-
```
433
-
434
-
Here is `BlogSearch`. It provides a reactive search box so as you type, another global function finds fragments in posts that match your current query.
The post you are reading here was deployed in a similar way.
467
-
468
311
## XMLUI for publishing
469
312
470
313
We get it, blog engines are a dime a dozen. We made this one because XMLUI was already a strong publishing system that we use for the [docs](https://docs.xmlui.org), [demo](https://demo.xmlui.org), and [landing page](https://xmlui.org). The `Markdown` component, with its support for playgrounds, works really well and it made sense to leverage that for our blog. We're not saying that you *should* build a blog engine with XMLUI but it's clearly something you *could* do. We think it's pretty easy to create a competent engine that makes life easy for authors and readers.
0 commit comments