Skip to content

Commit 3bfb275

Browse files
committed
Add app-mastro
1 parent feb5bf5 commit 3bfb275

12 files changed

Lines changed: 218 additions & 0 deletions

File tree

.github/frameworks.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@
145145
{ "type": "build", "runFrequency": 5 },
146146
{ "type": "dependencies" }
147147
]
148+
},
149+
"app": {
150+
"package": "app-mastro",
151+
"buildScript": "generate",
152+
"buildOutputDir": "generated",
153+
"measurements": [{ "type": "ssr" }]
148154
}
149155
},
150156
{
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"recommendations": ["ms-fast.fast-tagged-templates"]
3+
}

packages/app-mastro/README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Mastro Template Basic for Node.js
2+
3+
This is a basic TypeScript template for [Mastro](https://mastrojs.github.io) when using [Node.js](https://nodejs.org).
4+
5+
Click the green **Use this template** button in the top right to create your own copy of this repository. Then clone the **Code** to your computer.
6+
7+
## Run locally
8+
9+
If you have multiple projects on your computer that require different Node.js versions, you should install a tool to manage those version for you; for example [Volta](https://volta.sh/) (see [pnpm Support](https://docs.volta.sh/advanced/pnpm)).
10+
11+
Mastro requires Node.js >=24 (unless you want to install a [`URLPattern` polyfill](https://www.npmjs.com/package/urlpattern-polyfill)).
12+
13+
[JSR recommends](https://jsr.io/docs/npm-compatibility#installing-and-using-jsr-packages) to use `pnpm`.
14+
15+
The first time, you need to:
16+
17+
pnpm install
18+
19+
After that, to start the server:
20+
21+
pnpm run start
22+
23+
and open <http://localhost:8000> in your browser.
24+
25+
To generate the whole static site (this will create a `generated` folder):
26+
27+
pnpm run generate
28+
29+
## Next steps
30+
31+
To see how Mastro works, [follow the guide](https://mastrojs.github.io/guide/server-side-components-and-routing/).
32+
33+
To make sure you're using the latest Mastro packages:
34+
35+
pnpm update "@mastrojs/*" --latest
36+
37+
## Deploy to production
38+
39+
- [Deploy static site](https://mastrojs.github.io/guide/deploy/#deploy-static-site-with-ci%2Fcd)
40+
- [Deploy server](https://mastrojs.github.io/guide/deploy/#deploy-server-to-production)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { type Html, html } from '@mastrojs/mastro'
2+
3+
interface Props {
4+
children: Html
5+
title: string
6+
}
7+
8+
export const Layout = (props: Props) => html`
9+
<!DOCTYPE html>
10+
<html lang="en">
11+
<head>
12+
<meta charset="UTF-8" />
13+
<title>${props.title}</title>
14+
<link rel="stylesheet" href="/styles.css" />
15+
</head>
16+
<body>
17+
<h1>${props.title}</h1>
18+
${props.children}
19+
</body>
20+
</html>
21+
`
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { testData } from '../../testdata/src/ssr.ts'
2+
import { html, htmlToResponse } from '@mastrojs/mastro'
3+
import { Layout } from '../components/Layout.ts'
4+
5+
const entries = await testData()
6+
7+
export const GET = () =>
8+
htmlToResponse(
9+
Layout({
10+
title: 'Test',
11+
children: html`
12+
<table>
13+
<tbody>
14+
${entries.map(
15+
(entry) => html`
16+
<tr>
17+
<td>${entry.id}</td>
18+
<td>${entry.name}</td>
19+
</tr>
20+
`,
21+
)}
22+
</tbody>
23+
</table>
24+
`,
25+
}),
26+
)

packages/app-mastro/package.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "app-mastro",
3+
"private": true,
4+
"type": "module",
5+
"scripts": {
6+
"dev": "node --watch server.ts",
7+
"generate": "node node_modules/@mastrojs/mastro/src/generator.js",
8+
"type-check": "tsc"
9+
},
10+
"dependencies": {
11+
"@framework-tracker/testdata": "workspace:*",
12+
"@mastrojs/mastro": "jsr:^0",
13+
"@remix-run/node-fetch-server": "^0.11"
14+
},
15+
"devDependencies": {
16+
"@types/node": "^24",
17+
"typescript": "^5"
18+
},
19+
"engines": {
20+
"node": ">=24.12"
21+
}
22+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
html {
2+
font-family: sans-serif;
3+
}
4+
5+
h1,
6+
h2,
7+
h3,
8+
h4,
9+
h5,
10+
h6 {
11+
word-break: break-word;
12+
text-wrap-style: pretty;
13+
}
14+
15+
p {
16+
hyphens: auto;
17+
word-break: break-word;
18+
}
19+
20+
img {
21+
max-width: 100%;
22+
}
23+
24+
@view-transition {
25+
navigation: auto;
26+
}

packages/app-mastro/server.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as http from 'node:http'
2+
import { createRequestListener } from '@remix-run/node-fetch-server'
3+
import { Mastro } from '@mastrojs/mastro/server'
4+
import { GET as getHome } from './handlers/home.ts'
5+
6+
const app = new Mastro<unknown, void>().get('/', getHome)
7+
8+
export const handler = createRequestListener(app.createHandler())
9+
10+
const port = 8000
11+
12+
if (import.meta.main) {
13+
const server = http.createServer(handler)
14+
15+
server.on('error', (e) => {
16+
console.error(e)
17+
})
18+
19+
server.listen(port, () => {
20+
console.log(`Server running at http://localhost:${port}`)
21+
})
22+
}

packages/app-mastro/tsconfig.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"compilerOptions": {
3+
"allowImportingTsExtensions": true,
4+
"module": "NodeNext",
5+
"moduleResolution": "nodenext",
6+
"noEmit": true,
7+
"skipLibCheck": true,
8+
"strict": true,
9+
"verbatimModuleSyntax": true,
10+
11+
"noFallthroughCasesInSwitch": true,
12+
"noUncheckedIndexedAccess": true,
13+
"noImplicitOverride": true
14+
}
15+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { join } from 'node:path'
2+
import { pathToFileURL } from 'node:url'
3+
import { packagesDir } from '../../constants.ts'
4+
import type { SSRHandler } from '../types.ts'
5+
6+
export async function buildMastroHandler(): Promise<SSRHandler> {
7+
const entryPath = join(packagesDir, 'app-mastro', 'server.ts')
8+
const entryUrl = pathToFileURL(entryPath).href
9+
const { handler } = await import(entryUrl)
10+
return handler as SSRHandler
11+
}

0 commit comments

Comments
 (0)