{
    "emails": {
        "em-006": {
            "id": "em-006",
            "threadId": "th-006",
            "folder": "updates",
            "timestamp": "2026-07-01T10:18:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "I got hired at Tebra",
                "summary": "A new role, a long search, and interviewers who let the work speak for itself.",
                "format": "text",
                "body": "I got hired at Tebra as a Software Engineer III. I’d been looking since January and had sent out a couple hundred applications by then. My résumé had travelled considerably farther than I had, although neither of us seemed to be getting anywhere. I applied to Tebra in late May, and the conversations gave me something more useful to think about than what color bin my application might have been thrown into.\n\nWhat struck me most was how real the interviewers were. Like they all read that cheesy quote about checking your ego at the door. It was honestly a breath of fresh air talking about the work at hand instead of competing for smartest person in the room without making it obvious.\n\nThey let the job speak for itself, which is to say it wasn't going to change the course of human history. Just a software engineering position they needed a software engineer to fill. There's something reassuring about meeting people who can explain a job honestly and still leave you wanting to do it.\n\nI'm looking forward to finding out what we can build together. My résumé, meanwhile, can stay wherever it wandered off to last."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Career"
            ]
        },
        "em-007": {
            "id": "em-007",
            "threadId": "th-007",
            "folder": "primary",
            "timestamp": "2026-10-11T09:14:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "You probably have some questions.",
                "summary": "I should probably explain why my portfolio looks like an inbox. I wanted a place for my projects, writing, and updates, and somehow arrived at email as the thing people would voluntarily spend more time looking at. I’m aware of the flaw in that reasoning. Still, you opened this one.",
                "format": "text",
                "body": "I should probably explain why my portfolio looks like an inbox. I wanted a place for my projects, writing, and updates, and somehow arrived at email as the thing people would voluntarily spend more time looking at. I’m aware of the flaw in that reasoning. Still, you opened this one.\n\nThe idea is to give each thing its own conversation. Open a project and you can get into what I built and the decisions behind it. The articles are where I spend more time on an idea than the people around me probably wanted me to. Updates cover whatever’s been happening along the way.\n\nYou can browse the tabs or search for something specific. There’s no particular order, and you don’t need to read everything to make sense of any one thing. I’ve already done the part where I spend an unreasonable amount of time on this portfolio. You shouldn’t have to.\n\nDustin"
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [],
            "receivedAt": "firstVisit"
        },
        "em-008": {
            "id": "em-008",
            "threadId": "th-008",
            "folder": "primary",
            "timestamp": "2026-10-11T00:00:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "One last thing",
                "summary": "Part of the reason I chose an inbox is that you already know how to use one. You scan the subjects, open something that looks interesting, and decide how much of your afternoon it deserves. I thought this would save me from having to explain the website. Naturally, this is my second email explaining the website.",
                "format": "text",
                "body": "Part of the reason I chose an inbox is that you already know how to use one. You scan the subjects, open something that looks interesting, and decide how much of your afternoon it deserves. I thought this would save me from having to explain the website. Naturally, this is my second email explaining the website.\n\nIt also gives each project room for the details. A screenshot can establish that I’ve successfully placed several rectangles on a screen, but it leaves out most of the work. I’m more interested in explaining what I was trying to do, why I approached it that way, and what happened when the software was given an opportunity to disagree. Putting that in its own conversation means I can get into it without making you read the entire thing on your way to something else.\n\nThe tabs narrow things down by projects, articles, and updates. Search is there if you already have something in mind. Otherwise, pick a subject and see where it goes.\n\nAnyway, I’ll leave you to it.\n\nDustin"
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [],
            "delivery": {
                "afterOpen": "em-007"
            }
        },
        "em-009": {
            "id": "em-009",
            "threadId": "th-009",
            "folder": "primary",
            "timestamp": "2026-10-11T00:00:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "And another thing!",
                "summary": "I forgot to mention that you can actually send me a message from here.",
                "format": "text",
                "body": "I forgot to mention that you can actually send me a message from here. Write something, hit Send, and it becomes a private conversation between you and me. An email notification reaches my inbox after the conversation has been quiet for fifteen minutes, giving you time to add the thing you remembered immediately after sending. I’m familiar with the process.\n\nYou can write as a guest or sign in. Messages and attachments are saved by the backend, and an account lets your conversations and preferences follow you across devices. Unsent drafts stay around while you navigate the current page, but won’t survive closing or reloading it. Apparently even an email-themed portfolio needs to distinguish between thinking about saying something and having said it.\n\nThere’s also Norris, an assistant who can answer questions about my work inside your conversation. His answers draw from information I’ve provided about my projects and career. He remembers the discussion, and “Forget me” clears that memory while leaving the conversation in your inbox. I haven’t found an equivalent command for people.\n\nUnderneath all this is HTML, CSS, vanilla JavaScript, and a Go backend running on AWS. I’ll get into how those pieces fit together in Projects, where opening the explanation will at least have been your decision.\n\nThat covers the part I forgot while confidently telling you I’d covered everything.\n\nDustin"
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [],
            "delivery": {
                "afterOpen": "em-008"
            }
        },
        "em-010": {
            "id": "em-010",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-07-13T19:42:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "I’ve started working on a new portfolio after work. The idea is to organize my projects, writing, and updates as email conversations. Most people already have an inbox they’re avoiding, so naturally I thought I’d give them another one.",
                "format": "text",
                "body": "I’ve started working on a new portfolio after work. The idea is to organize my projects, writing, and updates as email conversations. Most people already have an inbox they’re avoiding, so naturally I thought I’d give them another one.\n\nThere is some reasoning behind this. A project usually needs more explanation than a screenshot and a list of technologies. An inbox gives you a subject and a preview, then leaves you to decide whether you want the rest of the story. I can write as much as the project deserves without making you scroll past all of it to find something else.\n\nFor now, I have a skeleton. There’s a place for navigation, a place for messages, and a fairly generous amount of nothing between them. It’s already doing an excellent impression of an inbox nobody has written to."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-011": {
            "id": "em-011",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-07-20T20:16:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "The basic layout is coming together. I’ve been working on the sidebar, search bar, category tabs, and message rows in the evenings. There’s a surprising amount of negotiation involved in getting a subject, a preview, and a date to share one line without one of them deciding it owns the place.",
                "format": "text",
                "body": "The basic layout is coming together. I’ve been working on the sidebar, search bar, category tabs, and message rows in the evenings. There’s a surprising amount of negotiation involved in getting a subject, a preview, and a date to share one line without one of them deciding it owns the place.\n\nI’m keeping the layout familiar because the content should be the interesting part. If someone recognizes how to open a message, switch sections, or search, they can start looking around without first learning how I think a website ought to work.\n\nProjects, Articles, and Updates now have their own tabs. That gives me room for different kinds of writing while keeping the overall experience consistent. It also saves me from trying to explain a backend project and something that happened last Tuesday in the same paragraph."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-012": {
            "id": "em-012",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-07-29T21:08:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "I’ve started getting the content into proper conversations. Until now, a lot of the work has involved making convincing places for information to eventually appear.",
                "format": "text",
                "body": "I’ve started getting the content into proper conversations. Until now, a lot of the work has involved making convincing places for information to eventually appear.\n\nEach conversation needs enough of a preview to tell you what you’re opening. Once you’re inside, there’s room for the explanation, screenshots, and later updates. I like that a project can keep developing in the same place. The first version doesn’t have to be presented as the final, unquestionable achievement of a person who apparently never changes his mind.\n\nThe content is also separate from the interface. Editing a paragraph shouldn’t require spending the rest of the evening remembering which JavaScript function is responsible for displaying it.\n\nThis has produced a new problem: I now have to finish writing some of the things I’ve built a website to display."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-013": {
            "id": "em-013",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-08-07T18:47:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "Search is working. This seems like a fairly small achievement until you put a search bar at the top of a page and realize you’ve made a promise to everyone who sees it.",
                "format": "text",
                "body": "Search is working. This seems like a fairly small achievement until you put a search bar at the top of a page and realize you’ve made a promise to everyone who sees it.\n\nIt looks through the messages themselves, including the parts that don’t fit in the preview. It also stays within the section you’re browsing. Searching Projects should give you matching projects; it shouldn’t quietly decide that you’d enjoy reading an unrelated update because I happened to use the same word.\n\nI’ve added more specific filters for things like subjects, dates, and message status. Ordinary words still work, which I consider an important feature of a search box.\n\nI’m enjoying this part more than I expected. There’s something satisfying about taking a collection of information and making it easier to get back to. Particularly when you’re the person who put it there and have already forgotten where."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-014": {
            "id": "em-014",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-08-18T20:32:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "Compose and Reply now have a working editor. You can write, format text, add links, and include images or attachments. It’s becoming difficult to claim that I’m just making a portfolio with an email theme. I appear to be taking the theme personally.",
                "format": "text",
                "body": "Compose and Reply now have a working editor. You can write, format text, add links, and include images or attachments. It’s becoming difficult to claim that I’m just making a portfolio with an email theme. I appear to be taking the theme personally.\n\nBoth places use the same editor underneath. That matters because a formatting button should behave the same way whether you’re starting a message or replying to one. It also means I can fix a problem once instead of maintaining two slightly different versions of the same mistake.\n\nI’ve been paying attention to the less obvious parts too, like keeping a draft around when you close the composer or look at another conversation. Taking a moment to check something shouldn’t be interpreted as a request to destroy what you were writing."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-015": {
            "id": "em-015",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-08-26T19:56:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "Messages and replies are being saved locally, so they survive a refresh. The browser now remembers that you were here, which is more than can be said for some people I’ve been introduced to several times.",
                "format": "text",
                "body": "Messages and replies are being saved locally, so they survive a refresh. The browser now remembers that you were here, which is more than can be said for some people I’ve been introduced to several times.\n\nI wanted the basic experience to work without asking someone to make an account. You should be able to open the portfolio and use it. Local storage makes that possible while keeping your saved conversations in your browser.\n\nThere are limits to that arrangement. Another device won’t have the same history, and clearing the site’s storage clears what’s saved there. Signing in and carrying conversations across devices belongs in the backend work.\n\nFor now, I’ve made sure the interface waits for a save to succeed before treating it as successful. If saving fails, your writing stays available. A cheerful confirmation is considerably less useful when it’s describing something that didn’t happen."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-016": {
            "id": "em-016",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-09-05T14:23:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "I’ve been working on the mobile layout. Shrinking the desktop version was a useful way to discover how much of the desktop version should not be on a phone.",
                "format": "text",
                "body": "I’ve been working on the mobile layout. Shrinking the desktop version was a useful way to discover how much of the desktop version should not be on a phone.\n\nThe navigation moves into a drawer, conversations get the full screen, and the composer uses the space available to it. The aim is to keep the same familiar actions while giving them enough room to be used by a thumb, which has never struck me as a particularly precise pointing instrument.\n\nI’m also keeping mobile behavior separate from desktop preferences. Opening the site on a phone shouldn’t rearrange the reading pane waiting on your computer.\n\nThis has been a good reminder that fitting something on a screen and making it usable are two different amounts of work. The first one was finished considerably earlier."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-017": {
            "id": "em-017",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-09-14T21:17:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "The frontend is HTML, CSS, and vanilla JavaScript. I’ve kept the work divided into browser modules for things like search, rendering, state, and storage. There’s no framework or build step between the files and the page.",
                "format": "text",
                "body": "The frontend is HTML, CSS, and vanilla JavaScript. I’ve kept the work divided into browser modules for things like search, rendering, state, and storage. There’s no framework or build step between the files and the page.\n\nThat doesn’t make the organization take care of itself. It just makes it fairly clear who to blame when it doesn’t.\n\nThe backend is written in Go. It handles the parts that need a server, including stored conversations, access rules, and uploaded files. Keeping it separate means I can work on the mailbox interface without making every visual adjustment an event involving the database.\n\nThe AWS setup is being worked out around S3, DynamoDB, EC2, and CloudFront. Message records and uploaded files have different storage needs, and the public site has different delivery needs from someone’s private conversation. Giving those things separate responsibilities should make the system easier to change without disturbing something unrelated."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-018": {
            "id": "em-018",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-09-23T20:41:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "The transitions are getting close to where I want them. I’ve been opening and closing the sidebar, moving between conversations, and watching the same small pieces of the interface more times than I care to explain.",
                "format": "text",
                "body": "The transitions are getting close to where I want them. I’ve been opening and closing the sidebar, moving between conversations, and watching the same small pieces of the interface more times than I care to explain.\n\nThe timing matters. Text shouldn’t appear before there’s room for it, and a panel shouldn’t make you wait while it completes an elaborate entrance. I want the motion to help you follow what changed, then get out of the way.\n\nI’m also respecting reduced-motion preferences and keeping keyboard navigation usable. Looking smooth is one part of the job. Letting someone reach the button is another fairly important one.\n\nThese are small changes individually, but the application feels more settled now. I’m reasonably pleased with it, although I suspect I’ve spent enough time watching the sidebar that it would feel rude to say otherwise."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-019": {
            "id": "em-019",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-10-02T19:28:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "I’ve added a short sequence of introductory emails. Opening “You probably have some questions” makes “One last thing” arrive. Opening that one brings in “And another thing!”",
                "format": "text",
                "body": "I’ve added a short sequence of introductory emails. Opening “You probably have some questions” makes “One last thing” arrive. Opening that one brings in “And another thing!”\n\nI could have put them all in the inbox immediately, but then you’d know from the beginning that I wasn’t going to keep my promise. This way, you get to discover that gradually.\n\nThe sequence also breaks the introduction into smaller pieces. The first email gets you oriented, the second explains more of the idea, and the third gets into the parts I conveniently neglected to mention.\n\nThe portfolio remembers which ones you’ve opened, so returning doesn’t start the introduction over. I’d like people to come back voluntarily, and making them sit through my explanation again seemed unlikely to help."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-020": {
            "id": "em-020",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-10-08T21:06:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "I’m getting the portfolio ready to deploy. Most of the recent work has been checking the less impressive things that become very impressive when they fail: navigation, saved messages, narrow screens, loading errors, and whether an unfinished draft stays where you left it.",
                "format": "text",
                "body": "I’m getting the portfolio ready to deploy. Most of the recent work has been checking the less impressive things that become very impressive when they fail: navigation, saved messages, narrow screens, loading errors, and whether an unfinished draft stays where you left it.\n\nI’m also drawing a line around this release. The portfolio and local mailbox experience are ready to go out. Real email delivery and signed-in access across devices still need to be connected. Saving a message locally is working, but I don’t want the interface to imply that it has reached my actual inbox until that’s true.\n\nWorking on this after work has made it fairly easy to keep finding one more thing to improve. There’s always another spacing adjustment or interaction that could use some attention. At some point, though, a portfolio needs to become a website someone else can visit.\n\nI’m aiming for the 13th. I’ve written that down now, which makes it slightly harder to pretend I meant some other Tuesday."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-021": {
            "id": "em-021",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-10-13T01:14:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "I’ve deployed the portfolio.",
                "format": "text",
                "body": "I’ve deployed the portfolio.\n\nAbout three months ago, this was a skeleton I was working on after work. It gradually acquired a layout, conversations, search, an editor, saved messages, a mobile version, and a collection of transitions that have received more personal attention than several household appliances.\n\nThe part I’m happiest with is how it all fits together. You can skim the subjects, open something that interests you, and get into the details at your own pace. The interface gives the projects room without requiring every visitor to share my level of interest in them.\n\nThere’s still backend work ahead, including real email delivery and account-based synchronization. But the portfolio itself is now somewhere other than the computer I’ve been building it on.\n\nI’m going to spend the rest of the evening looking at it like someone who didn’t write it. This should last until I notice a margin."
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-022": {
            "id": "em-022",
            "threadId": "th-022",
            "folder": "projects",
            "timestamp": "2026-10-13T01:37:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "Portfolio... A place for all the things",
                "summary": "I built this portfolio around an inbox because most people already know what to do with one.",
                "format": "rich",
                "body": [
                    {
                        "tag": "p",
                        "children": [
                            "I built this portfolio around an inbox because most people already know what to do with one. A subject tells you what something is about, a preview helps you decide whether to open it, and the full conversation waits until you’re interested. It seemed wasteful to throw away all the training we’ve received from people marking things urgent."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "The frontend uses ",
                            {
                                "tag": "strong",
                                "children": [
                                    "HTML, CSS, and vanilla JavaScript"
                                ]
                            },
                            ". HTML provides the structure, CSS handles the appearance, and JavaScript makes the controls do what their labels suggest. There’s no framework, bundler, or build step. Browser modules keep search, rendering, application state, and storage organized separately. Changing how a message looks shouldn’t alter whether it exists, a distinction I would prefer the software to maintain."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "Compose and Reply share an editor, so formatting, links, inline photos, and attachments behave consistently. Failed submissions keep your draft available for another attempt. The interface waits for a successful save before treating it as successful; confidence alone is a poor storage strategy."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "Search checks full message bodies, including earlier replies, within the section you’re browsing. You can narrow it by dates, people, labels, attachments, or particular phrases. Labels collect related conversations across the portfolio, and each conversation has an address you can bookmark or share. Stars, archive, and the other familiar mailbox controls let you organize your own view. Putting something in Trash hides it from your mailbox; it doesn’t quietly instruct the database to destroy the conversation."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "On smaller screens, navigation moves into a drawer, conversations use the full screen, and the composer makes room for the keyboard. Swipe gestures and keyboard shortcuts provide other ways to get around. Themes, fonts, reading-pane placement, and motion settings are adjustable. A sidebar should open smoothly without requiring the reader to attend its opening ceremony."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "Messages and uploads are saved by the backend. Sign in and your private conversations, preferences, and profile photo follow you across browsers. You can also send a message as a guest; creating an account attaches this browser’s guest mailbox to it. Unsent drafts remain in the current page session, so navigating elsewhere in the app preserves them, but reloading the page doesn’t."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "The backend is an independent ",
                            {
                                "tag": "strong",
                                "children": [
                                    "Go service within Starbase"
                                ]
                            },
                            ", with separate responsibilities for conversations, permissions, and uploaded files. ",
                            {
                                "tag": "strong",
                                "children": [
                                    "DynamoDB"
                                ]
                            },
                            " holds message records, ",
                            {
                                "tag": "strong",
                                "children": [
                                    "S3"
                                ]
                            },
                            " holds files, ",
                            {
                                "tag": "strong",
                                "children": [
                                    "EC2"
                                ]
                            },
                            " runs the backend, and ",
                            {
                                "tag": "strong",
                                "children": [
                                    "CloudFront"
                                ]
                            },
                            " delivers the public site’s files from locations closer to visitors. Amazon Cognito handles account credentials and email verification; the backend verifies that identity and establishes a browser session."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            {
                                "tag": "strong",
                                "children": [
                                    "Amazon SES"
                                ]
                            },
                            " handles email notifications to me, batched after fifteen minutes of conversation inactivity. Signed-in visitors can also forward conversation text to a recipient who has explicitly agreed to receive it. Attachments and inline images stay out of those forwards. These are separate actions, which matters when a website starts taking its resemblance to email this seriously."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "Norris adds contextual replies based on approved portfolio and career information. He remembers the conversation, with a “Forget me” control that clears his memory and pending replies while preserving your inbox history. Visitor conversations and their attachments are private to that visitor and me by default, with publication handled separately through owner review."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "You can check it out at ",
                            {
                                "tag": "a",
                                "children": [
                                    "dustinsnoap.com"
                                ],
                                "href": "https://dustinsnoap.com/"
                            },
                            ". If you’re reading this there, the link will take you there again. I’ve included it for completeness and for anyone who enjoys arriving twice."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "Dustin"
                        ]
                    }
                ]
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio",
                "JavaScript",
                "Go",
                "HTML",
                "CSS",
                "AWS",
                "DynamoDB",
                "S3",
                "EC2",
                "CloudFront",
                "Cognito",
                "SES"
            ]
        },
        "em-037": {
            "id": "em-037",
            "threadId": "th-037",
            "folder": "drafts",
            "timestamp": "2026-10-01T17:56:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "Reasonably Adequate Photo Studio",
                "summary": "I’m planning to build a browser-based photo editor called Reasonably Adequate Photo Studio. The name establishes a level of confidence I’m comfortable putting in writing. You’ll be able to open a photo, make a few adjustments, and save it without first developing a working knowledge of a program that could also produce the next Avatar movie.",
                "format": "rich",
                "body": [
                    {
                        "tag": "p",
                        "children": [
                            "I’m planning to build a browser-based photo editor called Reasonably Adequate Photo Studio. The name establishes a level of confidence I’m comfortable putting in writing. You’ll be able to open a photo, make a few adjustments, and save it without first developing a working knowledge of a program that could also produce the next ",
                            {
                                "tag": "em",
                                "children": [
                                    "Avatar"
                                ]
                            },
                            " movie."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "The idea is to make everyday editing straightforward while leaving enough room to get carried away. Crop, straighten, fix the lighting, adjust the colors. There’ll also be curves, noise reduction, selective color adjustments, and the other tools you start looking for once moving the brightness slider stops resolving your problems. Presets will give you somewhere to start, with individual controls for when you like everything about a particular look except what it’s done to your photograph."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "I want the design to give the photo most of the room. A clean, modern workspace, neutral colors, and controls grouped by what you’re trying to change. On a phone, those controls will need to make sense under a thumb. Shrinking a desktop interface until every button requires the precision of a surgical procedure seems like an unnecessarily hostile interpretation of portability."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "There’ll be before-and-after comparison and undo, both of which become important around the point where you’ve spent twenty minutes improving a photo and can no longer remember whether the grass was originally that color. Your original will stay intact. You’ll also be able to save a set of adjustments and reuse it across several photos, so an entire afternoon’s questionable lighting can be dealt with consistently."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "For bigger changes, I’m planning an optional enhancement tool where you can describe what you want: clean something up, restore an older image, or improve difficult lighting. You’ll decide when to run it and whether the result deserves to stay. Finished edits will have a saved library, with exports for wherever you intend to put them."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "I’ll start with the basic editing workflow and build from there. Open a photo, change something, compare it, save it. If I can make those four things feel easy, I’ll consider the name justified."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "Dustin"
                        ]
                    }
                ]
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": []
        },
        "em-038": {
            "id": "em-038",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-10-14T19:22:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "The backend work I mentioned in the last update is now connected.",
                "format": "text",
                "body": "The backend work I mentioned in the last update is now connected. You can send me a message, create an account, and pick up your conversations on another device. Messages and attachments are stored on the server, and I receive an email notification once the conversation has been quiet for fifteen minutes. This gives you a reasonable opportunity to send three corrections before I receive the original.\n\nI’ve also added Norris, an assistant who can answer questions about my projects and work history. He draws from information I’ve supplied and remembers what you’ve been discussing, so you can ask a follow-up without reintroducing the entire subject. There’s a “Forget me” option if you’d like him to start over. It clears his memory and pending replies, rather than removing the conversation you might still want to read.\n\nThe mailbox has acquired more of the things people expect from a mailbox. You can organize conversations with your own labels, star something for later, archive it, or use more specific searches to find the message you distinctly remember reading somewhere. Conversations also have shareable links. For actual forwarding, signed-in users can send text to a recipient who has agreed to receive it. One recipient at a time, without attachments or inline images.\n\nI’ve added more control over the reading experience too: colors, fonts, text size, spacing, and where the reading pane sits. The phone version now supports swipe navigation and long-press selection. These are mostly things you notice when they’re missing, which makes them slightly difficult to show off in a screenshot.\n\nThe important change is that the portfolio can now support a conversation after you’ve finished reading about my work. You can ask something, come back to it, and find it where you left it.\n\nI’d call that finished, but I have a dated message immediately above this one demonstrating how little authority I have on the subject.\n\nDustin"
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        },
        "em-039": {
            "id": "em-039",
            "threadId": "th-039",
            "folder": "drafts",
            "timestamp": "2026-10-24T13:58:13-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "One of us is going to learn something",
                "summary": "I want to learn machine learning, and I’ve decided to start with Pong. Two paddles, a ball, and two directions to choose from. It’s simple enough for almost anyone to pick up. If I can’t teach a computer to play it, I may need to reconsider which of us requires the more detailed instructions.",
                "format": "rich",
                "body": [
                    {
                        "tag": "p",
                        "children": [
                            "I want to learn machine learning, and I’ve decided to start with Pong. Two paddles, a ball, and two directions to choose from. It’s simple enough for almost anyone to pick up. If I can’t teach a computer to play it, I may need to reconsider which of us requires the more detailed instructions."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "The project is called PongML. The idea is to start with one model, teach it enough to beat a basic opponent, then make three copies and let them learn in different ways. I’m calling them James, Annika, and Brad. Giving them names should make it easier to keep track of their progress and considerably harder to remain impartial."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "James will learn by playing people. He’ll try things, score points, miss the ball, and use those results to adjust how he plays. I’m interested in seeing what he figures out when the person across from him doesn’t behave quite the way his training might suggest they should."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "Annika will work through Easy, Medium, and Hard programmed opponents, needing five consecutive wins at each stage before moving on. After that, she’ll play versions of herself. I also want to keep older versions available so you can play against them and see what changed. Ideally, she’ll improve. If she gets worse, I’d like to understand why before quietly replacing her and claiming everything went well."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "Brad will learn by studying human moves, giving more weight to actions associated with successful returns and points. James will learn from his attempts to beat you; Brad will watch what you do. This does mean some portion of his education will depend on people who opened the game while avoiding something else."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "All three will start from the same place, which should give me a useful way to explore how their different experiences affect their behavior. Pong keeps the problem small enough that I can follow what’s happening. When a paddle heads away from the ball, I won’t need a particularly sophisticated chart to establish that something needs attention."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "You’ll also be able to play ordinary Pong against the computer or another person. That part should remain enjoyable regardless of how my education is progressing."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "When it’s ready, it’ll live at ",
                            {
                                "tag": "a",
                                "children": [
                                    "dustinsnoap.com/apps/pongml"
                                ],
                                "href": "https://dustinsnoap.com/apps/pongml"
                            },
                            ". For now, there are four of us who need to learn how this works. I’m the one responsible for explaining it afterward."
                        ]
                    },
                    {
                        "tag": "br"
                    },
                    {
                        "tag": "p",
                        "children": [
                            "Dustin"
                        ]
                    }
                ]
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": []
        },
        "em-040": {
            "id": "em-040",
            "threadId": "th-010",
            "folder": "updates",
            "timestamp": "2026-10-22T17:22:00-04:00",
            "from": {
                "name": "Dustin Snoap",
                "avatar": "img/me.jpg",
                "email": "dustinsnoap@gmail.com"
            },
            "to": {
                "name": "you",
                "email": ""
            },
            "data": {
                "subject": "So I built a portfolio. This one in fact!",
                "summary": "I’ve added a few more ways to write a message: dictation, writing suggestions, and a Clean up option.",
                "format": "text",
                "body": "I’ve added a few more ways to write a message: dictation, writing suggestions, and a Clean up option. You can now talk to the composer, which is useful when you know what you want to say but would prefer the keyboard handle its own responsibilities.\n\nDictation runs right in your browser using a small speech-recognition model called Whistle. It downloads when you first use it, then stays cached for later. WebAssembly lets it do the processing on your device, so your microphone audio never needs to travel to a transcription service. I rather like that a browser can now turn speech into text while I’m still occasionally struggling to get it to put a button where I asked.\n\nThe writing suggestions give you editable starting points for things like an introduction or a project inquiry. Clean up works on something you’ve already written or dictated, including those occasions when you correct yourself halfway through a sentence and leave both versions there for the reader to negotiate.\n\nClean up is a separate, optional action that sends the draft text to OpenAI. The audio stays on your device, and you can undo the cleanup if it has misunderstood what you meant. Nothing gets sent to me until you press Send.\n\nThe idea is to make writing here a little easier, whether you arrive with a carefully considered question or discover what you’re asking somewhere in the third paragraph. I’d be in a poor position to object to the latter.\n\nDustin"
            },
            "status": {
                "read": false,
                "starred": false,
                "deleted": false
            },
            "labels": [
                "Portfolio"
            ]
        }
    }
}
