i'm a software engineer based in the philippines, driven by curiosity and whatever i find interesting. i learn fast with the caveat of goldfish memory (which i call my context lol) and i'm usually self-motivated that i forget to eat.
this is not like other portfolios. feel free to have a look around and explore what makes me, me.
drag cork to move. drag notes to rearrange. use +/− or pinch-wheel to zoom. click one to open.
how WFDs work, when to write one, the states a document can be in, frontmatter format, and the markdown features available.
wfd · 2026-07-22T00:00:00+08:00 · 9 min
W
weppi
a browser and electron interface for pi with a real local extension bridge.
current benchreactelectrontypescript
A
aiproxy
personal codex account router with usage tracking, refresh, and fallback routing.
current benchtypescriptoauthproxy
S
smollama
small terminal interface for chatting with ollama cloud models.
current benchterminalollama
rfd.shared.oxide.computer
Oxide's RFD system
from writings for discussionrfc-editor.org
IETF Request for Comments
from writings for discussiongithub.com
remark
from writings for discussiongithub.com
rehype
from writings for discussionshiki.style
shiki
from writings for discussionryanaque.com
a link
from writings for discussiongithub.com
@reactthree/fiber
from writings for discussiongithub.com
@reactthree/drei
from writings for discussionavery proactively writing a business guideavery v3chatgpt.com
ChatGPT
from do you want me to do that?en.wikipedia.org
RLHF
from do you want me to do that?arxiv.org
guarantees
from do you want me to do that?arxiv.org
Anthropic tested
from do you want me to do that?doi.org
58% sycophancy rate
from do you want me to do that?alignmentforum.org
activation steering
from do you want me to do that?
unfolding paper…
wfd / Jul 21, 2026 / 9 min
writings for discussion
writing things down is important. it forces you to think clearly about what you're building, what you've learned, and what you still don't understand. a half-formed idea in your head stays half-formed until you try to put it into sentences.
this WFD supersedes WFD 12. WFD 12 remains in the archive as a legacy document. WFDs are never deleted, even when superseded, because they're a record of how things were at the time they were written.
WFD (Writing for Discussion) is how i capture that process. it's a document format inspired by Oxide's RFD system, which itself draws from the original spirit of the IETF Request for Comments:
Notes are encouraged to be timely rather than polished. Philosophical positions without examples or other specifics, specific suggestions or implementation techniques without introductory or background explication, and explicit questions without any attempted answers are all acceptable. The minimum length for a note is one sentence.
the bar for writing a WFD is intentionally low. if you can explain it in a sentence, that's enough to start. polish comes later, or not at all.
when to write a wfd
this document says "you" a lot. the WFD format isn't proprietary or exclusive to this site. if the structure works for you, take it. adapt it. make it yours. that's the whole point.
anything worth remembering is worth writing down. some examples:
debugging a problem that took more than an hour
learning something that surprised you
building something and wanting to document the decisions
an opinion about tools, patterns, or process
something you'd want to reference later
there's no approval process. no review board. no minimum length beyond one sentence. if the idea matters to you, write it down.
writing conventions
don't repeat what another WFD already said
if something has been covered in a previous WFD, reference it instead of restating it. a link to the relevant WFD is always better than a paraphrase. this keeps documents focused and avoids content that drifts out of sync when the original gets updated.
drafts should use arguments for/against
when a WFD is in draft and hasn't reached a decision yet, lay out the tension explicitly:
arguments against:
- reason one
- reason two
arguments for:
- reason one
- reason two
this makes the open question visible. the reader can see exactly what's unresolved and why a decision hasn't been made yet. see WFD 18 and WFD 19 for examples.
wfd metadata and state
every WFD starts with YAML frontmatter:
---
number: 17
title: "writings for discussion"
updated: "2026-02-11T00:35:00"
state: "published"
labels: ["process"]
excerpt: "short description of what this document covers."
---
ISO 8601 datetime with time. the only timestamp that matters.
state
yes
current lifecycle state (see below).
labels
yes
array of tags. keep it to three or fewer. use [] for none.
excerpt
yes
one or two sentences. shows up in search results and the listing page.
states
a WFD can be in any of these states:
state
meaning
draft
placeholder. not ready for anyone to read.
discussion
actively being written or revised. feedback welcome.
published
the idea is formed and the document says what it means to say.
committed
i'm committing to this post. it's not going to change significantly.
living
actively maintained. will be kept up to date on a best effort basis.
legacy
written before the WFD system existed. migrated from the old blog format. may not follow current conventions.
abandoned
the idea didn't pan out. kept for the record.
states are freeform text. these are suggestions. i might not even follow them myself because i felt like a word meant something different that day, or because i wanted a state that doesn't exist yet. type whatever makes sense.
unlike Oxide's RFD process, there's no branch-per-document workflow, no pull request for discussion, and no formal review. documents are markdown files in a content directory. state changes are just a frontmatter edit.
numbering
WFDs are numbered sequentially. WFD 1, WFD 2, WFD 17. no dashes, no leading zeros in the display. the number is permanent. if a WFD is abandoned, the number stays taken.
updated, not created
there is no creation date. only updated. if you come back six months later and rewrite half the document, the timestamp reflects that. the creation date is noise. what matters is when the document was last touched.
the markdown engine
the rendering pipeline is custom. i didn't want to use an off-the-shelf markdown engine like MDX, Contentlayer, or Markdoc because they all impose opinions about how content should be structured, and i wanted full control over what syntax is available and how it renders.
the engine is built on remark and rehype for the base markdown-to-HTML conversion, with shiki for syntax highlighting. everything else is custom parsing on top.
the parser works in a single pass over the raw markdown lines. it maintains state machines for code blocks, admonitions, HTML blocks, and media groups. each line is checked against a series of regex patterns in order:
if we're inside a fenced code block, accumulate lines until the closing fence.
if we're inside an HTML block (<details>, <div>, etc.), pass lines through to remark as-is.
if we're inside an admonition (> [!NOTE]), accumulate continuation lines that start with >.
check for code block openings, heading patterns (for TOC extraction), admonition starts, component directives, and media lines.
if a line matches , @gif[alt](url), @video[caption](url), or @embed[title](url), it's collected into a media group.
consecutive media lines without a non-empty separator become a single carousel.
everything else is accumulated as text and flushed through remark when a non-text block is encountered.
the output is an array of typed content blocks (text, code, media, mermaid, admonition, component) that React components consume directly. there's no intermediate AST transformation or plugin chain beyond what remark and rehype provide for the text blocks.
this means adding new syntax is straightforward: add a regex to parseMediaLine or a new block type to the line scanner, add a corresponding React component, and it's done. the @gif, @video, @embed, and @component syntaxes were all added this way.
the tradeoff is that the parser is imperative and stateful rather than declarative. it's not as elegant as a proper AST visitor pattern, but it's simple to debug and easy to extend. every feature in this document was added in under an hour.
writing format
WFDs are written in markdown with some extensions. everything below is available in any WFD.
text
standard markdown: **bold**, *italic*, ~~strikethrough~~, `inline code`, [links](url).
bold text, italic text, bold and italic, strikethrough, inline code, a link
headings
use ## through ####. these are extracted for the table of contents sidebar on desktop and the bottom sheet on mobile. # is reserved for the document title.
code blocks
fenced with triple backticks. specify the language for syntax highlighting.
```typescript
const x: number = 42;
```
const x: number = 42;
tables
standard GFM tables. they render with rounded borders and a semi-transparent background.
> [!NOTE/Custom Title]
> content with a custom title.
useful information that readers should know, even when skimming.
helpful advice for doing things better or more easily.
key information that readers need to achieve their goal.
urgent information that needs immediate attention to avoid problems.
advises about risks or negative outcomes of certain actions.
Custom Title Here
admonitions can have custom titles instead of the default.
images

consecutive images on adjacent lines automatically group into a scrollable carousel. images display at their natural aspect ratio with a max-height constraint.
gifs
@gif[description](url)
videos
@video[caption](url)
link embeds
@embed[title](url)
wfd embeds
reference another WFD by slug or number to render an inline preview card with its title, excerpt, state, labels, and reading time.
embeds interactive React components directly in the document. components are registered in BlogComponents.tsx and render inside a macOS-style frame.
available components: PixelLoader, PixelLoaderDemo, PixelLoaderAdjacencyDemo, ThreeDemo
three.js scenes
Three.js scenes are a special case of react components. they render interactive 3D scenes inline using @react-three/fiber and @react-three/drei, dynamically imported with SSR disabled since WebGL requires a browser context.
the ThreeDemo component is a showcase. for actual WFD content, create purpose-built scene components in src/components/blog-demos/, register them in BlogComponents.tsx with next/dynamic and { ssr: false }, and reference them with @component[YourScene].
the pattern for adding a new Three.js component:
create the component in src/components/blog-demos/YourScene.tsx with "use client"
use @react-three/fiber's Canvas and @react-three/drei for helpers (controls, materials, environments)
use in markdown: @component[YourScene]({"height": 400})
Three.js components are heavy. keep scenes focused and avoid loading external models unless necessary. the dynamic import with ssr: false ensures the Three.js bundle only loads when the component scrolls into view on client.
discord-style spoiler syntax. text is hidden behind a blurred overlay and revealed on hover.
||spoiler text here||
this is a spoiler: ||the cake is a lie||. hover to reveal it.
spoiler tags work inline with other text and respect inline code, so ||this is not a spoiler|| inside backticks renders as-is. added in WFD 27 because some posts need to discuss plot details without ruining things for people who haven't watched yet.