### Running domstack Examples
Source: https://domstack.net/index
Provides instructions on how to clone the domstack repository, install dependencies, navigate to an example directory, install its specific dependencies, and start the example project.
```shell
$ git clone git@github.com:bcomnes/domstack.git
$ cd domstack
# install the top level deps
$ npm i
$ cd example:{example-name}
# install the example deps
$ npm i
# start the example
$ npm start
```
--------------------------------
### Install DOMStack Static Package
Source: https://domstack.net/index
Installs the core DOMStack static package using npm. This command is the primary way to begin using DOMStack for building static websites and web applications.
```bash
npm install @domstack/static
```
--------------------------------
### Markdown Page Example
Source: https://domstack.net/index
An example of a Markdown page file (`.md`) in DOMStack. It includes YAML front-matter for metadata and variables, and uses Handlebars for dynamic content rendering.
```markdown
---
title: A title for a markdown page
favoriteColor: 'Blue'
---
Just writing about web development.
## Favorite colors
My favorite color is {{ vars.favoriteColor }}.
```
--------------------------------
### HTML Page Example
Source: https://domstack.net/index
An example of an HTML page file (`.html`) in DOMStack. It demonstrates basic HTML structure and the use of Handlebars for rendering variables, which are typically defined in a `page.vars.js` file.
```html
Favorite frameworks
React
Vue
Svelte
{{ vars.favoriteFramework }}
```
--------------------------------
### JavaScript Page Example
Source: https://domstack.net/index
An example of a JavaScript page file in DOMStack. Similar to TypeScript, it exports a default function that accepts context including page variables and returns an HTML string.
```javascript
export default function (context) {
const { pageVars } = context;
return `
Welcome, ${pageVars.userName}!
The current time is ${new Date().toLocaleTimeString()}.
`;
}
```
--------------------------------
### TypeScript Page Example
Source: https://domstack.net/index
An example of a TypeScript page file in DOMStack. It shows how to export a default function that receives variables and returns an HTML string, which is then inserted into the page layout.
```typescript
import { PageContext } from "domstack";
export default function (context: PageContext) {
const { pageVars } = context;
return `
Hello, ${pageVars.name}!
Your favorite color is ${pageVars.favoriteColor}.
`;
}
```
--------------------------------
### domstack Project Structure Example
Source: https://domstack.net/index
Illustrates the typical directory structure within a domstack project's 'src' folder. It shows how different file types like README.md, client scripts (ts/js), stylesheets (css), HTML pages, and layout files are organized to define website pages and structure.
```shell
src % tree
.
├── md-page
│ ├── README.md # directories with README.md in them turn into /md-page/index.html.
│ ├── client.ts # Every page can define its own client.ts script that loads only with it.
│ ├── style.css # Every page can define its own style.css style that loads only with it.
│ ├── loose-md-page.md # loose markdown get built in place, but lacks some page features.
│ └── nested-page # pages are built in place and can nest.
│ ├── README.md # This page is accessed at /md-page/nested-page/.
│ ├── style.css # nested pages are just pages, so they also can have a page scoped client and style.
│ └── client.js # Anywhere JS loads, you can use .js or .ts
├── html-page
│ ├── client.tsx # client bundles can also be written in .jsx/.tsx
│ ├── page.html # Raw html pages are also supported. They support handlebars template blocks.
│ ├── page.vars.ts # pages can define page variables in a page.vars.ts
│ └── style.css
├── js-page
│ └── page.js # A page can also just be a plain javascript function that returns content. They can also be type checked.
├── ts-page
│ ├── client.ts # domstack provides type-stripping via Node.JS and esbuild
│ ├── page.vars.ts # use tsc to run typechecking
│ └── page.ts
├── feeds
│ └── feeds.template.ts # Templates let you generate any file you want from variables and page data.
├── page-with-workers
│ ├── client.ts
│ └── page.ts
│ ├── counter.worker.ts # Web workers use a .worker.{ts,js} naming convention and are auto-bundled
│ └── analytics.worker.js
├── layouts # layouts can live anywhere. The inner content of your page is slotted into your layout.
│ ├── blog.layout.ts # pages specify which layout they want by setting a `layout` page variable.
│ ├── blog.layout.css # layouts can define an additional layout style.
│ ├── blog.layout.client.ts # layouts can also define a layout client.
│ ├── article.layout.ts # layouts can extend other layouts, since they are just functions.
│ ├── javascript.layout.js # layouts can also be written in javascript
│ └── root.layout.ts # the default layout is called "root"
├── globals # global assets can live anywhere. Here they are in a folder called globals.
│ ├── global.client.ts # you can define a global client that loads on every page.
│ ├── global.css # you can define a global css file that loads on every page.
│ ├── global.vars.ts # site wide variables get defined in global.vars.ts
│ ├── markdown-it.settings.ts # You can customize the markdown-it instance used to render markdown
│ └── esbuild.settings.ts # You can even customize the build settings passed to esbuild
├── README.md # This is just a top level page built from a README.md file.
├── client.ts # the top level page can define a page scoped js client.
├── style.css # the top level page can define a page scoped css style.
└── favicon-16x16.png # static assets can live anywhere. Anything other than JS, CSS and HTML get copied over automatically.
```
--------------------------------
### PostVars Example: Generating Blog Post HTML
Source: https://domstack.net/index
Demonstrates an asynchronous `postVars` function that introspects pages to generate an HTML list of recent blog post titles and publish dates. This generated HTML can then be injected into markdown pages.
```typescript
import { html } from 'htm/preact'
import { render } from 'preact-render-to-string'
import type { PostVarsFunction } from '@domstack/static'
export const postVars: PostVarsFunction = async ({
pages
}) => {
const blogPosts = pages
.filter(page => page.vars.layout === 'article')
.sort((a, b) => new Date(b.vars.publishDate) - new Date(a.vars.publishDate))
.slice(0, 5)
const blogpostsHtml = render(html`
${typeof innerChildren === 'string'
? html``
: innerChildren
}
`)
const rootArgs = { ...rest, children }
return defaultRootLayout(rootArgs)
}
export default blogLayout
```
--------------------------------
### Automated Release via GitHub Actions
Source: https://domstack.net/CONTRIBUTING
Initiates the release process by triggering the 'npm bump' action in GitHub Actions. This action handles changelog generation, GitHub release creation, and npm package publishing.
```APIDOC
GitHub Actions - npm bump:
Description: Automates release workflow including version bumping, changelog generation, and publishing.
Trigger: Manual trigger via GitHub Actions tab.
Parameters:
- semantic_version_bump: (string) Required. Specifies the type of version bump (e.g., 'patch', 'minor', 'major').
Process:
1. Navigate to the project's GitHub Actions tab.
2. Select the 'npm bump' workflow.
3. Trigger the workflow, providing the required semantic version bump.
Outcome:
- Updates package.json version.
- Generates changelog.
- Creates a GitHub release.
- Publishes the package to npm.
Reference: [bret.io/projects/package-automation](https://bret.io/projects/package-automation/)
```
--------------------------------
### Page CSS with Imports
Source: https://domstack.net/index
Shows how to define local page styles using a `style.css` file. It demonstrates using CSS `@import` statements to include styles from npm modules or local files, and defines scoped styles.
```css
/* /some-page/style.css */
@import "some-npm-module/style.css";
@import "../common-styles/button.css";
.some-page-class {
color: blue;
& .button {
color: purple;
}
}
```
--------------------------------
### Page Layout Referencing
Source: https://domstack.net/index
Pages can specify which layout to use by setting the `layout` variable in their frontmatter. If no layout is specified, the page defaults to the `root` layout. Referencing a non-existent layout will cause a build error.
```yaml
---
layout: 'article'
title: 'My Article Title'
---
Thanks for reading my article
```
--------------------------------
### Handlebars Placeholder for PostVars Output
Source: https://domstack.net/index
Shows how to use a Handlebars placeholder to insert the `blogPostsHtml` variable, generated by the `postVars` function, into a markdown file.
```html
## [Blog](./blog/)
{{{ vars.blogPostsHtml }}}
```
--------------------------------
### Draft Page File Naming
Source: https://domstack.net/index
Pages can be designated as drafts by adding a `.draft` extension to their file names (e.g., `.draft.md`, `.draft.html`, `.draft.ts`, `.draft.js`). Draft pages are excluded from builds by default but can be included using the `--drafts` flag.
```text
page.draft.md
page.draft.html
page.draft.ts
page.draft.js
```
--------------------------------
### Recommended tsconfig.json for Domstack
Source: https://domstack.net/index
Provides a recommended `tsconfig.json` configuration for use with Domstack, extending `@voxpelli/tsconfig` for type checking and enabling specific compiler options for type stripping and module handling.
```json
{
"extends": "@voxpelli/tsconfig/node20.json",
"compilerOptions": {
"skipLibCheck": true,
"erasableSyntaxOnly": true,
"allowImportingTsExtensions": true,
"rewriteRelativeImportExtensions": true,
"verbatimModuleSyntax": true
},
"include": [
"**/*",
],
"exclude": [
"**/*.js",
"node_modules",
"coverage",
".github"
]
}
```
--------------------------------
### Configure markdown-it Plugins and Settings
Source: https://domstack.net/index
Enables customization of the markdown-it parser by exporting a default async function. This function accepts the markdown-it instance and allows adding plugins or modifying parser configurations.
```typescript
import markdownItContainer from 'markdown-it-container'
import markdownItPlantuml from 'markdown-it-plantuml'
import type { MarkdownIt } from 'markdown-it'
export default const markdownItSettingsOverride = async (md: MarkdownIt) => {
// Add custom plugins
md.use(markdownItContainer, 'spoiler', {
validate: (params: string) => {
return params.trim().match(/^spoiler\s+(.*)$/) !== null
},
render: (tokens: any[], idx: number) => {
const m = tokens[idx].info.trim().match(/^spoiler\s+(.*)$/)
if (tokens[idx].nesting === 1) {
return '' + md.utils.escapeHtml(m[1]) + '\n'
} else {
return '\n'
}
}
})
md.use(markdownItPlantuml)
return md
}
```
```typescript
import markdownIt, { MarkdownIt } from 'markdown-it'
import myCustomPlugin from './my-custom-plugin'
export default const markdownItSettingsOverride = async (md: MarkdownIt) => {
// Create a new instance with different settings
const newMd = markdownIt({
html: false, // Disable HTML tags in source
breaks: true, // Convert \n to
linkify: false, // Disable auto-linking
})
// Add only the plugins you want
newMd.use(myCustomPlugin)
return newMd
}
markdownItSettingsOverride
```
--------------------------------
### HTML Page Structure
Source: https://domstack.net/index
Defines the file system structure for HTML pages in DOMStack. HTML pages must be named `page.html` within their respective page directories.
```html
src/page-name/page.html
```
--------------------------------
### Importing Nested Layout Styles
Source: https://domstack.net/index
Demonstrates how to import CSS styles from a parent layout into a child layout to ensure all styles are included in the final build.
```css
@import "./root.layout.css";
```
--------------------------------
### Layout-Specific Client-Side Scripting
Source: https://domstack.net/index
Demonstrates how to include client-side JavaScript or TypeScript logic for a layout by creating a `.layout.client.ts` or `.layout.client.js` file. These bundles are processed by esbuild and executed on every page that utilizes the associated layout.
```typescript
/* /layouts/article.layout.client.ts */
console.log('I run on every page rendered with the \'article\' layout')
/* This layout client is included in every page rendered with the 'article' layout */
```
--------------------------------
### Importing Nested Layout Client Scripts
Source: https://domstack.net/index
Shows how to import client-side JavaScript from a parent layout into a child layout to ensure all client logic is bundled together.
```typescript
import './root.layout.client.ts'
```
--------------------------------
### Layout-Specific CSS Styling
Source: https://domstack.net/index
Illustrates how to associate CSS styles with a specific layout file by creating a companion `.layout.css` file. These styles are bundled by esbuild and automatically applied to all pages rendered using that particular layout.
```css
/* /layouts/article.layout.css */
.layout-specific-class {
color: blue;
& .button {
color: purple;
}
}
/* This layout style is included in every page rendered with the 'article' layout */
```
--------------------------------
### Basic TypeScript Page Structure
Source: https://domstack.net/index
Demonstrates the fundamental structure of a TypeScript page in Domstack. It shows how to export variables and a default async function that returns HTML content, accepting page variables.
```typescript
import type { PageFunction } from '@domstack/static'
export const vars = {
favoriteCookie: 'Chocolate Chip with Sea Salt'
}
export default const page: PageFunction = async ({ vars }) => {
return /* html */`
This is just some html.
My favorite cookie: ${vars.favoriteCookie}
`
}
```
--------------------------------
### DOMStack Copy Directories Flag
Source: https://domstack.net/index
Explains the --copy flag, which allows specifying directories outside the 'dest' folder to be copied verbatim into the destination. This is useful for including legacy or unprocessed static content.
```bash
domstack --copy ./oldsite
```
--------------------------------
### Page Variable Files
Source: https://domstack.net/index
Demonstrates creating page-specific variables using `page.vars.ts` or `page.vars.js`. It shows exporting variables as an object or as a synchronous or asynchronous function, detailing their precedence in the Domstack variable hierarchy.
```javascript
// export an object
export default {
my: 'vars'
}
// OR export a default function
export default () => {
return { my: 'vars' }
}
// OR export a default async function
export default async () => {
return { my: 'vars' }
}
```
--------------------------------
### Web Worker File Structure
Source: https://domstack.net/index
Web workers for a page are created by adding a `${name}.worker.ts` or `${name}.worker.js` file to the same directory as the page. DOMStack bundles these workers, and their entry points are managed via a `workers.json` file.
```text
page-directory/
├── page.js
├── client.js
├── counter.worker.js # Worker with counter functionality
└── data.worker.js # Worker for data processing
```
--------------------------------
### RSS and JSON Feed Generation (TypeScript)
Source: https://domstack.net/index
An AsyncIterator template demonstrating how to generate RSS and JSON feeds from website pages. It filters pages by layout, sorts them by publish date, and uses external libraries for conversion.
```typescript
import pMap from 'p-map'
import jsonfeedToAtom from 'jsonfeed-to-atom'
import type { TemplateAsyncIterator } from '@domstack/static'
interface TemplateVars {
title: string;
layout: string;
siteName: string;
homePageUrl: string;
authorName: string;
authorUrl: string;
authorImgUrl?: string;
siteDescription: string;
language: string;
}
export default const feedsTemplate: TemplateAsyncIterator = async function * ({
vars: {
siteName,
siteDescription,
homePageUrl,
language = 'en-us',
authorName,
authorUrl,
authorImgUrl,
},
pages
}) {
const blogPosts = pages
.filter(page => page.pageInfo.path.startsWith('blog/') && page.vars['layout'] === 'blog')
.sort((a, b) => new Date(b.vars.publishDate) - new Date(a.vars.publishDate))
.slice(0, 10)
const jsonFeed = {
version: 'https://jsonfeed.org/version/1',
title: siteName,
home_page_url: homePageUrl,
feed_url: `${homePageUrl}/feed.json`,
description: siteDescription,
author: {
name: authorName,
url: authorUrl,
avatar: authorImgUrl
},
items: await pMap(blogPosts, async (page) => {
return {
date_published: page.vars['publishDate'],
title: page.vars['title'],
url: `${homePageUrl}/${page.pageInfo.path}/`,
id: `${homePageUrl}/${page.pageInfo.path}/#${page.vars['publishDate']}`,
content_html: await page.renderInnerPage({ pages })
}
}, { concurrency: 4 })
}
yield {
content: JSON.stringify(jsonFeed, null, ' '),
outputName: './feeds/feed.json'
}
yield {
content: jsonfeedToAtom(jsonFeed),
outputName: './feeds/feed.xml'
}
}
```
--------------------------------
### Customize esbuild Settings
Source: https://domstack.net/index
Allows modification of esbuild build settings by exporting a default async function. This function receives the esbuild settings object and returns a modified version. Use with caution as it can break the build.
```typescript
import { polyfillNode } from 'esbuild-plugin-polyfill-node'
import type { BuildOptions } from '@domstack/static'
export default const esbuildSettingsOverride = async (esbuildSettings: BuildOptions): Promise => {
esbuildSettings.plugins = [polyfillNode()]
return esbuildSettings
}
```
--------------------------------
### DOMStack Eject Command
Source: https://domstack.net/index
Details the effects of the --eject flag, which extracts DOMStack's default layout, global CSS, and client-side JavaScript into the user's source directory for customization. It also lists the dependencies added to package.json.
```bash
domstack --eject
```
```json
Dependencies added:
* mine.css
* preact
* htm
* preact-render-to-string
* highlight.js
```
--------------------------------
### Markdown Page Structure
Source: https://domstack.net/index
Describes the file system structure for Markdown pages within DOMStack. Markdown files can be named README.md for index pages or any other name for specific pages.
```markdown
src/page-name/README.md
# or
src/page-name/loose-md.md
```
--------------------------------
### Default Root Layout Implementation with Preact and HTM
Source: https://domstack.net/index
This TypeScript code defines the default root layout for a Domstack project. It uses Preact and HTM to construct the main HTML structure, including head and body elements, and dynamically injects scripts and styles. The layout function receives various data objects to customize the page rendering.
```typescript
import { html } from 'htm/preact'
import { render } from 'preact-render-to-string'
import type { LayoutFunction } from '@domstack/static'
type RootLayoutVars = {
title: string,
siteName: string,
defaultStyle: boolean,
basePath?: string
}
export default const defaultRootLayout: LayoutFunction = ({
vars: {
title,
siteName = 'Domstack',
basePath,
/* defaultStyle = true Set this to false in global or page vars to disable the default style in the default layout */
},
scripts,
styles,
children,
pages,
page,
}) => {
return /* html */`
${render(html`
${title ? `${title}` : ''}${title && siteName ? ' | ' : ''}${siteName}
${scripts
? scripts.map(script => html``)
: null}
${styles
? styles.map(style => html``)
: null}
`)}
${render(html`
${typeof children === 'string'
? html``
: html`${children}`
}
`)}
`
}
```
--------------------------------
### Layout File Naming Convention
Source: https://domstack.net/index
Layouts are defined as outer page templates using the naming convention `${layout-name}.layout.js`. These files can reside anywhere within the `src` directory, and each layout name must be unique to avoid build errors.
```text
src/layouts/root.layout.js
src/other-layouts/article.layout.js
```
--------------------------------
### Global Client Script Injection
Source: https://domstack.net/index
Injects a script bundle that runs on every page. Useful for analytics or small global scripts. Minimize content to avoid performance impact.
```typescript
console.log('I run on every page in the site!')
```
--------------------------------
### TypeScript/JavaScript Page Structure
Source: https://domstack.net/index
Illustrates the file system structure for TypeScript or JavaScript pages in DOMStack. These files export a default function that resolves to an HTML fragment.
```typescript
src/page-name/page.ts
```
--------------------------------
### domstack Core Types Import
Source: https://domstack.net/index
Imports essential types from the '@domstack/static' package, enabling strong typing for layout, page, and template functions within a domstack project. These types are generic and can be adapted to custom template variables.
```typescript
import type {
LayoutFunction,
PostVarsFunction,
PageFunction,
TemplateFunction,
TemplateAsyncIterator
} from '@domstack/static'
```
--------------------------------
### Browser-Specific Global Variables (JavaScript)
Source: https://domstack.net/index
Exports browser-specific variables that are made available in all JavaScript bundles. These variables are passed to esbuild's `define` options and can be accessed globally in the browser environment.
```javascript
export const browser = {
'process.env.TRANSPORT': 'http',
'process.env.HOST': 'localhost'
}
```
--------------------------------
### Global Variables Definition (JavaScript)
Source: https://domstack.net/index
Defines global variables that are accessible to all pages and templates. The file should export a default object or function returning an object, with higher precedence given to page-specific variables.
```javascript
export default {
siteName: 'The name of my website',
authorName: 'Mr. Wallace'
}
```
--------------------------------
### AsyncIterator Template (TypeScript)
Source: https://domstack.net/index
An AsyncIterator template that yields objects with 'content' and 'outputName'. This pattern is suitable for generating content streams or sequences of files asynchronously, accessing global variables.
```typescript
import type { TemplateAsyncIterator } from '@domstack/static'
interface TemplateVars {
foo: string;
testVar: string;
}
export default const templateIterator: TemplateAsyncIterator = async function * ({
vars: {
foo,
testVar
}
}) {
// First item
yield {
content: `Hello world\n\nThis is just a file with access to global vars: ${foo}`,
outputName: 'yielded-1.txt'
}
// Second item
yield {
content: `Hello world again\n\nThis is just a file with access to global vars: ${testVar}`,
outputName: 'yielded-2.txt'
}
}
```
--------------------------------
### Object Array Template Function (TypeScript)
Source: https://domstack.net/index
A template function that returns an array of objects, each containing 'content' and 'outputName'. This allows generating multiple files from a single template, utilizing provided variables.
```typescript
import type { TemplateFunction } from '@domstack/static'
interface TemplateVars {
foo: string;
testVar: string;
}
export default const objectArrayTemplate: TemplateFunction = async ({
vars: {
foo,
testVar
}
}) => {
return [
{
content: `Hello world\n\nThis is just a file with access to global vars: ${foo}`,
outputName: 'object-array-1.txt'
},
{
content: `Hello world again\n\nThis is just a file with access to global vars: ${testVar}`,
outputName: 'object-array-2.txt'
}
]
}
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.