chore: add hydration starter to create
@@ -16,7 +16,7 @@ docs/_merged*
|
||||
|
||||
# sanity example has a separate backend that is unrelated to Rocket
|
||||
# therefore it does not need to follow it code rules
|
||||
/examples/sanity-minimal-starter/backend/
|
||||
/examples/04-sanity-minimal-starter/backend/
|
||||
|
||||
/packages/engine/test-node/fixtures/06-error-handling/01-page-error/docs/index.rocket.js
|
||||
/packages/engine/test-node/fixtures/03b-format-markdown/c01-md-in-js-to-md-html/md-in-js.js
|
||||
|
||||
44
examples/01-hydration-starter/README.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Rocket Starter Kit: Minimal
|
||||
|
||||
```
|
||||
npx @rocket/create@latest --template 01-hydration-starter
|
||||
```
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Rocket project, you'll see the following folders and files:
|
||||
|
||||
```
|
||||
.
|
||||
├── config
|
||||
│ └── rocket.config.js
|
||||
├── site
|
||||
│ ├── pages
|
||||
│ │ └── index.rocket.html
|
||||
│ └── public
|
||||
│ └── favicon.ico
|
||||
└── package.json
|
||||
```
|
||||
|
||||
Rocket looks for `.rocket.md` or `.rocket.js` or `.rocket.html` files in the `site/pages` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `site/src/components/`, but that's where we like to put our web components.
|
||||
|
||||
Any static assets, that is not referenced via HTML but you still want to be on the web server we can place in the `site/public/` directory.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :---------------- | :------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run start` | Starts local dev server at `localhost:8000` |
|
||||
| `npm run build` | Build your production site to `./_site/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Feel free to check [our documentation](https://rocket.modern-web.dev) or jump into our [Discord server](https://rocket.modern-web.dev/chat).
|
||||
23
examples/01-hydration-starter/package.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "rocket-hydration-starter",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"description": "Example on how to hydrate web components",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "rocket build",
|
||||
"dev": "npm start",
|
||||
"preview": "rocket preview",
|
||||
"start": "NODE_DEBUG=engine:rendering rocket start --open"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rocket/cli": "^0.20.0-alpha.17",
|
||||
"@rocket/engine": "^0.1.0-alpha.23",
|
||||
"@webcomponents/template-shadowroot": "^0.1.0",
|
||||
"lit": "^2.0.0"
|
||||
},
|
||||
"@rocket/template-name": "Hydration Starter",
|
||||
"imports": {
|
||||
"#components/*": "./site/src/components/*"
|
||||
}
|
||||
}
|
||||
33
examples/01-hydration-starter/site/pages/index.rocket.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/* START - Rocket auto generated - do not touch */
|
||||
export const sourceRelativeFilePath = 'index.rocket.js';
|
||||
import { html, components, layout } from './recursive.data.js';
|
||||
export { html, components, layout };
|
||||
export async function registerCustomElements() {
|
||||
// server-only components
|
||||
customElements.define(
|
||||
'hello-wave',
|
||||
await import('#components/HelloWave.js').then(m => m.HelloWave),
|
||||
);
|
||||
// hydrate-able components
|
||||
customElements.define(
|
||||
'hello-typer',
|
||||
await import('#components/HelloTyper.js').then(m => m.HelloTyper),
|
||||
);
|
||||
customElements.define(
|
||||
'my-counter',
|
||||
await import('#components/MyCounter.js').then(m => m.MyCounter),
|
||||
);
|
||||
}
|
||||
/* END - Rocket auto generated - do not touch */
|
||||
|
||||
export default () => html`
|
||||
<h1>Hello World</h1>
|
||||
<hello-wave></hello-wave>
|
||||
<hello-typer loading="hydrate:onVisible"></hello-typer>
|
||||
<details open>
|
||||
<!-- put an open attribute on the details element to check hydration as you scroll down -->
|
||||
<summary>👇</summary>
|
||||
<p style="height: 120vh;">Emptiness of space</p>
|
||||
</details>
|
||||
<my-counter loading="hydrate:onVisible"></my-counter>
|
||||
`;
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"h1": "Hello World",
|
||||
"name": "Hello World",
|
||||
"menuLinkText": "Hello World",
|
||||
"url": "/",
|
||||
"outputRelativeFilePath": "index.html",
|
||||
"sourceRelativeFilePath": "index.rocket.js",
|
||||
"level": 0
|
||||
}
|
||||
24
examples/01-hydration-starter/site/pages/recursive.data.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import { html } from 'lit';
|
||||
|
||||
export { html };
|
||||
|
||||
export const components = {
|
||||
'hello-wave': '#components/HelloWave.js::HelloWave',
|
||||
'hello-typer': '#components/HelloTyper.js::HelloTyper',
|
||||
'my-counter': '#components/MyCounter.js::MyCounter',
|
||||
// 👆 we are using a private import defined in the package json that maps
|
||||
// "#components/*": "./site/src/components/*"
|
||||
// (see https://nodejs.org/api/packages.html#packages_imports)
|
||||
};
|
||||
|
||||
export const layout = data => html`
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
${data.content()}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,54 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
|
||||
let i = 0;
|
||||
const fullText = [...'to this wonderful world of progressive hydration 🤯'];
|
||||
|
||||
export class HelloTyper extends LitElement {
|
||||
static properties = {
|
||||
msg: { type: String },
|
||||
counter: { type: Number },
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.msg = ' ';
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
updated(changedProperties) {
|
||||
super.updated(changedProperties);
|
||||
if (i < fullText.length) {
|
||||
setTimeout(() => {
|
||||
this.msg += fullText[i];
|
||||
i += 1;
|
||||
}, Math.floor(Math.random() * 50) + 40);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<p>🤔 Hello <span>${this.msg}</span>${'🤯'.repeat(this.counter)}</p>
|
||||
<button @click=${this._inc}>+</button>
|
||||
`;
|
||||
}
|
||||
|
||||
_inc() {
|
||||
if (i >= fullText.length) {
|
||||
this.counter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static styles = [
|
||||
css`
|
||||
button {
|
||||
font-size: 200%;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
background-color: seagreen;
|
||||
color: white;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
|
||||
export class HelloWave extends LitElement {
|
||||
render() {
|
||||
return html`<h2>Hello 👋</h2>`;
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
h2 {
|
||||
color: #e03131;
|
||||
}
|
||||
`;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { LitElement, css, html } from 'lit';
|
||||
|
||||
export class MyCounter extends LitElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<button @click=${() => (this.counter -= 1)}>-</button>
|
||||
<span>${this.counter}</span>
|
||||
<button @click=${() => (this.counter += 1)}>+</button>
|
||||
`;
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
* {
|
||||
font-size: 200%;
|
||||
}
|
||||
|
||||
span {
|
||||
width: 4rem;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
background-color: seagreen;
|
||||
color: white;
|
||||
}
|
||||
`;
|
||||
|
||||
static properties = {
|
||||
counter: { type: Number },
|
||||
};
|
||||
}
|
||||
@@ -2,6 +2,6 @@
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"checkJs": false,
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
# Rocket Starter Kit: Blog
|
||||
|
||||
```
|
||||
npx @rocket/create@latest --template blog
|
||||
npx @rocket/create@latest --template 02-blog-starter
|
||||
```
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@example/blog",
|
||||
"name": "rocket-blog-starter",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"description": "Get started with a new blog",
|
||||
@@ -16,9 +16,9 @@
|
||||
"start": "NODE_DEBUG=engine:rendering rocket start --open"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rocket/cli": "^0.20.0-alpha.11",
|
||||
"@rocket/engine": "^0.1.0-alpha.11",
|
||||
"@rocket/cli": "^0.20.0-alpha.17",
|
||||
"@rocket/engine": "^0.1.0-alpha.23",
|
||||
"lit": "^2.0.0"
|
||||
},
|
||||
"@rocket/template-name": "Blog"
|
||||
"@rocket/template-name": "Blog Starter"
|
||||
}
|
||||
@@ -6,9 +6,9 @@ export { html, layout, components };
|
||||
export async function registerCustomElements() {
|
||||
// server-only components
|
||||
// prettier-ignore
|
||||
customElements.define('blog-header', await import('@example/blog/components/BlogHeader').then(m => m.BlogHeader));
|
||||
customElements.define('blog-header', await import('rocket-blog-starter/components/BlogHeader').then(m => m.BlogHeader));
|
||||
// prettier-ignore
|
||||
customElements.define('site-footer', await import('@example/blog/components/SiteFooter').then(m => m.SiteFooter));
|
||||
customElements.define('site-footer', await import('rocket-blog-starter/components/SiteFooter').then(m => m.SiteFooter));
|
||||
}
|
||||
/* END - Rocket auto generated - do not touch */
|
||||
```
|
||||
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 1.8 MiB |
@@ -7,13 +7,13 @@ export { html, layout, components };
|
||||
export async function registerCustomElements() {
|
||||
// server-only components
|
||||
// prettier-ignore
|
||||
customElements.define('blog-header', await import('@example/blog/components/BlogHeader').then(m => m.BlogHeader));
|
||||
customElements.define('blog-header', await import('rocket-blog-starter/components/BlogHeader').then(m => m.BlogHeader));
|
||||
// prettier-ignore
|
||||
customElements.define('blog-author', await import('@example/blog/components/BlogAuthor').then(m => m.BlogAuthor));
|
||||
customElements.define('blog-author', await import('rocket-blog-starter/components/BlogAuthor').then(m => m.BlogAuthor));
|
||||
// prettier-ignore
|
||||
customElements.define('blog-post', await import('@example/blog/components/BlogPost').then(m => m.BlogPost));
|
||||
customElements.define('blog-post', await import('rocket-blog-starter/components/BlogPost').then(m => m.BlogPost));
|
||||
// prettier-ignore
|
||||
customElements.define('site-footer', await import('@example/blog/components/SiteFooter').then(m => m.SiteFooter));
|
||||
customElements.define('site-footer', await import('rocket-blog-starter/components/SiteFooter').then(m => m.SiteFooter));
|
||||
}
|
||||
/* END - Rocket auto generated - do not touch */
|
||||
|
||||
@@ -7,13 +7,13 @@ export { html, layout, components };
|
||||
export async function registerCustomElements() {
|
||||
// server-only components
|
||||
// prettier-ignore
|
||||
customElements.define('blog-header', await import('@example/blog/components/BlogHeader').then(m => m.BlogHeader));
|
||||
customElements.define('blog-header', await import('rocket-blog-starter/components/BlogHeader').then(m => m.BlogHeader));
|
||||
// prettier-ignore
|
||||
customElements.define('blog-author', await import('@example/blog/components/BlogAuthor').then(m => m.BlogAuthor));
|
||||
customElements.define('blog-author', await import('rocket-blog-starter/components/BlogAuthor').then(m => m.BlogAuthor));
|
||||
// prettier-ignore
|
||||
customElements.define('blog-post', await import('@example/blog/components/BlogPost').then(m => m.BlogPost));
|
||||
customElements.define('blog-post', await import('rocket-blog-starter/components/BlogPost').then(m => m.BlogPost));
|
||||
// prettier-ignore
|
||||
customElements.define('site-footer', await import('@example/blog/components/SiteFooter').then(m => m.SiteFooter));
|
||||
customElements.define('site-footer', await import('rocket-blog-starter/components/SiteFooter').then(m => m.SiteFooter));
|
||||
}
|
||||
/* END - Rocket auto generated - do not touch */
|
||||
|
||||
@@ -5,11 +5,11 @@ export { html, components };
|
||||
export async function registerCustomElements() {
|
||||
// server-only components
|
||||
// prettier-ignore
|
||||
customElements.define('blog-header', await import('@example/blog/components/BlogHeader').then(m => m.BlogHeader));
|
||||
customElements.define('blog-header', await import('rocket-blog-starter/components/BlogHeader').then(m => m.BlogHeader));
|
||||
// prettier-ignore
|
||||
customElements.define('blog-post-preview', await import('@example/blog/components/BlogPostPreview').then(m => m.BlogPostPreview));
|
||||
customElements.define('blog-post-preview', await import('rocket-blog-starter/components/BlogPostPreview').then(m => m.BlogPostPreview));
|
||||
// prettier-ignore
|
||||
customElements.define('site-footer', await import('@example/blog/components/SiteFooter').then(m => m.SiteFooter));
|
||||
customElements.define('site-footer', await import('rocket-blog-starter/components/SiteFooter').then(m => m.SiteFooter));
|
||||
}
|
||||
/* END - Rocket auto generated - do not touch */
|
||||
|
||||
15
examples/02-blog-starter/site/pages/recursive.data.js
Normal file
@@ -0,0 +1,15 @@
|
||||
// everything you export here will be automatically injected into all pages
|
||||
|
||||
import { LayoutPage } from '../src/layouts/LayoutPage.js';
|
||||
|
||||
export { html } from 'lit';
|
||||
|
||||
export const layout = new LayoutPage();
|
||||
|
||||
export const components = {
|
||||
'blog-author': 'rocket-blog-starter/components/BlogAuthor::BlogAuthor',
|
||||
'blog-header': 'rocket-blog-starter/components/BlogHeader::BlogHeader',
|
||||
'blog-post': 'rocket-blog-starter/components/BlogPost::BlogPost',
|
||||
'blog-post-preview': 'rocket-blog-starter/components/BlogPostPreview::BlogPostPreview',
|
||||
'site-footer': 'rocket-blog-starter/components/SiteFooter::SiteFooter',
|
||||
};
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -34,6 +34,6 @@ export function baseHead({ title, description, permalink }) {
|
||||
rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&family=IBM+Plex+Sans:wght@400;700&display=swap"
|
||||
/>
|
||||
<link rel="stylesheet" href="resolve:@example/blog/styles/blog.css" />
|
||||
<link rel="stylesheet" href="resolve:rocket-blog-starter/styles/blog.css" />
|
||||
`;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"checkJs": false,
|
||||
"module": "esnext"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
# Rocket Starter Kit: Minimal
|
||||
|
||||
```
|
||||
npx @rocket/create@latest --template minimal
|
||||
npx @rocket/create@latest --template 03-minimal-starter
|
||||
```
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@example/minimal",
|
||||
"name": "rocket-minimal-starter",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"description": "Only includes the minimal basics",
|
||||
@@ -11,9 +11,9 @@
|
||||
"start": "NODE_DEBUG=engine:rendering rocket start --open"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rocket/cli": "^0.20.0-alpha.11",
|
||||
"@rocket/engine": "^0.1.0-alpha.11",
|
||||
"@rocket/cli": "^0.20.0-alpha.17",
|
||||
"@rocket/engine": "^0.1.0-alpha.23",
|
||||
"lit": "^2.0.0"
|
||||
},
|
||||
"@rocket/template-name": "Minimal"
|
||||
"@rocket/template-name": "Minimal Starter"
|
||||
}
|
||||
11
examples/03-minimal-starter/site/pages/about.rocket.js
Normal file
@@ -0,0 +1,11 @@
|
||||
/* START - Rocket auto generated - do not touch */
|
||||
export const sourceRelativeFilePath = 'about.rocket.js';
|
||||
import { html, layout } from './recursive.data.js';
|
||||
export { html, layout };
|
||||
/* END - Rocket auto generated - do not touch */
|
||||
|
||||
export default () => html`
|
||||
<h1>About</h1>
|
||||
|
||||
<a href="./index.rocket.html">to Home</a>
|
||||
`;
|
||||
11
examples/03-minimal-starter/site/pages/index.rocket.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<script type="module" server>
|
||||
/* START - Rocket auto generated - do not touch */
|
||||
export const sourceRelativeFilePath = 'index.rocket.html';
|
||||
import { html, layout } from './recursive.data.js';
|
||||
export { html, layout };
|
||||
/* END - Rocket auto generated - do not touch */
|
||||
</script>
|
||||
|
||||
<h1>Rocket</h1>
|
||||
|
||||
<a href="./about.rocket.js">to about</a>
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"title": "Rocket",
|
||||
"h1": "Rocket",
|
||||
"name": "Rocket",
|
||||
"menuLinkText": "Rocket",
|
||||
"url": "/",
|
||||
"outputRelativeFilePath": "index.html",
|
||||
"sourceRelativeFilePath": "index.rocket.html",
|
||||
"level": 0,
|
||||
"children": [
|
||||
{
|
||||
"title": "Rocket",
|
||||
"h1": "About",
|
||||
"name": "About",
|
||||
"menuLinkText": "About",
|
||||
"url": "/about/",
|
||||
"outputRelativeFilePath": "about/index.html",
|
||||
"sourceRelativeFilePath": "about.rocket.js",
|
||||
"level": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
17
examples/03-minimal-starter/site/pages/recursive.data.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { html } from 'lit';
|
||||
|
||||
export { html };
|
||||
|
||||
export const layout = data => html`
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>Rocket</title>
|
||||
</head>
|
||||
<body>
|
||||
${data.content()}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
7
examples/03-minimal-starter/tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"allowJs": true,
|
||||
"checkJs": false,
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
# Rocket Starter Kit: Sanity Minimal Starter
|
||||
|
||||
```
|
||||
npx @rocket/create@latest --template sanity-minimal-starter
|
||||
npx @rocket/create@latest --template 04-sanity-minimal-starter
|
||||
```
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,3 @@
|
||||
export default /** @type {import('@rocket/cli').RocketCliOptions} */ ({
|
||||
absoluteBaseUrl: 'http://localhost:8080',
|
||||
});
|
||||