{
"path": "/3melth74t6s2o",
"site": "https://leaflet.pub/p/did:plc:g5hiaok54wc2rpigewi75kdu",
"tags": [],
"$type": "site.standard.document",
"title": "Hello Leaflet!",
"content": {
"$type": "pub.leaflet.content",
"pages": [
{
"id": "019c4d37-ad1c-7aa1-8b47-d92f88681d37",
"$type": "pub.leaflet.pages.linearDocument",
"blocks": [
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 91,
"byteStart": 86
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#bold"
}
]
},
{
"index": {
"byteEnd": 99,
"byteStart": 92
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#italic"
}
]
},
{
"index": {
"byteEnd": 107,
"byteStart": 100
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#strikethrough"
}
]
}
],
"plaintext": "This is my first leaflet doc. Nothing special, but I'm poking around. Nice to see the usual styling options."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 22,
"byteStart": 17
},
"features": [
{
"uri": "https://www.youtube.com/watch?v=XfELJU1mRMg",
"$type": "pub.leaflet.richtext.facet#link"
}
]
}
],
"plaintext": "I can also embed links and images:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.image",
"image": {
"$type": "blob",
"ref": {
"$link": "bafkreieukavimj53fzccu3bgbcqhwgkmsiaspbq63a7nmdyx4f55vez5aq"
},
"mimeType": "image/jpeg",
"size": 21174
},
"aspectRatio": {
"width": 719,
"height": 367
}
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "How about a helpful horizontal line to denote the next section?"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.horizontalRule"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "I can embed Bluesky posts! How about an art post?"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.bskyPost",
"postRef": {
"cid": "bafyreids2pgjja3yqrvrkr6abziomkiuoki4jjgu53gbzowm4tyhkhf4hm",
"uri": "at://did:plc:jjsc5rflv3cpv6hgtqhn2dcm/app.bsky.feed.post/3melppga3ik2y"
}
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 79,
"byteStart": 71
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
}
],
"plaintext": "Ooh, I can put code in here! Here's a piece of my UI engine, a generic Renderer that configures the provided render pass to execute the render."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "rust",
"plaintext": "pub struct Renderer {\n pipeline: wgpu::RenderPipeline,\n vertices: wgpu::Buffer,\n instances: wgpu::Buffer,\n number: u32,\n bindgroups: HashMap<u32, BindGroup>,\n}\n\nimpl Renderer {\n pub fn render(&self, pass: &mut RenderPass) {\n pass.set_pipeline(&self.pipeline);\n pass.set_vertex_buffer(0, self.vertices.slice(..));\n pass.set_vertex_buffer(1, self.instances.slice(..));\n self.bindgroups.iter().for_each(|(&index, group)| {\n pass.set_bind_group(index, group, &[]);\n });\n pass.draw(0..4, 0..self.number);\n }\n}"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 37,
"byteStart": 25
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
}
],
"plaintext": "In conjunction with this IntoRenderer trait, I can fairly easily produce renderers for just about anything."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "rust",
"plaintext": "pub trait IntoRenderer<I: Vertex, U: Uniforms> {\n const SHADER: ShaderModuleDescriptor<'static>;\n\n fn vertices(&self) -> Vec<Pos> {\n BBox {\n center: (0., 0.),\n size: (1., 1.),\n }.into()\n }\n\n fn instances(&self) -> &[I];\n fn uniforms(&self) -> U;\n\n fn renderer(&self, device: &Device, format: &TextureFormat) -> Renderer {\n let module = &device.create_shader_module(Self::SHADER);\n let vertices = self.vertices();\n let instances = self.instances();\n let uniforms = self.uniforms();\n\n let layout = uniforms.pipeline_layout().map(|desc| device.create_pipeline_layout(&desc));\n \n Renderer {\n pipeline: device.create_render_pipeline(&RenderPipelineDescriptor {\n label: Some(\"Shape Render Pipeline\"),\n layout: layout.as_ref(), // Uniforms would be set here\n vertex: wgpu::VertexState {\n module,\n entry_point: Some(\"vs_main\"),\n compilation_options: wgpu::PipelineCompilationOptions::default(),\n buffers: &[Pos::LAYOUT, I::LAYOUT],\n },\n fragment: Some(wgpu::FragmentState {\n module,\n entry_point: Some(\"fs_border\"),\n compilation_options: wgpu::PipelineCompilationOptions::default(),\n targets: &[Some(wgpu::ColorTargetState { // 4.\n format: *format,\n blend: Some(wgpu::BlendState::ALPHA_BLENDING),\n write_mask: wgpu::ColorWrites::ALL,\n })],\n }),\n primitive: wgpu::PrimitiveState {\n topology: wgpu::PrimitiveTopology::TriangleStrip, // 1.\n strip_index_format: None,\n front_face: wgpu::FrontFace::Cw, // 2.\n cull_mode: Some(wgpu::Face::Back),\n // Setting this to anything other than Fill requires Features::NON_FILL_POLYGON_MODE\n polygon_mode: wgpu::PolygonMode::Fill,\n // Requires Features::DEPTH_CLIP_CONTROL\n unclipped_depth: false,\n // Requires Features::CONSERVATIVE_RASTERIZATION\n conservative: false,\n },\n depth_stencil: None,\n multisample: wgpu::MultisampleState {\n count: 1,\n mask: !0,\n alpha_to_coverage_enabled: false,\n },\n cache: None,\n multiview_mask: None,\n }),\n vertices: device.create_buffer_init(&BufferInitDescriptor {\n label: Some(\"circle vertices\"),\n contents: vertices.as_bytes(),\n usage: BufferUsages::VERTEX,\n }),\n instances: device.create_buffer_init(&BufferInitDescriptor {\n label: Some(\"circle instances\"),\n contents: instances.as_bytes(),\n usage: BufferUsages::VERTEX\n }),\n number: instances.len() as u32,\n bindgroups: uniforms.bindgroups(device),\n }\n }\n}"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "With that trait and its dependencies defined, that allows me to write a circle with a very manageable amount of code:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "rust",
"plaintext": "#[derive(Clone, IntoBytes, Immutable, VertexLayout)]\n#[layout(Instance)]\n#[location = 1]\npub struct Circle {\n pub center: [f32; 2],\n pub radius: f32,\n pub thickness: f32,\n pub color: [f32; 3],\n}\n\nimpl Vertex for Circle {}\n\nimpl IntoRenderer<Circle, ()> for &[Circle] {\n const SHADER: wgpu::ShaderModuleDescriptor<'static> = include_wgsl!(\"../shaders/circle.wgsl\");\n\n fn instances(&self) -> &[Circle] {\n self\n }\n\n /// Empty function with no return type implicitly returns `()`\n fn uniforms(&self) { }\n}"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "Anyhow, let's explore more features! We've got math, so here's Euler's formula:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"tex": "-1=e^{i\\pi}",
"$type": "pub.leaflet.blocks.math"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "We've also got website embeds, so here's 3Blue1Brown with an explainer of Euler's formula."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"url": "https://www.3blue1brown.com/?v=ldm-eulers-formula",
"$type": "pub.leaflet.blocks.iframe",
"height": 360
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "We've got polls! Let's do a poll on polls."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.poll",
"pollRef": {
"cid": "bafyreidy45v64h5is6riudu2uhgzdeqa2rvrs2erhxrbdeojnyhktxcbcm",
"uri": "at://did:plc:g5hiaok54wc2rpigewi75kdu/pub.leaflet.poll.definition/019c4d59-1a4d-722d-a004-4b41e3bab03a"
}
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "We can do buttons too. Click this one to go somewhere interesting."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"url": "https://semble.so",
"text": "Here's a Button",
"$type": "pub.leaflet.blocks.button"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "There's date times! At time of writing:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "Block quotes are nice."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.blockquote",
"facets": [],
"plaintext": "An especially rousing and inspiring quote."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "Last but not least, the most interesting of the features: The canvas."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"id": "019c4d5d-8f4d-722d-a00a-31d9c543aed2",
"$type": "pub.leaflet.blocks.page"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "That's most of the feature. Good enough for an introductory post, I reckon."
}
}
]
},
{
"id": "019c4d5d-8f4d-722d-a00a-31d9c543aed2",
"$type": "pub.leaflet.pages.canvas",
"blocks": [
{
"x": 102,
"y": 33,
"$type": "pub.leaflet.pages.canvas#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "So I can just organize the other things here however I want, huh"
},
"width": 360
},
{
"x": 484,
"y": 139,
"$type": "pub.leaflet.pages.canvas#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 1,
"facets": [],
"plaintext": "A Title There"
},
"width": 360,
"rotation": 8
},
{
"x": 345,
"y": 63,
"$type": "pub.leaflet.pages.canvas#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 1,
"facets": [],
"plaintext": "A Title Here"
},
"width": 360,
"rotation": -12
},
{
"x": 242,
"y": 179,
"$type": "pub.leaflet.pages.canvas#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 29,
"byteStart": 0
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#highlight"
}
]
}
],
"textSize": "large",
"plaintext": "I have no idea what I'm doing"
},
"width": 360
},
{
"x": 686,
"y": 70,
"$type": "pub.leaflet.pages.canvas#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "rust",
"plaintext": "fn main() {\n let event_loop = EventLoop::new().unwrap();\n event_loop.set_control_flow(ControlFlow::Wait);\n event_loop.run_app(&mut App::default()).unwrap();\n}"
},
"width": 589
},
{
"x": 704,
"y": 35,
"$type": "pub.leaflet.pages.canvas#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [],
"plaintext": "How about some more Rust?"
},
"width": 360
}
]
}
]
},
"bskyPostRef": {
"cid": "bafyreidfuwzf5vksb6su7dbrq4dxhmfdbh2fwh7stnh45p4lq3nc2wl7ja",
"uri": "at://did:plc:g5hiaok54wc2rpigewi75kdu/app.bsky.feed.post/3melthellxk2o",
"commit": {
"cid": "bafyreiarsu5hrefvsnfzmrao4lmmyfcmo6scliauq4cqlx63webhjcv2p4",
"rev": "3melthep7h22p"
},
"validationStatus": "valid"
},
"description": "Playing with the features.",
"publishedAt": "2026-02-11T15:51:59.432Z"
}