silly personal website
1

Configure Feed

Select the types of activity you want to include in your feed.

feat: slot-based layout

july (Mar 1, 2026, 10:20 AM -0300) 641b7097 c0cc937d

+40 -1
+1 -1
deno.json
··· 24 24 ] 25 25 }, 26 26 "compilerOptions": { 27 - "jsx": "precompile", 27 + "jsx": "react-jsx", 28 28 "jsxImportSource": "@july/snarl", 29 29 "lib": ["deno.ns", "dom", "dom.iterable"] 30 30 },
+39
src/layout.tsx
··· 1 + import { Context } from "@july/snarl"; 2 + import { JsxElement } from "@july/snarl/jsx-runtime"; 3 + 4 + export interface LayoutProps { 5 + children?: JsxElement | JsxElement[]; 6 + } 7 + 8 + function flatten(arr: any[]): any[] { 9 + return arr.flatMap((x) => Array.isArray(x) ? flatten(x) : x); 10 + } 11 + 12 + export function Layout(props: LayoutProps = {}) { 13 + const children = flatten(props.children ? (Array.isArray(props.children) ? props.children : [props.children]) : []); 14 + const head: JsxElement[] = [], body: JsxElement[] = [], main: JsxElement[] = []; 15 + 16 + for (const child of children) { 17 + if (child?.tag === "head") { 18 + head.push(...child.props?.children ?? []); 19 + } else if (child?.tag === "body") { 20 + body.push(...child.props?.children ?? []); 21 + } else { 22 + main.push(child); 23 + } 24 + } 25 + 26 + return ( 27 + <html lang="en"> 28 + <head> 29 + <meta charset="utf-8" /> 30 + <meta name="viewport" content="width=device-width, initial-scale=1" /> 31 + {head.map((node) => <>{node}</>)} 32 + </head> 33 + <body> 34 + {main.map((node, i) => <>{node}</>)} 35 + {body.map((node, i) => <>{node}</>)} 36 + </body> 37 + </html> 38 + ); 39 + }