[HN Gopher] Show HN: Munal OS: a graphical experimental OS with ...
___________________________________________________________________
Show HN: Munal OS: a graphical experimental OS with WASM sandboxing
Hello HN! Showing off the first version of Munal OS, an
experimental operating system I have been writing in Rust on and
off for the past few years. https://github.com/Askannz/munal-os
It's an unikernel design that is compiled as a single EFI binary
and does not use virtual address spaces for process isolation.
Instead, applications are compiled to WASM and run inside of an
embedded WASM engine. Other features: * Fully graphical interface
in HD resolution with mouse and keyboard support * Desktop shell
with window manager and contextual radial menus * PCI and VirtIO
drivers * Ethernet and TCP stack * Customizable UI toolkit
providing various widgets, responsive layouts and flexible text
rendering * Embedded selection of applications including:
* A web browser supporting DNS, HTTPS and very basic HTML
* A text editor * A Python terminal Checkout the
README for the technical breakdown. Demo video:
https://streamable.com/5xqjcf
Author : Gazoche
Score : 145 points
Date : 2025-06-09 17:34 UTC (5 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| 9d wrote:
| This is _incredible_. I wonder if this will be the future of
| OSes.
|
| This readme is really, _really_ interesting to read through.
|
| Why did you use wasmi instead of wasmtime?
|
| I might actually try to use this OS inside a VM.
|
| Half of me wants to port my own reactive GUI lib to Munal.
| Gazoche wrote:
| Thanks! I tried to get wasmtime working but it was too much of
| a pain to compile in no_std mode, so I settled for wasmi
| instead.
| herobird wrote:
| Wasmi author here. Glad to see Wasmi being used in embedded
| contexts were it really shines. :)
|
| I just watched the demo video of Munal OS and am still in awe
| of all of its features. Really impressive work!
| 9d wrote:
| Yeah it's one of those projects were I'm so impressed that
| I'm saying nothing because there's nothing to say, it's
| just really impressive. I'm not sure what will come of this
| project, but it has a lot of potential to _at least_
| inspire other projects or spark important discussions
| around its innovations.
| Gazoche wrote:
| Thank you! And thanks for making Wasmi, it's a really
| impressive project and it's the reason why I decided to go
| this whole WASM sandbox route (because I could embed it
| easily) :)
| herobird wrote:
| Awww, makes me very happy to hear! :) Thank you!
| phickey wrote:
| Wasmtime maintainer here - curious to hear what went wrong, I
| and several other users of wasmtime have production
| embeddings under no_std, so it should do everything you need,
| including building out WASI preview 2 support. You can find
| me on the bytecode alliance zulip if you need help.
| lasiotus wrote:
| I'm not the OP, but I have a similar experience with Motor
| OS: wasmi compiles and works "out of the box", while
| wasmtime has a bunch of dependencies (e.g. target-lexicon)
| that won't compile on custom targets even if all features
| are turned off in wasmtime.
| 9d wrote:
| But if this benchmark is right, then wasmtime is 5x
| faster than wasmi for it:
|
| https://github.com/khvzak/script-bench-rs
| herobird wrote:
| Wasmtime, being an optimizing JIT, usually is ~10 times
| faster than Wasmi during execution.
|
| However, execution is just one metric that might be of
| importance.
|
| For example, Wasmi's lazy startup time is much better
| (~100-1000x) since it does not have to produce machine
| code. This can result in cases where Wasmi is done
| executing while Wasmtime is still generating machine
| code.
|
| Old post with some measurements: https://wasmi-
| labs.github.io/blog/posts/wasmi-v0.32/
|
| Always benchmark and choose the best tool for your usage
| pattern.
| 9d wrote:
| That's a good point I didn't think about.
|
| I guess it's like v8 compared to quickjs.
|
| Anyway all this talk about wasm makes me want to write a
| scriptable Rust app!
| phickey wrote:
| Not sure how to help with this much information but I've
| built and run wasmtime on some pretty squalid
| architectures (xtensa and riscv32 microcontrollers among
| others) but the right collection of features might not be
| obvious. We can help you find the right configuration on
| the Bytecode Alliance zulip or the wasmtime issue tracker
| if you need it.
| Gazoche wrote:
| I think I was a bit spooked by the examples (https://github
| .com/bytecodealliance/wasmtime/tree/main/examp...), and the
| need to implement platform dependencies in C code (which
| would have complicated the build process). Makes sense
| since it's a more complex and mature project, but Wasmi on
| the other hand was just a pure Rust dependency that only
| required a single line in the Cargo.toml. So in short I
| went the lazy route :)
| phickey wrote:
| All of the C primitives there implemented in (unsafe)
| Rust, but we built that example for an audience that
| already had some platform elements in C. We'll try to
| improve the example so that both integrating with C, and
| using pure Rust, are covered.
| dmitrygr wrote:
| > I wonder if this will be the future of OSes.
|
| SPECTRE and MELTDOWN enter the chat
| 9d wrote:
| What the DLL, Dmitry. Don't be a buzzkill.
| fsflover wrote:
| > I wonder if this will be the future of OSes.
|
| If you are talking about the app isolation through
| virtualization, then I've been living in this future for quite
| some time with Qubes OS. The isolation there is also extremely
| reliable.
| 9d wrote:
| Mostly I meant WASM as a platform (waap?) which seems so
| futuristic to me. I hope one day all OSes can natively run
| WASM code, though I'm not sold on WASI since then we're back
| to square one with security it seems.
| 9d wrote:
| > The downside of course is that each step of the loop is not
| allowed to hold the CPU for arbitrary amounts of time, and must
| explicitly yield for long-running tasks.
|
| Seems to me that a bigger downside is that the more apps you have
| open, the slower each one will become. I don't remember ever
| having more than like 10 open, but I've definitely had 30 tabs
| open, so if they're each separate procs then wouldn't that slow
| each one down by 30x? I guess if the whole computer is fast
| enough that's fine, but _intense_ processes like video renderers
| would slow down noticably, even if not fast, even if just going
| from 1sec to 30sec. But in any case this is a really, really
| clever shortcut for the general case to get _a whole operating
| system_ working, which is no small feat, and really exciting!
| jdiff wrote:
| As long as they all finish their jobs in time, they shouldn't
| run any slower at all. They run, they complete, they wait for
| the next frame. If resources are constrained enough to shrink
| that wait to 0 or below, then yes, everything slows down, and
| somewhat less gracefully than with a more fair and more complex
| scheduling system. But it sounds like each program yields
| explicitly when it's ready for the upcoming frame, so if a
| program doesn't have much to do, its "share" of the time is
| free real estate.
| bionhoward wrote:
| Great job! Congrats on shipping, this looks like a big project
| herobird wrote:
| > Every iteration of the loop polls the network and input
| drivers, draws the desktop interface, runs one step of each
| active WASM application, and flushes the GPU framebuffer.
|
| This is really interesting and I was wondering how you
| implemented that using Wasmi. Seems like the code for that is
| here:
|
| https://github.com/Askannz/munal-os/blob/2d3d361f67888cb2fe8...
|
| It might interest you that newer versions of Wasmi (v0.45+)
| extended the resumable function call feature to make it possible
| to yield upon running out of fuel:
| https://docs.rs/wasmi/latest/wasmi/struct.TypedFunc.html#met...
|
| Seeing that you are already using Wasmi's fuel metering this
| might be a more efficient or failure proof approach to execute
| Wasm apps in steps.
|
| An example for how to do this can be found in Wasmi's own Wast
| runner: https://github.com/wasmi-
| labs/wasmi/blob/019806547aae542d148...
| 9d wrote:
| Not OP, but I'm confused how this would be helpful. You're
| saying for example, he can use this function to create a
| coroutine out of a function, begin it, and if the function
| fails by e.g. running out of memory, you can give the module
| more memory and then resume the coroutine? If so, how is that
| different than what naturally happens? Does wasm not have
| try/catch? Also, wouldn't the module then need to back up
| manually and _retry_ the malloc after it failed? I 'm so lost.
| herobird wrote:
| Great question!
|
| Wasmi's fuel metering can be thought of as is there was an
| adjustable counter and for each instruction that Wasmi
| executes this counter is decreased by some amount. If it
| reached 0 the resumable call will yield back to the host (in
| this case the OS) where it can be decided how to, or if, the
| call shall be resumed.
|
| For efficiency reasons fuel metering in Wasmi is not
| implemented as described above but I wanted to provide a
| simple description.
|
| With this, one is no longer reliant on clocks or on other
| measures to provide each call its own time frame by providing
| an amount of fuel for each Wasm app that can be renewed (or
| not) when it runs out of fuel. So this is useful for building
| a Wasm scheduler.
| 9d wrote:
| > Great question!
|
| Thanks! I have lots more too. Are there directions in
| space? What kind of matter is fire made of? If you shine a
| laser into a box with one-way mirrors on the inside, will
| it reflect forever? Do ants feel like they're going in
| regular motion and we're just going in slow motion? Why do
| people mainly marry and make friends with people who look
| extraordinarily similar to themselves? How do futures work
| in Rust? Why is the C standard still behind a paywall? Let
| me know if you need any more great questions.
| lukan wrote:
| "If you shine a laser into a box with one-way mirrors on
| the inside, will it reflect forever?"
|
| No, because each reflection comes at a cost (some light
| transformed to heat)
|
| "Why do people mainly marry and make friends with people
| who look extraordinarily similar to themselves?"
|
| To not get so much surprises and have a more stable life.
| (I didn't choose that path.)
|
| (But I feel it would be too much OT answering the other
| questions and don't want to distract from this great
| submission or the interesting Wasmi concept)
| 9d wrote:
| No, I do not accept this. There must be a way. What if
| the mirror box has a high enough heat? Would it work
| then? The box could be made of a heat resistant material,
| like fiberglass.
| pimeys wrote:
| We used fuel metering with wasmtime, but that made
| everything quite slow, certain things veeery slow.
|
| How is the performance when using fuel with wasmi?
|
| We are considering to use epoch counter, but for now we
| just turned fuel off.
| 9d wrote:
| I had no idea what fuel is until this discussion.
|
| What's the rationale? Just preventing infinite loops from
| hanging the host?
|
| If the inefficiency is the counter, what if you just
| calculated an instruction offset - start < threshold
| every once in a while?
|
| This probably makes no sense, ignore it, I'm way in over
| my head.
|
| [1]
| https://github.com/bytecodealliance/wasmtime/issues/4109
|
| [2] https://github.com/bytecodealliance/wasmtime/blob/mai
| n/examp...
| herobird wrote:
| Yes, rational is to provide a pragmatic and efficient
| solution to infinite loops.
|
| There is a variety of ways to implement fuel metering
| with varying trade-offs, e.g. performance, determinism
| and precision.
|
| In this comment I roughly described how Wasmi implements
| its fuel metering:
| https://news.ycombinator.com/item?id=44229953
|
| Wasmi's design focuses on performance and determinism but
| isn't as precise since instructions are always considered
| as group.
| herobird wrote:
| I don't know how fuel metering in Wasmtime works and what
| its overhead is but keep in mind that Wasmi is an
| interpreter based Wasm runtime whereas Wasmtime generates
| machine code (JIT).
|
| In past experiments I remember that fuel metering adds
| roughly 5-10% overhead to Wasmi executions. The trick is
| to not bump or decrease a counter for every single
| executed instruction but instead to group instructions
| together in so-called basic blocks and bump a counter for
| the whole group of instructions.
|
| This is also the approach that is implemented by certain
| Wasm tools to add fuel metering to an existing Wasm
| binary.
| Gazoche wrote:
| Thanks again for making Wasmi :)
|
| > It might interest you that newer versions of Wasmi (v0.45+)
| extended the resumable function call feature to make it
| possible to yield upon running out of fuel:
|
| That is really interesting! I remember looking for something
| like that in the Wasmi docs at some point but it must have been
| before that feature was implemented. I would probably have
| chosen a different design for the WASM apps if I had it.
| herobird wrote:
| I am really sorry I have waited so long to extend Wasmi's
| resumable calls with this very useful feature. :S Feel free
| to message me if you ever plan to adjust your design to make
| use of it.
| baq wrote:
| Fun project. The grey beards will gladly read how is it
| qualitatively different from early Windows or maybe even AmigaOS
| Workbench? The dinosaurs will probably point to bytecode
| interpreters mixed with OSes like Lisp machines or smalltalk
| environments, could be an interesting comparison, too.
| Ericson2314 wrote:
| This is a very good bucking of conventional wisdom. Good job!
|
| Now that Redox aims to support WASI too, it would be interesting
| to see if the syscall interfaces of these two can grow together
| other time, even as the implementation strategy remains radically
| different.
| catapart wrote:
| This is so interesting!
| pacman1337 wrote:
| Very cool and impressive, you probably learned a lot. BUT! Why
| spend so much time and effort on something that has almost zero
| value to humanity. I honestly think many great programmers just
| don't know what to work on. They don't know their worth, their
| value, the impact and immense need there is for their expertise.
| They have so much power to improve and fight against the
| dystopian world that is being created by all these evil
| corporations, if they just realized what we actually need to
| build.
| 9d wrote:
| Not sure why you were downvoted. I think you're probably right
| about a lot of that. I do know that it's certainly the case for
| me. I have a lot of talent, but I can't harness it unless I
| find a project I truly believe in. But who's to say which
| projects are worthwhile, which projects genuinely help
| humanity? Not everything we do and breathe needs to be activism
| against injustice all the time. Take pico8 as an example. That
| has rejuvenated the joy and wonder of countless aging
| programmers, and probably taught many young people how to make
| games. Is that not inherently a good thing? And it made money
| doing it, should it not?
| owebmaster wrote:
| Imagine being the guy saying this to Linus Torvalds when he did
| the OG "Show HN": Hello everybody out there
| using minix - I'm doing a (free) operating system
| (just a hobby, won't be big and professional like gnu) for
| 386(486) AT clones. ... It is NOT portable (uses 386
| task switching etc), and it probably never will support
| anything other than AT harddisks, as that's all I have :-(.
| I'd like any feedback on things people like/dislike in minix,
| as my OS resembles it somewhat (same physical layout of the
| file-system (due to practical reasons) among other things).
| ... Linus (torvalds@kruuna.helsinki.fi)
| masijo wrote:
| Jesus, can't people have fun anymore? Does everything have to
| be "important for humanity"?
|
| Do you listen to music, read books, have sex etc? I bet you do.
| And I also bet that you would find it pretty ridiculous if
| someone asked you why you do those things instead of helping
| humanity.
| graypegg wrote:
| > They have so much power to improve and fight against the
| dystopian world that is being created by all these evil
| corporations, if they just realized what we actually need to
| build.
|
| That is a tad dramatic. You could also say the same thing about
| any art form.
|
| - Painters spend all of their time working on artwork only a
| few people will ever see!
|
| - Musicians don't realize how their time is wasted composing
| music that won't solve any problems!
|
| - People are starving right now, as another writer dares to
| write a story that simply tries to entertain the reader.
|
| Everything is political, and we all should keep that in mind.
| We all have effects on society no matter what. But also, it's
| fine to make a cromulent thing because it's interesting. We've
| all only got so much time alive, but you're going to squander
| the experience if you try to min-max impact on those 90-odd
| years. People do have to live for themselves sometimes, and
| this person likes making a neat homebrew OS.
| simonw wrote:
| Thinking like that is a trap. No matter _what_ you are working
| on there could always be some other project that has greater
| "value to humanity".
|
| I for one celebrate any time people invest their efforts in
| building something unique, new and interesting. This project is
| absolutely delightful.
| knowitnone wrote:
| you already provided 3 reasons: "Very cool and impressive, you
| probably learned a lot". Why does everything you do have to
| serve humanity? what have you done to serve humanity and why
| are your other projects not serving humanity? And who are you
| to push your views and dictate what others do?
| crq-yml wrote:
| The majority of what we make is temporary, and a majority of
| software amounts to wheel reinvention. But this is true
| throughout history. Crafted objects had always have their
| design iterated upon and adjusted to meet the available
| dependencies.
|
| Liberation isn't found in "fighting", as if there were some
| kind of ideological showdown that resolved everything. That's a
| way to drain your energy for living while waiting for a final
| resolution that never comes. Indeed, by directing it towards
| "enemies" you can accumulate guilt in yourself, and become
| increasingly unstable.
|
| Rather, it has to be part of living and personal character, to
| take opportunities to "do hard things" because they are
| interesting, not because you are coerced. When you do this,
| succeed, and pass down the knowledge, the potential opens up to
| others. You don't have to believe right things to stumble into
| new ideas.
| geoctl wrote:
| Great work. I've always wondered if WASM could actually be used
| as a more generic alternative alternative to eBPF where you could
| actually do more complex logic than the average eBPF program at
| the kernel level and still have customized and restricted access
| to the kernel APIs and data structures like you're actually
| developing a typical kernel module.
| jauntywundrkind wrote:
| I can't wait to see what attempts like this might look like after
| wasm components start becoming real(-er).
|
| I have huge respect for unikernel designs, and this looks
| amazingly festureful. & Yet... I don't know why it matters to me
| as much as it does, but I want so very much for wasm to be useful
| for more than one big precompiled app.
|
| There's all sorts of work going into wasi preview3 right now, to
| allow sync and async code to co-exist. Once that happens, it
| feels like wasm will finally have all the necessary ingredients
| down to be an everything runtime (although I'd hoped the host-
| object bridging was going to get more love too, & it's not clear
| to me that there's any itnent to go beyond js-based bridges like
| rust web-sys, on and on).
|
| I hope we see more interest in wasm runtimes being used to host
| more dynamic sub environments, to host not just one amazing
| process but many processes. The promise of wasm components is to
| give us: standard, portable, lightweight, finely sandboxed,
| cross-language, compositional module (according to the wonderful
| talk linked below), and it seems so near, but this status quo of
| it being used so extensively in unikernel like applications,
| needing everything compiled ahead of time, feels like the area I
| want to see wasm expanding into not as a specification (the spec
| seems there!) but as a practicable doable thing, like what I want
| wasm components to be good for. Not just a distribution format
| but a runtime capability.
|
| _What is a Component (and Why)_ https://youtu.be/y3x4-nQeXxc
| 9d wrote:
| I started on a Rust app that uses SDL3 and lets you script it
| via embedded V8[1]. But I'm _very seriously_ tempted to fork it
| and embed wasmtime or wasmi and let you script it in _anything_
| , and include a few wasm compilers into the app for convenience
| so you just give it a file and it does the rest. Mainly because
| of the speed of wasmtime and wasmi compared to alternatives[2].
| But my biggest concern is that this isn't adding any real
| convenience. You still have to set up whole code environments,
| which defeats the purpose of _scripting_ it. Still, it 's such
| a neat idea that I don't want to not do it, and I just might.
|
| [1] https://sdegutis.github.io/blog/dear-everyone-hire-me-to-
| mak...
|
| [2] https://github.com/khvzak/script-bench-rs
| simonw wrote:
| Wow, this thing even has its own web browser!
| https://github.com/Askannz/munal-os/tree/master/wasm_apps/we...
|
| You can see a snippet of it running (and rendering Hacker News)
| in the demo video.
| pjmlp wrote:
| /rant mode on
|
| Every few years since Xerox PARC, we get yet another attempt to
| bytecode userspace.
|
| So far only IBM i, ChromeOS and Android managed to stick around,
| mostly thanks for their owners having the "my way or the highway"
| attitude, with management willing to support the teams no matter
| for how long it takes.
|
| /rant mode off
|
| Anyway, all the best for the project, looks cool.
| 9d wrote:
| ChromeOS only uses V8 by happenstance, being an OS that's just
| a browser.
|
| Android could have used anything and it would have been
| successful, even C++.
|
| These were both successful purely because they're cheap, not
| because technology.
| pjmlp wrote:
| What matters is what is available for developers on
| userspace, regardless if they like it or not.
|
| Great technology sadly wins on merit.
|
| Technology wins on either being cheaply available, in a worse
| is better fashion, as devs rather drink free lemon juice
| instead of nice costly orange one, or by having companies
| with willingness and deep pockets to push it no matter what.
| knowitnone wrote:
| this is very impressive. I really like that you have a browser
| which is almost mandatory for a desktop OS now. You should write
| down your TODO list and I hope you keep working on this. I think
| there is room for many OSes especially ones written in Rust.
| IshKebab wrote:
| Apart from the cooperative scheduling, I think Spectre probably
| kills the security model, and I can't understand how this could
| work efficiently without virtual memory. How do you implement
| `memory.grow`? Do you have to `memmove` an entire app's memory
| when it wants to grow by 10 kB and another app is in the way? Is
| that even possible?
|
| Still, very impressive project!
| 9d wrote:
| Could you elaborate?
| jasonthorsness wrote:
| Incredible that it's a client OS! I think this kind of design can
| have immediate use server-side because it eliminates quite a bit
| of security boundary by making the kernel much smaller and
| eliminating all other libraries and applications besides the
| thing you are running. I think a key/value store for example
| would be an excellent candidate to run like this.
|
| Is it possible to achieve decent network performance with this IO
| model? Can it play any tricks with memory to eliminate some of
| the copies required when hosting WASM in most programs?
| rollcat wrote:
| The radial menu is brilliant.
|
| It is reminiscent of how basic team communication works in
| StarCraft 2. You alt-click to ping the minimap (draw allies'
| attention to something in that general area). If it's something
| more specific, you can hold alt, and drag-click to open a
| directional menu, from which you can choose one of four orders:
| attack, defend, retreat, and OMW. Some pings are also context-
| sensitive: click on the minerals/gas to say "I want to gather
| these resources", useful for establishing expansion patterns,
| strategy in the early game (macro/rush), tech transitions (ping
| your hydralisk den to say "I'm gonna make hydras"). All of this
| is key in a game with hundreds of APM and split-second reaction
| times.
|
| It's a similar story with GUI actions. Power users appreciate
| good key shortcuts more than almost anything. If you do something
| thousands of times a day, it needs to be near-instant. The mouse
| is often disregarded, and IMHO that's because nobody is really
| doing any serious research in that area. Radial menus pack a lot
| of actions (where three mouse buttons fall short), exploit Fitt's
| law, muscle memory, etc. They are also discoverable and provide
| immediate visual feedback (contrary how "mouse gestures" work in
| some applications).
|
| Couple notes on the current implementation (from what I've
| gathered from the video):
|
| - Settle on how many actions *at most* do you want available in
| the menu (4? 6? 8?), divide the menu accordingly, and display
| those divisions regardless of whether there's an actionable item.
| This will help develop muscle memory. If you need more than say 8
| actions, the menu might already be getting more crammed than
| you'd find useful.
|
| - When figuring out where to place stuff, I would suggest
| prioritising the four cardinal directions for the most common
| actions, starting with the horizontal positions. "Surprising" or
| destructive actions (even if un-doable) should be placed at the
| harder-to-reach positions.
|
| - Keep the actions as consistent as possible between different
| contexts, e.g. left on the document closes the document, left on
| the title bar closes the window, but not: left on an icon deletes
| the file.
|
| Questions worth considering:
|
| - I'm not sure if a launcher is a good use for this model; once
| you have a dozen apps (or more than 3-4 windows to switch
| between), it's gonna get awkward. Maybe a more traditional list-
| menu, and/or a dock? But I'd be intrigued if you come up with
| something original.
|
| - What happens when you open a menu too close to the screen edge?
| It's an interesting case to consider. Warping the pointer might
| be an option (the physical mouse can keep moving, after all).
|
| - Is this going to work well with a trackpad? Maybe use a
| two/three finger swipe, but that depends on how precise is your
| hardware.
|
| - What about a trackpoint, or die-hard keyboard users? Perhaps
| you can trigger the menu by holding down the space key?
|
| Anyway, this is really inspiring.
| diskzero wrote:
| Marking Menus [1], Pie Menus, Radial Menus and friends have
| been around for a while. There is good body of research on
| them, with some recent research done on their use in multi-
| touch environments. [2]
|
| While working at DreamWorks, I would often watch artists
| navigate complex marking menu hierarchies and invoke a command
| before the menu items themselves could actually be read by a
| non-trained user. In our custom lighting tool, you could
| execute the marking menu command by invoking the menu command
| and making them mouse movement before the menu actually drew.
|
| 1. https://www.billbuxton.com/MMUserLearn.html 2.
| https://damassets.autodesk.net/content/dam/autodesk/research...
| baudaux wrote:
| Once wasm wasi runtime for exaequOS is ready (I hope soon) I will
| have a look for running munal OS app in the browser
| senkora wrote:
| I have to ask, were you influenced at all by the talk "The Birth
| and Death in of Javascript" from Pycon 2014?
|
| https://www.destroyallsoftware.com/talks/the-birth-and-death...
|
| It describes a hypothetical future where operating systems use
| asm.js (precursor to wasm) sandboxes as an alternative to virtual
| memory protection. I always thought it was a cool idea, and it
| seems to be a key part of your design.
___________________________________________________________________
(page generated 2025-06-09 23:00 UTC)