Repository navigation
Tags
Tags
fix: small fixes (home description, purple leftovers, dead code, a fl… …aky e2e, /api/og rate limit) (#638) - The home meta description drops the age and college for the site's current line: "Mike Odnis is a software engineer building web software end to end: projects, experience, certifications, places and live stats." The #612 test is split so the college keyword still names no city. - The project page's border beam uses the brand tokens instead of #7209b7 → #d6b3f0; the unused PurpleBackground.svg is gone. - The legacy ui/filter-bar.tsx (no route uses it since #633) and the dead pinned-repos and repository components are removed; their tests move to the shared kit (sticky classes, the count, a new server-HTML test). - The places-filters e2e waits for the list to shrink after typing before comparing markers. - /api/og runs the API's existing guard first: 30 requests a minute per IP, 429 with Retry-After when over, 403 for a banned IP, and it fails open (draws the card) when the limiter is unavailable. The prerendered site card is untouched.
feat(seo): Live Console sharing cards and a rebuilt app manifest (#636) * feat(seo): Live Console sharing cards and a rebuilt app manifest - The sharing cards move from the old purple Kodchasan card to the site's palette and Geist: a site card for / (name, role line, links, a live site index) prerendered as opengraph-image and twitter-image, and a matching page card from /api/og for other pages. Pages with their own images keep them; project pages without one no longer fall back to the stale static card. - The manifest is rebuilt: id and scope, the current name and description, maskable 192/512 icons, shortcuts to today's sections, and wide and narrow install screenshots. The share target and protocol handler the site never handled are gone, along with the broken /hire shortcut. - New favicon and apple-touch icon; 233 stale files are removed (the old auto-generated icon set, 29 of whose WebP files were corrupt, the Kodchasan fonts, old screenshots and cards). - Geist fonts for the cards ship with their OFL licence; the card text fitting and palette are pinned by tests against the site's tokens. * chore(seo): keep the old icon set and fonts until the cleanup PR Nothing references the old icon set, Kodchasan fonts or old screenshots any more. Their deletion moves to a separate PR so this one stays small enough to review; the tests here check that the manifest and cards no longer point at them, and the on-disk checks move with the deletion.
feat(places): the quiet photo folder on cards and a Photos view (wall… … on a mouse, grid on touch) (#635) * feat(places): the quiet photo folder on cards and a Photos view (wall on a mouse, grid on touch) - Each place card's footer becomes the lab's quiet photo folder: up to three slivers of the place's photos behind a pill that opens the place page. CSS-only, so it works without JavaScript; a place without photos keeps a plain details link. - /places/photos is the Photos view, linked from /places by a two-link Places | Photos nav. It keeps the same q and category, so the photos follow the chips and search, and the URL rule (only q and category) holds. - A fine pointer starts on the wall (drag or keys to move, lazily loaded, with a no-op fallback if its code fails to load); touch and no JavaScript start on the grid. A switch toggles between them. - One photo opens in a dialog at its real ratio, with focus trapped, Escape, focus returned and a layout that fits tall photos, small windows and zoomed text. - Empty states say when no photos match and link the places list with the same filters. - Photos come only from the past-only loaders. The viewer's photo URL helper moves to places/_lib so the list, the photos view and the place page share it. - Palette only, motion on the tokens, reduced motion and forced colours respected. * fix(places): address review on the photos view - The place page's viewer uses usablePhotos, so it skips a malformed photo exactly as the card and the map count do, instead of failing the page. - The wall leaves any arrow key held with Alt, Ctrl, Meta or Shift to the browser, so Alt+Left and Cmd+Left still go back while the wall has focus. - Tests: the compositor-only CSS helper splits transitions on top-level commas, so a cubic-bezier's own commas aren't read as properties; the server-side import guard also catches lazy import() calls.
feat(places): the shared filter bar in bar density, past places only … …everywhere (#633) - /places moves onto the shared FilterBar in its sticky bar density: search plus six category chips (single-select, fixed order, counts, a chip at 0 stays). Old ?category= forms ('Tech Office', 'Tech+Office', any case) resolve; new links write kebab slugs. useDebounce is gone: the list and the map read the same results and keep up with typing. - The map rebuilds markers only when the shown places change, gestures are cooperative (a wheel scrolls the page), and markers, clusters and the info card use palette tokens only. - loading.tsx is gone: every past place is in the server HTML, with or without JavaScript. - Past places only, on every surface: the list, place pages, the sitemap, the places API and the home count drop a place that is today, running, to come or undated. - Kit: a keyboard-focused chip in a scrolling row is revealed; the bar band no longer draws a second edge when stuck; on short screens the bar stays in the page. - The copyright check skips the generated GraphQL file, and map.css gets its header.
feat(projects): the open Index with a hover preview, multi-select tec… …h and a featured rank (#632) * feat(projects): the open Index with a hover preview, multi-select tech and a featured rank - /projects becomes the open index (table style 2, tint hover) on the shared filter and table kit: a Featured group, then the rest by start year, each a real table. - A sticky filter bar with search, Kind chips (?category=, old links and combined categories still resolve) and a Technology picker that takes several at once (?tech= repeats). - On a fine pointer, hovering or focusing a row shows a preview card (cover, summary, stack) under the row, with no lean; it never covers its row, the focused link or the sticky bar, Escape dismisses it, and its code loads lazily so first load stays close to /certifications. - Studio gets an optional "Featured rank" (1-99). Until any rank exists, Featured shows the first 4 projects switched to Featured; ranked projects lead in rank order. - loading.tsx is gone: every row is in the server HTML, with or without JavaScript. - The kit's scroll chip row wraps on phones, keeps focus rings unclipped and shows a fade when chips run past the edge. * fix(projects): keep the index when the preview's code fails to load lazy() rethrows a rejected import during render and Suspense doesn't catch errors, so a chunk that failed to load (a deploy skew, a dropped connection, a blocked request) would have replaced the whole /projects index with the route's error view on a fine pointer. The import now resolves to a component that renders nothing, and the rows carry on. The module-boundary test now forbids value imports of the live half only; an `import type` is erased and keeps the lazy split intact.
fix(guestbook): recover from a slow sign-in on phones, count your own… … post (#631) - A sign-in Firebase completes after it already reported the popup closed now clears the error and shows the visitor signed in, instead of leaving "Sign-in cancelled." on screen. - Each sign-in attempt carries a token, so a superseded attempt (a second press, a sign-out, another tab) never overwrites newer state or hides a real error. - The closed-popup message says what happened and how to retry: "The sign-in page closed before sign-in finished. Choose a sign-in option to try again." - Google opens on its account chooser (prompt: select_account) instead of forcing the consent screen every time, so returning visitors spend less time in the popup tab. - The header count includes the visitor's own stored post, so "27 messages" no longer sits above 28 rows until the next navigation. - Failed sign-ins and late completions log only the Firebase code, provider and timing to Sentry, never anything about the visitor, so the next case can be diagnosed.
fix: address old review threads on files that still exist (#630) - Pin renovatebot/github-action to the commit its v46.3.13 tag points to (`@sha # v46.3.13`). The step runs with the repo's PAT, and Renovate still updates the SHA and the comment together, so version bumps keep their patch/minor auto-merge rule. - bunfig.toml sets saveTextLockfile = true explicitly, matching the committed text bun.lock; the old comment contradicted the old value. - scripts/package-cost.ts: JSDoc says what the thresholds and size mean (inclusive bounds in bytes), which tier files are read where (medium/high by next.config.ts, low is a report), and the Medium label no longer overlaps Low at exactly 1 MB.
fix: address older review threads (#629) - NumberTicker follows prefers-reduced-motion as it changes, not only at mount: turning it on mid-count jumps to the final value. - The hero renders the settings it last loaded in the first flush on a warm server, outside Suspense, so a reload past the cache's TTL can't stream a tagline of another length into an unreserved box. The reloaded copy shows from the next request. - The instrumentation guard's source scanner ends directives and // comments at any line terminator (LF, CR, U+2028, U+2029) and reads a backslash before CRLF as one continuation.
PreviousNext