Conversation
…claim Unclaimed anonymous accounts now live 24h instead of 7d, and the token issued by POST /users/anonymous expires with them, so a reaped user gets a real 401 instead of a 404 the frontend renders as a 500. CustomJwtService.sign takes optional JwtSignOptions and the anonymous endpoint passes expiresIn built from the same env config the reaper reads, so both move together. Claiming a temporary account into a new account now requires termsAccepted, matching sign up. Claiming into an existing account is unchanged.
Monitor creation is called browser-direct from the landing page, so the client address is the real one: budget it at 20 requests per minute per IP. Lower the per-project unclaimed monitor cap from 100 to 3 so a single project cannot be used to park monitors the pinger then has to keep checking.
The unclaimed pass used to read every project of every tier every 15 seconds
just to build an $in list. Query { claimed: false, mode } straight from the
monitors collection instead, backed by a new { claimed: 1, createdAt: -1 }
index. Claimed monitors keep their tier-based selection.
Claiming a monitor lowers the unclaimed count, so gating it on the unclaimed cap made no sense; at the new cap of 3 it also became reachable, leaving a project that holds 3 unclaimed monitors unable to claim any of them. Split the check so creation keeps both the unclaimed cap and the tier limit while claim only asks about the tier limit, and restore the ttl spec fixture order that was only working around this.
The GET and POST bodies depend on the session cookie, so a shared cache in front of the app could hand one user's token to another. Send Cache-Control no-store and Vary Cookie on every response.
The oauth state cookie now carries the flow, so the github and google
callbacks can tell a claim from a login without trusting the callback url.
On a claim they probe /users/me with the session cookie, and only an
anonymous user is claimed through POST /auth/{provider}/claim; the returned
token replaces the cookie and the user lands on the dashboard. A 409 sends
them back to the claim form with the project limit banner and keeps the
temporary session alive.
Anonymous users hitting an upgrade are routed to the claim form with their
tier, which the callback restores so the stripe redirect still runs.
A 5xx or a timeout on the /users/me probe used to fall through to the login flow, which overwrites the anonymous token cookie and leaves the user in a different account with their dashboard unreachable. An unavailable probe now sends them back to the claim form with the session cookie untouched, and only a genuine unauthorized or missing user still falls back to login. Every other claim failure, including a cancelled consent with no code, a burnt code and an unusable claimed token, also returns to the claim form with an error code instead of the sign up screen whose primary button would overwrite the same cookie. Any claim failure clears the onboarding tier so a still anonymous user is not sent to stripe checkout. Also moves the token max age helper next to decodeJwtPayload and reuses it in the session bff.
…ards Anonymous users now see a persistent claim banner with a live countdown on every cluster page, a one-click /app/quick-setup entry point that skips straight to a temporary dashboard, and a claim CTA on the metrics tile once the free-tier metrics limit is hit. Claiming an account from any of these surfaces now round-trips back through claimed=1 so the account_claimed analytics event actually fires, and the layout no longer crashes when that param is present on the very first page load (replaceState was being called before the SvelteKit router finished initializing). Also removes the vestigial anonymousProject preload that nothing consumed anymore, and collapses the quick-setup link in AuthForm now that the route exists.
…uplicate Push mode created an unclaimed monitor as soon as the name was valid, then finishing setup created a second monitor and claimed only that one, leaving the first behind. With the 3-unclaimed-monitor cap this reliably 409s after a few attempts. Finishing now claims the pending monitor directly (updating its name first if it changed), and pull mode is unaffected. A 409 during setup now shows a message about too many monitors waiting to be claimed instead of a generic failure. Also fixes claimMonitor storing the claim endpoint's empty response body under the monitor id, which made the UI immediately request /monitors/undefined/http_ping_buckets; it now refetches the monitor from the project's monitor list. Dropped the unused limit parameter on loadPingBuckets, which the ping-buckets endpoint never accepted.
A 401 from /users/me was never reaching the expired-session redirect: logdashAPI's unauthorized handler throws its own SvelteKit redirect before the caller's error message can be inspected, and that thrown Redirect was not an Error instance so the existing string-based check always missed it, silently bouncing the user to a bare /app/auth with the stale cookie still set. isExpiredSession now also recognizes a thrown redirect. Separately, the preload method crashed outright (this was undefined) because resolve_data_preloader hands callers a detached method reference; isExpiredSession is now a plain function instead of relying on `this`.
Replace the Business Source License with MIT (both co-authors agreed), set the licence field in every package and rename the backend package from the starter template name. Add the repository front door for a public project: README with the product, the honest self-hosting status (tracked in #251), local development steps and contribution pointers; CONTRIBUTING, SECURITY and CODE_OF_CONDUCT; issue and pull request templates; a dev compose file for Mongo, Redis and ClickHouse; root scripts for dev, build, check, test and format; a pinned node version; and .context/ ignored so agent scratch directories never get committed.
Editor-specific config is gone. The frontend and backend rules and the component cleanup command live in .agents/, indexed by a root AGENTS.md that Cursor, Codex and Copilot pick up on their own.
…de 22 The frontend workflow runs svelte-check, prettier, the solid colour and background transition guards and a production build. Backend actions move to node 22 and re-run when the shared templates change.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
logdash-io | 7ba5f5c | Commit Preview URL Branch Preview URL |
Sep 05 2026, 09:41 AM |
One OKLCH-derived neutral ramp with a hairline token, flat surfaces, daisyUI components narrowed so backgrounds never ease, native scrollbars styled through scrollbar-width and scrollbar-color, a ScrollArea that is a plain native scroller, press feedback for buttons, and a Tooltip that positions its fixed element without adding the window scroll offset. Public dashboard components pick up the same tokens.
…ross the app Translucent greys (text-*/NN, bg-*/NN, opacity tints) become solid steps of the neutral scale and background colours no longer ease on hover, focus or selection; only ink, borders and transforms transition. Cards, tiles, sidebars, settings, the logs tile, auth screens and the shared components follow the same flat direction as the landing.
A Linear-style lined layout: hero with a no-signup URL composer over a product-faithful app frame on a lit stage, live demo sections (log tail, metrics, downtime feed), first-thirty-days, testimonials switcher, FAQ, attio-style footer with the wordmark rising out of the page. Product and Resources open one shared nav panel that unfolds and resizes between menus. Docs and guides sit in a bounded frame with a sidebar and an on-this-page column, fed by typed content blocks; SEO families cover alternatives, health checks and vs pages, with a generated sitemap. Pages scroll the document, so the browser restores scroll before the first paint; app.html blocks rendering until the document is parsed and restores the saved offset at parse end for engines that would wait for load. Only the article fades between docs pages; same-page anchors scroll smoothly. Inter replaces Kumbh Sans. Two lint guards ban translucent greys and easing backgrounds; Playwright specs cover the anonymous landing flow and SEO metadata. Fabricated social proof is gone: the incidents odometer placeholder and the logo wall were removed, the eyebrow names the three founders whose testimonials appear on the page, and the downtime feed's posts are marked as invented. Self-hosting docs and README link the tracking issue #251.
The app carried 128 eslint errors and 39 warnings that kept eslint out of
the pull request workflow. Every {#each} is keyed, internal navigations go
through resolve() from $app/paths with typed route ids, useless children
snippets and mustaches are unwrapped, unused imports, variables and
parameters are gone, `any` icon props are typed as Component, dependency
reads in effects are explicit `void` expressions, empty catches return,
and a write-only polling map is deleted. The remaining eslint-disable
directives each carry a reason: our own static legal HTML, a caller-
supplied href and an absolute status page URL from state.
CI and `npm run lint` now run eslint with --max-warnings 0.
…ites spec Logs are queued and flushed by a once-a-second cron whose insert is fire and forget, so a fixed 1.5 s sleep before reading them back raced on a slow CI runner: "creates multiple logs in batch" saw 0 of 3 logs. A waitFor helper polls ClickHouse every 300 ms until the expected rows are there (10 s cap) and returns the last read so a real failure still shows what was found. The four waits in this spec use it.
szymeo
force-pushed
the
redesign-landing
branch
from
September 5, 2026 09:40
cff5d7b to
7ba5f5c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
The landing, docs and SEO pages are redesigned in a lined layout, visitors can start monitoring a URL without an account (anonymous accounts that GitHub or Google login later claims), and the repository is set up as a public open source project: MIT licence, README, CONTRIBUTING, SECURITY, CODE_OF_CONDUCT, issue and PR templates, a frontend check workflow.
Highlights:
POST /users/anonymous, claiming anonymous projects on OAuth login, monitor limits and rate limiting for anonymous users.Why
The previous landing no longer matched the product, signup was the first thing a visitor hit, and the repository goes public under MIT with the docs a public project needs. Self-hosting status is documented honestly and tracked in #251.
How it was tested
pnpm --filter frontend check(svelte-check, 0 errors), prettier, both guards, eslint with--max-warnings 0,pnpm --filter frontend build.Screenshots
To be attached from the Conductor workspace (
.context/validate/reload/hero-1440.png,nav-lines.png,docs-top.png).type(scope): summary🤖 Generated with Claude Code